diff options
author | Michael Brown <mcb30@ipxe.org> | 2023-11-24 12:26:43 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2023-11-24 21:57:39 +0000 |
commit | b829b1750de041f7d4fd0f4f86fbf968bdccda6a (patch) | |
tree | b87d73ffff26504448ef582fefa935823edff78d | |
parent | 03ff1bb99a28230397fb583853ab2160ff227e77 (diff) | |
download | ipxe-b829b1750de041f7d4fd0f4f86fbf968bdccda6a.tar.gz |
[efi] Maximise image base address
iPXE images are linked with a starting virtual address of zero. Other
images (such as wimboot) may use a non-zero starting virtual address.
There is no direct equivalent of the PE ImageBase address field within
ELF object files. Choose to use the highest possible address that
accommodates all sections and the PE header itself, since this will
minimise the memory allocated to hold the loaded image.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/util/elf2efi.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c index 72d50d386..e97601390 100644 --- a/src/util/elf2efi.c +++ b/src/util/elf2efi.c @@ -730,6 +730,47 @@ static struct pe_section * process_section ( struct elf_file *elf, } /** + * Update image base address + * + * @v pe_header PE file header + * @v pe_sections List of PE sections + * @v pe_reltab PE relocation table + */ +static void update_image_base ( struct pe_header *pe_header, + struct pe_section *pe_sections, + struct pe_relocs *pe_reltab ) { + struct pe_section *section; + struct pe_relocs *pe_rel; + unsigned long base = -1UL; + + /* Set ImageBase to the highest possible value, leaving space + * for the PE header itself. + */ + for ( section = pe_sections ; section ; section = section->next ) { + if ( ! section->hidden ) { + if ( base > section->hdr.VirtualAddress ) + base = section->hdr.VirtualAddress; + } + } + base -= EFI_IMAGE_ALIGN; + pe_header->nt.OptionalHeader.ImageBase = base; + + /* Adjust RVAs to match ImageBase */ + pe_header->nt.OptionalHeader.AddressOfEntryPoint -= base; + pe_header->nt.OptionalHeader.BaseOfCode -= base; +#if defined(EFI_TARGET32) + pe_header->nt.OptionalHeader.BaseOfData -= base; +#endif + pe_header->nt.OptionalHeader.SizeOfImage -= base; + for ( section = pe_sections ; section ; section = section->next ) { + section->hdr.VirtualAddress -= base; + } + for ( pe_rel = pe_reltab ; pe_rel ; pe_rel = pe_rel->next ) { + pe_rel->start_rva -= base; + } +} + +/** * Process relocation record * * @v elf ELF file @@ -1113,6 +1154,9 @@ static void elf2pe ( const char *elf_name, const char *pe_name, } } + /* Update image base address */ + update_image_base ( &pe_header, pe_sections, pe_reltab ); + /* Create the .reloc section */ *(next_pe_section) = create_reloc_section ( &pe_header, pe_reltab ); next_pe_section = &(*next_pe_section)->next; |