diff options
author | Marvin Häuser <mhaeuser@posteo.de> | 2021-04-08 20:04:16 +0200 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2021-04-10 13:43:47 +0100 |
commit | f1e9e2b062fab46a6e3aec1f08d4554dd5dd2b98 (patch) | |
tree | 46210b293db4dbe620b6941163fdf41c58be01c4 | |
parent | 1cc87565110014205f647fd413f897a1a5a04b22 (diff) | |
download | ipxe-f1e9e2b062fab46a6e3aec1f08d4554dd5dd2b98.tar.gz |
[efi] Align EFI image sections by page size
For optimal memory permission management, PE sections need to be
aligned by the platform's minimum page size. Currently, the PE
section alignment is fixed to 32 bytes, which is below the typical 4kB
page size. Align all sections to 4kB and adjust ELF to PE image
conversion accordingly.
Signed-off-by: Marvin Häuser <mhaeuser@posteo.de>
-rw-r--r-- | src/scripts/efi.lds | 18 | ||||
-rw-r--r-- | src/util/elf2efi.c | 35 |
2 files changed, 33 insertions, 20 deletions
diff --git a/src/scripts/efi.lds b/src/scripts/efi.lds index 36022545d..dd7b3f019 100644 --- a/src/scripts/efi.lds +++ b/src/scripts/efi.lds @@ -8,22 +8,22 @@ SECTIONS { /* The file starts at a virtual address of zero, and sections are - * contiguous. Each section is aligned to at least _max_align, - * which defaults to 32. Load addresses are equal to virtual + * contiguous. Each section is aligned to at least _page_align, + * which defaults to 4096. Load addresses are equal to virtual * addresses. */ - _max_align = 32; + _page_align = 4096; - /* Allow plenty of space for file headers */ - . = 0x1000; + /* Allow one page of space for file headers, common PE/COFF layout */ + . = _page_align; /* * The text section * */ - . = ALIGN ( _max_align ); + . = ALIGN ( _page_align ); .text : { _text = .; *(.text) @@ -36,7 +36,7 @@ SECTIONS { * */ - . = ALIGN ( _max_align ); + . = ALIGN ( _page_align ); .rodata : { _rodata = .; *(.rodata) @@ -49,7 +49,7 @@ SECTIONS { * */ - . = ALIGN ( _max_align ); + . = ALIGN ( _page_align ); .data : { _data = .; *(.data) @@ -65,7 +65,7 @@ SECTIONS { * */ - . = ALIGN ( _max_align ); + . = ALIGN ( _page_align ); .bss : { _bss = .; *(.bss) diff --git a/src/util/elf2efi.c b/src/util/elf2efi.c index 38eb29964..b0d546645 100644 --- a/src/util/elf2efi.c +++ b/src/util/elf2efi.c @@ -125,7 +125,8 @@ #define R_ARM_V4BX 40 #endif -#define EFI_FILE_ALIGN 0x20 +#define EFI_FILE_ALIGN 0x20 +#define EFI_IMAGE_ALIGN 0x1000 struct elf_file { void *data; @@ -173,9 +174,9 @@ static struct pe_header efi_pe_header = { .Magic = EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC, .MajorLinkerVersion = 42, .MinorLinkerVersion = 42, - .SectionAlignment = EFI_FILE_ALIGN, + .SectionAlignment = EFI_IMAGE_ALIGN, .FileAlignment = EFI_FILE_ALIGN, - .SizeOfImage = sizeof ( efi_pe_header ), + .SizeOfImage = EFI_IMAGE_ALIGN, .SizeOfHeaders = sizeof ( efi_pe_header ), .NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES, @@ -217,6 +218,16 @@ static unsigned long efi_file_align ( unsigned long offset ) { } /** + * Align section within PE image + * + * @v offset Unaligned offset + * @ret aligned_offset Aligned offset + */ +static unsigned long efi_image_align ( unsigned long offset ) { + return ( ( offset + EFI_IMAGE_ALIGN - 1 ) & ~( EFI_IMAGE_ALIGN - 1 ) ); +} + +/** * Generate entry in PE relocation table * * @v pe_reltab PE relocation table @@ -605,7 +616,7 @@ static struct pe_section * process_section ( struct elf_file *elf, pe_header->nt.FileHeader.NumberOfSections++; pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( new->hdr ); pe_header->nt.OptionalHeader.SizeOfImage = - efi_file_align ( data_end ); + efi_image_align ( data_end ); return new; } @@ -728,13 +739,15 @@ static struct pe_section * create_reloc_section ( struct pe_header *pe_header, struct pe_relocs *pe_reltab ) { struct pe_section *reloc; + size_t section_rawsz; size_t section_memsz; size_t section_filesz; EFI_IMAGE_DATA_DIRECTORY *relocdir; /* Allocate PE section */ - section_memsz = output_pe_reltab ( pe_reltab, NULL ); - section_filesz = efi_file_align ( section_memsz ); + section_rawsz = output_pe_reltab ( pe_reltab, NULL ); + section_filesz = efi_file_align ( section_rawsz ); + section_memsz = efi_image_align ( section_rawsz ); reloc = xmalloc ( sizeof ( *reloc ) + section_filesz ); memset ( reloc, 0, sizeof ( *reloc ) + section_filesz ); @@ -754,11 +767,11 @@ create_reloc_section ( struct pe_header *pe_header, /* Update file header details */ pe_header->nt.FileHeader.NumberOfSections++; pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( reloc->hdr ); - pe_header->nt.OptionalHeader.SizeOfImage += section_filesz; + pe_header->nt.OptionalHeader.SizeOfImage += section_memsz; relocdir = &(pe_header->nt.OptionalHeader.DataDirectory [EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]); relocdir->VirtualAddress = reloc->hdr.VirtualAddress; - relocdir->Size = reloc->hdr.Misc.VirtualSize; + relocdir->Size = section_rawsz; return reloc; } @@ -796,8 +809,8 @@ create_debug_section ( struct pe_header *pe_header, const char *filename ) { } *contents; /* Allocate PE section */ - section_memsz = sizeof ( *contents ); - section_filesz = efi_file_align ( section_memsz ); + section_memsz = efi_image_align ( sizeof ( *contents ) ); + section_filesz = efi_file_align ( sizeof ( *contents ) ); debug = xmalloc ( sizeof ( *debug ) + section_filesz ); memset ( debug, 0, sizeof ( *debug ) + section_filesz ); contents = ( void * ) debug->contents; @@ -828,7 +841,7 @@ create_debug_section ( struct pe_header *pe_header, const char *filename ) { /* Update file header details */ pe_header->nt.FileHeader.NumberOfSections++; pe_header->nt.OptionalHeader.SizeOfHeaders += sizeof ( debug->hdr ); - pe_header->nt.OptionalHeader.SizeOfImage += section_filesz; + pe_header->nt.OptionalHeader.SizeOfImage += section_memsz; debugdir = &(pe_header->nt.OptionalHeader.DataDirectory [EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); debugdir->VirtualAddress = debug->hdr.VirtualAddress; |