aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Kerr <jeremy.kerr@au1.ibm.com>2014-09-12 14:26:06 +0800
committerStewart Smith <stewart@linux.vnet.ibm.com>2014-10-30 16:50:39 +1100
commit4797b3eee3a0fc41ff5d68408dc73ac5e6fd248e (patch)
tree3e7660ee2ae9beaaf6205997041fac5509f64b43
parentb2a374da98aa710b4c55556f9a9047d4d4a8665d (diff)
downloadskiboot-4797b3eee3a0fc41ff5d68408dc73ac5e6fd248e.zip
skiboot-4797b3eee3a0fc41ff5d68408dc73ac5e6fd248e.tar.gz
skiboot-4797b3eee3a0fc41ff5d68408dc73ac5e6fd248e.tar.bz2
platform: add a platform hook for loading external resources
Currently, in core/init.c we do a fsp-specific load procedure to grab the kernel image. We'd like to do two things: allow other types of resources, and have paths for non-FSP platforms to perform loads. This change adds a platform-specific load_resource hook, and moves the currently loading code to fsp_load_resource. To allow other resource types, we add an identifier to indicate the type of resouce to load. Signed-off-by: Jeremy Kerr <jeremy.kerr@au.ibm.com> Acked-by: Stewart Smith <stewart@linux.vnet.ibm.com> Acked-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--core/init.c54
-rw-r--r--hw/fsp/fsp.c48
-rw-r--r--include/fsp.h1
-rw-r--r--include/platform.h11
-rw-r--r--platforms/ibm-fsp/apollo.c1
-rw-r--r--platforms/ibm-fsp/firenze.c1
6 files changed, 78 insertions, 38 deletions
diff --git a/core/init.c b/core/init.c
index d88f759..bd360ac 100644
--- a/core/init.c
+++ b/core/init.c
@@ -260,12 +260,6 @@ static bool try_load_elf32(struct elf_hdr *header)
return true;
}
-/* LID numbers. For now we hijack some of pHyp's own until i figure
- * out the whole business with the MasterLID
- */
-#define KERNEL_LID_PHYP 0x80a00701
-#define KERNEL_LID_OPAL 0x80f00101
-
extern char __builtin_kernel_start[];
extern char __builtin_kernel_end[];
extern uint64_t boot_offset;
@@ -273,50 +267,34 @@ extern uint64_t boot_offset;
static bool load_kernel(void)
{
struct elf_hdr *kh;
- uint32_t lid;
- size_t ksize;
- const char *ltype;
+ size_t ksize = 0;
- ltype = dt_prop_get_def(dt_root, "lid-type", NULL);
+ /* Try to load an external kernel payload through the platform hooks */
+ if (platform.load_resource) {
+ ksize = KERNEL_LOAD_SIZE;
+ if (!platform.load_resource(RESOURCE_ID_KERNEL,
+ KERNEL_LOAD_BASE, &ksize)) {
+ printf("INIT: platform kernel load failed\n");
+ ksize = 0;
+ }
+ }
- /* No lid-type, assume stradale, currently pre-loaded at fixed
- * address
- */
- if (!ltype) {
- printf("No lid-type property, assuming FSP-less setup\n");
+ /* Try embedded kernel payload */
+ if (!ksize) {
ksize = __builtin_kernel_end - __builtin_kernel_start;
if (ksize) {
/* Move the built-in kernel up */
uint64_t builtin_base =
((uint64_t)__builtin_kernel_start) -
- SKIBOOT_BASE + boot_offset;
+ SKIBOOT_BASE + boot_offset;
printf("Using built-in kernel\n");
memmove(KERNEL_LOAD_BASE, (void*)builtin_base, ksize);
- } else
- printf("Assuming kernel at 0x%p\n", KERNEL_LOAD_BASE);
- } else {
- ksize = KERNEL_LOAD_SIZE;
-
- /* First try to load an OPAL secondary LID always */
- lid = fsp_adjust_lid_side(KERNEL_LID_OPAL);
- printf("Trying to load OPAL secondary LID...\n");
- if (fsp_fetch_data(0, FSP_DATASET_NONSP_LID, lid, 0,
- KERNEL_LOAD_BASE, &ksize) != 0) {
- if (!strcmp(ltype, "opal")) {
- prerror("Failed to load in OPAL mode...\n");
- return false;
- }
- printf("Trying to load as PHYP LID...\n");
- lid = fsp_adjust_lid_side(KERNEL_LID_PHYP);
- ksize = KERNEL_LOAD_SIZE;
- if (fsp_fetch_data(0, FSP_DATASET_NONSP_LID, lid, 0,
- KERNEL_LOAD_BASE, &ksize) != 0) {
- prerror("Failed to load kernel\n");
- return false;
- }
}
}
+ if (!ksize)
+ printf("Assuming kernel at 0x%p\n", KERNEL_LOAD_BASE);
+
printf("INIT: Kernel loaded, size: %zu bytes (0 = unknown preload)\n",
ksize);
diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c
index 51d06b0..7a07835 100644
--- a/hw/fsp/fsp.c
+++ b/hw/fsp/fsp.c
@@ -98,6 +98,12 @@ static u64 fsp_hir_timeout;
#define FSP_CRITICAL_OP_TIMEOUT 128
#define FSP_DRCR_CLEAR_TIMEOUT 128
+/* LID numbers. For now we hijack some of pHyp's own until i figure
+ * out the whole business with the MasterLID
+ */
+#define KERNEL_LID_PHYP 0x80a00701
+#define KERNEL_LID_OPAL 0x80f00101
+
/*
* We keep track on last logged values for some things to print only on
* value changes, but also to releive pressure on the tracer which
@@ -2171,6 +2177,48 @@ int fsp_fetch_data_queue(uint8_t flags, uint16_t id, uint32_t sub_id,
return OPAL_SUCCESS;
}
+bool fsp_load_resource(enum resource_id id, void *buf, size_t *size)
+{
+ uint32_t lid_no, lid;
+ size_t tmp_size;
+ int rc;
+
+ switch (id) {
+ case RESOURCE_ID_KERNEL:
+ lid_no = KERNEL_LID_OPAL;
+ break;
+ default:
+ return false;
+ }
+
+retry:
+ tmp_size = *size;
+
+ printf("Trying to load OPAL LID %08x...\n", lid_no);
+ lid = fsp_adjust_lid_side(lid_no);
+ rc = fsp_fetch_data(0, FSP_DATASET_NONSP_LID, lid, 0, buf, &tmp_size);
+
+ /* Fall back to a PHYP LID for kernel loads */
+ if (rc && lid_no == KERNEL_LID_OPAL) {
+ const char *ltype = dt_prop_get_def(dt_root, "lid-type", NULL);
+ if (!ltype || strcmp(ltype, "opal")) {
+ prerror("Failed to load in OPAL mode...\n");
+ return false;
+ }
+ printf("Trying to load as PHYP LID...\n");
+ lid_no = KERNEL_LID_PHYP;
+ goto retry;
+ }
+
+ if (rc) {
+ prerror("Failed to load LID\n");
+ return false;
+ }
+
+ *size = tmp_size;
+ return true;
+}
+
void fsp_used_by_console(void)
{
fsp_lock.in_con_path = true;
diff --git a/include/fsp.h b/include/fsp.h
index 0464da4..e41498e 100644
--- a/include/fsp.h
+++ b/include/fsp.h
@@ -709,6 +709,7 @@ extern int fsp_fetch_data(uint8_t flags, uint16_t id, uint32_t sub_id,
extern int fsp_fetch_data_queue(uint8_t flags, uint16_t id, uint32_t sub_id,
uint32_t offset, void *buffer, size_t *length,
void (*comp)(struct fsp_msg *msg));
+extern bool fsp_load_resource(enum resource_id id, void *buf, size_t *size);
/* FSP console stuff */
extern void fsp_console_preinit(void);
diff --git a/include/platform.h b/include/platform.h
index b916e5e..77d025b 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -22,6 +22,10 @@ struct phb;
struct pci_device;
struct errorlog;
+enum resource_id {
+ RESOURCE_ID_KERNEL,
+};
+
/*
* Each platform can provide a set of hooks
* that can affect the generic code
@@ -119,6 +123,13 @@ struct platform {
uint32_t (*occ_timeout)(void);
int (*elog_commit)(struct errorlog *buf);
+
+ /*
+ * Load an external resource (eg, kernel payload) into a preallocated
+ * buffer. Returns true on success.
+ */
+ bool (*load_resource)(enum resource_id id,
+ void *buf, size_t *len);
};
extern struct platform __platforms_start;
diff --git a/platforms/ibm-fsp/apollo.c b/platforms/ibm-fsp/apollo.c
index 37315ba..fc01e64 100644
--- a/platforms/ibm-fsp/apollo.c
+++ b/platforms/ibm-fsp/apollo.c
@@ -59,4 +59,5 @@ DECLARE_PLATFORM(apollo) = {
.nvram_start_read = fsp_nvram_start_read,
.nvram_write = fsp_nvram_write,
.elog_commit = elog_fsp_commit,
+ .load_resource = fsp_load_resource,
};
diff --git a/platforms/ibm-fsp/firenze.c b/platforms/ibm-fsp/firenze.c
index b68dd70..29cbde0 100644
--- a/platforms/ibm-fsp/firenze.c
+++ b/platforms/ibm-fsp/firenze.c
@@ -248,4 +248,5 @@ DECLARE_PLATFORM(firenze) = {
.nvram_write = fsp_nvram_write,
.occ_timeout = ibm_fsp_occ_timeout,
.elog_commit = elog_fsp_commit,
+ .load_resource = fsp_load_resource,
} ;