Blame SOURCES/skiboot-6.0.4-e247710814227a7122915ff44474e0c8aa26fd3a.patch

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 */