|
|
c83195 |
commit e247710814227a7122915ff44474e0c8aa26fd3a
|
|
|
c83195 |
Author: Samuel Mendoza-Jonas <sam@mendozajonas.com>
|
|
|
c83195 |
Date: Wed Nov 21 17:16:01 2018 +1100
|
|
|
c83195 |
|
|
|
c83195 |
libflash: Don't merge ECC-protected ranges
|
|
|
c83195 |
|
|
|
c83195 |
Libflash currently merges contiguous ECC-protected ranges, but doesn't
|
|
|
c83195 |
check that the ECC bytes at the end of the first and start of the second
|
|
|
c83195 |
range actually match sanely. More importantly, if blocklevel_read() is
|
|
|
c83195 |
called with a position at the start of a partition that is contained
|
|
|
c83195 |
somewhere within a region that has been merged it will update the
|
|
|
c83195 |
position assuming ECC wasn't being accounted for. This results in the
|
|
|
c83195 |
position being somewhere well after the actual start of the partition
|
|
|
c83195 |
which is incorrect.
|
|
|
c83195 |
|
|
|
c83195 |
For now, remove the code merging ranges. This means more ranges must be
|
|
|
c83195 |
held and checked however it prevents incorrectly reading ECC-correct
|
|
|
c83195 |
regions like below:
|
|
|
c83195 |
|
|
|
c83195 |
[ 174.334119453,7] FLASH: CAPP partition has ECC
|
|
|
c83195 |
[ 174.437349574,3] ECC: uncorrectable error: ffffffffffffffff ff
|
|
|
c83195 |
[ 174.437426306,3] FLASH: failed to read the first 0x1000 from CAPP partition, rc 14
|
|
|
c83195 |
[ 174.439919343,3] CAPP: Error loading ucode lid. index=201d1
|
|
|
c83195 |
|
|
|
c83195 |
Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
|
|
|
c83195 |
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
|
|
|
c83195 |
|
|
|
c83195 |
diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c
|
|
|
c83195 |
index bbcc8e61..5b57d3c6 100644
|
|
|
c83195 |
--- a/libflash/blocklevel.c
|
|
|
c83195 |
+++ b/libflash/blocklevel.c
|
|
|
c83195 |
@@ -53,9 +53,9 @@ static int ecc_protected(struct blocklevel_device *bl, uint64_t pos, uint64_t le
|
|
|
c83195 |
}
|
|
|
c83195 |
|
|
|
c83195 |
/*
|
|
|
c83195 |
- * Since we merge regions on inserting we can be sure that a
|
|
|
c83195 |
- * partial fit means that the non fitting region won't fit in another ecc
|
|
|
c83195 |
- * region
|
|
|
c83195 |
+ * Even if ranges are merged we can't currently guarantee two
|
|
|
c83195 |
+ * contiguous regions are sanely ECC protected so a partial fit
|
|
|
c83195 |
+ * is no good.
|
|
|
c83195 |
*/
|
|
|
c83195 |
if ((bl->ecc_prot.prot[i].start >= pos && bl->ecc_prot.prot[i].start < pos + len) ||
|
|
|
c83195 |
(bl->ecc_prot.prot[i].start <= pos &&
|
|
|
c83195 |
@@ -696,26 +696,6 @@ static bool insert_bl_prot_range(struct blocklevel_range *ranges, struct bl_prot
|
|
|
c83195 |
prot = new_ranges;
|
|
|
c83195 |
}
|
|
|
c83195 |
|
|
|
c83195 |
- /* Probably only worth mergeing when we're low on space */
|
|
|
c83195 |
- if (ranges->n_prot + 1 == ranges->total_prot) {
|
|
|
c83195 |
- FL_DBG("%s: merging ranges\n", __func__);
|
|
|
c83195 |
- /* Check to see if we can merge ranges */
|
|
|
c83195 |
- for (i = 0; i < ranges->n_prot - 1; i++) {
|
|
|
c83195 |
- if (prot[i].start + prot[i].len == prot[i + 1].start) {
|
|
|
c83195 |
- int j;
|
|
|
c83195 |
- FL_DBG("%s: merging 0x%" PRIx64 "..0x%" PRIx64 " with "
|
|
|
c83195 |
- "0x%" PRIx64 "..0x%" PRIx64 "\n",
|
|
|
c83195 |
- __func__, prot[i].start, prot[i].start + prot[i].len,
|
|
|
c83195 |
- prot[i + 1].start, prot[i + 1].start + prot[i + 1].len);
|
|
|
c83195 |
- prot[i].len += prot[i + 1].len;
|
|
|
c83195 |
- for (j = i + 1; j < ranges->n_prot - 1; j++)
|
|
|
c83195 |
- memcpy(&prot[j] , &prot[j + 1], sizeof(range));
|
|
|
c83195 |
- ranges->n_prot--;
|
|
|
c83195 |
- i--; /* Maybe the next one can merge too */
|
|
|
c83195 |
- }
|
|
|
c83195 |
- }
|
|
|
c83195 |
- }
|
|
|
c83195 |
-
|
|
|
c83195 |
return true;
|
|
|
c83195 |
}
|
|
|
c83195 |
|
|
|
c83195 |
diff --git a/libflash/test/test-blocklevel.c b/libflash/test/test-blocklevel.c
|
|
|
c83195 |
index 42ad146a..a67f5888 100644
|
|
|
c83195 |
--- a/libflash/test/test-blocklevel.c
|
|
|
c83195 |
+++ b/libflash/test/test-blocklevel.c
|
|
|
c83195 |
@@ -289,24 +289,6 @@ int main(void)
|
|
|
c83195 |
ERR("Failed to blocklevel_ecc_protect(0x6200, 0x100)\n");
|
|
|
c83195 |
return 1;
|
|
|
c83195 |
}
|
|
|
c83195 |
- /*This addition should cause this one to merge the other two together*/
|
|
|
c83195 |
- if (blocklevel_ecc_protect(bl, 0x6100, 0x100)) {
|
|
|
c83195 |
- ERR("Failed to blocklevel_ecc_protect(0x6100, 0x100)\n");
|
|
|
c83195 |
- return 1;
|
|
|
c83195 |
- }
|
|
|
c83195 |
- /* Make sure we trigger the merging code */
|
|
|
c83195 |
- for (i = bl->ecc_prot.n_prot; i < bl->ecc_prot.total_prot; i++)
|
|
|
c83195 |
- blocklevel_ecc_protect(bl, 0x10000 + i * 0x200, 0x10);
|
|
|
c83195 |
- /* Check that the region merging works */
|
|
|
c83195 |
- for (i = 0; i < bl->ecc_prot.n_prot - 1; i++) {
|
|
|
c83195 |
- if (bl->ecc_prot.prot[i].start + bl->ecc_prot.prot[i].len == bl->ecc_prot.prot[i + 1].start ||
|
|
|
c83195 |
- bl->ecc_prot.prot[i + 1].start + bl->ecc_prot.prot[i + 1].len == bl->ecc_prot.prot[i].start) {
|
|
|
c83195 |
- ERR("Problem with protection range merge code, region starting at 0x%08lx for 0x%08lx appears "
|
|
|
c83195 |
- "to touch region 0x%lx for 0x%lx\n", bl->ecc_prot.prot[i].start, bl->ecc_prot.prot[i].len,
|
|
|
c83195 |
- bl->ecc_prot.prot[i + 1].start, bl->ecc_prot.prot[i + 1].len);
|
|
|
c83195 |
- return 1;
|
|
|
c83195 |
- }
|
|
|
c83195 |
- }
|
|
|
c83195 |
|
|
|
c83195 |
/* Test ECC reading and writing being 100% transparent to the
|
|
|
c83195 |
* caller */
|