Alexandru Gagniuc (mr.nuke.me@gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4579
-gerrit
commit 843f7e9e2d7246638b6f4f577fede101e9f89faf Author: Alexandru Gagniuc mr.nuke.me@gmail.com Date: Fri Dec 27 16:13:04 2013 -0500
lib/cbfs: Copy stage header to stack before decompressing stage
On SoCs with limited amount of SRAM, we have to cache the romstage in the same memory block in which it will be used. The header of the stage is within this cached region, and risks being overwritten by cbfs_decompress() when called from cbfs_load_stage(). In order to ensure that the header does not get overwritten, copy it to the stack and use the information in the stack.
This is especially useful in the bootblock on lower-end ARM SoCs, which do not have enough SRAM to hold the bootblock, stack, romstage and the CBFS cache.
Change-Id: Ibb7f769645b02377745d568fe539919f83da8d68 Signed-off-by: Alexandru Gagniuc mr.nuke.me@gmail.com --- src/lib/cbfs.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-)
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index 1f44695..bfed6a4 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -256,36 +256,44 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name)
void * cbfs_load_stage(struct cbfs_media *media, const char *name) { - struct cbfs_stage *stage = (struct cbfs_stage *) + struct cbfs_stage stage; + struct cbfs_stage *mm_stage = (struct cbfs_stage *) cbfs_get_file_content(media, name, CBFS_TYPE_STAGE); /* this is a mess. There is no ntohll. */ /* for now, assume compatible byte order until we solve this. */ uint32_t entry; uint32_t final_size;
- if (stage == NULL) + if (mm_stage == NULL) return (void *) -1;
+ /* Copy the stage header to the stack. On ARM SoCs, the memory region + * returned by cbfs_get_file_content() may be in the CBFS cache, and if + * the stage is to be copied to the same region, the header can be + * overwritten by cbfs_decompress(). + */ + memcpy(&stage, mm_stage, sizeof(stage)); + LOG("loading stage %s @ 0x%x (%d bytes), entry @ 0x%llx\n", name, - (uint32_t) stage->load, stage->memlen, - stage->entry); + (uint32_t) stage.load, stage.memlen, + stage.entry);
- final_size = cbfs_decompress(stage->compression, - ((unsigned char *) stage) + + final_size = cbfs_decompress(stage.compression, + ((unsigned char *) mm_stage) + sizeof(struct cbfs_stage), - (void *) (uint32_t) stage->load, - stage->len); + (void *) (uint32_t) stage.load, + stage.len); if (!final_size) return (void *) -1;
/* Stages rely the below clearing so that the bss is initialized. */ - memset((void *)((uintptr_t)stage->load + final_size), 0, - stage->memlen - final_size); + memset((void *)((uintptr_t)stage.load + final_size), 0, + stage.memlen - final_size);
DEBUG("stage loaded.\n");
- entry = stage->entry; + entry = stage.entry; // entry = ntohll(stage->entry);
return (void *) entry;