162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * header.S 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Based on bootsect.S and setup.S 862306a36Sopenharmony_ci * modified by more people than can be counted 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Rewritten as a common file by H. Peter Anvin (Apr 2007) 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment 1362306a36Sopenharmony_ci * addresses must be multiplied by 16 to obtain their respective linear 1462306a36Sopenharmony_ci * addresses. To avoid confusion, linear addresses are written using leading 1562306a36Sopenharmony_ci * hex while segment addresses are written as segment:offset. 1662306a36Sopenharmony_ci * 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci#include <linux/pe.h> 1962306a36Sopenharmony_ci#include <asm/segment.h> 2062306a36Sopenharmony_ci#include <asm/boot.h> 2162306a36Sopenharmony_ci#include <asm/page_types.h> 2262306a36Sopenharmony_ci#include <asm/setup.h> 2362306a36Sopenharmony_ci#include <asm/bootparam.h> 2462306a36Sopenharmony_ci#include "boot.h" 2562306a36Sopenharmony_ci#include "voffset.h" 2662306a36Sopenharmony_ci#include "zoffset.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciBOOTSEG = 0x07C0 /* original address of boot-sector */ 2962306a36Sopenharmony_ciSYSSEG = 0x1000 /* historical load address >> 4 */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#ifndef SVGA_MODE 3262306a36Sopenharmony_ci#define SVGA_MODE ASK_VGA 3362306a36Sopenharmony_ci#endif 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#ifndef ROOT_RDONLY 3662306a36Sopenharmony_ci#define ROOT_RDONLY 1 3762306a36Sopenharmony_ci#endif 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci .set salign, 0x1000 4062306a36Sopenharmony_ci .set falign, 0x200 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci .code16 4362306a36Sopenharmony_ci .section ".bstext", "ax" 4462306a36Sopenharmony_ci#ifdef CONFIG_EFI_STUB 4562306a36Sopenharmony_ci # "MZ", MS-DOS header 4662306a36Sopenharmony_ci .word MZ_MAGIC 4762306a36Sopenharmony_ci .org 0x38 4862306a36Sopenharmony_ci # 4962306a36Sopenharmony_ci # Offset to the PE header. 5062306a36Sopenharmony_ci # 5162306a36Sopenharmony_ci .long LINUX_PE_MAGIC 5262306a36Sopenharmony_ci .long pe_header 5362306a36Sopenharmony_cipe_header: 5462306a36Sopenharmony_ci .long PE_MAGIC 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cicoff_header: 5762306a36Sopenharmony_ci#ifdef CONFIG_X86_32 5862306a36Sopenharmony_ci .set image_file_add_flags, IMAGE_FILE_32BIT_MACHINE 5962306a36Sopenharmony_ci .set pe_opt_magic, PE_OPT_MAGIC_PE32 6062306a36Sopenharmony_ci .word IMAGE_FILE_MACHINE_I386 6162306a36Sopenharmony_ci#else 6262306a36Sopenharmony_ci .set image_file_add_flags, 0 6362306a36Sopenharmony_ci .set pe_opt_magic, PE_OPT_MAGIC_PE32PLUS 6462306a36Sopenharmony_ci .word IMAGE_FILE_MACHINE_AMD64 6562306a36Sopenharmony_ci#endif 6662306a36Sopenharmony_ci .word section_count # nr_sections 6762306a36Sopenharmony_ci .long 0 # TimeDateStamp 6862306a36Sopenharmony_ci .long 0 # PointerToSymbolTable 6962306a36Sopenharmony_ci .long 1 # NumberOfSymbols 7062306a36Sopenharmony_ci .word section_table - optional_header # SizeOfOptionalHeader 7162306a36Sopenharmony_ci .word IMAGE_FILE_EXECUTABLE_IMAGE | \ 7262306a36Sopenharmony_ci image_file_add_flags | \ 7362306a36Sopenharmony_ci IMAGE_FILE_DEBUG_STRIPPED | \ 7462306a36Sopenharmony_ci IMAGE_FILE_LINE_NUMS_STRIPPED # Characteristics 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cioptional_header: 7762306a36Sopenharmony_ci .word pe_opt_magic 7862306a36Sopenharmony_ci .byte 0x02 # MajorLinkerVersion 7962306a36Sopenharmony_ci .byte 0x14 # MinorLinkerVersion 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci .long ZO__data # SizeOfCode 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci .long ZO__end - ZO__data # SizeOfInitializedData 8462306a36Sopenharmony_ci .long 0 # SizeOfUninitializedData 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci .long setup_size + ZO_efi_pe_entry # AddressOfEntryPoint 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci .long setup_size # BaseOfCode 8962306a36Sopenharmony_ci#ifdef CONFIG_X86_32 9062306a36Sopenharmony_ci .long 0 # data 9162306a36Sopenharmony_ci#endif 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ciextra_header_fields: 9462306a36Sopenharmony_ci#ifdef CONFIG_X86_32 9562306a36Sopenharmony_ci .long 0 # ImageBase 9662306a36Sopenharmony_ci#else 9762306a36Sopenharmony_ci .quad 0 # ImageBase 9862306a36Sopenharmony_ci#endif 9962306a36Sopenharmony_ci .long salign # SectionAlignment 10062306a36Sopenharmony_ci .long falign # FileAlignment 10162306a36Sopenharmony_ci .word 0 # MajorOperatingSystemVersion 10262306a36Sopenharmony_ci .word 0 # MinorOperatingSystemVersion 10362306a36Sopenharmony_ci .word LINUX_EFISTUB_MAJOR_VERSION # MajorImageVersion 10462306a36Sopenharmony_ci .word LINUX_EFISTUB_MINOR_VERSION # MinorImageVersion 10562306a36Sopenharmony_ci .word 0 # MajorSubsystemVersion 10662306a36Sopenharmony_ci .word 0 # MinorSubsystemVersion 10762306a36Sopenharmony_ci .long 0 # Win32VersionValue 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci .long setup_size + ZO__end # SizeOfImage 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci .long salign # SizeOfHeaders 11262306a36Sopenharmony_ci .long 0 # CheckSum 11362306a36Sopenharmony_ci .word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application) 11462306a36Sopenharmony_ci#ifdef CONFIG_EFI_DXE_MEM_ATTRIBUTES 11562306a36Sopenharmony_ci .word IMAGE_DLL_CHARACTERISTICS_NX_COMPAT # DllCharacteristics 11662306a36Sopenharmony_ci#else 11762306a36Sopenharmony_ci .word 0 # DllCharacteristics 11862306a36Sopenharmony_ci#endif 11962306a36Sopenharmony_ci#ifdef CONFIG_X86_32 12062306a36Sopenharmony_ci .long 0 # SizeOfStackReserve 12162306a36Sopenharmony_ci .long 0 # SizeOfStackCommit 12262306a36Sopenharmony_ci .long 0 # SizeOfHeapReserve 12362306a36Sopenharmony_ci .long 0 # SizeOfHeapCommit 12462306a36Sopenharmony_ci#else 12562306a36Sopenharmony_ci .quad 0 # SizeOfStackReserve 12662306a36Sopenharmony_ci .quad 0 # SizeOfStackCommit 12762306a36Sopenharmony_ci .quad 0 # SizeOfHeapReserve 12862306a36Sopenharmony_ci .quad 0 # SizeOfHeapCommit 12962306a36Sopenharmony_ci#endif 13062306a36Sopenharmony_ci .long 0 # LoaderFlags 13162306a36Sopenharmony_ci .long (section_table - .) / 8 # NumberOfRvaAndSizes 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci .quad 0 # ExportTable 13462306a36Sopenharmony_ci .quad 0 # ImportTable 13562306a36Sopenharmony_ci .quad 0 # ResourceTable 13662306a36Sopenharmony_ci .quad 0 # ExceptionTable 13762306a36Sopenharmony_ci .quad 0 # CertificationTable 13862306a36Sopenharmony_ci .quad 0 # BaseRelocationTable 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci # Section table 14162306a36Sopenharmony_cisection_table: 14262306a36Sopenharmony_ci .ascii ".setup" 14362306a36Sopenharmony_ci .byte 0 14462306a36Sopenharmony_ci .byte 0 14562306a36Sopenharmony_ci .long pecompat_fstart - salign # VirtualSize 14662306a36Sopenharmony_ci .long salign # VirtualAddress 14762306a36Sopenharmony_ci .long pecompat_fstart - salign # SizeOfRawData 14862306a36Sopenharmony_ci .long salign # PointerToRawData 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci .long 0, 0, 0 15162306a36Sopenharmony_ci .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ 15262306a36Sopenharmony_ci IMAGE_SCN_MEM_READ | \ 15362306a36Sopenharmony_ci IMAGE_SCN_MEM_DISCARDABLE # Characteristics 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci#ifdef CONFIG_EFI_MIXED 15662306a36Sopenharmony_ci .asciz ".compat" 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci .long pecompat_fsize # VirtualSize 15962306a36Sopenharmony_ci .long pecompat_fstart # VirtualAddress 16062306a36Sopenharmony_ci .long pecompat_fsize # SizeOfRawData 16162306a36Sopenharmony_ci .long pecompat_fstart # PointerToRawData 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci .long 0, 0, 0 16462306a36Sopenharmony_ci .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ 16562306a36Sopenharmony_ci IMAGE_SCN_MEM_READ | \ 16662306a36Sopenharmony_ci IMAGE_SCN_MEM_DISCARDABLE # Characteristics 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* 16962306a36Sopenharmony_ci * Put the IA-32 machine type and the associated entry point address in 17062306a36Sopenharmony_ci * the .compat section, so loaders can figure out which other execution 17162306a36Sopenharmony_ci * modes this image supports. 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_ci .pushsection ".pecompat", "a", @progbits 17462306a36Sopenharmony_ci .balign salign 17562306a36Sopenharmony_ci .globl pecompat_fstart 17662306a36Sopenharmony_cipecompat_fstart: 17762306a36Sopenharmony_ci .byte 0x1 # Version 17862306a36Sopenharmony_ci .byte 8 # Size 17962306a36Sopenharmony_ci .word IMAGE_FILE_MACHINE_I386 # PE machine type 18062306a36Sopenharmony_ci .long setup_size + ZO_efi32_pe_entry # Entrypoint 18162306a36Sopenharmony_ci .byte 0x0 # Sentinel 18262306a36Sopenharmony_ci .popsection 18362306a36Sopenharmony_ci#else 18462306a36Sopenharmony_ci .set pecompat_fstart, setup_size 18562306a36Sopenharmony_ci#endif 18662306a36Sopenharmony_ci .ascii ".text" 18762306a36Sopenharmony_ci .byte 0 18862306a36Sopenharmony_ci .byte 0 18962306a36Sopenharmony_ci .byte 0 19062306a36Sopenharmony_ci .long ZO__data 19162306a36Sopenharmony_ci .long setup_size 19262306a36Sopenharmony_ci .long ZO__data # Size of initialized data 19362306a36Sopenharmony_ci # on disk 19462306a36Sopenharmony_ci .long setup_size 19562306a36Sopenharmony_ci .long 0 # PointerToRelocations 19662306a36Sopenharmony_ci .long 0 # PointerToLineNumbers 19762306a36Sopenharmony_ci .word 0 # NumberOfRelocations 19862306a36Sopenharmony_ci .word 0 # NumberOfLineNumbers 19962306a36Sopenharmony_ci .long IMAGE_SCN_CNT_CODE | \ 20062306a36Sopenharmony_ci IMAGE_SCN_MEM_READ | \ 20162306a36Sopenharmony_ci IMAGE_SCN_MEM_EXECUTE # Characteristics 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci .ascii ".data\0\0\0" 20462306a36Sopenharmony_ci .long ZO__end - ZO__data # VirtualSize 20562306a36Sopenharmony_ci .long setup_size + ZO__data # VirtualAddress 20662306a36Sopenharmony_ci .long ZO__edata - ZO__data # SizeOfRawData 20762306a36Sopenharmony_ci .long setup_size + ZO__data # PointerToRawData 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci .long 0, 0, 0 21062306a36Sopenharmony_ci .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ 21162306a36Sopenharmony_ci IMAGE_SCN_MEM_READ | \ 21262306a36Sopenharmony_ci IMAGE_SCN_MEM_WRITE # Characteristics 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci .set section_count, (. - section_table) / 40 21562306a36Sopenharmony_ci#endif /* CONFIG_EFI_STUB */ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci # Kernel attributes; used by setup. This is part 1 of the 21862306a36Sopenharmony_ci # header, from the old boot sector. 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci .section ".header", "a" 22162306a36Sopenharmony_ci .globl sentinel 22262306a36Sopenharmony_cisentinel: .byte 0xff, 0xff /* Used to detect broken loaders */ 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci .globl hdr 22562306a36Sopenharmony_cihdr: 22662306a36Sopenharmony_ci .byte setup_sects - 1 22762306a36Sopenharmony_ciroot_flags: .word ROOT_RDONLY 22862306a36Sopenharmony_cisyssize: .long ZO__edata / 16 22962306a36Sopenharmony_ciram_size: .word 0 /* Obsolete */ 23062306a36Sopenharmony_civid_mode: .word SVGA_MODE 23162306a36Sopenharmony_ciroot_dev: .word 0 /* Default to major/minor 0/0 */ 23262306a36Sopenharmony_ciboot_flag: .word 0xAA55 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci # offset 512, entry point 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci .globl _start 23762306a36Sopenharmony_ci_start: 23862306a36Sopenharmony_ci # Explicitly enter this as bytes, or the assembler 23962306a36Sopenharmony_ci # tries to generate a 3-byte jump here, which causes 24062306a36Sopenharmony_ci # everything else to push off to the wrong offset. 24162306a36Sopenharmony_ci .byte 0xeb # short (2-byte) jump 24262306a36Sopenharmony_ci .byte start_of_setup-1f 24362306a36Sopenharmony_ci1: 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci # Part 2 of the header, from the old setup.S 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci .ascii "HdrS" # header signature 24862306a36Sopenharmony_ci .word 0x020f # header version number (>= 0x0105) 24962306a36Sopenharmony_ci # or else old loadlin-1.5 will fail) 25062306a36Sopenharmony_ci .globl realmode_swtch 25162306a36Sopenharmony_cirealmode_swtch: .word 0, 0 # default_switch, SETUPSEG 25262306a36Sopenharmony_cistart_sys_seg: .word SYSSEG # obsolete and meaningless, but just 25362306a36Sopenharmony_ci # in case something decided to "use" it 25462306a36Sopenharmony_ci .word kernel_version-512 # pointing to kernel version string 25562306a36Sopenharmony_ci # above section of header is compatible 25662306a36Sopenharmony_ci # with loadlin-1.5 (header v1.5). Don't 25762306a36Sopenharmony_ci # change it. 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_citype_of_loader: .byte 0 # 0 means ancient bootloader, newer 26062306a36Sopenharmony_ci # bootloaders know to change this. 26162306a36Sopenharmony_ci # See Documentation/arch/x86/boot.rst for 26262306a36Sopenharmony_ci # assigned ids 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci# flags, unused bits must be zero (RFU) bit within loadflags 26562306a36Sopenharmony_ciloadflags: 26662306a36Sopenharmony_ci .byte LOADED_HIGH # The kernel is to be loaded high 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cisetup_move_size: .word 0x8000 # size to move, when setup is not 26962306a36Sopenharmony_ci # loaded at 0x90000. We will move setup 27062306a36Sopenharmony_ci # to 0x90000 then just before jumping 27162306a36Sopenharmony_ci # into the kernel. However, only the 27262306a36Sopenharmony_ci # loader knows how much data behind 27362306a36Sopenharmony_ci # us also needs to be loaded. 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_cicode32_start: # here loaders can put a different 27662306a36Sopenharmony_ci # start address for 32-bit code. 27762306a36Sopenharmony_ci .long 0x100000 # 0x100000 = default for big kernel 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ciramdisk_image: .long 0 # address of loaded ramdisk image 28062306a36Sopenharmony_ci # Here the loader puts the 32-bit 28162306a36Sopenharmony_ci # address where it loaded the image. 28262306a36Sopenharmony_ci # This only will be read by the kernel. 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ciramdisk_size: .long 0 # its size in bytes 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_cibootsect_kludge: 28762306a36Sopenharmony_ci .long 0 # obsolete 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ciheap_end_ptr: .word _end+STACK_SIZE-512 29062306a36Sopenharmony_ci # (Header version 0x0201 or later) 29162306a36Sopenharmony_ci # space from here (exclusive) down to 29262306a36Sopenharmony_ci # end of setup code can be used by setup 29362306a36Sopenharmony_ci # for local heap purposes. 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ciext_loader_ver: 29662306a36Sopenharmony_ci .byte 0 # Extended boot loader version 29762306a36Sopenharmony_ciext_loader_type: 29862306a36Sopenharmony_ci .byte 0 # Extended boot loader type 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_cicmd_line_ptr: .long 0 # (Header version 0x0202 or later) 30162306a36Sopenharmony_ci # If nonzero, a 32-bit pointer 30262306a36Sopenharmony_ci # to the kernel command line. 30362306a36Sopenharmony_ci # The command line should be 30462306a36Sopenharmony_ci # located between the start of 30562306a36Sopenharmony_ci # setup and the end of low 30662306a36Sopenharmony_ci # memory (0xa0000), or it may 30762306a36Sopenharmony_ci # get overwritten before it 30862306a36Sopenharmony_ci # gets read. If this field is 30962306a36Sopenharmony_ci # used, there is no longer 31062306a36Sopenharmony_ci # anything magical about the 31162306a36Sopenharmony_ci # 0x90000 segment; the setup 31262306a36Sopenharmony_ci # can be located anywhere in 31362306a36Sopenharmony_ci # low memory 0x10000 or higher. 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ciinitrd_addr_max: .long 0x7fffffff 31662306a36Sopenharmony_ci # (Header version 0x0203 or later) 31762306a36Sopenharmony_ci # The highest safe address for 31862306a36Sopenharmony_ci # the contents of an initrd 31962306a36Sopenharmony_ci # The current kernel allows up to 4 GB, 32062306a36Sopenharmony_ci # but leave it at 2 GB to avoid 32162306a36Sopenharmony_ci # possible bootloader bugs. 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_cikernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment 32462306a36Sopenharmony_ci #required for protected mode 32562306a36Sopenharmony_ci #kernel 32662306a36Sopenharmony_ci#ifdef CONFIG_RELOCATABLE 32762306a36Sopenharmony_cirelocatable_kernel: .byte 1 32862306a36Sopenharmony_ci#else 32962306a36Sopenharmony_cirelocatable_kernel: .byte 0 33062306a36Sopenharmony_ci#endif 33162306a36Sopenharmony_cimin_alignment: .byte MIN_KERNEL_ALIGN_LG2 # minimum alignment 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_cixloadflags: 33462306a36Sopenharmony_ci#ifdef CONFIG_X86_64 33562306a36Sopenharmony_ci# define XLF0 XLF_KERNEL_64 /* 64-bit kernel */ 33662306a36Sopenharmony_ci#else 33762306a36Sopenharmony_ci# define XLF0 0 33862306a36Sopenharmony_ci#endif 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64) 34162306a36Sopenharmony_ci /* kernel/boot_param/ramdisk could be loaded above 4g */ 34262306a36Sopenharmony_ci# define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G 34362306a36Sopenharmony_ci#else 34462306a36Sopenharmony_ci# define XLF1 0 34562306a36Sopenharmony_ci#endif 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci#ifdef CONFIG_EFI_HANDOVER_PROTOCOL 34862306a36Sopenharmony_ci# ifdef CONFIG_EFI_MIXED 34962306a36Sopenharmony_ci# define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64) 35062306a36Sopenharmony_ci# else 35162306a36Sopenharmony_ci# ifdef CONFIG_X86_64 35262306a36Sopenharmony_ci# define XLF23 XLF_EFI_HANDOVER_64 /* 64-bit EFI handover ok */ 35362306a36Sopenharmony_ci# else 35462306a36Sopenharmony_ci# define XLF23 XLF_EFI_HANDOVER_32 /* 32-bit EFI handover ok */ 35562306a36Sopenharmony_ci# endif 35662306a36Sopenharmony_ci# endif 35762306a36Sopenharmony_ci#else 35862306a36Sopenharmony_ci# define XLF23 0 35962306a36Sopenharmony_ci#endif 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci#if defined(CONFIG_X86_64) && defined(CONFIG_EFI) && defined(CONFIG_KEXEC_CORE) 36262306a36Sopenharmony_ci# define XLF4 XLF_EFI_KEXEC 36362306a36Sopenharmony_ci#else 36462306a36Sopenharmony_ci# define XLF4 0 36562306a36Sopenharmony_ci#endif 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci#ifdef CONFIG_X86_64 36862306a36Sopenharmony_ci#ifdef CONFIG_X86_5LEVEL 36962306a36Sopenharmony_ci#define XLF56 (XLF_5LEVEL|XLF_5LEVEL_ENABLED) 37062306a36Sopenharmony_ci#else 37162306a36Sopenharmony_ci#define XLF56 XLF_5LEVEL 37262306a36Sopenharmony_ci#endif 37362306a36Sopenharmony_ci#else 37462306a36Sopenharmony_ci#define XLF56 0 37562306a36Sopenharmony_ci#endif 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci .word XLF0 | XLF1 | XLF23 | XLF4 | XLF56 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_cicmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, 38062306a36Sopenharmony_ci #added with boot protocol 38162306a36Sopenharmony_ci #version 2.06 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cihardware_subarch: .long 0 # subarchitecture, added with 2.07 38462306a36Sopenharmony_ci # default to 0 for normal x86 PC 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_cihardware_subarch_data: .quad 0 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cipayload_offset: .long ZO_input_data 38962306a36Sopenharmony_cipayload_length: .long ZO_z_input_len 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cisetup_data: .quad 0 # 64-bit physical pointer to 39262306a36Sopenharmony_ci # single linked list of 39362306a36Sopenharmony_ci # struct setup_data 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cipref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci# 39862306a36Sopenharmony_ci# Getting to provably safe in-place decompression is hard. Worst case 39962306a36Sopenharmony_ci# behaviours need to be analyzed. Here let's take the decompression of 40062306a36Sopenharmony_ci# a gzip-compressed kernel as example, to illustrate it: 40162306a36Sopenharmony_ci# 40262306a36Sopenharmony_ci# The file layout of gzip compressed kernel is: 40362306a36Sopenharmony_ci# 40462306a36Sopenharmony_ci# magic[2] 40562306a36Sopenharmony_ci# method[1] 40662306a36Sopenharmony_ci# flags[1] 40762306a36Sopenharmony_ci# timestamp[4] 40862306a36Sopenharmony_ci# extraflags[1] 40962306a36Sopenharmony_ci# os[1] 41062306a36Sopenharmony_ci# compressed data blocks[N] 41162306a36Sopenharmony_ci# crc[4] orig_len[4] 41262306a36Sopenharmony_ci# 41362306a36Sopenharmony_ci# ... resulting in +18 bytes overhead of uncompressed data. 41462306a36Sopenharmony_ci# 41562306a36Sopenharmony_ci# (For more information, please refer to RFC 1951 and RFC 1952.) 41662306a36Sopenharmony_ci# 41762306a36Sopenharmony_ci# Files divided into blocks 41862306a36Sopenharmony_ci# 1 bit (last block flag) 41962306a36Sopenharmony_ci# 2 bits (block type) 42062306a36Sopenharmony_ci# 42162306a36Sopenharmony_ci# 1 block occurs every 32K -1 bytes or when there 50% compression 42262306a36Sopenharmony_ci# has been achieved. The smallest block type encoding is always used. 42362306a36Sopenharmony_ci# 42462306a36Sopenharmony_ci# stored: 42562306a36Sopenharmony_ci# 32 bits length in bytes. 42662306a36Sopenharmony_ci# 42762306a36Sopenharmony_ci# fixed: 42862306a36Sopenharmony_ci# magic fixed tree. 42962306a36Sopenharmony_ci# symbols. 43062306a36Sopenharmony_ci# 43162306a36Sopenharmony_ci# dynamic: 43262306a36Sopenharmony_ci# dynamic tree encoding. 43362306a36Sopenharmony_ci# symbols. 43462306a36Sopenharmony_ci# 43562306a36Sopenharmony_ci# 43662306a36Sopenharmony_ci# The buffer for decompression in place is the length of the uncompressed 43762306a36Sopenharmony_ci# data, plus a small amount extra to keep the algorithm safe. The 43862306a36Sopenharmony_ci# compressed data is placed at the end of the buffer. The output pointer 43962306a36Sopenharmony_ci# is placed at the start of the buffer and the input pointer is placed 44062306a36Sopenharmony_ci# where the compressed data starts. Problems will occur when the output 44162306a36Sopenharmony_ci# pointer overruns the input pointer. 44262306a36Sopenharmony_ci# 44362306a36Sopenharmony_ci# The output pointer can only overrun the input pointer if the input 44462306a36Sopenharmony_ci# pointer is moving faster than the output pointer. A condition only 44562306a36Sopenharmony_ci# triggered by data whose compressed form is larger than the uncompressed 44662306a36Sopenharmony_ci# form. 44762306a36Sopenharmony_ci# 44862306a36Sopenharmony_ci# The worst case at the block level is a growth of the compressed data 44962306a36Sopenharmony_ci# of 5 bytes per 32767 bytes. 45062306a36Sopenharmony_ci# 45162306a36Sopenharmony_ci# The worst case internal to a compressed block is very hard to figure. 45262306a36Sopenharmony_ci# The worst case can at least be bounded by having one bit that represents 45362306a36Sopenharmony_ci# 32764 bytes and then all of the rest of the bytes representing the very 45462306a36Sopenharmony_ci# very last byte. 45562306a36Sopenharmony_ci# 45662306a36Sopenharmony_ci# All of which is enough to compute an amount of extra data that is required 45762306a36Sopenharmony_ci# to be safe. To avoid problems at the block level allocating 5 extra bytes 45862306a36Sopenharmony_ci# per 32767 bytes of data is sufficient. To avoid problems internal to a 45962306a36Sopenharmony_ci# block adding an extra 32767 bytes (the worst case uncompressed block size) 46062306a36Sopenharmony_ci# is sufficient, to ensure that in the worst case the decompressed data for 46162306a36Sopenharmony_ci# block will stop the byte before the compressed data for a block begins. 46262306a36Sopenharmony_ci# To avoid problems with the compressed data's meta information an extra 18 46362306a36Sopenharmony_ci# bytes are needed. Leading to the formula: 46462306a36Sopenharmony_ci# 46562306a36Sopenharmony_ci# extra_bytes = (uncompressed_size >> 12) + 32768 + 18 46662306a36Sopenharmony_ci# 46762306a36Sopenharmony_ci# Adding 8 bytes per 32K is a bit excessive but much easier to calculate. 46862306a36Sopenharmony_ci# Adding 32768 instead of 32767 just makes for round numbers. 46962306a36Sopenharmony_ci# 47062306a36Sopenharmony_ci# Above analysis is for decompressing gzip compressed kernel only. Up to 47162306a36Sopenharmony_ci# now 6 different decompressor are supported all together. And among them 47262306a36Sopenharmony_ci# xz stores data in chunks and has maximum chunk of 64K. Hence safety 47362306a36Sopenharmony_ci# margin should be updated to cover all decompressors so that we don't 47462306a36Sopenharmony_ci# need to deal with each of them separately. Please check 47562306a36Sopenharmony_ci# the description in lib/decompressor_xxx.c for specific information. 47662306a36Sopenharmony_ci# 47762306a36Sopenharmony_ci# extra_bytes = (uncompressed_size >> 12) + 65536 + 128 47862306a36Sopenharmony_ci# 47962306a36Sopenharmony_ci# LZ4 is even worse: data that cannot be further compressed grows by 0.4%, 48062306a36Sopenharmony_ci# or one byte per 256 bytes. OTOH, we can safely get rid of the +128 as 48162306a36Sopenharmony_ci# the size-dependent part now grows so fast. 48262306a36Sopenharmony_ci# 48362306a36Sopenharmony_ci# extra_bytes = (uncompressed_size >> 8) + 65536 48462306a36Sopenharmony_ci# 48562306a36Sopenharmony_ci# ZSTD compressed data grows by at most 3 bytes per 128K, and only has a 22 48662306a36Sopenharmony_ci# byte fixed overhead but has a maximum block size of 128K, so it needs a 48762306a36Sopenharmony_ci# larger margin. 48862306a36Sopenharmony_ci# 48962306a36Sopenharmony_ci# extra_bytes = (uncompressed_size >> 8) + 131072 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 131072) 49262306a36Sopenharmony_ci#if ZO_z_output_len > ZO_z_input_len 49362306a36Sopenharmony_ci# define ZO_z_extract_offset (ZO_z_output_len + ZO_z_extra_bytes - \ 49462306a36Sopenharmony_ci ZO_z_input_len) 49562306a36Sopenharmony_ci#else 49662306a36Sopenharmony_ci# define ZO_z_extract_offset ZO_z_extra_bytes 49762306a36Sopenharmony_ci#endif 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci/* 50062306a36Sopenharmony_ci * The extract_offset has to be bigger than ZO head section. Otherwise when 50162306a36Sopenharmony_ci * the head code is running to move ZO to the end of the buffer, it will 50262306a36Sopenharmony_ci * overwrite the head code itself. 50362306a36Sopenharmony_ci */ 50462306a36Sopenharmony_ci#if (ZO__ehead - ZO_startup_32) > ZO_z_extract_offset 50562306a36Sopenharmony_ci# define ZO_z_min_extract_offset ((ZO__ehead - ZO_startup_32 + 4095) & ~4095) 50662306a36Sopenharmony_ci#else 50762306a36Sopenharmony_ci# define ZO_z_min_extract_offset ((ZO_z_extract_offset + 4095) & ~4095) 50862306a36Sopenharmony_ci#endif 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_min_extract_offset) 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci#define VO_INIT_SIZE (VO__end - VO__text) 51362306a36Sopenharmony_ci#if ZO_INIT_SIZE > VO_INIT_SIZE 51462306a36Sopenharmony_ci# define INIT_SIZE ZO_INIT_SIZE 51562306a36Sopenharmony_ci#else 51662306a36Sopenharmony_ci# define INIT_SIZE VO_INIT_SIZE 51762306a36Sopenharmony_ci#endif 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci .macro __handover_offset 52062306a36Sopenharmony_ci#ifndef CONFIG_EFI_HANDOVER_PROTOCOL 52162306a36Sopenharmony_ci .long 0 52262306a36Sopenharmony_ci#elif !defined(CONFIG_X86_64) 52362306a36Sopenharmony_ci .long ZO_efi32_stub_entry 52462306a36Sopenharmony_ci#else 52562306a36Sopenharmony_ci /* Yes, this is really how we defined it :( */ 52662306a36Sopenharmony_ci .long ZO_efi64_stub_entry - 0x200 52762306a36Sopenharmony_ci#ifdef CONFIG_EFI_MIXED 52862306a36Sopenharmony_ci .if ZO_efi32_stub_entry != ZO_efi64_stub_entry - 0x200 52962306a36Sopenharmony_ci .error "32-bit and 64-bit EFI entry points do not match" 53062306a36Sopenharmony_ci .endif 53162306a36Sopenharmony_ci#endif 53262306a36Sopenharmony_ci#endif 53362306a36Sopenharmony_ci .endm 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ciinit_size: .long INIT_SIZE # kernel initialization size 53662306a36Sopenharmony_cihandover_offset: __handover_offset 53762306a36Sopenharmony_cikernel_info_offset: .long ZO_kernel_info 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci# End of setup header ##################################################### 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci .section ".entrytext", "ax" 54262306a36Sopenharmony_cistart_of_setup: 54362306a36Sopenharmony_ci# Force %es = %ds 54462306a36Sopenharmony_ci movw %ds, %ax 54562306a36Sopenharmony_ci movw %ax, %es 54662306a36Sopenharmony_ci cld 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds, 54962306a36Sopenharmony_ci# which happened to work by accident for the old code. Recalculate the stack 55062306a36Sopenharmony_ci# pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the 55162306a36Sopenharmony_ci# stack behind its own code, so we can't blindly put it directly past the heap. 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci movw %ss, %dx 55462306a36Sopenharmony_ci cmpw %ax, %dx # %ds == %ss? 55562306a36Sopenharmony_ci movw %sp, %dx 55662306a36Sopenharmony_ci je 2f # -> assume %sp is reasonably set 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci # Invalid %ss, make up a new stack 55962306a36Sopenharmony_ci movw $_end, %dx 56062306a36Sopenharmony_ci testb $CAN_USE_HEAP, loadflags 56162306a36Sopenharmony_ci jz 1f 56262306a36Sopenharmony_ci movw heap_end_ptr, %dx 56362306a36Sopenharmony_ci1: addw $STACK_SIZE, %dx 56462306a36Sopenharmony_ci jnc 2f 56562306a36Sopenharmony_ci xorw %dx, %dx # Prevent wraparound 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci2: # Now %dx should point to the end of our stack space 56862306a36Sopenharmony_ci andw $~3, %dx # dword align (might as well...) 56962306a36Sopenharmony_ci jnz 3f 57062306a36Sopenharmony_ci movw $0xfffc, %dx # Make sure we're not zero 57162306a36Sopenharmony_ci3: movw %ax, %ss 57262306a36Sopenharmony_ci movzwl %dx, %esp # Clear upper half of %esp 57362306a36Sopenharmony_ci sti # Now we should have a working stack 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci# We will have entered with %cs = %ds+0x20, normalize %cs so 57662306a36Sopenharmony_ci# it is on par with the other segments. 57762306a36Sopenharmony_ci pushw %ds 57862306a36Sopenharmony_ci pushw $6f 57962306a36Sopenharmony_ci lretw 58062306a36Sopenharmony_ci6: 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci# Check signature at end of setup 58362306a36Sopenharmony_ci cmpl $0x5a5aaa55, setup_sig 58462306a36Sopenharmony_ci jne setup_bad 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci# Zero the bss 58762306a36Sopenharmony_ci movw $__bss_start, %di 58862306a36Sopenharmony_ci movw $_end+3, %cx 58962306a36Sopenharmony_ci xorl %eax, %eax 59062306a36Sopenharmony_ci subw %di, %cx 59162306a36Sopenharmony_ci shrw $2, %cx 59262306a36Sopenharmony_ci rep; stosl 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci# Jump to C code (should not return) 59562306a36Sopenharmony_ci calll main 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci# Setup corrupt somehow... 59862306a36Sopenharmony_cisetup_bad: 59962306a36Sopenharmony_ci movl $setup_corrupt, %eax 60062306a36Sopenharmony_ci calll puts 60162306a36Sopenharmony_ci # Fall through... 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci .globl die 60462306a36Sopenharmony_ci .type die, @function 60562306a36Sopenharmony_cidie: 60662306a36Sopenharmony_ci hlt 60762306a36Sopenharmony_ci jmp die 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci .size die, .-die 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci .section ".initdata", "a" 61262306a36Sopenharmony_cisetup_corrupt: 61362306a36Sopenharmony_ci .byte 7 61462306a36Sopenharmony_ci .string "No setup signature found...\n" 615