aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2023-11-24 12:26:43 +0000
committerMichael Brown <mcb30@ipxe.org>2023-11-24 21:57:39 +0000
commitb829b1750de041f7d4fd0f4f86fbf968bdccda6a (patch)
treeb87d73ffff26504448ef582fefa935823edff78d
parent03ff1bb99a28230397fb583853ab2160ff227e77 (diff)
downloadipxe-b829b1750de041f7d4fd0f4f86fbf968bdccda6a.zip
ipxe-b829b1750de041f7d4fd0f4f86fbf968bdccda6a.tar.gz
ipxe-b829b1750de041f7d4fd0f4f86fbf968bdccda6a.tar.bz2
[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.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c
index 72d50d3..e976013 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;