[PATCH 3/7] arm64: efi: move EFI header and related data to a separate .S file
Ard Biesheuvel
ard.biesheuvel at linaro.org
Mon Feb 6 09:07:31 PST 2017
On 6 February 2017 at 17:03, Mark Rutland <mark.rutland at arm.com> wrote:
> On Mon, Feb 06, 2017 at 04:24:31PM +0000, Ard Biesheuvel wrote:
>> In preparation of yet another round of modifications to the PE/COFF
>> header, macroize it and move the definition into a separate source
>> file.
>
> I'm really not keen on portioning out bits of the arm64 header like
> this.
>
> The __jmp macro obscures the first few byes of the header, and we lose
> the obvious relationship between the overlapping portions of the arm64
> and PE/COFF headrs.
>
> I think those portions which have a fixed offset from _head (which is at
> least the overlapping PE/COFF and arm64 header bits) should stay in
> head.S.
>
> Can we factor out only the portions with a dynamic offset from the start
> of the image? i.e. only pe_header and beyond?
>
I have no problem at all with that. It is primarily the PE header, and
not the Image header that clutters up head.S, which is what I am
trying to address with this patch.
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel at linaro.org>
>> ---
>> arch/arm64/kernel/efi-header.S | 182 ++++++++++++++++++++
>> arch/arm64/kernel/head.S | 171 +-----------------
>> 2 files changed, 186 insertions(+), 167 deletions(-)
>>
>> diff --git a/arch/arm64/kernel/efi-header.S b/arch/arm64/kernel/efi-header.S
>> new file mode 100644
>> index 000000000000..8c8cd0a8192b
>> --- /dev/null
>> +++ b/arch/arm64/kernel/efi-header.S
>> @@ -0,0 +1,182 @@
>> +/*
>> + * Copyright (C) 2013 - 2017 Linaro, Ltd.
>> + * Copyright (C) 2013, 2014 Red Hat, Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>> +
>> + .macro __jmp, target
>> +#ifdef CONFIG_EFI
>> + /*
>> + * This add instruction has no meaningful effect except that
>> + * its opcode forms the magic "MZ" signature required by UEFI.
>> + */
>> + add x13, x18, #0x16
>> + b \target
>> +#else
>> + b \target // branch to kernel start, magic
>> + .long 0 // reserved
>> +#endif
>> + .endm
>> +
>> + .macro __EFI_HEADER
>> +#ifdef CONFIG_EFI
>> + .long pe_header - _head // Offset to the PE header.
>> +#else
>> + .word 0 // reserved
>> +#endif
>> +
>> +#ifdef CONFIG_EFI
>> + .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 _end - efi_header_end // SizeOfCode
>> + .long 0 // SizeOfInitializedData
>> + .long 0 // SizeOfUninitializedData
>> + .long __efistub_entry - _head // AddressOfEntryPoint
>> + .long efi_header_end - _head // BaseOfCode
>> +
>> +extra_header_fields:
>> + .quad 0 // ImageBase
>> + .long 0x1000 // SectionAlignment
>> + .long PECOFF_FILE_ALIGNMENT // FileAlignment
>> + .short 0 // MajorOperatingSystemVersion
>> + .short 0 // MinorOperatingSystemVersion
>> + .short 0 // MajorImageVersion
>> + .short 0 // MinorImageVersion
>> + .short 0 // MajorSubsystemVersion
>> + .short 0 // MinorSubsystemVersion
>> + .long 0 // Win32VersionValue
>> +
>> + .long _end - _head // SizeOfImage
>> +
>> + // Everything before the kernel image is considered part of the header
>> + .long efi_header_end - _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 (section_table - .) / 8 // NumberOfRvaAndSizes
>> +
>> + .quad 0 // ExportTable
>> + .quad 0 // ImportTable
>> + .quad 0 // ResourceTable
>> + .quad 0 // ExceptionTable
>> + .quad 0 // CertificationTable
>> + .quad 0 // BaseRelocationTable
>> +
>> +#ifdef CONFIG_DEBUG_EFI
>> + .long efi_debug_table - _head // DebugTable
>> + .long efi_debug_table_size
>> +#endif
>> +
>> + // 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 _end - efi_header_end // VirtualSize
>> + .long efi_header_end - _head // VirtualAddress
>> + .long _edata - efi_header_end // SizeOfRawData
>> + .long efi_header_end - _head // PointerToRawData
>> +
>> + .long 0 // PointerToRelocations
>> + .long 0 // PointerToLineNumbers
>> + .short 0 // NumberOfRelocations
>> + .short 0 // NumberOfLineNumbers
>> + .long 0xe0500020 // Characteristics
>> +
>> +#ifdef CONFIG_DEBUG_EFI
>> + /*
>> + * The debug table is referenced via its Relative Virtual Address (RVA),
>> + * which is only defined for those parts of the image that are covered
>> + * by a section declaration. Since this header is not covered by any
>> + * section, the debug table must be emitted elsewhere. So stick it in
>> + * the .init.rodata section instead.
>> + *
>> + * Note that the EFI debug entry itself may legally have a zero RVA,
>> + * which means we can simply put it right after the section headers.
>> + */
>> + __INITRODATA
>> +
>> + .align 2
>> +efi_debug_table:
>> + // EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
>> + .long 0 // Characteristics
>> + .long 0 // TimeDateStamp
>> + .short 0 // MajorVersion
>> + .short 0 // MinorVersion
>> + .long 2 // Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW
>> + .long efi_debug_entry_size // SizeOfData
>> + .long 0 // RVA
>> + .long efi_debug_entry - _head // FileOffset
>> +
>> + .set efi_debug_table_size, . - efi_debug_table
>> + .previous
>> +
>> +efi_debug_entry:
>> + // EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
>> + .ascii "NB10" // Signature
>> + .long 0 // Unknown
>> + .long 0 // Unknown2
>> + .long 0 // Unknown3
>> +
>> + .asciz VMLINUX_PATH
>> +
>> + .set efi_debug_entry_size, . - efi_debug_entry
>> +#endif
>> +
>> + /*
>> + * EFI will load .text onwards at the 4k section alignment
>> + * described in the PE/COFF header. To ensure that instruction
>> + * sequences using an adrp and a :lo12: immediate will function
>> + * correctly at this alignment, we must ensure that .text is
>> + * placed at a 4k boundary in the Image to begin with.
>> + */
>> + .align 12
>> +efi_header_end:
>> +#endif
>> + .endm
>> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
>> index c6cc82ec190b..aca9b184035a 100644
>> --- a/arch/arm64/kernel/head.S
>> +++ b/arch/arm64/kernel/head.S
>> @@ -42,6 +42,8 @@
>> #include <asm/thread_info.h>
>> #include <asm/virt.h>
>>
>> +#include "efi-header.S"
>> +
>> #define __PHYS_OFFSET (KERNEL_START - TEXT_OFFSET)
>>
>> #if (TEXT_OFFSET & 0xfff) != 0
>> @@ -72,17 +74,7 @@ _head:
>> /*
>> * DO NOT MODIFY. Image header expected by Linux boot-loaders.
>> */
>> -#ifdef CONFIG_EFI
>> - /*
>> - * This add instruction has no meaningful effect except that
>> - * its opcode forms the magic "MZ" signature required by UEFI.
>> - */
>> - add x13, x18, #0x16
>> - b stext
>> -#else
>> - b stext // branch to kernel start, magic
>> - .long 0 // reserved
>> -#endif
>> + __jmp stext // Executable code
>> le64sym _kernel_offset_le // Image load offset from start of RAM, little-endian
>> le64sym _kernel_size_le // Effective size of kernel image, little-endian
>> le64sym _kernel_flags_le // Informative flags, little-endian
>> @@ -93,163 +85,8 @@ _head:
>> .byte 0x52
>> .byte 0x4d
>> .byte 0x64
>> -#ifdef CONFIG_EFI
>> - .long pe_header - _head // Offset to the PE header.
>> -#else
>> - .word 0 // reserved
>> -#endif
>> -
>> -#ifdef CONFIG_EFI
>> - .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 _end - efi_header_end // SizeOfCode
>> - .long 0 // SizeOfInitializedData
>> - .long 0 // SizeOfUninitializedData
>> - .long __efistub_entry - _head // AddressOfEntryPoint
>> - .long efi_header_end - _head // BaseOfCode
>> -
>> -extra_header_fields:
>> - .quad 0 // ImageBase
>> - .long 0x1000 // SectionAlignment
>> - .long PECOFF_FILE_ALIGNMENT // FileAlignment
>> - .short 0 // MajorOperatingSystemVersion
>> - .short 0 // MinorOperatingSystemVersion
>> - .short 0 // MajorImageVersion
>> - .short 0 // MinorImageVersion
>> - .short 0 // MajorSubsystemVersion
>> - .short 0 // MinorSubsystemVersion
>> - .long 0 // Win32VersionValue
>> -
>> - .long _end - _head // SizeOfImage
>> -
>> - // Everything before the kernel image is considered part of the header
>> - .long efi_header_end - _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 (section_table - .) / 8 // NumberOfRvaAndSizes
>> -
>> - .quad 0 // ExportTable
>> - .quad 0 // ImportTable
>> - .quad 0 // ResourceTable
>> - .quad 0 // ExceptionTable
>> - .quad 0 // CertificationTable
>> - .quad 0 // BaseRelocationTable
>> -
>> -#ifdef CONFIG_DEBUG_EFI
>> - .long efi_debug_table - _head // DebugTable
>> - .long efi_debug_table_size
>> -#endif
>> -
>> - // 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 _end - efi_header_end // VirtualSize
>> - .long efi_header_end - _head // VirtualAddress
>> - .long _edata - efi_header_end // SizeOfRawData
>> - .long efi_header_end - _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)
>> -
>> -#ifdef CONFIG_DEBUG_EFI
>> - /*
>> - * The debug table is referenced via its Relative Virtual Address (RVA),
>> - * which is only defined for those parts of the image that are covered
>> - * by a section declaration. Since this header is not covered by any
>> - * section, the debug table must be emitted elsewhere. So stick it in
>> - * the .init.rodata section instead.
>> - *
>> - * Note that the EFI debug entry itself may legally have a zero RVA,
>> - * which means we can simply put it right after the section headers.
>> - */
>> - __INITRODATA
>> -
>> - .align 2
>> -efi_debug_table:
>> - // EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
>> - .long 0 // Characteristics
>> - .long 0 // TimeDateStamp
>> - .short 0 // MajorVersion
>> - .short 0 // MinorVersion
>> - .long 2 // Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW
>> - .long efi_debug_entry_size // SizeOfData
>> - .long 0 // RVA
>> - .long efi_debug_entry - _head // FileOffset
>> -
>> - .set efi_debug_table_size, . - efi_debug_table
>> - .previous
>> -
>> -efi_debug_entry:
>> - // EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
>> - .ascii "NB10" // Signature
>> - .long 0 // Unknown
>> - .long 0 // Unknown2
>> - .long 0 // Unknown3
>> -
>> - .asciz VMLINUX_PATH
>> -
>> - .set efi_debug_entry_size, . - efi_debug_entry
>> -#endif
>> -
>> - /*
>> - * EFI will load .text onwards at the 4k section alignment
>> - * described in the PE/COFF header. To ensure that instruction
>> - * sequences using an adrp and a :lo12: immediate will function
>> - * correctly at this alignment, we must ensure that .text is
>> - * placed at a 4k boundary in the Image to begin with.
>> - */
>> - .align 12
>> -efi_header_end:
>> -#endif
>> + __EFI_HEADER
>>
>> __INIT
>>
>> --
>> 2.7.4
>>
More information about the linux-arm-kernel
mailing list