[coreboot] New patch to review for coreboot: 301254d coreboot: add caching loaded ramstage interface

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Tue Mar 19 01:59:20 CET 2013


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2805

-gerrit

commit 301254ddb13a47b257a4910593dd6f0c333d6fc2
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Fri Feb 15 23:26:52 2013 -0600

    coreboot: add caching loaded ramstage interface
    
    Instead of hard coding the policy for how a relocated ramstage
    image is saved add an interface. The interface consists of two
    functions.  cache_loaded_ramstage() and load_cached_ramstage()
    are the functions to cache and load the relocated ramstage,
    respectively. There are default implementations which cache and
    load the relocated ramstage just below where the ramstage runs.
    
    Change-Id: I4346e873d8543e7eee4c1cd484847d846f297bb0
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/include/cbfs.h | 21 +++++++++++++++
 src/lib/cbfs.c     | 77 +++++++++++++++++++++++++++++++++++-------------------
 2 files changed, 71 insertions(+), 27 deletions(-)

diff --git a/src/include/cbfs.h b/src/include/cbfs.h
index 9bfe2ce..811df88 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -83,5 +83,26 @@ int selfboot(struct lb_memory *mem, struct cbfs_payload *payload);
 /* Defined in individual arch / board implementation. */
 int init_default_cbfs_media(struct cbfs_media *media);
 
+#if CONFIG_RELOCATABLE_RAMSTAGE && defined(__PRE_RAM__)
+/* The cache_loaded_ramstage() and load_cached_ramstage() functions are defined
+ * to be weak so that board and chipset code may override them. Their job is to
+ * cache and load the ramstage for quick S3 resume. By default a copy of the
+ * relocated ramstage is saved just below the running ramstage region. These
+ * functions are only valid during romstage. */
+
+struct romstage_handoff;
+
+/* The implementer of cache_loaded_ramstage() needs to ensure that the
+ * reserve_* fields in in romstage_handoff reflect the memory footprint of the
+ * ramstage (including cached region). Note that the handoff variable can be
+ * NULL. */
+void __attribute__((weak))
+cache_loaded_ramstage(struct romstage_handoff *handoff, void *ramstage_base,
+                      uint32_t ramstage_size, void *entry_point);
+/* Return NULL on error or entry point on success. */
+void * __attribute__((weak))
+load_cached_ramstage(struct romstage_handoff *handoff);
+#endif /* CONFIG_RELOCATABLE_RAMSTAGE */
+
 #endif
 
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index 6e89a39..8bcb000 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -123,16 +123,53 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
  * for the romstage, the rmodule loader is used. The ramstage is placed just
  * below the cbmem location. */
 
+void __attribute__((weak))
+cache_loaded_ramstage(struct romstage_handoff *handoff, void *ramstage_base,
+                      uint32_t ramstage_size, void *entry_point)
+{
+	if (handoff == NULL)
+		return;
+
+	/* Cache the loaded ramstage just below the to-be-run ramstage. Then
+	 * save the base, size, and entry point in the handoff area. */
+	handoff->reserve_base = (uint32_t)ramstage_base - ramstage_size;
+	handoff->reserve_size = ramstage_size;
+	handoff->ramstage_entry_point = (uint32_t)entry_point;
+
+	memcpy((void *)handoff->reserve_base, ramstage_base, ramstage_size);
+
+	/* Update the reserve region by 2x in order to store the cached copy. */
+	handoff->reserve_size += handoff->reserve_size;
+}
+
+void * __attribute__((weak))
+load_cached_ramstage(struct romstage_handoff *handoff)
+{
+	uint32_t ramstage_size;
+
+	if (handoff == NULL)
+		return NULL;
+
+	/* Load the cached ramstage copy into the to-be-run region. It is just
+	 * above the cached copy. */
+	ramstage_size = handoff->reserve_size / 2;
+	memcpy((void *)(handoff->reserve_base + ramstage_size),
+	       (void *)handoff->reserve_base, ramstage_size);
+
+	return (void *)handoff->ramstage_entry_point;
+}
+
 static void *load_stage_from_cbfs(struct cbfs_media *media, const char *name,
                                   struct romstage_handoff *handoff)
 {
 	struct cbfs_stage *stage;
 	struct rmodule ramstage;
-	void *cbmem_base;
-	void *ramstage_base;
+	char *cbmem_base;
+	char *ramstage_base;
 	void *decompression_loc;
 	void *ramstage_loc;
 	void *entry_point;
+	uint32_t ramstage_size;
 
 	stage = (struct cbfs_stage *)
 		cbfs_get_file_content(media, name, CBFS_TYPE_STAGE);
@@ -140,7 +177,7 @@ static void *load_stage_from_cbfs(struct cbfs_media *media, const char *name,
 	if (stage == NULL)
 		return (void *) -1;
 
-	cbmem_base = get_cbmem_toc();
+	cbmem_base = (void *)get_cbmem_toc();
 	if (cbmem_base == NULL)
 		return (void *) -1;
 
@@ -165,24 +202,9 @@ static void *load_stage_from_cbfs(struct cbfs_media *media, const char *name,
 
 	entry_point = rmodule_entry(&ramstage);
 
-	if (handoff) {
-		handoff->reserve_base = (uint32_t)ramstage_base;
-		handoff->reserve_size = (uint32_t)cbmem_base -
-		                        (uint32_t)ramstage_base;
-		/* Save an entire copy in RAM of the relocated ramstage for
-		 * the S3 resume path. The size of the saved relocated ramstage
-		 * is larger than necessary. It could be optimized by saving
-		 * just the text/data segment of the ramstage. The rmodule
-		 * API would need to be modified to expose these details. For
-		 * the time being, just save the entire used region. */
-		memcpy((void *)(handoff->reserve_base - handoff->reserve_size),
-		       (void *)handoff->reserve_base, handoff->reserve_size);
-		/* Update the size and base of the reserve region. */
-		handoff->reserve_base -= handoff->reserve_size;
-		handoff->reserve_size += handoff->reserve_size;
-		/* Save the entry point in the handoff area. */
-		handoff->ramstage_entry_point = (uint32_t)entry_point;
-	}
+	ramstage_size = cbmem_base - ramstage_base;
+	cache_loaded_ramstage(handoff, ramstage_base, ramstage_size,
+	                      entry_point);
 
 	return entry_point;
 }
@@ -190,6 +212,7 @@ static void *load_stage_from_cbfs(struct cbfs_media *media, const char *name,
 void * cbfs_load_stage(struct cbfs_media *media, const char *name)
 {
 	struct romstage_handoff *handoff;
+	void *entry;
 
 	handoff = romstage_handoff_find_or_add();
 
@@ -199,13 +222,13 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name)
 	} else if (!handoff->s3_resume)
 		return load_stage_from_cbfs(media, name, handoff);
 
-	/* S3 resume path. Copy from the saved relocated program buffer to
-	 * the running location. load_stage_from_cbfs() keeps a copy of the
-	 * relocated program just below the relocated program. */
-	memcpy((void *)(handoff->reserve_base + (handoff->reserve_size / 2)),
-	       (void *)handoff->reserve_base, handoff->reserve_size / 2);
+	/* S3 resume path. Load a cached copy of the loaded ramstage. If
+	 * return value is NULL load from cbfs. */
+	entry = load_cached_ramstage(handoff);
+	if (entry == NULL)
+		return load_stage_from_cbfs(name, handoff);
 
-	return (void *)handoff->ramstage_entry_point;
+	return entry;
 }
 
 #else



More information about the coreboot mailing list