From 8e4a355773cc64a89b3fc4d79981cfb02bda7e66 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Fri, 8 Feb 2013 17:28:04 -0600 Subject: coreboot: introduce CONFIG_RELOCATABLE_RAMSTAGE This patch adds an option to build the ramstage as a reloctable binary. It uses the rmodule library for the relocation. The main changes consist of the following: 1. The ramstage is loaded just under the cmbem space. 2. Payloads cannot be loaded over where ramstage is loaded. If a payload is attempted to load where the relocatable ramstage resides the load is aborted. 3. The memory occupied by the ramstage is reserved from the OS's usage using the romstage_handoff structure stored in cbmem. This region is communicated to ramstage by an CBMEM_ID_ROMSTAGE_INFO entry in cbmem. 4. There is no need to reserve cbmem space for the OS controlled memory for the resume path because the ramsage region has been reserved in #3. 5. Since no memory needs to be preserved in the wake path, the loading and begin of execution of a elf payload is straight forward. Change-Id: Ia66cf1be65c29fa25ca7bd9ea6c8f11d7eee05f5 Signed-off-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/2792 Reviewed-by: Ronald G. Minnich Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/lib/cbfs.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'src/lib/cbfs.c') diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index c56f550e17..4dac4bb5c2 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -36,6 +36,7 @@ #include #include +#include #ifdef LIBPAYLOAD # include @@ -114,6 +115,65 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor, return dest; } +#if CONFIG_RELOCATABLE_RAMSTAGE && defined(__PRE_RAM__) + +#include +#include +/* When CONFIG_RELOCATABLE_RAMSTAGE is enabled and this file is being compiled + * for the romstage the rmodule loader is used. The ramstage is placed just + * below the cbemem location. */ + +void * cbfs_load_stage(struct cbfs_media *media, const char *name) +{ + struct cbfs_stage *stage; + struct rmodule ramstage; + void *cbmem_base; + void *ramstage_base; + void *decompression_loc; + void *ramstage_loc; + struct romstage_handoff *handoff; + + stage = (struct cbfs_stage *) + cbfs_get_file_content(media, name, CBFS_TYPE_STAGE); + + if (stage == NULL) + return (void *) -1; + + cbmem_base = get_cbmem_toc(); + if (cbmem_base == NULL) + return (void *) -1; + + ramstage_base = rmodule_find_region_below(cbmem_base, stage->memlen, + &ramstage_loc, + &decompression_loc); + + LOG("Decompressing stage %s @ 0x%p (%d bytes)\n", + name, decompression_loc, stage->memlen); + + if (cbfs_decompress(stage->compression, &stage[1], + decompression_loc, stage->len)) + return (void *) -1; + + if (rmodule_parse(decompression_loc, &ramstage)) + return (void *) -1; + + /* The ramstage is responsible for clearing its own bss. */ + if (rmodule_load(ramstage_loc, &ramstage)) + return (void *) -1; + + handoff = cbmem_add(CBMEM_ID_ROMSTAGE_INFO, sizeof(*handoff)); + if (handoff) { + handoff->reserve_base = (uint32_t)ramstage_base; + handoff->reserve_size = (uint32_t)cbmem_base - + (uint32_t)ramstage_base; + } else + LOG("Couldn't allocate romstage handoff.\n"); + + return rmodule_entry(&ramstage); +} + +#else + void * cbfs_load_stage(struct cbfs_media *media, const char *name) { struct cbfs_stage *stage = (struct cbfs_stage *) @@ -146,6 +206,7 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name) return (void *) entry; } +#endif /* CONFIG_RELOCATABLE_RAMSTAGE */ int cbfs_execute_stage(struct cbfs_media *media, const char *name) { -- cgit v1.2.3