[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