]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Maximise image base address
authorMichael Brown <mcb30@ipxe.org>
Fri, 24 Nov 2023 12:26:43 +0000 (12:26 +0000)
committerMichael Brown <mcb30@ipxe.org>
Fri, 24 Nov 2023 21:57:39 +0000 (21:57 +0000)
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>
src/util/elf2efi.c

index 72d50d386c85b57d2012fc748141480e2cf81cc5..e9760139023376bc1fbd8601198001cf0a906641 100644 (file)
@@ -729,6 +729,47 @@ static struct pe_section * process_section ( struct elf_file *elf,
        return new;
 }
 
+/**
+ * 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
  *
@@ -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;