[Skiboot] [PATCH 2/3 v3] core/flash: port pnor_load_resource to flash code

Jeremy Kerr jk at ozlabs.org
Thu Feb 19 09:34:53 AEDT 2015


Since we have a flash device registered as the system flash, use this as
a generic load_resource backend.

Signed-off-by: Jeremy Kerr <jk at ozlabs.org>
Reviewed-by: Joel Stanley <joel at jms.id.au>

---
 core/flash.c                |  186 ++++++++++++++++++++++++++++++++++++
 include/skiboot.h           |    3 
 platforms/astbmc/astbmc.h   |    3 
 platforms/astbmc/habanero.c |    2 
 platforms/astbmc/palmetto.c |    2 
 platforms/astbmc/pnor.c     |  167 --------------------------------
 6 files changed, 190 insertions(+), 173 deletions(-)

diff --git a/core/flash.c b/core/flash.c
index 33e9242..c6b01ad 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -223,3 +223,189 @@ static int64_t opal_flash_erase(uint64_t id, uint64_t offset, uint64_t size,
 opal_call(OPAL_FLASH_READ, opal_flash_read, 5);
 opal_call(OPAL_FLASH_WRITE, opal_flash_write, 5);
 opal_call(OPAL_FLASH_ERASE, opal_flash_erase, 4);
+
+/* flash resource API */
+static struct {
+	enum resource_id	id;
+	uint32_t		subid;
+	char			name[PART_NAME_MAX+1];
+} part_name_map[] = {
+	{ RESOURCE_ID_KERNEL,	RESOURCE_SUBID_NONE,		"KERNEL" },
+	{ RESOURCE_ID_INITRAMFS,RESOURCE_SUBID_NONE,		"ROOTFS" },
+};
+
+/* This mimics the hostboot SBE format */
+#define FLASH_SUBPART_ALIGNMENT 0x1000
+#define FLASH_SUBPART_HEADER_SIZE FLASH_SUBPART_ALIGNMENT
+
+struct flash_hostboot_toc {
+	be32 ec;
+	be32 offset; /* From start of header.  4K aligned */
+	be32 size;
+};
+#define FLASH_HOSTBOOT_TOC_MAX_ENTRIES ((FLASH_SUBPART_HEADER_SIZE - 8) \
+		/sizeof(struct flash_hostboot_toc))
+
+struct flash_hostboot_header {
+	char eyecatcher[4];
+	be32 version;
+	struct flash_hostboot_toc toc[FLASH_HOSTBOOT_TOC_MAX_ENTRIES];
+};
+
+static int flash_find_subpartition(struct flash_chip *chip, uint32_t subid,
+		uint32_t *start, uint32_t *total_size)
+{
+	struct flash_hostboot_header *header;
+	char eyecatcher[5];
+	uint32_t i;
+	bool rc;
+
+	header = malloc(FLASH_SUBPART_HEADER_SIZE);
+	if (!header)
+		return false;
+
+	/* Get the TOC */
+	rc = flash_read(chip, *start, header, FLASH_SUBPART_HEADER_SIZE);
+	if (rc) {
+		prerror("FLASH: flash subpartition TOC read failed %i", rc);
+		goto end;
+	}
+
+	/* Perform sanity */
+	i = be32_to_cpu(header->version);
+	if (i != 1) {
+		prerror("FLASH: flash subpartition TOC version unknown %i", i);
+		rc = OPAL_RESOURCE;
+		goto end;
+	}
+	/* NULL terminate eyecatcher */
+	strncpy(eyecatcher, header->eyecatcher, 4);
+	eyecatcher[4] = 0;
+	prlog(PR_DEBUG, "FLASH: flash subpartition eyecatcher %s\n",
+			eyecatcher);
+
+	rc = OPAL_RESOURCE;
+	for (i = 0; i< FLASH_HOSTBOOT_TOC_MAX_ENTRIES; i++) {
+		uint32_t ec, offset, size;
+
+		ec = be32_to_cpu(header->toc[i].ec);
+		offset = be32_to_cpu(header->toc[i].offset);
+		size = be32_to_cpu(header->toc[i].size);
+		/* Check for null terminating entry */
+		if (!ec && !offset && !size) {
+			prerror("FLASH: flash subpartition not found.");
+			goto end;
+		}
+
+		if (ec != subid)
+			continue;
+
+		/* Sanity check the offset and size */
+		if (offset + size > *total_size) {
+			prerror("FLASH: flash subpartition too big: %i", i);
+			goto end;
+		}
+		if (!size) {
+			prerror("FLASH: flash subpartition zero size: %i", i);
+			goto end;
+		}
+		if (offset < FLASH_SUBPART_HEADER_SIZE) {
+			prerror("FLASH: flash subpartition "
+					"offset too small: %i", i);
+			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);
+		*start += offset;
+		size = (size + (FLASH_SUBPART_ALIGNMENT - 1)) &
+				~(FLASH_SUBPART_ALIGNMENT - 1);
+		*total_size = size;
+		rc = 0;
+		goto end;
+	}
+
+end:
+	free(header);
+	return rc;
+}
+
+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;
+	struct ffs_handle *ffs;
+	struct flash *flash;
+	const char *name;
+	bool status;
+
+	status = false;
+
+	lock(&flash_lock);
+
+	if (!system_flash)
+		goto out_unlock;
+
+	flash = system_flash;
+
+	for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) {
+		if (part_name_map[i].id == id) {
+			name = part_name_map[i].name;
+			subid = part_name_map[i].subid;
+			break;
+		}
+	}
+	if (!name) {
+		prerror("FLASH: Couldn't find partition for id %d\n", id);
+		goto out_unlock;
+	}
+
+	rc = ffs_open_flash(flash->chip, 0, flash->size, &ffs);
+	if (rc) {
+		prerror("FLASH: Can't open ffs handle\n");
+		goto out_unlock;
+	}
+
+	rc = ffs_lookup_part(ffs, name, &part_num);
+	if (rc) {
+		prerror("FLASH: No %s partition\n", name);
+		goto out_free_ffs;
+	}
+	rc = ffs_part_info(ffs, part_num, NULL,
+			   &part_start, &part_size, NULL);
+	if (rc) {
+		prerror("FLASH: Failed to get %s partition info\n", name);
+		goto out_free_ffs;
+	}
+
+	if (part_size > *len) {
+		prerror("FLASH: %s image too large (%d > %zd)\n", name,
+			part_size, *len);
+		goto out_free_ffs;
+	}
+
+	/* Find the sub partition if required */
+	if (subid != RESOURCE_SUBID_NONE) {
+		rc = flash_find_subpartition(flash->chip, subid, &part_start,
+					    &part_size);
+		if (rc)
+			return false;
+	}
+
+	rc = flash_read(flash->chip, part_start, buf, part_size);
+	if (rc) {
+		prerror("FLASH: failed to read %s partition\n", name);
+		goto out_free_ffs;
+	}
+
+	*len = part_size;
+	status = true;
+
+out_free_ffs:
+	ffs_close(ffs);
+out_unlock:
+	unlock(&flash_lock);
+	return status;
+}
diff --git a/include/skiboot.h b/include/skiboot.h
index dbc2057..f6fcc63 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -199,7 +199,8 @@ extern void occ_fsp_init(void);
 /* flash support */
 struct flash_chip;
 extern int flash_register(struct flash_chip *chip, bool is_system_flash);
-extern bool flash_load_resource(enum resource_id id, void *buf, size_t *len);
+extern bool flash_load_resource(enum resource_id id, uint32_t subid,
+		void *buf, size_t *len);
 
 /* NVRAM support */
 extern void nvram_init(void);
diff --git a/platforms/astbmc/astbmc.h b/platforms/astbmc/astbmc.h
index cff4757..cee475a 100644
--- a/platforms/astbmc/astbmc.h
+++ b/platforms/astbmc/astbmc.h
@@ -24,8 +24,5 @@ extern int64_t astbmc_ipmi_power_down(uint64_t request);
 extern void astbmc_init(void);
 extern void astbmc_ext_irq(unsigned int chip_id);
 extern int pnor_init(void);
-extern int pnor_load_part(const char *name, void *addr, size_t *len);
-extern bool pnor_load_resource(enum resource_id id, uint32_t subid,
-			       void *buf, size_t *len);
 
 #endif /* __ASTBMC_H */
diff --git a/platforms/astbmc/habanero.c b/platforms/astbmc/habanero.c
index a19aafd..0ec867f 100644
--- a/platforms/astbmc/habanero.c
+++ b/platforms/astbmc/habanero.c
@@ -49,5 +49,5 @@ DECLARE_PLATFORM(habanero) = {
 	.external_irq		= astbmc_ext_irq,
 	.cec_power_down         = astbmc_ipmi_power_down,
 	.cec_reboot             = astbmc_ipmi_reboot,
-	.load_resource		= pnor_load_resource,
+	.load_resource		= flash_load_resource,
 };
diff --git a/platforms/astbmc/palmetto.c b/platforms/astbmc/palmetto.c
index 210d10a..3435d0b 100644
--- a/platforms/astbmc/palmetto.c
+++ b/platforms/astbmc/palmetto.c
@@ -51,6 +51,6 @@ DECLARE_PLATFORM(palmetto) = {
 	.cec_power_down         = astbmc_ipmi_power_down,
 	.cec_reboot             = astbmc_ipmi_reboot,
 	.elog_commit		= ipmi_elog_commit,
-	.load_resource		= pnor_load_resource,
+	.load_resource		= flash_load_resource,
 	.exit			= ipmi_wdt_final_reset,
 };
diff --git a/platforms/astbmc/pnor.c b/platforms/astbmc/pnor.c
index c566877..e5bc269 100644
--- a/platforms/astbmc/pnor.c
+++ b/platforms/astbmc/pnor.c
@@ -84,170 +84,3 @@ int pnor_init(void)
 	return rc;
 }
 
-static struct {
-	enum resource_id	id;
-	uint32_t		subid;
-	char			name[PART_NAME_MAX+1];
-} part_name_map[] = {
-	{ RESOURCE_ID_KERNEL,	RESOURCE_SUBID_NONE,		"KERNEL" },
-	{ RESOURCE_ID_INITRAMFS,RESOURCE_SUBID_NONE,		"ROOTFS" },
-};
-
-/* This mimics the hostboot SBE format */
-#define PNOR_SUBPART_ALIGNMENT 0x1000
-#define PNOR_SUBPART_HEADER_SIZE PNOR_SUBPART_ALIGNMENT
-struct pnor_hostboot_toc {
-	be32 ec;
-	be32 offset; /* From start of header.  4K aligned */
-	be32 size;
-};
-#define PNOR_HOSTBOOT_TOC_MAX_ENTRIES ((PNOR_SUBPART_HEADER_SIZE - 8)/sizeof(struct pnor_hostboot_toc))
-struct pnor_hostboot_header {
-	char eyecatcher[4];
-	be32 version;
-	struct pnor_hostboot_toc toc[PNOR_HOSTBOOT_TOC_MAX_ENTRIES];
-};
-
-static int pnor_find_subpartition(struct flash_chip *chip,
-			      uint32_t subid,
-			      uint32_t *start,
-			      uint32_t *total_size)
-{
-	struct pnor_hostboot_header *header;
-	uint32_t i;
-	bool rc;
-	char eyecatcher[5];
-
-	header = malloc(PNOR_SUBPART_HEADER_SIZE);
-	if (!header)
-		return false;
-
-	/* Get the TOC */
-	rc = flash_read(chip, *start, header, PNOR_SUBPART_HEADER_SIZE);
-	if (rc) {
-		prerror("PLAT: pnor subpartition TOC read failed %i", rc);
-		goto end;
-	}
-
-	/* Perform sanity */
-	i = be32_to_cpu(header->version);
-	if (i != 1) {
-		prerror("PLAT: pnor subpartition TOC version unknown %i", i);
-		rc = OPAL_RESOURCE;
-		goto end;
-	}
-	/* NULL terminate eyecatcher */
-	strncpy(eyecatcher, header->eyecatcher, 4);
-	eyecatcher[4] = 0;
-	printf("PLAT: pnor subpartition eyecatcher %s\n", eyecatcher);
-
-	rc = OPAL_RESOURCE;
-	for (i = 0; i< PNOR_HOSTBOOT_TOC_MAX_ENTRIES; i++) {
-		uint32_t ec, offset, size;
-
-		ec = be32_to_cpu(header->toc[i].ec);
-		offset = be32_to_cpu(header->toc[i].offset);
-		size = be32_to_cpu(header->toc[i].size);
-		/* Check for null terminating entry */
-		if (!ec && !offset && !size) {
-			prerror("PLAT: pnor subpartition not found.");
-			goto end;
-		}
-
-		if (ec != subid)
-			continue;
-
-		/* Sanity check the offset and size */
-		if (offset + size > *total_size) {
-			prerror("PLAT: pnor subpartition too big: %i", i);
-			goto end;
-		}
-		if (!size) {
-			prerror("PLAT: pnor subpartition zero size: %i", i);
-			goto end;
-		}
-		if (offset < PNOR_SUBPART_HEADER_SIZE) {
-			prerror("PLAT: pnor subpartition offset too small: %i", i);
-			goto end;
-		}
-
-		/* All good, let's adjust the start and size */
-		printf("PLAT: pnor found subpartition: %i size: %i offset %i\n",
-		       i, size, offset);
-		*start += offset;
-		size = (size + (PNOR_SUBPART_ALIGNMENT - 1)) & ~(PNOR_SUBPART_ALIGNMENT - 1);
-		*total_size = size;
-		rc = 0;
-		goto end;
-	}
-
-end:
-	free(header);
-	return rc;
-}
-
-bool pnor_load_resource(enum resource_id id, uint32_t subid,
-			void *buf, size_t *len)
-{
-	int i, rc, part_num, part_size, part_start;
-	const char *name;
-
-	if (!pnor_ffs || !pnor_chip)
-		return false;
-
-	for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) {
-		if (part_name_map[i].id == id) {
-			name = part_name_map[i].name;
-			break;
-		}
-	}
-	if (!name) {
-		prerror("PLAT: Couldn't find partition for id %d\n", id);
-		return false;
-	}
-
-	/*
-	 * If partition doesn't have a subindex but the caller specifies one,
-	 * we fail.  eg. kernel partition doesn't have a subindex
-	 */
-	if ((part_name_map[i].subid == RESOURCE_SUBID_NONE) &&
-	    (subid != RESOURCE_SUBID_NONE)) {
-		prerror("PLAT: Partition %s doesn't have subindex\n", name);
-		return false;
-	}
-
-	rc = ffs_lookup_part(pnor_ffs, name, &part_num);
-	if (rc) {
-		prerror("PLAT: No %s partition in PNOR\n", name);
-		return false;
-	}
-	rc = ffs_part_info(pnor_ffs, part_num, NULL,
-			   &part_start, &part_size, NULL);
-	if (rc) {
-		prerror("PLAT: Failed to get %s partition info\n", name);
-		return false;
-	}
-
-	/* Find the sub partition if required */
-	if (subid != RESOURCE_SUBID_NONE) {
-		rc = pnor_find_subpartition(pnor_chip, subid, &part_start,
-					    &part_size);
-		if (rc)
-			return false;
-	}
-	if (part_size > *len) {
-		prerror("PLAT: %s image too large (%d > %zd)\n", name,
-			part_size, *len);
-		return false;
-	}
-
-	rc = flash_read(pnor_chip, part_start, buf, part_size);
-	if (rc) {
-		prerror("PLAT: failed to read %s partition\n", name);
-		return false;
-	}
-
-	*len = part_size;
-
-	return true;
-}


More information about the Skiboot mailing list