[coreboot-gerrit] Patch set updated for coreboot: 0087e6e vboot2: load decompressed stage directly to load address

Aaron Durbin (adurbin@google.com) gerrit at coreboot.org
Mon Mar 23 23:24:23 CET 2015


Aaron Durbin (adurbin at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8883

-gerrit

commit 0087e6ed6760dfa061feff3994ab39c501e9b106
Author: Daisuke Nojiri <dnojiri at chromium.org>
Date:   Fri Sep 19 09:56:15 2014 -0700

    vboot2: load decompressed stage directly to load address
    
    this change allows vboot_load_stage to load a decompressed stage directly to the
    load address without using the cbfs cache.
    
    BUG=None
    TEST=Booted Nyan Blaze.
    BRANCH=None
    Signed-off-by: Daisuke Nojiri <dnojiri at chromium.org>
    
    Original-Change-Id: I76530276ff9a87b44f98a33f2c34bd5b2de6888f
    Original-Reviewed-on: https://chromium-review.googlesource.com/219028
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
    Original-Commit-Queue: Daisuke Nojiri <dnojiri at chromium.org>
    Original-Tested-by: Daisuke Nojiri <dnojiri at chromium.org>
    (cherry picked from commit 0ad6f7fee9df31e1b35d4df9a8c373516416a235)
    
    Change-Id: I7abdbdda0cc549894dfb9d599a576bba0a4fadfc
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/include/cbfs.h                        |  1 +
 src/lib/cbfs.c                            | 72 ++++++++++++++++++-------------
 src/vendorcode/google/chromeos/chromeos.c | 31 +++++--------
 3 files changed, 54 insertions(+), 50 deletions(-)

diff --git a/src/include/cbfs.h b/src/include/cbfs.h
index 5297230..9aa2c96 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -55,6 +55,7 @@
 void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
 			  uint16_t device, void * dest);
 void *cbfs_load_stage(struct cbfs_media *media, const char *name);
+void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset);
 
 /* Simple buffer for streaming media. */
 struct cbfs_simple_buffer {
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index 9e9f4a7..54d159f 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -73,41 +73,55 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
 	return dest;
 }
 
-void * cbfs_load_stage(struct cbfs_media *media, const char *name)
+void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset)
 {
-	struct cbfs_stage *stage = (struct cbfs_stage *)
-	cbfs_get_file_content(media, name, CBFS_TYPE_STAGE, NULL);
-	/* this is a mess. There is no ntohll. */
-	/* for now, assume compatible byte order until we solve this. */
-	uintptr_t entry;
-	uint32_t final_size;
-
-	if (stage == NULL)
-		return (void *) -1;
-
-	LOG("loading stage %s @ 0x%llx (%d bytes), entry @ 0x%llx\n",
-			name,
-			stage->load, stage->memlen,
-			stage->entry);
-
-	final_size = cbfs_decompress(stage->compression,
-				     ((unsigned char *) stage) +
-				     sizeof(struct cbfs_stage),
-				     (void *) (uintptr_t) stage->load,
-				     stage->len);
-	if (!final_size)
-		return (void *) -1;
+	struct cbfs_stage stage;
+
+	if (cbfs_read(media, &stage, offset, sizeof(stage)) != sizeof(stage)) {
+		ERROR("ERROR: failed to read stage header\n");
+		return (void *)-1;
+	}
+
+	LOG("loading stage @ 0x%llx (%d bytes), entry @ 0x%llx\n",
+	    stage.load, stage.memlen, stage.entry);
 
 	/* 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, 0, stage.memlen);
+
+	if (stage.compression == CBFS_COMPRESS_NONE) {
+		if (cbfs_read(media, (void *)(uintptr_t)stage.load,
+			      offset + sizeof(stage), stage.len) != stage.len) {
+			ERROR("ERROR: Reading stage failed.\n");
+			return (void *)-1;
+		}
+	} else {
+		void *data = media->map(media, offset + sizeof(stage),
+					stage.len);
+		if (data == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
+			ERROR("ERROR: Mapping stage failed.\n");
+			return (void *)-1;
+		}
+		if (!cbfs_decompress(stage.compression, data,
+				    (void *)(uintptr_t)stage.load, stage.len))
+			return (void *)-1;
+		media->unmap(media, data);
+	}
 
-	DEBUG("stage loaded.\n");
+	DEBUG("stage loaded\n");
+
+	return (void *)(uintptr_t)stage.entry;
+}
+
+void *cbfs_load_stage(struct cbfs_media *media, const char *name)
+{
+	struct cbfs_file file;
+	ssize_t offset;
 
-	entry = stage->entry;
-	// entry = ntohll(stage->entry);
+	offset = cbfs_locate_file(media, &file, name);
+	if (offset < 0 || file.type != CBFS_TYPE_STAGE)
+		return (void *)-1;
 
-	return (void *) entry;
+	return cbfs_load_stage_by_offset(media, offset);
 }
 
 /* Simple buffer */
diff --git a/src/vendorcode/google/chromeos/chromeos.c b/src/vendorcode/google/chromeos/chromeos.c
index bd72e77..5696aec 100644
--- a/src/vendorcode/google/chromeos/chromeos.c
+++ b/src/vendorcode/google/chromeos/chromeos.c
@@ -222,9 +222,10 @@ void *vboot_load_stage(int stage_index,
 		       struct vboot_region *fw_main,
 		       struct vboot_components *fw_info)
 {
-	struct cbfs_stage *stage;
+	struct cbfs_media default_media, *media = &default_media;
 	uintptr_t fc_addr;
 	uint32_t fc_size;
+	void *entry;
 
 	if (stage_index >= fw_info->num_components) {
 		printk(BIOS_INFO, "invalid stage index\n");
@@ -239,27 +240,15 @@ void *vboot_load_stage(int stage_index,
 		return NULL;
 	}
 
-	/* Loading to cbfs cache. This stage data must be retained until it's
-	 * decompressed. */
-	stage = vboot_get_region(fc_addr, fc_size, NULL);
+	init_default_cbfs_media(media);
 
-	if (stage == NULL) {
-		printk(BIOS_INFO, "failed to load a stage\n");
-		return NULL;
-	}
-
-	/* Stages rely the below clearing so that the bss is initialized. */
-	memset((void *) (uintptr_t)stage->load, 0, stage->memlen);
-
-	if (cbfs_decompress(stage->compression,
-			    (unsigned char *)stage + sizeof(*stage),
-			    (void *) (uintptr_t) stage->load,
-			    stage->len)) {
-		printk(BIOS_INFO, "failed to decompress a stage\n");
-		return NULL;
-	}
-
-	return (void *)(uintptr_t)stage->entry;
+	/* we're making cbfs access offset outside of the region managed by
+	 * cbfs. this works because cbfs_load_stage_by_offset does not check
+	 * the offset. */
+	entry = cbfs_load_stage_by_offset(media, fc_addr);
+	if (entry == (void *)-1)
+		entry = NULL;
+	return entry;
 }
 
 struct vb2_working_data * const vboot_get_working_data(void)



More information about the coreboot-gerrit mailing list