diff mbox

[v3] astbmc: Allow loading of payload from flash

Message ID 1422919260-31411-1-git-send-email-joel@jms.id.au
State Accepted
Headers show

Commit Message

Joel Stanley Feb. 2, 2015, 11:21 p.m. UTC
To date BMC platforms have had their payload built in to the skiboot
binary. This patch adds the option of loading from a flash partition
instead.

This has been tested on palmetto with a separate skiboot and
kernel+rootfs partition. In the future we may have separate kernel and
rootfs, which should just work. For now this is what we see when booting:

  [10648940943,5] INIT: Kernel loaded, size: 15728640 bytes (0 = unknown
  preload)
  [10649094578,5] INIT: 32-bit kernel entry at 0x2001015c
  [10649170607,3] PLAT: No ROOTFS partition in PNOR

If the partition named cannot be found, the core loading logic will fall
back to using the built-in payload. In this case, the user gets the
following messages:

  [2214557191,3] PLAT: No KERNEL partition in PNOR.
  [2220486159,5] INIT: platform kernel load failed.
  [2221293286,5] Using built-in kernel.
  [2265861935,5] INIT: Kernel loaded, size: 14706638 bytes (0 = unknown
  preload).

Signed-off-by: Joel Stanley <joel@jms.id.au>
---
v3:
 - map resouce ids to names in pnor_load_resoruce to make things easier for
   mikey's future capi loading patches
v2:
 Review from jk:
 - use KERNEL instead of SKIROOT for partition name
 - s/astbmc_load_resource/pnor_load_resource/

 platforms/astbmc/astbmc.h   |  1 +
 platforms/astbmc/habanero.c |  1 +
 platforms/astbmc/palmetto.c |  1 +
 platforms/astbmc/pnor.c     | 56 ++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 58 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/platforms/astbmc/astbmc.h b/platforms/astbmc/astbmc.h
index cee475a..7e33f61 100644
--- a/platforms/astbmc/astbmc.h
+++ b/platforms/astbmc/astbmc.h
@@ -24,5 +24,6 @@  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 bool pnor_load_resource(enum resource_id id, void *buf, size_t *len);
 
 #endif /* __ASTBMC_H */
diff --git a/platforms/astbmc/habanero.c b/platforms/astbmc/habanero.c
index d442d1f..a19aafd 100644
--- a/platforms/astbmc/habanero.c
+++ b/platforms/astbmc/habanero.c
@@ -49,4 +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,
 };
diff --git a/platforms/astbmc/palmetto.c b/platforms/astbmc/palmetto.c
index a0030e8..cfa7236 100644
--- a/platforms/astbmc/palmetto.c
+++ b/platforms/astbmc/palmetto.c
@@ -51,4 +51,5 @@  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,
 };
diff --git a/platforms/astbmc/pnor.c b/platforms/astbmc/pnor.c
index f6e7a5d..2cdb29b 100644
--- a/platforms/astbmc/pnor.c
+++ b/platforms/astbmc/pnor.c
@@ -14,7 +14,6 @@ 
  * limitations under the License.
  */
 
-
 #include <skiboot.h>
 #include <device.h>
 #include <console.h>
@@ -85,3 +84,58 @@  int pnor_init(void)
 	return rc;
 }
 
+static const struct {
+	enum resource_id id;
+	char name[PART_NAME_MAX+1];
+} part_name_map[] = {
+	{ RESOURCE_ID_KERNEL, "KERNEL" },
+	{ RESOURCE_ID_INITRAMFS, "ROOTFS" },
+};
+
+bool pnor_load_resource(enum resource_id id, 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;
+	}
+
+	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;
+	}
+
+	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;
+}