diff mbox

[Xen-devel,RFC,15/19] Add PE/COFF header in head.S

Message ID 1403918735-30027-16-git-send-email-roy.franz@linaro.org
State New
Headers show

Commit Message

Roy Franz June 28, 2014, 1:25 a.m. UTC
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(-)

Comments

Ian Campbell July 2, 2014, 12:02 p.m. UTC | #1
On Sat, 2014-06-28 at 02:25 +0100, Roy Franz wrote:
> 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.

This looks good to me. A few minor comments:

Some of the whitespace is off (please use space and not hard tabs
throughout)

I think we could perhaps get rid of CONFIG_EFI_STUB at least at the
arm64 subarch level. We don't in general support the same level of
configurability in Xen as Linux -- it's mostly just a single
configuration for everyone. It'd need to be retain at the arch level to
cope with arm32 not doing efi, but removing it here would make things
simpler I think?

Would it be possible to find sort of link/reference to a spec for the
header structs which you are adding and stick them in comments before
each one please.

> 
> 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

I love this hack ;-)

Ian.
Roy Franz July 9, 2014, 6:35 p.m. UTC | #2
On Wed, Jul 2, 2014 at 5:02 AM, Ian Campbell <Ian.Campbell@citrix.com> wrote:
> On Sat, 2014-06-28 at 02:25 +0100, Roy Franz wrote:
>> 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.
>
> This looks good to me. A few minor comments:
>
> Some of the whitespace is off (please use space and not hard tabs
> throughout)
I'll clean that up.

>
> I think we could perhaps get rid of CONFIG_EFI_STUB at least at the
> arm64 subarch level. We don't in general support the same level of
> configurability in Xen as Linux -- it's mostly just a single
> configuration for everyone. It'd need to be retain at the arch level to
> cope with arm32 not doing efi, but removing it here would make things
> simpler I think?
I agree. I don't think the arm64 stub needs to be configurable, as it
should not
affect non-stub users when it is enabled, and should be a fairly small amount
of code.  It will need to be disabled for arm32.

>
> Would it be possible to find sort of link/reference to a spec for the
> header structs which you are adding and stick them in comments before
> each one please.
I will try to track down some documentation to link to.  It may end up
being a single
link to a PDF (or even a microsoft Word document, since it is a Microsoft spec.)

>
>>
>> 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
>
> I love this hack ;-)
>
> Ian.
>
diff mbox

Patch

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 = .;