root/arch/arm64/kernel/efi-header.S
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2013 - 2017 Linaro, Ltd.
 * Copyright (C) 2013, 2014 Red Hat, Inc.
 */

#include <linux/pe.h>
#include <linux/sizes.h>

        .macro  efi_signature_nop
#ifdef CONFIG_EFI
.L_head:
        /*
         * This ccmp instruction has no meaningful effect except that
         * its opcode forms the magic "MZ" signature required by UEFI.
         */
        ccmp    x18, #0, #0xd, pl
#else
        /*
         * Bootloaders may inspect the opcode at the start of the kernel
         * image to decide if the kernel is capable of booting via UEFI.
         * So put an ordinary NOP here, not the "MZ.." pseudo-nop above.
         */
        nop
#endif
        .endm

        .macro  __EFI_PE_HEADER
#ifdef CONFIG_EFI
        .set    .Lpe_header_offset, . - .L_head
        .long   IMAGE_NT_SIGNATURE
        .short  IMAGE_FILE_MACHINE_ARM64                // Machine
        .short  .Lsection_count                         // NumberOfSections
        .long   0                                       // TimeDateStamp
        .long   0                                       // PointerToSymbolTable
        .long   0                                       // NumberOfSymbols
        .short  .Lsection_table - .Loptional_header     // SizeOfOptionalHeader
        .short  IMAGE_FILE_DEBUG_STRIPPED | \
                IMAGE_FILE_EXECUTABLE_IMAGE | \
                IMAGE_FILE_LINE_NUMS_STRIPPED           // Characteristics

.Loptional_header:
        .short  IMAGE_NT_OPTIONAL_HDR64_MAGIC           // PE32+ format
        .byte   0x02                                    // MajorLinkerVersion
        .byte   0x14                                    // MinorLinkerVersion
        .long   __initdata_begin - .Lefi_header_end     // SizeOfCode
        .long   __pecoff_data_size                      // SizeOfInitializedData
        .long   0                                       // SizeOfUninitializedData
        .long   __efistub_efi_pe_entry - .L_head        // AddressOfEntryPoint
        .long   .Lefi_header_end - .L_head              // BaseOfCode

        .quad   0                                       // ImageBase
        .long   SEGMENT_ALIGN                           // SectionAlignment
        .long   PECOFF_FILE_ALIGNMENT                   // FileAlignment
        .short  0                                       // MajorOperatingSystemVersion
        .short  0                                       // MinorOperatingSystemVersion
        .short  LINUX_EFISTUB_MAJOR_VERSION             // MajorImageVersion
        .short  LINUX_EFISTUB_MINOR_VERSION             // MinorImageVersion
        .short  0                                       // MajorSubsystemVersion
        .short  0                                       // MinorSubsystemVersion
        .long   0                                       // Win32VersionValue

        .long   _end - .L_head                          // SizeOfImage

        // Everything before the kernel image is considered part of the header
        .long   .Lefi_header_end - .L_head              // SizeOfHeaders
        .long   0                                       // CheckSum
        .short  IMAGE_SUBSYSTEM_EFI_APPLICATION         // Subsystem
        .short  IMAGE_DLLCHARACTERISTICS_NX_COMPAT      // DllCharacteristics
        .quad   0                                       // SizeOfStackReserve
        .quad   0                                       // SizeOfStackCommit
        .quad   0                                       // SizeOfHeapReserve
        .quad   0                                       // SizeOfHeapCommit
        .long   0                                       // LoaderFlags
        .long   (.Lsection_table - .) / 8               // NumberOfRvaAndSizes

        .quad   0                                       // ExportTable
        .quad   0                                       // ImportTable
        .quad   0                                       // ResourceTable
        .quad   0                                       // ExceptionTable
        .quad   0                                       // CertificationTable
        .quad   0                                       // BaseRelocationTable

#if defined(CONFIG_DEBUG_EFI) || defined(CONFIG_ARM64_BTI_KERNEL)
        .long   .Lefi_debug_table - .L_head             // DebugTable
        .long   .Lefi_debug_table_size

        /*
         * 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 payloads themselves are permitted to have zero RVAs,
         * which means we can simply put those right after the section headers.
         */
        __INITRODATA

        .align  2
.Lefi_debug_table:
#ifdef CONFIG_DEBUG_EFI
        // EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
        .long   0                                       // Characteristics
        .long   0                                       // TimeDateStamp
        .short  0                                       // MajorVersion
        .short  0                                       // MinorVersion
        .long   IMAGE_DEBUG_TYPE_CODEVIEW               // Type
        .long   .Lefi_debug_entry_size                  // SizeOfData
        .long   0                                       // RVA
        .long   .Lefi_debug_entry - .L_head             // FileOffset
#endif
#ifdef CONFIG_ARM64_BTI_KERNEL
        .long   0                                       // Characteristics
        .long   0                                       // TimeDateStamp
        .short  0                                       // MajorVersion
        .short  0                                       // MinorVersion
        .long   IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS  // Type
        .long   4                                       // SizeOfData
        .long   0                                       // RVA
        .long   .Lefi_dll_characteristics_ex - .L_head  // FileOffset
#endif
        .set    .Lefi_debug_table_size, . - .Lefi_debug_table
        .previous
#endif

        // Section table
.Lsection_table:
        .ascii  ".text\0\0\0"
        .long   __initdata_begin - .Lefi_header_end     // VirtualSize
        .long   .Lefi_header_end - .L_head              // VirtualAddress
        .long   __initdata_begin - .Lefi_header_end     // SizeOfRawData
        .long   .Lefi_header_end - .L_head              // PointerToRawData

        .long   0                                       // PointerToRelocations
        .long   0                                       // PointerToLineNumbers
        .short  0                                       // NumberOfRelocations
        .short  0                                       // NumberOfLineNumbers
        .long   IMAGE_SCN_CNT_CODE | \
                IMAGE_SCN_MEM_READ | \
                IMAGE_SCN_MEM_EXECUTE                   // Characteristics

        .ascii  ".data\0\0\0"
        .long   __pecoff_data_size                      // VirtualSize
        .long   __initdata_begin - .L_head              // VirtualAddress
        .long   __pecoff_data_rawsize                   // SizeOfRawData
        .long   __initdata_begin - .L_head              // PointerToRawData

        .long   0                                       // PointerToRelocations
        .long   0                                       // PointerToLineNumbers
        .short  0                                       // NumberOfRelocations
        .short  0                                       // NumberOfLineNumbers
        .long   IMAGE_SCN_CNT_INITIALIZED_DATA | \
                IMAGE_SCN_MEM_READ | \
                IMAGE_SCN_MEM_WRITE                     // Characteristics

        .set    .Lsection_count, (. - .Lsection_table) / 40

#ifdef CONFIG_DEBUG_EFI
.Lefi_debug_entry:
        // EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
        .ascii  "NB10"                                  // Signature
        .long   0                                       // Unknown
        .long   0                                       // Unknown2
        .long   0                                       // Unknown3

        .asciz  VMLINUX_PATH

        .set    .Lefi_debug_entry_size, . - .Lefi_debug_entry
#endif
#ifdef CONFIG_ARM64_BTI_KERNEL
.Lefi_dll_characteristics_ex:
        .long   IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT
#endif

        .balign SEGMENT_ALIGN
.Lefi_header_end:
#else
        .set    .Lpe_header_offset, 0x0
#endif
        .endm