[coreboot-gerrit] New patch to review for coreboot: 843f7e9 lib/cbfs: Copy stage header to stack before decompressing stage

Alexandru Gagniuc (mr.nuke.me@gmail.com) gerrit at coreboot.org
Fri Dec 27 22:34:37 CET 2013


Alexandru Gagniuc (mr.nuke.me at 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 at 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 at 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;



More information about the coreboot-gerrit mailing list