@@ -7,6 +7,8 @@ CFLAGS += -I$(BASEDIR)/include
CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-generic
CFLAGS += -I$(BASEDIR)/include/asm-x86/mach-default
CFLAGS += -DXEN_IMG_OFFSET=$(XEN_IMG_OFFSET)
+CFLAGS += -DXEN_LOAD_ALIGN=XEN_IMG_OFFSET
+CFLAGS += -DXEN_FILE_ALIGN=PAGE_SIZE
CFLAGS += '-D__OBJECT_LABEL__=$(subst /,$$,$(subst -,_,$(subst $(BASEDIR)/,,$(CURDIR))/$@))'
# Prevent floating-point variables from creeping into Xen.
@@ -1,3 +1,4 @@
+#include <xen/compile.h>
#include <xen/multiboot.h>
#include <xen/multiboot2.h>
#include <public/xen.h>
@@ -44,6 +45,150 @@
.Lmb2ht_init_end\@:
.endm
+ .section .efi.pe.header, "a", @progbits
+
+ENTRY(efi_pe_head)
+ /*
+ * Legacy EXE header.
+ *
+ * Most of it is copied from binutils package, version 2.28,
+ * include/coff/pe.h:struct external_PEI_filehdr and
+ * bfd/peXXigen.c:_bfd_XXi_only_swap_filehdr_out().
+ *
+ * Page is equal 512 bytes here.
+ * Paragraph is equal 16 bytes here.
+ */
+ .short 0x5a4d /* EXE magic number. */
+ .short 0x90 /* Bytes on last page of file. */
+ .short 0x3 /* Pages in file. */
+ .short 0 /* Relocations. */
+ .short 0x4 /* Size of header in paragraphs. */
+ .short 0 /* Minimum extra paragraphs needed. */
+ .short 0xffff /* Maximum extra paragraphs needed. */
+ .short 0 /* Initial (relative) SS value. */
+ .short 0xb8 /* Initial SP value. */
+ .short 0 /* Checksum. */
+ .short 0 /* Initial IP value. */
+ .short 0 /* Initial (relative) CS value. */
+ .short 0x40 /* File address of relocation table. */
+ .short 0 /* Overlay number. */
+ .fill 4, 2, 0 /* Reserved words. */
+ .short 0 /* OEM identifier. */
+ .short 0 /* OEM information. */
+ .fill 10, 2, 0 /* Reserved words. */
+ .long pe_header - efi_pe_head /* File address of the PE header. */
+
+ /*
+ * DOS message.
+ *
+ * It is copied from binutils package, version 2.28,
+ * include/coff/pe.h:struct external_PEI_filehdr and
+ * bfd/peXXigen.c:_bfd_XXi_only_swap_filehdr_out().
+ */
+ .long 0x0eba1f0e
+ .long 0xcd09b400
+ .long 0x4c01b821
+ .long 0x685421cd
+ .long 0x70207369
+ .long 0x72676f72
+ .long 0x63206d61
+ .long 0x6f6e6e61
+ .long 0x65622074
+ .long 0x6e757220
+ .long 0x206e6920
+ .long 0x20534f44
+ .long 0x65646f6d
+ .long 0x0a0d0d2e
+ .long 0x24
+ .long 0
+
+ /*
+ * PE/COFF header.
+ *
+ * The PE/COFF format is defined by Microsoft, and is available from
+ * http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
+ *
+ * Some ideas are taken from Linux kernel and Xen ARM64.
+ */
+
+pe_header:
+ .ascii "PE\0\0" /* PE signature. */
+ .short 0x8664 /* Machine: IMAGE_FILE_MACHINE_AMD64. */
+ .short 1 /* NumberOfSections. */
+ .long XEN_COMPILE_POSIX_TIME /* TimeDateStamp. */
+ .long 0 /* PointerToSymbolTable. */
+ .long 0 /* NumberOfSymbols. */
+ .short section_table - optional_header /* SizeOfOptionalHeader. */
+ .short 0x226 /* Characteristics:
+ * IMAGE_FILE_EXECUTABLE_IMAGE |
+ * IMAGE_FILE_LARGE_ADDRESS_AWARE |
+ * IMAGE_FILE_DEBUG_STRIPPED |
+ * IMAGE_FILE_LINE_NUMS_STRIPPED
+ */
+
+optional_header:
+ .short 0x20b /* PE format: PE32+ */
+ .byte 0x02 /* MajorLinkerVersion. */
+ .byte 0x14 /* MinorLinkerVersion. */
+ .long __2M_rwdata_end - efi_pe_head_end /* SizeOfCode. */
+ .long 0 /* SizeOfInitializedData. */
+ .long 0 /* SizeOfUninitializedData. */
+ .long sym_offs(efi_start) /* AddressOfEntryPoint. */
+ .long sym_offs(start) /* BaseOfCode. */
+ .quad sym_offs(__image_base__) /* ImageBase. */
+ .long XEN_LOAD_ALIGN /* SectionAlignment. */
+ .long XEN_FILE_ALIGN /* FileAlignment. */
+ .short 2 /* MajorOperatingSystemVersion. */
+ .short 0 /* MinorOperatingSystemVersion. */
+ .short XEN_VERSION /* MajorImageVersion. */
+ .short XEN_SUBVERSION /* MinorImageVersion. */
+ .short 2 /* MajorSubsystemVersion. */
+ .short 0 /* MinorSubsystemVersion. */
+ .long 0 /* Win32VersionValue. */
+ .long __pe_SizeOfImage /* SizeOfImage. */
+ .long efi_pe_head_end - efi_pe_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. */
+
+ /* Data Directories. */
+ .quad 0 /* Export Table. */
+ .quad 0 /* Import Table. */
+ .quad 0 /* Resource Table. */
+ .quad 0 /* Exception Table. */
+ .quad 0 /* Certificate Table. */
+ .quad 0 /* Base Relocation Table. */
+
+section_table:
+ .ascii ".text\0\0\0" /* Name. */
+ .long __2M_rwdata_end - efi_pe_head_end /* VirtualSize. */
+ .long sym_offs(start) /* VirtualAddress. */
+ .long __bss_start - efi_pe_head_end /* SizeOfRawData. */
+ .long efi_pe_head_end - efi_pe_head /* PointerToRawData. */
+ .long 0 /* PointerToRelocations. */
+ .long 0 /* PointerToLinenumbers. */
+ .short 0 /* NumberOfRelocations. */
+ .short 0 /* NumberOfLinenumbers. */
+ .long 0xe0500020 /* Characteristics:
+ * IMAGE_SCN_CNT_CODE |
+ * IMAGE_SCN_ALIGN_16BYTES |
+ * IMAGE_SCN_MEM_EXECUTE |
+ * IMAGE_SCN_MEM_READ |
+ * IMAGE_SCN_MEM_WRITE
+ */
+
+ .align XEN_FILE_ALIGN
+ENTRY(efi_pe_head_end)
+
+ .text
+ .code32
+
ENTRY(start)
jmp __start
@@ -54,7 +54,12 @@ SECTIONS
__2M_text_start = .; /* Start of 2M superpages, mapped RX. */
#endif
- . = __XEN_VIRT_START + XEN_IMG_OFFSET;
+ . = __XEN_VIRT_START + XEN_IMG_OFFSET - efi_pe_head_end + efi_pe_head;
+
+ .efi.pe.header : {
+ *(.efi.pe.header)
+ } :NONE
+
_start = .;
.text : {
_stext = .; /* Text and read-only data */
@@ -234,6 +239,8 @@ SECTIONS
*(.data.rel)
*(.data.rel.*)
CONSTRUCTORS
+ /* PE file must end at XEN_FILE_ALIGN boundary. */
+ . = ALIGN(XEN_FILE_ALIGN);
} :text
.bss : { /* BSS */
@@ -259,6 +266,8 @@ SECTIONS
#endif
__2M_rwdata_end = .;
+ __pe_SizeOfImage = ALIGN(. - __image_base__, XEN_LOAD_ALIGN);
+
#ifdef EFI
. = ALIGN(4);
.reloc : {
@@ -337,3 +346,8 @@ ASSERT((trampoline_end - trampoline_start) < TRAMPOLINE_SPACE - MBI_SPACE_MIN,
"not enough room for trampoline and mbi data")
ASSERT((wakeup_stack - wakeup_stack_start) >= WAKEUP_STACK_MIN,
"wakeup stack too small")
+
+ASSERT(efi_pe_head_end == _start, "PE header does not end at the beginning of .text section")
+ASSERT(_start == __XEN_VIRT_START + XEN_IMG_OFFSET, ".text section begins at wrong address")
+ASSERT(IS_ALIGNED(_start, XEN_FILE_ALIGN), "_start misaligned")
+ASSERT(IS_ALIGNED(__bss_start, XEN_FILE_ALIGN), "__bss_start misaligned")
This is the first step to get: - one binary which can be loaded by the EFI loader, Multiboot and Multiboot2 protocols, - if we wish, in the future we can drop xen/xen.gz and build xen.efi only, - crash dumps generated by the xen.efi loaded from the EFI loader can be analyzed by crash tool, - simpler code, - simpler build, - Xen build will no longer depend on ld i386pep support. Signed-off-by: Daniel Kiper <daniel.kiper@oracle.com> --- xen/arch/x86/Rules.mk | 2 + xen/arch/x86/boot/head.S | 145 ++++++++++++++++++++++++++++++++++++++++++++++ xen/arch/x86/xen.lds.S | 16 ++++- 3 files changed, 162 insertions(+), 1 deletion(-)