diff options
author | Jeremy Kerr <jeremy.kerr@au1.ibm.com> | 2014-09-12 14:26:06 +0800 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2014-10-30 16:50:39 +1100 |
commit | 4797b3eee3a0fc41ff5d68408dc73ac5e6fd248e (patch) | |
tree | 3e7660ee2ae9beaaf6205997041fac5509f64b43 | |
parent | b2a374da98aa710b4c55556f9a9047d4d4a8665d (diff) | |
download | skiboot-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.c | 54 | ||||
-rw-r--r-- | hw/fsp/fsp.c | 48 | ||||
-rw-r--r-- | include/fsp.h | 1 | ||||
-rw-r--r-- | include/platform.h | 11 | ||||
-rw-r--r-- | platforms/ibm-fsp/apollo.c | 1 | ||||
-rw-r--r-- | platforms/ibm-fsp/firenze.c | 1 |
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, } ; |