aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Häuser <mhaeuser@posteo.de>2021-04-08 20:04:16 +0200
committerMichael Brown <mcb30@ipxe.org>2021-04-10 13:43:47 +0100
commitf1e9e2b062fab46a6e3aec1f08d4554dd5dd2b98 (patch)
tree46210b293db4dbe620b6941163fdf41c58be01c4
parent1cc87565110014205f647fd413f897a1a5a04b22 (diff)
downloadipxe-f1e9e2b062fab46a6e3aec1f08d4554dd5dd2b98.zip
ipxe-f1e9e2b062fab46a6e3aec1f08d4554dd5dd2b98.tar.gz
ipxe-f1e9e2b062fab46a6e3aec1f08d4554dd5dd2b98.tar.bz2
[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.lds18
-rw-r--r--src/util/elf2efi.c35
2 files changed, 33 insertions, 20 deletions
diff --git a/src/scripts/efi.lds b/src/scripts/efi.lds
index 3602254..dd7b3f0 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 38eb299..b0d5466 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;