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>
This commit is contained in:
Aaron Durbin
2013-02-08 17:28:04 -06:00
committed by Stefan Reinauer
parent 43e4a80a92
commit 8e4a355773
11 changed files with 170 additions and 0 deletions

View File

@ -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)
{