aboutsummaryrefslogtreecommitdiff
path: root/src/lib/cbfs.c
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2013-02-08 17:28:04 -0600
committerStefan Reinauer <stefan.reinauer@coreboot.org>2013-03-21 22:28:28 +0100
commit8e4a355773cc64a89b3fc4d79981cfb02bda7e66 (patch)
tree01a9e6d5fc66568fd5c318e5edf17d47e73f65e8 /src/lib/cbfs.c
parent43e4a80a92bf00540e4d9b0734eb53f32044226f (diff)
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 <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/2792 Reviewed-by: Ronald G. Minnich <rminnich@gmail.com> Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@google.com>
Diffstat (limited to 'src/lib/cbfs.c')
-rw-r--r--src/lib/cbfs.c61
1 files changed, 61 insertions, 0 deletions
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 <cbfs.h>
#include <string.h>
+#include <cbmem.h>
#ifdef LIBPAYLOAD
# include <stdio.h>
@@ -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 <rmodule.h>
+#include <romstage_handoff.h>
+/* 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)
{