[Skiboot] [PATCH 11/16] flash: Add ECC to load_resource()

Michael Neuling mikey at neuling.org
Fri Feb 20 11:37:54 AEDT 2015


Add decoding, checking and correction of ECC enabled partitions in
pnor_load_resource().

Signed-off-by: Michael Neuling <mikey at neuling.org>
---
 core/flash.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 52 insertions(+), 15 deletions(-)

diff --git a/core/flash.c b/core/flash.c
index e107aaf..51a66c9 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -22,6 +22,7 @@
 #include <device.h>
 #include <libflash/libflash.h>
 #include <libflash/libffs.h>
+#include <ecc.h>
 
 struct flash {
 	bool			registered;
@@ -353,20 +354,28 @@ struct flash_hostboot_header {
 	struct flash_hostboot_toc toc[FLASH_HOSTBOOT_TOC_MAX_ENTRIES];
 };
 
+/* start and total size include ECC */
 static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid,
-		uint32_t *start, uint32_t *total_size)
+				   uint32_t *start, uint32_t *total_size,
+				   bool *ecc)
 {
 	struct flash_hostboot_header *header;
 	char eyecatcher[5];
-	uint32_t i;
+	uint32_t i, partsize;
 	bool rc;
 
 	header = malloc(FLASH_SUBPART_HEADER_SIZE);
 	if (!header)
 		return false;
 
+	/* Get raw partition size without ECC */
+	partsize = *total_size;
+	if (ecc)
+		partsize = BUFFER_SIZE_MINUS_ECC(*total_size);
+
 	/* Get the TOC */
-	rc = flash_read(chip, *start, header, FLASH_SUBPART_HEADER_SIZE);
+	rc = ffs_flash_read(chip, *start, header, FLASH_SUBPART_HEADER_SIZE,
+			    ecc);
 	if (rc) {
 		prerror("FLASH: flash subpartition TOC read failed %i\n", rc);
 		goto end;
@@ -401,8 +410,8 @@ static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid,
 		if (ec != subid)
 			continue;
 
-		/* Sanity check the offset and size */
-		if (offset + size > *total_size) {
+		/* Sanity check the offset and size. */
+		if (offset + size > partsize) {
 			prerror("FLASH: flash subpartition too big: %i\n", i);
 			goto end;
 		}
@@ -416,14 +425,20 @@ static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid,
 			goto end;
 		}
 
-		/* All good, let's adjust the start and size */
 		prlog(PR_DEBUG, "FLASH: flash found subpartition: "
 				"%i size: %i offset %i\n",
 				i, size, offset);
+
+		/*
+		 * Adjust the start and size.  The start location in the needs
+		 * to account for ecc but the size doesn't.
+		 */
 		*start += offset;
-		size = (size + (FLASH_SUBPART_ALIGNMENT - 1)) &
-				~(FLASH_SUBPART_ALIGNMENT - 1);
 		*total_size = size;
+		if (ecc) {
+			*start += ECC_SIZE(offset);
+			*total_size += ECC_SIZE(size);
+		}
 		rc = 0;
 		goto end;
 	}
@@ -433,14 +448,18 @@ end:
 	return rc;
 }
 
+/*
+ * load a resource from FLASH
+ * buf and len shouldn't account for ECC even if partition is ECCed.
+ */
 bool flash_load_resource(enum resource_id id, uint32_t subid,
 		void *buf, size_t *len)
 {
-	int i, rc, part_num, part_size, part_start;
+	int i, rc, part_num, part_size, part_start, size;
 	struct ffs_handle *ffs;
 	struct flash *flash;
 	const char *name;
-	bool status;
+	bool status, ecc;
 
 	status = false;
 
@@ -483,33 +502,51 @@ bool flash_load_resource(enum resource_id id, uint32_t subid,
 		goto out_free_ffs;
 	}
 	rc = ffs_part_info(ffs, part_num, NULL,
-			   &part_start, &part_size, NULL, NULL);
+			   &part_start, &part_size, NULL, &ecc);
 	if (rc) {
 		prerror("FLASH: Failed to get %s partition info\n", name);
 		goto out_free_ffs;
 	}
+	prlog(PR_DEBUG,"FLASH: %s partition %s ECC\n",
+	      name, ecc  ? "has" : "doesn't have");
+
+	/*
+	 * part_start/size are raw pointers into the partition.
+	 *  ie. they will account for ECC if included.
+	 */
 
 	/* Find the sub partition if required */
 	if (subid != RESOURCE_SUBID_NONE) {
 		rc = flash_find_subpartition(flash->chip, subid, &part_start,
-					    &part_size);
+					     &part_size, &ecc);
 		if (rc)
 			goto out_free_ffs;
 	}
 
-	if (part_size > *len) {
+	/* Work out what the final size of buffer will be without ECC */
+	size = part_size;
+	if (ecc) {
+		if ECC_BUFFER_SIZE_CHECK(part_size) {
+			prerror("FLASH: %s image invalid size for ECC %d\n",
+				name, part_size);
+			goto out_free_ffs;
+		}
+		size = BUFFER_SIZE_MINUS_ECC(part_size);
+	}
+
+	if (size > *len) {
 		prerror("FLASH: %s image too large (%d > %zd)\n", name,
 			part_size, *len);
 		goto out_free_ffs;
 	}
 
-	rc = flash_read(flash->chip, part_start, buf, part_size);
+	rc = ffs_flash_read(flash->chip, part_start, buf, size, ecc);
 	if (rc) {
 		prerror("FLASH: failed to read %s partition\n", name);
 		goto out_free_ffs;
 	}
 
-	*len = part_size;
+	*len = size;
 	status = true;
 
 out_free_ffs:
-- 
2.1.0



More information about the Skiboot mailing list