This patch adds a simple PE/COFF header in head.S. PE/COFF linker support is not available for arm64, so a native build is not possible. Also, this allows the binary to be both a PE/COFF EFI application, and a normal Image file bootable like a Linux kernel. The arm and arm64 Linux kernels use the same methodology to create a single image that is both an EFI application and a zImage/Image file.
Signed-off-by: Roy Franz roy.franz@linaro.org --- xen/arch/arm/arm64/head.S | 118 +++++++++++++++++++++++++++++++++++++++++++++- xen/arch/arm/xen.lds.S | 1 + 2 files changed, 117 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/arm64/head.S b/xen/arch/arm/arm64/head.S index 2a13527..9b88aeb 100644 --- a/xen/arch/arm/arm64/head.S +++ b/xen/arch/arm/arm64/head.S @@ -84,7 +84,7 @@ #endif /* !CONFIG_EARLY_PRINTK */
/*.aarch64*/ - +#define CONFIG_EFI_STUB /* * Kernel startup entry point. * --------------------------- @@ -100,12 +100,24 @@ */
.global start +efi_stub_entry: /* Dummy symbol so we can compile before actual stub added */ start: +#ifdef CONFIG_EFI_STUB /* * DO NOT MODIFY. Image header expected by Linux boot-loaders. */ - b real_start /* branch to kernel start, magic */ +efi_head: + /* + * This add instruction has no meaningful effect except that + * its opcode forms the magic "MZ" signature of a PE/COFF file + * that is required for UEFI applications. + */ + add x13, x18, #0x16 + b real_start /* branch to kernel start */ +#else + b real_start /* branch to kernel start */ .long 0 /* reserved */ +#endif .quad 0 /* Image load offset from start of RAM */ .quad 0 /* reserved */ .quad 0 /* reserved */ @@ -116,7 +128,109 @@ start: .byte 0x52 .byte 0x4d .byte 0x64 +#ifdef CONFIG_EFI_STUB + .long pe_header - efi_head /* Offset to the PE header. */ +#else .word 0 /* reserved */ +#endif + +#ifdef CONFIG_EFI_STUB + .align 3 +pe_header: + .ascii "PE" + .short 0 +coff_header: + .short 0xaa64 // AArch64 + .short 2 // nr_sections + .long 0 // TimeDateStamp + .long 0 // PointerToSymbolTable + .long 1 // NumberOfSymbols + .short section_table - optional_header // SizeOfOptionalHeader + .short 0x206 // Characteristics. + // IMAGE_FILE_DEBUG_STRIPPED | + // IMAGE_FILE_EXECUTABLE_IMAGE | + // IMAGE_FILE_LINE_NUMS_STRIPPED +optional_header: + .short 0x20b // PE32+ format + .byte 0x02 // MajorLinkerVersion + .byte 0x14 // MinorLinkerVersion + .long __init_end_efi - real_start // SizeOfCode + .long 0 // SizeOfInitializedData + .long 0 // SizeOfUninitializedData + .long efi_stub_entry - efi_head // AddressOfEntryPoint + .long real_start - efi_head // BaseOfCode + +extra_header_fields: + .quad 0 // ImageBase + .long 0x200000 // SectionAlignment (2MByte) + .long 0x8 // FileAlignment + .short 0 // MajorOperatingSystemVersion + .short 0 // MinorOperatingSystemVersion + .short 0 // MajorImageVersion + .short 0 // MinorImageVersion + .short 0 // MajorSubsystemVersion + .short 0 // MinorSubsystemVersion + .long 0 // Win32VersionValue + + .long __init_end_efi - efi_head // SizeOfImage + + // Everything before the kernel image is considered part of the header + .long real_start - efi_head // SizeOfHeaders + .long 0 // CheckSum + .short 0xa // Subsystem (EFI application) + .short 0 // DllCharacteristics + .quad 0 // SizeOfStackReserve + .quad 0 // SizeOfStackCommit + .quad 0 // SizeOfHeapReserve + .quad 0 // SizeOfHeapCommit + .long 0 // LoaderFlags + .long 0x6 // NumberOfRvaAndSizes + + .quad 0 // ExportTable + .quad 0 // ImportTable + .quad 0 // ResourceTable + .quad 0 // ExceptionTable + .quad 0 // CertificationTable + .quad 0 // BaseRelocationTable + + // Section table +section_table: + + /* + * The EFI application loader requires a relocation section + * because EFI applications must be relocatable. This is a + * dummy section as far as we are concerned. + */ + .ascii ".reloc" + .byte 0 + .byte 0 // end of 0 padding of section name + .long 0 + .long 0 + .long 0 // SizeOfRawData + .long 0 // PointerToRawData + .long 0 // PointerToRelocations + .long 0 // PointerToLineNumbers + .short 0 // NumberOfRelocations + .short 0 // NumberOfLineNumbers + .long 0x42100040 // Characteristics (section flags) + + + .ascii ".text" + .byte 0 + .byte 0 + .byte 0 // end of 0 padding of section name + .long __init_end_efi - real_start // VirtualSize + .long real_start - efi_head // VirtualAddress + .long __init_end_efi - real_start // SizeOfRawData + .long real_start - efi_head // PointerToRawData + + .long 0 // PointerToRelocations (0 for executables) + .long 0 // PointerToLineNumbers (0 for executables) + .short 0 // NumberOfRelocations (0 for executables) + .short 0 // NumberOfLineNumbers (0 for executables) + .long 0xe0500020 // Characteristics (section flags) + .align 5 +#endif
real_start: msr DAIFSet, 0xf /* Disable all interrupts */ diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S index be55dad..62b9d5b 100644 --- a/xen/arch/arm/xen.lds.S +++ b/xen/arch/arm/xen.lds.S @@ -135,6 +135,7 @@ SECTIONS *(.xsm_initcall.init) __xsm_initcall_end = .; } :text + __init_end_efi = .; . = ALIGN(STACK_SIZE); __init_end = .;