[coreboot-gerrit] Patch set updated for coreboot: 0c6d067 rmodule: add ability to calculate module placement

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Thu Mar 21 01:00:13 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/2788

-gerrit

commit 0c6d067913068103eb56e4d0b6fd62cd7c3510ee
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Fri Feb 8 17:05:36 2013 -0600

    rmodule: add ability to calculate module placement
    
    There is a need to calculate the proper placement for an rmodule
    in memory. e.g. loading a compressed rmodule from flash into ram
    can be an issue. Determining the placement is hard since the header
    is not readable until it is decompressed so choosing the wrong location
    may require a memmove() after decompression. This patch provides
    a function to perform this calculation by finding region below a given
    address while making an assumption on the size of the rmodule header..
    
    Change-Id: I2703438f58ae847ed6e80b58063ff820fbcfcbc0
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/include/rmodule.h |  8 ++++++++
 src/lib/rmodule.c     | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git a/src/include/rmodule.h b/src/include/rmodule.h
index 5300c63..2d8fc0f 100644
--- a/src/include/rmodule.h
+++ b/src/include/rmodule.h
@@ -20,6 +20,7 @@
 #define RMODULE_H
 
 #include <stdint.h>
+#include <stddef.h>
 
 #define RMODULE_MAGIC 0xf8fe
 #define RMODULE_VERSION_1 1
@@ -40,6 +41,13 @@ int rmodule_entry_offset(const struct rmodule *m);
 int rmodule_memory_size(const struct rmodule *m);
 int rmodule_load(void *loc, struct rmodule *m);
 int rmodule_load_alignment(const struct rmodule *m);
+/* Returns the an aligned pointer that reflects a region used below addr
+ * based on the rmodule_size. i.e. the returned pointer up to addr is memory
+ * that may be utilized by the rmodule. program_start and rmodule_start
+ * are pointers updated to reflect where the rmodule program starts and where
+ * the rmodule (including header) should be placed respectively. */
+void *rmodule_find_region_below(void *addr, size_t rmodule_size,
+                                void **program_start, void **rmodule_start);
 
 #define FIELD_ENTRY(x_) ((u32)&x_)
 #define RMODULE_HEADER(entry_, type_)					\
diff --git a/src/lib/rmodule.c b/src/lib/rmodule.c
index 56d7c6d..81e9ef1 100644
--- a/src/lib/rmodule.c
+++ b/src/lib/rmodule.c
@@ -17,6 +17,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 #include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 #include <console/console.h>
 #include <rmodule.h>
@@ -165,6 +166,12 @@ static void rmodule_copy_payload(const struct rmodule *module)
 	       "filesize: 0x%x memsize: 0x%x\n",
 	       module->location, rmodule_entry(module),
 	       module->payload_size, rmodule_memory_size(module));
+
+	/* No need to copy the payload if the load location and the
+	 * payload location are the same. */
+	if (module->location == module->payload)
+		return;
+
 	memcpy(module->location, module->payload, module->payload_size);
 }
 
@@ -243,3 +250,47 @@ int rmodule_load(void *base, struct rmodule *module)
 	return rmodule_relocate(module);
 }
 
+void *rmodule_find_region_below(void *addr, size_t rmodule_size,
+                                void **program_start, void **rmodule_start)
+{
+	unsigned long ceiling;
+	unsigned long program_base;
+	unsigned long placement_loc;
+	unsigned long program_begin;
+
+	ceiling = (unsigned long)addr;
+	/* Place the rmodule just under the ceiling. The rmodule files
+	 * themselves are packed as a header and a payload, however the rmodule
+	 * itself is linked along with the header. The header starts at address
+	 * 0. Immediately following the header in the file is the program,
+	 * however its starting address is determined by the rmodule linker
+	 * script. In short, sizeof(struct rmodule_header) can be less than
+	 * or equal to the linked address of the program. Therefore we want
+	 * to place the rmodule so that the program falls on the aligned
+	 * address with the header just before it. Therefore, we need at least
+	 * a page to account for the size of the header. */
+	program_base = ALIGN((ceiling - (rmodule_size + 4096)), 4096);
+	/* The program starts immediately after the header. However,
+	 * it needs to be aligned to a 4KiB boundary. Therefore, adjust the
+	 * program location so that the program lands on a page boundary.  The
+	 * layout looks like the following:
+	 *
+	 * +--------------------------------+  ceiling
+	 * |  >= 0 bytes from alignment     |
+	 * +--------------------------------+  program end (4KiB aligned)
+	 * |  program size                  |
+	 * +--------------------------------+  program_begin (4KiB aligned)
+	 * |  sizeof(struct rmodule_header) |
+	 * +--------------------------------+  rmodule header start
+	 * |  >= 0 bytes from alignment     |
+	 * +--------------------------------+  program_base (4KiB aligned)
+	 */
+	placement_loc = ALIGN(program_base + sizeof(struct rmodule_header),
+	                      4096) - sizeof(struct rmodule_header);
+	program_begin = placement_loc + sizeof(struct rmodule_header);
+
+	*program_start = (void *)program_begin;
+	*rmodule_start = (void *)placement_loc;
+
+	return (void *)program_base;
+}



More information about the coreboot-gerrit mailing list