summaryrefslogtreecommitdiffstats
path: root/src/lib/rmodule.ld
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2012-12-24 14:28:37 -0600
committerRonald G. Minnich <rminnich@gmail.com>2013-03-18 18:40:34 +0100
commitad93552b86579afd29e99da1b2fcacb0d872cd1a (patch)
tree55a91404826f8c9e94ad2544295b94a981eb2fd6 /src/lib/rmodule.ld
parent21efd8c0378a8a42ee2fd71957be318416b6f5af (diff)
downloadcoreboot-ad93552b86579afd29e99da1b2fcacb0d872cd1a.tar.gz
coreboot-ad93552b86579afd29e99da1b2fcacb0d872cd1a.tar.bz2
coreboot-ad93552b86579afd29e99da1b2fcacb0d872cd1a.zip
lib: add rmodule support
A rmodule is short for relocation module. Relocaiton modules are standalone programs. These programs are linked at address 0 as a shared object with a special linker script that maintains the relocation entries for the object. These modules can then be embedded as a raw binary (objcopy -O binary) to be loaded at any location desired. Initially, the only arch support is for x86. All comments below apply to x86 specific properties. The intial user of this support would be for SMM handlers since those handlers sometimes need to be located at a dynamic address (e.g. TSEG region). The relocation entries are currently Elf32_Rel. They are 8 bytes large, and the entries are not necessarily in sorted order. An future optimization would be to have a tool convert the unsorted relocations into just sorted offsets. This would reduce the size of the blob produced after being processed. Essentialy, 8 bytes per relocation meta entry would reduce to 4 bytes. Change-Id: I2236dcb66e9d2b494ce2d1ae40777c62429057ef Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: http://review.coreboot.org/2692 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'src/lib/rmodule.ld')
-rw-r--r--src/lib/rmodule.ld115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/lib/rmodule.ld b/src/lib/rmodule.ld
new file mode 100644
index 000000000000..4c13c8466659
--- /dev/null
+++ b/src/lib/rmodule.ld
@@ -0,0 +1,115 @@
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+
+/*
+ * This linker script is used to link rmodules (relocatable modules). It
+ * links at zero so that relocation fixups are easy when placing the binaries
+ * anywhere in the address space.
+ *
+ * NOTE: The program's loadable sections (text, module_params, and data) are
+ * packed into the flat blob using the AT directive. The rmodule loader assumes
+ * the entire program resides in one contiguous address space. Therefore,
+ * alignment for a given section (if required) needs to be done at the end of
+ * the preceeding section. e.g. if the data section should be aligned to an 8
+ * byte address the text section should have ALIGN(8) at the end of its section.
+ * Otherwise there won't be a consistent mapping between the flat blob and the
+ * loaded program.
+ */
+
+BASE_ADDRESS = 0x00000;
+
+SECTIONS
+{
+ . = BASE_ADDRESS;
+
+ .header : AT (0) {
+ *(.module_header);
+ . = ALIGN(8);
+ }
+
+ /* Align the start of the module program to a large enough alignment
+ * so that any data in the program with an alignement property is met.
+ * Essentially, this alignment is the maximum possible data alignment
+ * property a program can have. */
+ . = ALIGN(4096);
+ _module_link_start_addr = .;
+ _payload_begin_offset = LOADADDR(.header) + SIZEOF(.header);
+
+ .text : AT (_payload_begin_offset) {
+ /* C code of the module. */
+ *(.text);
+ *(.text.*);
+ /* C read-only data. */
+ . = ALIGN(16);
+ *(.rodata);
+ *(.rodata.*);
+ . = ALIGN(4);
+ }
+
+ .module_params : AT (LOADADDR(.text) + SIZEOF(.text)) {
+ /* The parameters section can be used to pass parameters
+ * to a module, however there has to be an prior agreement
+ * on how to interpret the parameters. */
+ _module_params_begin = .;
+ *(.module_parameters);
+ _module_params_end = .;
+ . = ALIGN(4);
+ }
+
+ .data : AT (LOADADDR(.module_params) + SIZEOF(.module_params)) {
+ _sdata = .;
+ *(.data);
+ . = ALIGN(4);
+ _edata = .;
+ }
+
+ /* _payload_end marks the end of the module's code and data. */
+ _payload_end_offset = LOADADDR(.data) + SIZEOF(.data);
+
+ .bss (NOLOAD) : {
+ /* C uninitialized data of the SMM handler */
+ _bss_begin = .;
+ *(.bss);
+ *(.sbss);
+ *(COMMON);
+ . = ALIGN(8);
+ _bss_end = .;
+ }
+
+ .heap (NOLOAD) : {
+ /*
+ * Place the heap after BSS. The heap size is passed in by
+ * by way of ld --defsym=__heap_size=<>
+ */
+ _heap = .;
+ . = . + __heap_size;
+ _eheap = .;
+ }
+
+ /* _module_program_size is the total memory used by the program. */
+ _module_program_size = _eheap - _module_link_start_addr;
+
+ /* The relocation information is linked on top of the BSS section
+ * because the BSS section takes no space on disk. The relocation data
+ * resides directly after the data section in the flat binary. */
+ .relocations ADDR(.bss) : AT (_payload_end_offset) {
+ *(.rel.*);
+ }
+ _relocations_begin_offset = LOADADDR(.relocations);
+ _relocations_end_offset = _relocations_begin_offset +
+ SIZEOF(.relocations);
+
+ /DISCARD/ : {
+ /* Drop unnecessary sections. Since these modules are linked
+ * as shared objects there are dynamic sections. These sections
+ * aren't needed so drop them. */
+ *(.comment);
+ *(.note);
+ *(.note.*);
+ *(.dynamic);
+ *(.dynsym);
+ *(.dynstr);
+ *(.gnu.hash);
+ *(.eh_frame);
+ }
+}