summaryrefslogtreecommitdiffstats
path: root/libflash/blocklevel.c
diff options
context:
space:
mode:
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>2018-11-21 17:16:01 +1100
committerStewart Smith <stewart@linux.ibm.com>2018-11-21 21:55:53 -0600
commite247710814227a7122915ff44474e0c8aa26fd3a (patch)
treedd03b6b3ac9940a982e5bd8c9a67e0839bbbdcac /libflash/blocklevel.c
parent4b92a1b80f6dd27195ab50ab8370c7915a4a9b17 (diff)
downloadblackbird-skiboot-e247710814227a7122915ff44474e0c8aa26fd3a.tar.gz
blackbird-skiboot-e247710814227a7122915ff44474e0c8aa26fd3a.zip
libflash: Don't merge ECC-protected ranges
Libflash currently merges contiguous ECC-protected ranges, but doesn't check that the ECC bytes at the end of the first and start of the second range actually match sanely. More importantly, if blocklevel_read() is called with a position at the start of a partition that is contained somewhere within a region that has been merged it will update the position assuming ECC wasn't being accounted for. This results in the position being somewhere well after the actual start of the partition which is incorrect. For now, remove the code merging ranges. This means more ranges must be held and checked however it prevents incorrectly reading ECC-correct regions like below: [ 174.334119453,7] FLASH: CAPP partition has ECC [ 174.437349574,3] ECC: uncorrectable error: ffffffffffffffff ff [ 174.437426306,3] FLASH: failed to read the first 0x1000 from CAPP partition, rc 14 [ 174.439919343,3] CAPP: Error loading ucode lid. index=201d1 Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'libflash/blocklevel.c')
-rw-r--r--libflash/blocklevel.c26
1 files changed, 3 insertions, 23 deletions
diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c
index bbcc8e61..5b57d3c6 100644
--- a/libflash/blocklevel.c
+++ b/libflash/blocklevel.c
@@ -53,9 +53,9 @@ static int ecc_protected(struct blocklevel_device *bl, uint64_t pos, uint64_t le
}
/*
- * Since we merge regions on inserting we can be sure that a
- * partial fit means that the non fitting region won't fit in another ecc
- * region
+ * Even if ranges are merged we can't currently guarantee two
+ * contiguous regions are sanely ECC protected so a partial fit
+ * is no good.
*/
if ((bl->ecc_prot.prot[i].start >= pos && bl->ecc_prot.prot[i].start < pos + len) ||
(bl->ecc_prot.prot[i].start <= pos &&
@@ -696,26 +696,6 @@ static bool insert_bl_prot_range(struct blocklevel_range *ranges, struct bl_prot
prot = new_ranges;
}
- /* Probably only worth mergeing when we're low on space */
- if (ranges->n_prot + 1 == ranges->total_prot) {
- FL_DBG("%s: merging ranges\n", __func__);
- /* Check to see if we can merge ranges */
- for (i = 0; i < ranges->n_prot - 1; i++) {
- if (prot[i].start + prot[i].len == prot[i + 1].start) {
- int j;
- FL_DBG("%s: merging 0x%" PRIx64 "..0x%" PRIx64 " with "
- "0x%" PRIx64 "..0x%" PRIx64 "\n",
- __func__, prot[i].start, prot[i].start + prot[i].len,
- prot[i + 1].start, prot[i + 1].start + prot[i + 1].len);
- prot[i].len += prot[i + 1].len;
- for (j = i + 1; j < ranges->n_prot - 1; j++)
- memcpy(&prot[j] , &prot[j + 1], sizeof(range));
- ranges->n_prot--;
- i--; /* Maybe the next one can merge too */
- }
- }
- }
-
return true;
}
OpenPOWER on IntegriCloud