memtest86plus/boot/header.S
Martin Whitaker e38ad8e6a4 Mark EFI image .text section as writable.
The EFI image .text section is taken from memtest_shared.bin, which is
a combined code and data section. Some recent UEFI BIOSs set the page
protection attributes when loading EFI images, so we need to mark this
section as both executable and writable to prevent page faults.

Fixes issue #413 and should fix issue #377.
2024-08-10 16:11:08 +01:00

253 lines
6.6 KiB
ArmAsm

// SPDX-License-Identifier: GPL-2.0
//
// header.S supports booting directly from a UEFI BIOS or via an intermediate
// bootloader that supports the Linux boot protocol. When booted directly from
// the BIOS, it provides the MS-DOS & PE/COFF headers. When using an intermediate
// bootloader, it provides the first few bytes of the Linux boot header (at the
// end of the boot sector), with the remainder of the header being provided by
// setup.S.
//
// Copyright (C) 2020-2024 Martin Whitaker.
//
// Derived from Linux 5.6 arch/x86/boot/header.S:
//
// Copyright (C) 1991, 1992 Linus Torvalds
//
// Based on bootsect.S and setup.S
// modified by more people than can be counted
//
// Rewritten as a common file by H. Peter Anvin (Apr 2007)
#define __ASSEMBLY__
#include "boot.h"
#include "peimage.h"
# The EFI loader loads the header at ImageBase, so we have to locate the main program
# after that. This means we can't load the main program at HIGH_LOAD_ADDR. Pick a load
# address well away from HIGH_LOAD_ADDR, to avoid overlap when relocating the code.
#define IMAGE_BASE 0x200000
.section ".header", "ax", @progbits
.code16
.globl boot
boot:
# "MZ", the MS-DOS header signature.
.byte 0x4d
.byte 0x5a
# In case we are booted by a legacy BIOS, print an error message.
# Fortunately the MS-DOS header translates to harmless instructions.
ljmp $BOOT_SEG, $(error - boot)
error:
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
xorw %sp, %sp
sti
cld
movw $error_msg, %si
0: lodsb
andb %al, %al
jz wait
movb $0xe, %ah
movw $7, %bx
int $0x10
jmp 0b
wait:
# Allow the user to press a key, then reboot.
xorw %ax, %ax
int $0x16
int $0x19
# int 0x19 should never return. In case it does, invoke the BIOS.
# reset code.
ljmp $0xf000,$0xfff0
# The PE header pointer.
.org 0x3c
.long pe_header
error_msg:
.ascii "This is a UEFI bootable image\r\n"
.ascii "\n"
.asciz "Press any key to reboot\r\n"
pe_header:
.ascii "PE"
.word 0
coff_header:
#ifdef __x86_64__
.word IMAGE_FILE_MACHINE_X64 # Machine (x86-64)
#else
.word IMAGE_FILE_MACHINE_I386 # Machine (i386)
#endif
.word 3 # NumberOfSections
.long 0 # TimeDateStamp
.long 0 # PointerToSymbolTable
.long 0 # NumberOfSymbols
.word section_table - optional_header # SizeOfOptionalHeader
#ifdef __x86_64__
.word IMAGE_FILE_DEBUG_STRIPPED \
| IMAGE_FILE_LOCAL_SYMS_STRIPPED \
| IMAGE_FILE_LINE_NUMS_STRIPPED \
| IMAGE_FILE_EXECUTABLE_IMAGE # Characteristics
#else
.word IMAGE_FILE_32BIT_MACHINE \
| IMAGE_FILE_DEBUG_STRIPPED \
| IMAGE_FILE_LOCAL_SYMS_STRIPPED \
| IMAGE_FILE_LINE_NUMS_STRIPPED \
| IMAGE_FILE_EXECUTABLE_IMAGE # Characteristics.
#endif
optional_header:
#ifdef __x86_64__
.word IMAGE_NT_OPTIONAL_HDR64_MAGIC # PE32+ format
#else
.word IMAGE_NT_OPTIONAL_HDR32_MAGIC # PE32 format
#endif
.byte 0x02 # MajorLinkerVersion
.byte 0x14 # MinorLinkerVersion
.long _virt_text_size # SizeOfCode
.long _virt_sbat_size # SizeOfInitializedData
.long 0 # SizeOfUninitializedData
.long _virt_text_start + 0x1e0 # AddressOfEntryPoint
.long _virt_text_start # BaseOfCode
#ifndef __x86_64__
.long _virt_sbat_start # BaseOfData
#endif
extra_header_fields:
#ifdef __x86_64__
.quad IMAGE_BASE # ImageBase
#else
.long IMAGE_BASE # ImageBase
#endif
.long 4096 # SectionAlignment
.long 512 # FileAlignment
.word 0 # MajorOperatingSystemVersion
.word 0 # MinorOperatingSystemVersion
.word 0 # MajorImageVersion
.word 0 # MinorImageVersion
.word 0 # MajorSubsystemVersion
.word 0 # MinorSubsystemVersion
.long 0 # Win32VersionValue
.long _virt_img_size # SizeOfImage
.long _file_head_size # SizeOfHeaders
.long 0 # CheckSum
.word 10 # Subsystem (EFI application)
.word 0 # DllCharacteristics
#ifdef __x86_64__
.quad 0 # SizeOfStackReserve
.quad 0 # SizeOfStackCommit
.quad 0 # SizeOfHeapReserve
.quad 0 # SizeOfHeapCommit
#else
.long 0 # SizeOfStackReserve
.long 0 # SizeOfStackCommit
.long 0 # SizeOfHeapReserve
.long 0 # SizeOfHeapCommit
#endif
.long 0 # LoaderFlags
.long IMAGE_DIRECTORY_ENTRY_DEBUG # NumberOfRvaAndSizes
.long 0 # DataDirectory.Export.VirtualAddress
.long 0 # DataDirectory.Export.Size
.long 0 # DataDirectory.Import.VirtualAddress
.long 0 # DataDirectory.Import.Size
.long 0 # DataDirectory.Resource.VirtualAddress
.long 0 # DataDirectory.Resource.Size
.long 0 # DataDirectory.Exception.VirtualAddress
.long 0 # DataDirectory.Exception.Size
.long 0 # DataDirectory.Certs.VirtualAddress
.long 0 # DataDirectory.Certs.Size
.long _virt_reloc_start # DataDirectory.BaseReloc.VirtualAddress
.long _real_reloc_size # DataDirectory.BaseReloc.Size
# Section table
section_table:
.ascii ".text"
.byte 0
.byte 0
.byte 0
.long _virt_text_size # VirtualSize
.long _virt_text_start # VirtualAddress
.long _file_text_size # SizeOfRawData
.long _file_text_start # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_MEM_READ \
| IMAGE_SCN_MEM_WRITE \
| IMAGE_SCN_MEM_EXECUTE \
| IMAGE_SCN_CNT_CODE # Characteristics (section flags)
.ascii ".reloc"
.byte 0
.byte 0
.long _virt_reloc_size # VirtualSize
.long _virt_reloc_start # VirtualAddress
.long _file_reloc_size # SizeOfRawData
.long _file_reloc_start # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_MEM_READ \
| IMAGE_SCN_CNT_INITIALIZED_DATA # Characteristics (section flags)
.ascii ".sbat"
.byte 0
.byte 0
.byte 0
.long _virt_sbat_size # VirtualSize
.long _virt_sbat_start # VirtualAddress
.long _file_sbat_size # SizeOfRawData
.long _file_sbat_start # PointerToRawData
.long 0 # PointerToRelocations
.long 0 # PointerToLineNumbers
.word 0 # NumberOfRelocations
.word 0 # NumberOfLineNumbers
.long IMAGE_SCN_MEM_READ \
| IMAGE_SCN_CNT_INITIALIZED_DATA # Characteristics (section flags)
# Emulate the Linux boot header, to allow loading by intermediate boot loaders.
.org 497
setup_sects:
.byte SETUP_SECS
root_flags:
.word 0
sys_size:
.long _sys_size
ram_size:
.word 0
vid_mode:
.word 0
root_dev:
.word 0
boot_flag:
.word 0xAA55
.org 512
.section ".reloc"
.long 0 // Page RVA
.long 10 // Block Size (2*4+2)
.word (IMAGE_REL_BASED_ABSOLUTE << 12) + 0 // reloc 0 -> 0
.section ".sbat", "a", @progbits
.incbin "../boot/sbat.csv"