[Skiboot] [PATCH 2/4] core/flash-subpartition: compute partition size from subpartition struct

Stewart Smith stewart at linux.vnet.ibm.com
Tue Oct 25 18:15:00 AEDT 2016


>From the subpartition structure, we have the ability to compute
the full partition size. Do that.

This lets us only read the amount of a subpartition that is valid
and needed to be read, rather than having to read the entire thing.

We continue the current behaviour of loading flash partitions though.

Based-on-patch-by: Claudio Carvalho <cclaudio at linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart at linux.vnet.ibm.com>
---
 core/flash-subpartition.c          | 86 +++++++++++++++++++++++---------------
 core/flash.c                       |  2 +-
 core/test/run-flash-subpartition.c |  6 ++-
 include/skiboot.h                  |  3 +-
 4 files changed, 60 insertions(+), 37 deletions(-)

diff --git a/core/flash-subpartition.c b/core/flash-subpartition.c
index ba7f0a37829a..1e91c1bd06e6 100644
--- a/core/flash-subpartition.c
+++ b/core/flash-subpartition.c
@@ -31,16 +31,24 @@ struct flash_hostboot_header {
 	struct flash_hostboot_toc toc[FLASH_HOSTBOOT_TOC_MAX_ENTRIES];
 };
 
-int flash_subpart_info(void *part_header, uint32_t part_size, uint32_t subid,
-		       uint32_t *offset, uint32_t *size)
+int flash_subpart_info(void *part_header, uint32_t header_len,
+		       uint32_t part_size, uint32_t *part_actual,
+		       uint32_t subid, uint32_t *offset, uint32_t *size)
 {
 	struct flash_hostboot_header *header;
 	char eyecatcher[5];
-	uint32_t i, ec;
+	uint32_t i, ec, o, s, toc;
+	bool subpart_found;
 
-	if (!part_header || !offset || !size) {
-		prlog(PR_ERR, "FLASH: invalid parameters: "
-		      "ph %p of %p sz %p\n", part_header, offset, size);
+	if (!part_header || ( !offset && !size && !part_actual)) {
+		prlog(PR_ERR, "FLASH: invalid parameters: ph %p of %p sz %p "
+		      "tsz %p\n", part_header, offset, size, part_actual);
+		return OPAL_PARAMETER;
+	}
+
+	if (header_len < FLASH_SUBPART_HEADER_SIZE) {
+		prlog(PR_ERR, "FLASH: subpartition header too small 0x%x\n",
+		      header_len);
 		return OPAL_PARAMETER;
 	}
 
@@ -50,53 +58,63 @@ int flash_subpart_info(void *part_header, uint32_t part_size, uint32_t subid,
 	i = be32_to_cpu(header->version);
 	if (i != 1) {
 		prerror("FLASH: flash subpartition TOC version unknown %i\n", i);
-		goto end;
+		return OPAL_RESOURCE;
 	}
 
 	/* NULL terminate eyecatcher */
 	strncpy(eyecatcher, header->eyecatcher, 4);
 	eyecatcher[4] = '\0';
 	prlog(PR_DEBUG, "FLASH: flash subpartition eyecatcher %s\n",
-			eyecatcher);
+	      eyecatcher);
 
+	subpart_found = false;
+	*part_actual = 0;
+	toc = sizeof(header->eyecatcher) + sizeof(header->version);
 	for (i = 0; i < FLASH_HOSTBOOT_TOC_MAX_ENTRIES; i++) {
 
 		ec = be32_to_cpu(header->toc[i].ec);
-		*offset = be32_to_cpu(header->toc[i].offset);
-		*size = be32_to_cpu(header->toc[i].size);
+		o = be32_to_cpu(header->toc[i].offset);
+		s = be32_to_cpu(header->toc[i].size);
 
 		/* Check for null terminating entry */
-		if (!ec && !*offset && !*size) {
-			prerror("FLASH: flash subpartition not found.\n");
-			goto end;
-		}
-
-		if (ec != subid)
-			continue;
+		if (!ec && !o && !s)
+			break;
 
 		/* Sanity check the offset and size. */
-		if (*offset + *size > part_size) {
+		if (o + s > part_size) {
 			prerror("FLASH: flash subpartition too big: %i\n", i);
-			goto end;
+			return OPAL_RESOURCE;
 		}
-		if (!*size) {
+		if (!s) {
 			prerror("FLASH: flash subpartition zero size: %i\n", i);
-			goto end;
+			return OPAL_RESOURCE;
 		}
-		if (*offset < FLASH_SUBPART_HEADER_SIZE) {
-			prerror("FLASH: flash subpartition "
-					"offset too small: %i\n", i);
-			goto end;
+		if (o < FLASH_SUBPART_HEADER_SIZE) {
+			prerror("FLASH: flash subpartition offset too small: "
+			        "%i\n", i);
+			return OPAL_RESOURCE;
 		}
+		/*
+		 * Subpartitions content are different, but multiple toc entries
+		 * may point to the same subpartition.
+		 */
+		if (ALIGN_UP(o + s, FLASH_SUBPART_HEADER_SIZE) > *part_actual)
+			*part_actual = ALIGN_UP(o + s, FLASH_SUBPART_HEADER_SIZE);
 
-		prlog(PR_DEBUG, "FLASH: flash found subpartition: "
-				"%i size: %i offset %i\n",
-				i, *size, *offset);
-
-		return OPAL_SUCCESS;
+		if (ec == subid) {
+			if (offset)
+				*offset += o;
+			if (size)
+				*size = s;
+			if (!part_actual)
+				return OPAL_SUCCESS;
+			subpart_found = true;
+		}
+		toc += sizeof(struct flash_hostboot_toc);
+	}
+	if (!subpart_found && (offset || size)) {
+		prerror("FLASH: flash subpartition not found.\n");
+		return OPAL_RESOURCE;
 	}
-end:
-	*size = 0;
-	*offset = 0;
-	return OPAL_RESOURCE;
+	return OPAL_SUCCESS;
 }
diff --git a/core/flash.c b/core/flash.c
index 4b7f4b38ea46..2299f45c814c 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -459,7 +459,7 @@ static int flash_find_subpartition(struct blocklevel_device *bl, uint32_t subid,
 		goto end;
 	}
 
-	rc = flash_subpart_info(header, partsize, subid, &offset, &size);
+	rc = flash_subpart_info(header, partsize, partsize, NULL, subid, &offset, &size);
 	if (rc)
 		goto end;
 
diff --git a/core/test/run-flash-subpartition.c b/core/test/run-flash-subpartition.c
index 169362ef72cb..419de887e050 100644
--- a/core/test/run-flash-subpartition.c
+++ b/core/test/run-flash-subpartition.c
@@ -35,20 +35,24 @@ char capp[4096] = {0x43, 0x41, 0x50, 0x50, 0x00, 0x00, 0x00, 0x01,
 int main(void)
 {
 	int rc;
+	uint32_t part_actual;
 	uint32_t offset;
 	uint32_t size;
 	uint32_t subids[] = { 0x100ea, 0x200ea, 0x200ef, 0x201ef, 0x100d3 };
 
 	for (int i = 0; i < sizeof(subids)/sizeof(uint32_t); i++) {
 		offset = 0;
-		rc = flash_subpart_info(capp, 0x24000, subids[i],
+		rc = flash_subpart_info(capp, sizeof(capp), 0x24000,
+					&part_actual, subids[i],
 					&offset, &size);
 		printf("\nsubid %x\n", subids[i]);
+		printf("part_actual %u\n", part_actual);
 		printf("offset %u\n", offset);
 		printf("size %u\n", size);
 		assert (rc == 0);
 		assert (size == 36432);
 		assert (offset == 4096);
+		assert (part_actual == 40960);
 	}
 
 	return 0;
diff --git a/include/skiboot.h b/include/skiboot.h
index 30149a1ac999..75c5207f9c1f 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -227,7 +227,8 @@ extern bool flash_reserve(void);
 extern void flash_release(void);
 #define FLASH_SUBPART_ALIGNMENT 0x1000
 #define FLASH_SUBPART_HEADER_SIZE FLASH_SUBPART_ALIGNMENT
-extern int flash_subpart_info(void *part_header, uint32_t part_size,
+extern int flash_subpart_info(void *part_header, uint32_t header_len,
+			      uint32_t part_size, uint32_t *part_actual,
 			      uint32_t subid, uint32_t *offset,
 			      uint32_t *size);
 /* NVRAM support */
-- 
2.1.4



More information about the Skiboot mailing list