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:
committed by
Stefan Reinauer
parent
43e4a80a92
commit
8e4a355773
@@ -110,6 +110,7 @@ $(obj)/lib/uart8250.smm.o : $(OPTION_TABLE_H)
|
||||
|
||||
ifeq ($(CONFIG_RELOCATABLE_MODULES),y)
|
||||
ramstage-y += rmodule.c
|
||||
romstage-$(CONFIG_RELOCATABLE_RAMSTAGE) += rmodule.c
|
||||
|
||||
RMODULE_LDSCRIPT := $(src)/lib/rmodule.ld
|
||||
RMODULE_LDFLAGS := -nostartfiles -shared -z defs -nostdlib -Bsymbolic -T $(RMODULE_LDSCRIPT)
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -78,6 +78,16 @@ struct segment {
|
||||
|
||||
static unsigned long bounce_size, bounce_buffer;
|
||||
|
||||
#if CONFIG_RELOCATABLE_RAMSTAGE
|
||||
static void get_bounce_buffer(struct lb_memory *mem, unsigned long req_size)
|
||||
{
|
||||
/* When the ramstage is relocatable there is no need for a bounce
|
||||
* buffer. All payloads should not overlap the ramstage.
|
||||
*/
|
||||
bounce_buffer = ~0UL;
|
||||
bounce_size = 0;
|
||||
}
|
||||
#else
|
||||
static void get_bounce_buffer(struct lb_memory *mem, unsigned long req_size)
|
||||
{
|
||||
unsigned long lb_size;
|
||||
@@ -114,6 +124,7 @@ static void get_bounce_buffer(struct lb_memory *mem, unsigned long req_size)
|
||||
bounce_buffer = buffer;
|
||||
bounce_size = req_size;
|
||||
}
|
||||
#endif /* CONFIG_RELOCATABLE_RAMSTAGE */
|
||||
|
||||
static int valid_area(struct lb_memory *mem, unsigned long buffer,
|
||||
unsigned long start, unsigned long len)
|
||||
@@ -394,8 +405,13 @@ static int load_self_segments(
|
||||
for(ptr = head->next; ptr != head; ptr = ptr->next) {
|
||||
if (!overlaps_coreboot(ptr))
|
||||
continue;
|
||||
#if CONFIG_RELOCATABLE_RAMSTAGE
|
||||
/* payloads are required to not overlap ramstage. */
|
||||
return 0;
|
||||
#else
|
||||
if (ptr->s_dstaddr + ptr->s_memsz > bounce_high)
|
||||
bounce_high = ptr->s_dstaddr + ptr->s_memsz;
|
||||
#endif
|
||||
}
|
||||
get_bounce_buffer(mem, bounce_high - lb_start);
|
||||
if (!bounce_buffer) {
|
||||
|
Reference in New Issue
Block a user