From 3eb8eb7eba55cdfd64c8d50181ea066526ff6485 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Mon, 10 Mar 2014 16:13:58 -0500 Subject: rmodules: use rmodtool to create rmodules Start using the rmodtool for generating rmodules. rmodule_link() has been changed to create 2 rules: one for the passed in , the other for creating .rmod which is an ELF file in the format of an rmodule. Since the header is not compiled and linked together with an rmodule there needs to be a way of marking which symbol is the entry point. __rmodule_entry is the symbol used for knowing the entry point. There was a little churn in SMM modules to ensure an rmodule entry point symbol takes a single argument. Change-Id: Ie452ed866f6596bf13f137f5b832faa39f48d26e Signed-off-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/5379 Reviewed-by: Stefan Reinauer Tested-by: build bot (Jenkins) --- src/lib/Makefile.inc | 12 +++++--- src/lib/rmodule.c | 86 +++++++++------------------------------------------- src/lib/rmodule.ld | 66 ++++++---------------------------------- 3 files changed, 33 insertions(+), 131 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index acd334e25d..93babd3c1f 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -133,17 +133,21 @@ ramstage-y += rmodule.c romstage-$(CONFIG_RELOCATABLE_RAMSTAGE) += rmodule.c RMODULE_LDSCRIPT := $(src)/lib/rmodule.ld -RMODULE_LDFLAGS := -nostartfiles -shared -z defs -nostdlib -Bsymbolic -T $(RMODULE_LDSCRIPT) +RMODULE_LDFLAGS := -nostartfiles -Wl,--emit-relocs -Wl,-z,defs -Wl,-Bsymbolic -Wl,-T,$(RMODULE_LDSCRIPT) # rmodule_link_rules is a function that should be called with: # (1) the object name to link # (2) the dependencies # (3) heap size of the relocatable module -# It will create the necessary Make rules. +# It will create the necessary Make rules to create a rmodule. The resulting +# rmdoule is named $(1).rmod define rmodule_link -$(strip $(1)): $(strip $(2)) $$(RMODULE_LDSCRIPT) $$(obj)/ldoptions - $$(LD) $$(RMODULE_LDFLAGS) --defsym=__heap_size=$(strip $(3)) -o $$@ $(strip $(2)) +$(strip $(1)): $(strip $(2)) $$(RMODULE_LDSCRIPT) $$(obj)/ldoptions $$(RMODTOOL) + $$(CC) $$(CFLAGS) $$(RMODULE_LDFLAGS) -Wl,--defsym=__heap_size=$(strip $(3)) -o $$@ -Wl,--start-group $(strip $(2)) $$(LIBGCC_FILE_NAME) -Wl,--end-group $$(NM) -n $$@ > $$(basename $$@).map + +$(strip $(1)).rmod: $(strip $(1)) + $$(RMODTOOL) -i $$^ -o $$@ endef endif diff --git a/src/lib/rmodule.c b/src/lib/rmodule.c index 2cb70b8f33..a73e667fef 100644 --- a/src/lib/rmodule.c +++ b/src/lib/rmodule.c @@ -26,44 +26,6 @@ /* Change this define to get more verbose debugging for module loading. */ #define PK_ADJ_LEVEL BIOS_NEVER -#if CONFIG_ARCH_X86 -/* - * On X86, the only relocations currently allowed are R_386_RELATIVE which - * have '0' for the symbol info in the relocation metadata (in r_info). - * The reason is that the module is fully linked and just has the relocations' - * locations. - */ -typedef struct { - uint32_t r_offset; - uint32_t r_info; -} Elf32_Rel; - -#define R_386_RELATIVE 8 - -#define RELOCTION_ENTRY_SIZE sizeof(Elf32_Rel) -static inline int rmodule_reloc_offset(const void *reloc) -{ - const Elf32_Rel *rel = reloc; - return rel->r_offset; -} - -static inline int rmodule_reloc_valid(const void *reloc) -{ - const Elf32_Rel *rel = reloc; - return (rel->r_info == R_386_RELATIVE); -} - -static inline void *remodule_next_reloc(const void *reloc) -{ - const Elf32_Rel *rel = reloc; - rel++; - return (void *)rel; -} - -#else -#error Arch needs to add relocation information support for RMODULE -#endif - static inline int rmodule_is_loaded(const struct rmodule *module) { return module->location != NULL; @@ -71,7 +33,7 @@ static inline int rmodule_is_loaded(const struct rmodule *module) /* Calculate a loaded program address based on the blob address. */ static inline void *rmodule_load_addr(const struct rmodule *module, - uint32_t blob_addr) + uintptr_t blob_addr) { char *loc = module->location; return &loc[blob_addr - module->header->module_link_start_address]; @@ -151,13 +113,13 @@ static void rmodule_clear_bss(struct rmodule *module) memset(begin, 0, size); } -static inline int rmodule_number_relocations(const struct rmodule *module) +static inline size_t rmodule_number_relocations(const struct rmodule *module) { - int r; + size_t r; r = module->header->relocations_end_offset; r -= module->header->relocations_begin_offset; - r /= RELOCTION_ENTRY_SIZE; + r /= sizeof(uintptr_t); return r; } @@ -176,51 +138,33 @@ static void rmodule_copy_payload(const struct rmodule *module) memcpy(module->location, module->payload, module->payload_size); } -static inline uint32_t *rmodule_adjustment_location(const struct rmodule *module, - const void *reloc) -{ - int reloc_offset; - - /* Don't relocate header field entries -- only program relocations. */ - reloc_offset = rmodule_reloc_offset(reloc); - if (reloc_offset < module->header->module_link_start_address) - return NULL; - - return rmodule_load_addr(module, reloc_offset); -} - static int rmodule_relocate(const struct rmodule *module) { - int num_relocations; - const void *reloc; - uint32_t adjustment; + size_t num_relocations; + const uintptr_t *reloc; + uintptr_t adjustment; /* Each relocation needs to be adjusted relative to the beginning of * the loaded program. */ - adjustment = (uint32_t)rmodule_load_addr(module, 0); + adjustment = (uintptr_t)rmodule_load_addr(module, 0); reloc = module->relocations; num_relocations = rmodule_number_relocations(module); - printk(BIOS_DEBUG, "Processing %d relocs with adjust value of 0x%08x\n", + printk(BIOS_DEBUG, "Processing %zu relocs. Offset value of 0x%08x\n", num_relocations, adjustment); while (num_relocations > 0) { - uint32_t *adjust_loc; - - if (!rmodule_reloc_valid(reloc)) - return -1; + uintptr_t *adjust_loc; /* If the adjustment location is non-NULL adjust it. */ - adjust_loc = rmodule_adjustment_location(module, reloc); - if (adjust_loc != NULL) { - printk(PK_ADJ_LEVEL, "Adjusting %p: 0x%08x -> 0x%08x\n", + adjust_loc = rmodule_load_addr(module, *reloc); + printk(PK_ADJ_LEVEL, "Adjusting %p: 0x%08x -> 0x%08x\n", adjust_loc, *adjust_loc, *adjust_loc + adjustment); *adjust_loc += adjustment; - } - reloc = remodule_next_reloc(reloc); + reloc++; num_relocations--; } @@ -232,8 +176,8 @@ int rmodule_load_alignment(const struct rmodule *module) /* The load alignment is the start of the program's linked address. * The base address where the program is loaded needs to be a multiple * of the program's starting link address. That way all data alignment - * in the program is preserved. */ - return module->header->module_link_start_address; + * in the program is preserved. Default to 4KiB. */ + return 4096; } int rmodule_load(void *base, struct rmodule *module) diff --git a/src/lib/rmodule.ld b/src/lib/rmodule.ld index 0cdbb2fa25..9222f3b876 100644 --- a/src/lib/rmodule.ld +++ b/src/lib/rmodule.ld @@ -1,19 +1,15 @@ -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. + * packed into the flat blob. 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; @@ -22,21 +18,9 @@ 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); - - .payload : AT (_payload_begin_offset) { + .payload : { /* C code of the module. */ + _ram_seg = .; *(.textfirst); *(.text); *(.text.*); @@ -88,9 +72,6 @@ SECTIONS . = ALIGN(8); } - /* _payload_end marks the end of the module's code and data. */ - _payload_end_offset = LOADADDR(.payload) + SIZEOF(.payload); - .bss (NOLOAD) : { /* C uninitialized data of the module. */ _bss = .; @@ -107,38 +88,11 @@ SECTIONS _heap = .; . = . + __heap_size; _eheap = .; + _eram_seg = .; } - /* _module_program_size is the total memory used by the program. */ - _module_program_size = _eheap - _module_link_start_addr; - - /* coreboot's ramstage uses the _ram_seg and _eram_seg symbols - * for determining its load location. Provide those to help it out. - * It's a nop for any non-ramstage rmodule. */ - _ram_seg = _module_link_start_addr; - _eram_seg = _module_link_start_addr + _module_program_size; - - /* 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); + /* Drop unnecessary sections. */ *(.eh_frame); } } -- cgit v1.2.3