From 2e064b1e131eba262c0ba4268cb79dbc72edeece Mon Sep 17 00:00:00 2001 From: Jordan Justen Date: Fri, 23 Mar 2012 09:35:04 -0700 Subject: x86, efi: Fix issue of overlapping .reloc section for EFI_STUB Previously the .reloc section was embedded in the .text section. No relocations are required during the PE/COFF loading phase for the kernel using the EFI_STUB UEFI loader. To fix the issue of overlapping sections, create a .reloc section with a zero length. The .reloc section header must exist to make sure the image will be loaded by the UEFI firmware, but a zero-length section header seems to be sufficient. Signed-off-by: Jordan Justen Link: http://lkml.kernel.org/r/1332520506-6472-2-git-send-email-jordan.l.justen@intel.com Acked-by: Matt Fleming Signed-off-by: H. Peter Anvin --- arch/x86/boot/header.S | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index f1bbeeb0914..4e9124b148c 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -217,18 +217,17 @@ section_table: # # The EFI application loader requires a relocation section - # because EFI applications are relocatable and not having - # this section seems to confuse it. But since we don't need - # the loader to fixup any relocs for us just fill it with a - # single dummy reloc. + # because EFI applications must be relocatable. But since + # we don't need the loader to fixup any relocs for us, we + # just create an empty (zero-length) .reloc section header. # .ascii ".reloc" .byte 0 .byte 0 - .long reloc_end - reloc_start - .long reloc_start - .long reloc_end - reloc_start # SizeOfRawData - .long reloc_start # PointerToRawData + .long 0 + .long 0 + .long 0 # SizeOfRawData + .long 0 # PointerToRawData .long 0 # PointerToRelocations .long 0 # PointerToLineNumbers .word 0 # NumberOfRelocations @@ -469,10 +468,3 @@ setup_corrupt: .data dummy: .long 0 - - .section .reloc -reloc_start: - .long dummy - reloc_start - .long 10 - .word 0 -reloc_end: -- cgit v1.2.3-18-g5258 From e31be363df3092821bf179cf4baa076f501b8ae6 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 23 Mar 2012 09:35:05 -0700 Subject: x86, efi: Fix .text section overlapping image header for EFI_STUB This change modifes the PE .text section to start after the first sector of the kernel image. The header may be modified by the UEFI secure boot signing, so it is not appropriate for it to be included in one of the image sections. Since the sections are part of the secure boot hash, this modification to the .text section contents would invalidate the secure boot signed hash. Note: UEFI secure boot does hash the image header, but fields that are changed by the signing process are excluded from the hash calculation. This exclusion process is only handled for the image header, and not image sections. Luckily, we can still easily boot without the first sector by initializing a few fields in arch/x86/boot/compressed/eboot.c. Signed-off-by: Matt Fleming Link: http://lkml.kernel.org/r/1332520506-6472-3-git-send-email-jordan.l.justen@intel.com [jordan.l.justen@intel.com: set .text vma & file offset] Signed-off-by: Jordan Justen Signed-off-by: H. Peter Anvin --- arch/x86/boot/compressed/eboot.c | 14 +++++++++++--- arch/x86/boot/header.S | 2 +- arch/x86/boot/tools/build.c | 25 ++++++++++++++++++++++--- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index fec216f4fbc..01cbb8707a3 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -904,11 +904,19 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) memset(boot_params, 0x0, 0x4000); - /* Copy first two sectors to boot_params */ - memcpy(boot_params, image->image_base, 1024); - hdr = &boot_params->hdr; + /* Copy the second sector to boot_params */ + memcpy(&hdr->jump, image->image_base + 512, 512); + + /* + * Fill out some of the header fields ourselves because the + * EFI firmware loader doesn't load the first sector. + */ + hdr->root_flags = 1; + hdr->vid_mode = 0xffff; + hdr->boot_flag = 0xAA55; + /* * The EFI firmware loader could have placed the kernel image * anywhere in memory, but the kernel has various restrictions diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 4e9124b148c..4ceb56e9a4c 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -147,7 +147,7 @@ optional_header: # Filled in by build.c .long 0x0000 # AddressOfEntryPoint - .long 0x0000 # BaseOfCode + .long 0x0200 # BaseOfCode #ifdef CONFIG_X86_32 .long 0 # data #endif diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index 4e9bd6bcafa..2aeab3dc9e5 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -202,12 +202,19 @@ int main(int argc, char ** argv) pe_header = *(unsigned int *)&buf[0x3c]; - /* Size of code */ - *(unsigned int *)&buf[pe_header + 0x1c] = file_sz; - /* Size of image */ *(unsigned int *)&buf[pe_header + 0x50] = file_sz; + /* + * Subtract the size of the first section (512 bytes) which + * includes the header and .reloc section. The remaining size + * is that of the .text section. + */ + file_sz -= 512; + + /* Size of code */ + *(unsigned int *)&buf[pe_header + 0x1c] = file_sz; + #ifdef CONFIG_X86_32 /* Address of entry point */ *(unsigned int *)&buf[pe_header + 0x28] = i; @@ -215,8 +222,14 @@ int main(int argc, char ** argv) /* .text size */ *(unsigned int *)&buf[pe_header + 0xb0] = file_sz; + /* .text vma */ + *(unsigned int *)&buf[pe_header + 0xb4] = 0x200; + /* .text size of initialised data */ *(unsigned int *)&buf[pe_header + 0xb8] = file_sz; + + /* .text file offset */ + *(unsigned int *)&buf[pe_header + 0xbc] = 0x200; #else /* * Address of entry point. startup_32 is at the beginning and @@ -228,8 +241,14 @@ int main(int argc, char ** argv) /* .text size */ *(unsigned int *)&buf[pe_header + 0xc0] = file_sz; + /* .text vma */ + *(unsigned int *)&buf[pe_header + 0xc4] = 0x200; + /* .text size of initialised data */ *(unsigned int *)&buf[pe_header + 0xc8] = file_sz; + + /* .text file offset */ + *(unsigned int *)&buf[pe_header + 0xcc] = 0x200; #endif /* CONFIG_X86_32 */ #endif /* CONFIG_EFI_STUB */ -- cgit v1.2.3-18-g5258 From e47bb0bda46bf50f81671db502d0c903e0a32604 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 23 Mar 2012 09:35:06 -0700 Subject: x86, efi: Fix NumberOfRvaAndSizes field in PE32 header for EFI_STUB We've actually got six data directories in the header, not one. Even though the firmware loader doesn't seem to mind, when we come to sign the kernel image the signing tool thinks that there is no Certificate Table data directory, even though we've allocated space for one. Signed-off-by: Matt Fleming Link: http://lkml.kernel.org/r/1332520506-6472-4-git-send-email-jordan.l.justen@intel.com Reviewed-by: Jordan Justen Signed-off-by: H. Peter Anvin --- arch/x86/boot/header.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 4ceb56e9a4c..8bbea6aa40d 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -189,7 +189,7 @@ extra_header_fields: .quad 0 # SizeOfHeapCommit #endif .long 0 # LoaderFlags - .long 0x1 # NumberOfRvaAndSizes + .long 0x6 # NumberOfRvaAndSizes .quad 0 # ExportTable .quad 0 # ImportTable -- cgit v1.2.3-18-g5258