1*4882a593Smuzhiyun/* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun/* 3*4882a593Smuzhiyun * header.S 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright (C) 1991, 1992 Linus Torvalds 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * Based on bootsect.S and setup.S 8*4882a593Smuzhiyun * modified by more people than can be counted 9*4882a593Smuzhiyun * 10*4882a593Smuzhiyun * Rewritten as a common file by H. Peter Anvin (Apr 2007) 11*4882a593Smuzhiyun * 12*4882a593Smuzhiyun * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment 13*4882a593Smuzhiyun * addresses must be multiplied by 16 to obtain their respective linear 14*4882a593Smuzhiyun * addresses. To avoid confusion, linear addresses are written using leading 15*4882a593Smuzhiyun * hex while segment addresses are written as segment:offset. 16*4882a593Smuzhiyun * 17*4882a593Smuzhiyun */ 18*4882a593Smuzhiyun#include <linux/pe.h> 19*4882a593Smuzhiyun#include <asm/segment.h> 20*4882a593Smuzhiyun#include <asm/boot.h> 21*4882a593Smuzhiyun#include <asm/page_types.h> 22*4882a593Smuzhiyun#include <asm/setup.h> 23*4882a593Smuzhiyun#include <asm/bootparam.h> 24*4882a593Smuzhiyun#include "boot.h" 25*4882a593Smuzhiyun#include "voffset.h" 26*4882a593Smuzhiyun#include "zoffset.h" 27*4882a593Smuzhiyun 28*4882a593SmuzhiyunBOOTSEG = 0x07C0 /* original address of boot-sector */ 29*4882a593SmuzhiyunSYSSEG = 0x1000 /* historical load address >> 4 */ 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun#ifndef SVGA_MODE 32*4882a593Smuzhiyun#define SVGA_MODE ASK_VGA 33*4882a593Smuzhiyun#endif 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun#ifndef ROOT_RDONLY 36*4882a593Smuzhiyun#define ROOT_RDONLY 1 37*4882a593Smuzhiyun#endif 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun .code16 40*4882a593Smuzhiyun .section ".bstext", "ax" 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun .global bootsect_start 43*4882a593Smuzhiyunbootsect_start: 44*4882a593Smuzhiyun#ifdef CONFIG_EFI_STUB 45*4882a593Smuzhiyun # "MZ", MS-DOS header 46*4882a593Smuzhiyun .word MZ_MAGIC 47*4882a593Smuzhiyun#endif 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun # Normalize the start address 50*4882a593Smuzhiyun ljmp $BOOTSEG, $start2 51*4882a593Smuzhiyun 52*4882a593Smuzhiyunstart2: 53*4882a593Smuzhiyun movw %cs, %ax 54*4882a593Smuzhiyun movw %ax, %ds 55*4882a593Smuzhiyun movw %ax, %es 56*4882a593Smuzhiyun movw %ax, %ss 57*4882a593Smuzhiyun xorw %sp, %sp 58*4882a593Smuzhiyun sti 59*4882a593Smuzhiyun cld 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun movw $bugger_off_msg, %si 62*4882a593Smuzhiyun 63*4882a593Smuzhiyunmsg_loop: 64*4882a593Smuzhiyun lodsb 65*4882a593Smuzhiyun andb %al, %al 66*4882a593Smuzhiyun jz bs_die 67*4882a593Smuzhiyun movb $0xe, %ah 68*4882a593Smuzhiyun movw $7, %bx 69*4882a593Smuzhiyun int $0x10 70*4882a593Smuzhiyun jmp msg_loop 71*4882a593Smuzhiyun 72*4882a593Smuzhiyunbs_die: 73*4882a593Smuzhiyun # Allow the user to press a key, then reboot 74*4882a593Smuzhiyun xorw %ax, %ax 75*4882a593Smuzhiyun int $0x16 76*4882a593Smuzhiyun int $0x19 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun # int 0x19 should never return. In case it does anyway, 79*4882a593Smuzhiyun # invoke the BIOS reset code... 80*4882a593Smuzhiyun ljmp $0xf000,$0xfff0 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun#ifdef CONFIG_EFI_STUB 83*4882a593Smuzhiyun .org 0x3c 84*4882a593Smuzhiyun # 85*4882a593Smuzhiyun # Offset to the PE header. 86*4882a593Smuzhiyun # 87*4882a593Smuzhiyun .long pe_header 88*4882a593Smuzhiyun#endif /* CONFIG_EFI_STUB */ 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun .section ".bsdata", "a" 91*4882a593Smuzhiyunbugger_off_msg: 92*4882a593Smuzhiyun .ascii "Use a boot loader.\r\n" 93*4882a593Smuzhiyun .ascii "\n" 94*4882a593Smuzhiyun .ascii "Remove disk and press any key to reboot...\r\n" 95*4882a593Smuzhiyun .byte 0 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun#ifdef CONFIG_EFI_STUB 98*4882a593Smuzhiyunpe_header: 99*4882a593Smuzhiyun .long PE_MAGIC 100*4882a593Smuzhiyun 101*4882a593Smuzhiyuncoff_header: 102*4882a593Smuzhiyun#ifdef CONFIG_X86_32 103*4882a593Smuzhiyun .set image_file_add_flags, IMAGE_FILE_32BIT_MACHINE 104*4882a593Smuzhiyun .set pe_opt_magic, PE_OPT_MAGIC_PE32 105*4882a593Smuzhiyun .word IMAGE_FILE_MACHINE_I386 106*4882a593Smuzhiyun#else 107*4882a593Smuzhiyun .set image_file_add_flags, 0 108*4882a593Smuzhiyun .set pe_opt_magic, PE_OPT_MAGIC_PE32PLUS 109*4882a593Smuzhiyun .word IMAGE_FILE_MACHINE_AMD64 110*4882a593Smuzhiyun#endif 111*4882a593Smuzhiyun .word section_count # nr_sections 112*4882a593Smuzhiyun .long 0 # TimeDateStamp 113*4882a593Smuzhiyun .long 0 # PointerToSymbolTable 114*4882a593Smuzhiyun .long 1 # NumberOfSymbols 115*4882a593Smuzhiyun .word section_table - optional_header # SizeOfOptionalHeader 116*4882a593Smuzhiyun .word IMAGE_FILE_EXECUTABLE_IMAGE | \ 117*4882a593Smuzhiyun image_file_add_flags | \ 118*4882a593Smuzhiyun IMAGE_FILE_DEBUG_STRIPPED | \ 119*4882a593Smuzhiyun IMAGE_FILE_LINE_NUMS_STRIPPED # Characteristics 120*4882a593Smuzhiyun 121*4882a593Smuzhiyunoptional_header: 122*4882a593Smuzhiyun .word pe_opt_magic 123*4882a593Smuzhiyun .byte 0x02 # MajorLinkerVersion 124*4882a593Smuzhiyun .byte 0x14 # MinorLinkerVersion 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun # Filled in by build.c 127*4882a593Smuzhiyun .long 0 # SizeOfCode 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun .long 0 # SizeOfInitializedData 130*4882a593Smuzhiyun .long 0 # SizeOfUninitializedData 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun # Filled in by build.c 133*4882a593Smuzhiyun .long 0x0000 # AddressOfEntryPoint 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun .long 0x0200 # BaseOfCode 136*4882a593Smuzhiyun#ifdef CONFIG_X86_32 137*4882a593Smuzhiyun .long 0 # data 138*4882a593Smuzhiyun#endif 139*4882a593Smuzhiyun 140*4882a593Smuzhiyunextra_header_fields: 141*4882a593Smuzhiyun # PE specification requires ImageBase to be 64k aligned 142*4882a593Smuzhiyun .set image_base, (LOAD_PHYSICAL_ADDR + 0xffff) & ~0xffff 143*4882a593Smuzhiyun#ifdef CONFIG_X86_32 144*4882a593Smuzhiyun .long image_base # ImageBase 145*4882a593Smuzhiyun#else 146*4882a593Smuzhiyun .quad image_base # ImageBase 147*4882a593Smuzhiyun#endif 148*4882a593Smuzhiyun .long 0x20 # SectionAlignment 149*4882a593Smuzhiyun .long 0x20 # FileAlignment 150*4882a593Smuzhiyun .word 0 # MajorOperatingSystemVersion 151*4882a593Smuzhiyun .word 0 # MinorOperatingSystemVersion 152*4882a593Smuzhiyun .word LINUX_EFISTUB_MAJOR_VERSION # MajorImageVersion 153*4882a593Smuzhiyun .word LINUX_EFISTUB_MINOR_VERSION # MinorImageVersion 154*4882a593Smuzhiyun .word 0 # MajorSubsystemVersion 155*4882a593Smuzhiyun .word 0 # MinorSubsystemVersion 156*4882a593Smuzhiyun .long 0 # Win32VersionValue 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun # 159*4882a593Smuzhiyun # The size of the bzImage is written in tools/build.c 160*4882a593Smuzhiyun # 161*4882a593Smuzhiyun .long 0 # SizeOfImage 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun .long 0x200 # SizeOfHeaders 164*4882a593Smuzhiyun .long 0 # CheckSum 165*4882a593Smuzhiyun .word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application) 166*4882a593Smuzhiyun .word 0 # DllCharacteristics 167*4882a593Smuzhiyun#ifdef CONFIG_X86_32 168*4882a593Smuzhiyun .long 0 # SizeOfStackReserve 169*4882a593Smuzhiyun .long 0 # SizeOfStackCommit 170*4882a593Smuzhiyun .long 0 # SizeOfHeapReserve 171*4882a593Smuzhiyun .long 0 # SizeOfHeapCommit 172*4882a593Smuzhiyun#else 173*4882a593Smuzhiyun .quad 0 # SizeOfStackReserve 174*4882a593Smuzhiyun .quad 0 # SizeOfStackCommit 175*4882a593Smuzhiyun .quad 0 # SizeOfHeapReserve 176*4882a593Smuzhiyun .quad 0 # SizeOfHeapCommit 177*4882a593Smuzhiyun#endif 178*4882a593Smuzhiyun .long 0 # LoaderFlags 179*4882a593Smuzhiyun .long (section_table - .) / 8 # NumberOfRvaAndSizes 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun .quad 0 # ExportTable 182*4882a593Smuzhiyun .quad 0 # ImportTable 183*4882a593Smuzhiyun .quad 0 # ResourceTable 184*4882a593Smuzhiyun .quad 0 # ExceptionTable 185*4882a593Smuzhiyun .quad 0 # CertificationTable 186*4882a593Smuzhiyun .quad 0 # BaseRelocationTable 187*4882a593Smuzhiyun 188*4882a593Smuzhiyun # Section table 189*4882a593Smuzhiyunsection_table: 190*4882a593Smuzhiyun # 191*4882a593Smuzhiyun # The offset & size fields are filled in by build.c. 192*4882a593Smuzhiyun # 193*4882a593Smuzhiyun .ascii ".setup" 194*4882a593Smuzhiyun .byte 0 195*4882a593Smuzhiyun .byte 0 196*4882a593Smuzhiyun .long 0 197*4882a593Smuzhiyun .long 0x0 # startup_{32,64} 198*4882a593Smuzhiyun .long 0 # Size of initialized data 199*4882a593Smuzhiyun # on disk 200*4882a593Smuzhiyun .long 0x0 # startup_{32,64} 201*4882a593Smuzhiyun .long 0 # PointerToRelocations 202*4882a593Smuzhiyun .long 0 # PointerToLineNumbers 203*4882a593Smuzhiyun .word 0 # NumberOfRelocations 204*4882a593Smuzhiyun .word 0 # NumberOfLineNumbers 205*4882a593Smuzhiyun .long IMAGE_SCN_CNT_CODE | \ 206*4882a593Smuzhiyun IMAGE_SCN_MEM_READ | \ 207*4882a593Smuzhiyun IMAGE_SCN_MEM_EXECUTE | \ 208*4882a593Smuzhiyun IMAGE_SCN_ALIGN_16BYTES # Characteristics 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun # 211*4882a593Smuzhiyun # The EFI application loader requires a relocation section 212*4882a593Smuzhiyun # because EFI applications must be relocatable. The .reloc 213*4882a593Smuzhiyun # offset & size fields are filled in by build.c. 214*4882a593Smuzhiyun # 215*4882a593Smuzhiyun .ascii ".reloc" 216*4882a593Smuzhiyun .byte 0 217*4882a593Smuzhiyun .byte 0 218*4882a593Smuzhiyun .long 0 219*4882a593Smuzhiyun .long 0 220*4882a593Smuzhiyun .long 0 # SizeOfRawData 221*4882a593Smuzhiyun .long 0 # PointerToRawData 222*4882a593Smuzhiyun .long 0 # PointerToRelocations 223*4882a593Smuzhiyun .long 0 # PointerToLineNumbers 224*4882a593Smuzhiyun .word 0 # NumberOfRelocations 225*4882a593Smuzhiyun .word 0 # NumberOfLineNumbers 226*4882a593Smuzhiyun .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ 227*4882a593Smuzhiyun IMAGE_SCN_MEM_READ | \ 228*4882a593Smuzhiyun IMAGE_SCN_MEM_DISCARDABLE | \ 229*4882a593Smuzhiyun IMAGE_SCN_ALIGN_1BYTES # Characteristics 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun#ifdef CONFIG_EFI_MIXED 232*4882a593Smuzhiyun # 233*4882a593Smuzhiyun # The offset & size fields are filled in by build.c. 234*4882a593Smuzhiyun # 235*4882a593Smuzhiyun .asciz ".compat" 236*4882a593Smuzhiyun .long 0 237*4882a593Smuzhiyun .long 0x0 238*4882a593Smuzhiyun .long 0 # Size of initialized data 239*4882a593Smuzhiyun # on disk 240*4882a593Smuzhiyun .long 0x0 241*4882a593Smuzhiyun .long 0 # PointerToRelocations 242*4882a593Smuzhiyun .long 0 # PointerToLineNumbers 243*4882a593Smuzhiyun .word 0 # NumberOfRelocations 244*4882a593Smuzhiyun .word 0 # NumberOfLineNumbers 245*4882a593Smuzhiyun .long IMAGE_SCN_CNT_INITIALIZED_DATA | \ 246*4882a593Smuzhiyun IMAGE_SCN_MEM_READ | \ 247*4882a593Smuzhiyun IMAGE_SCN_MEM_DISCARDABLE | \ 248*4882a593Smuzhiyun IMAGE_SCN_ALIGN_1BYTES # Characteristics 249*4882a593Smuzhiyun#endif 250*4882a593Smuzhiyun 251*4882a593Smuzhiyun # 252*4882a593Smuzhiyun # The offset & size fields are filled in by build.c. 253*4882a593Smuzhiyun # 254*4882a593Smuzhiyun .ascii ".text" 255*4882a593Smuzhiyun .byte 0 256*4882a593Smuzhiyun .byte 0 257*4882a593Smuzhiyun .byte 0 258*4882a593Smuzhiyun .long 0 259*4882a593Smuzhiyun .long 0x0 # startup_{32,64} 260*4882a593Smuzhiyun .long 0 # Size of initialized data 261*4882a593Smuzhiyun # on disk 262*4882a593Smuzhiyun .long 0x0 # startup_{32,64} 263*4882a593Smuzhiyun .long 0 # PointerToRelocations 264*4882a593Smuzhiyun .long 0 # PointerToLineNumbers 265*4882a593Smuzhiyun .word 0 # NumberOfRelocations 266*4882a593Smuzhiyun .word 0 # NumberOfLineNumbers 267*4882a593Smuzhiyun .long IMAGE_SCN_CNT_CODE | \ 268*4882a593Smuzhiyun IMAGE_SCN_MEM_READ | \ 269*4882a593Smuzhiyun IMAGE_SCN_MEM_EXECUTE | \ 270*4882a593Smuzhiyun IMAGE_SCN_ALIGN_16BYTES # Characteristics 271*4882a593Smuzhiyun 272*4882a593Smuzhiyun .set section_count, (. - section_table) / 40 273*4882a593Smuzhiyun#endif /* CONFIG_EFI_STUB */ 274*4882a593Smuzhiyun 275*4882a593Smuzhiyun # Kernel attributes; used by setup. This is part 1 of the 276*4882a593Smuzhiyun # header, from the old boot sector. 277*4882a593Smuzhiyun 278*4882a593Smuzhiyun .section ".header", "a" 279*4882a593Smuzhiyun .globl sentinel 280*4882a593Smuzhiyunsentinel: .byte 0xff, 0xff /* Used to detect broken loaders */ 281*4882a593Smuzhiyun 282*4882a593Smuzhiyun .globl hdr 283*4882a593Smuzhiyunhdr: 284*4882a593Smuzhiyunsetup_sects: .byte 0 /* Filled in by build.c */ 285*4882a593Smuzhiyunroot_flags: .word ROOT_RDONLY 286*4882a593Smuzhiyunsyssize: .long 0 /* Filled in by build.c */ 287*4882a593Smuzhiyunram_size: .word 0 /* Obsolete */ 288*4882a593Smuzhiyunvid_mode: .word SVGA_MODE 289*4882a593Smuzhiyunroot_dev: .word 0 /* Filled in by build.c */ 290*4882a593Smuzhiyunboot_flag: .word 0xAA55 291*4882a593Smuzhiyun 292*4882a593Smuzhiyun # offset 512, entry point 293*4882a593Smuzhiyun 294*4882a593Smuzhiyun .globl _start 295*4882a593Smuzhiyun_start: 296*4882a593Smuzhiyun # Explicitly enter this as bytes, or the assembler 297*4882a593Smuzhiyun # tries to generate a 3-byte jump here, which causes 298*4882a593Smuzhiyun # everything else to push off to the wrong offset. 299*4882a593Smuzhiyun .byte 0xeb # short (2-byte) jump 300*4882a593Smuzhiyun .byte start_of_setup-1f 301*4882a593Smuzhiyun1: 302*4882a593Smuzhiyun 303*4882a593Smuzhiyun # Part 2 of the header, from the old setup.S 304*4882a593Smuzhiyun 305*4882a593Smuzhiyun .ascii "HdrS" # header signature 306*4882a593Smuzhiyun .word 0x020f # header version number (>= 0x0105) 307*4882a593Smuzhiyun # or else old loadlin-1.5 will fail) 308*4882a593Smuzhiyun .globl realmode_swtch 309*4882a593Smuzhiyunrealmode_swtch: .word 0, 0 # default_switch, SETUPSEG 310*4882a593Smuzhiyunstart_sys_seg: .word SYSSEG # obsolete and meaningless, but just 311*4882a593Smuzhiyun # in case something decided to "use" it 312*4882a593Smuzhiyun .word kernel_version-512 # pointing to kernel version string 313*4882a593Smuzhiyun # above section of header is compatible 314*4882a593Smuzhiyun # with loadlin-1.5 (header v1.5). Don't 315*4882a593Smuzhiyun # change it. 316*4882a593Smuzhiyun 317*4882a593Smuzhiyuntype_of_loader: .byte 0 # 0 means ancient bootloader, newer 318*4882a593Smuzhiyun # bootloaders know to change this. 319*4882a593Smuzhiyun # See Documentation/x86/boot.rst for 320*4882a593Smuzhiyun # assigned ids 321*4882a593Smuzhiyun 322*4882a593Smuzhiyun# flags, unused bits must be zero (RFU) bit within loadflags 323*4882a593Smuzhiyunloadflags: 324*4882a593Smuzhiyun .byte LOADED_HIGH # The kernel is to be loaded high 325*4882a593Smuzhiyun 326*4882a593Smuzhiyunsetup_move_size: .word 0x8000 # size to move, when setup is not 327*4882a593Smuzhiyun # loaded at 0x90000. We will move setup 328*4882a593Smuzhiyun # to 0x90000 then just before jumping 329*4882a593Smuzhiyun # into the kernel. However, only the 330*4882a593Smuzhiyun # loader knows how much data behind 331*4882a593Smuzhiyun # us also needs to be loaded. 332*4882a593Smuzhiyun 333*4882a593Smuzhiyuncode32_start: # here loaders can put a different 334*4882a593Smuzhiyun # start address for 32-bit code. 335*4882a593Smuzhiyun .long 0x100000 # 0x100000 = default for big kernel 336*4882a593Smuzhiyun 337*4882a593Smuzhiyunramdisk_image: .long 0 # address of loaded ramdisk image 338*4882a593Smuzhiyun # Here the loader puts the 32-bit 339*4882a593Smuzhiyun # address where it loaded the image. 340*4882a593Smuzhiyun # This only will be read by the kernel. 341*4882a593Smuzhiyun 342*4882a593Smuzhiyunramdisk_size: .long 0 # its size in bytes 343*4882a593Smuzhiyun 344*4882a593Smuzhiyunbootsect_kludge: 345*4882a593Smuzhiyun .long 0 # obsolete 346*4882a593Smuzhiyun 347*4882a593Smuzhiyunheap_end_ptr: .word _end+STACK_SIZE-512 348*4882a593Smuzhiyun # (Header version 0x0201 or later) 349*4882a593Smuzhiyun # space from here (exclusive) down to 350*4882a593Smuzhiyun # end of setup code can be used by setup 351*4882a593Smuzhiyun # for local heap purposes. 352*4882a593Smuzhiyun 353*4882a593Smuzhiyunext_loader_ver: 354*4882a593Smuzhiyun .byte 0 # Extended boot loader version 355*4882a593Smuzhiyunext_loader_type: 356*4882a593Smuzhiyun .byte 0 # Extended boot loader type 357*4882a593Smuzhiyun 358*4882a593Smuzhiyuncmd_line_ptr: .long 0 # (Header version 0x0202 or later) 359*4882a593Smuzhiyun # If nonzero, a 32-bit pointer 360*4882a593Smuzhiyun # to the kernel command line. 361*4882a593Smuzhiyun # The command line should be 362*4882a593Smuzhiyun # located between the start of 363*4882a593Smuzhiyun # setup and the end of low 364*4882a593Smuzhiyun # memory (0xa0000), or it may 365*4882a593Smuzhiyun # get overwritten before it 366*4882a593Smuzhiyun # gets read. If this field is 367*4882a593Smuzhiyun # used, there is no longer 368*4882a593Smuzhiyun # anything magical about the 369*4882a593Smuzhiyun # 0x90000 segment; the setup 370*4882a593Smuzhiyun # can be located anywhere in 371*4882a593Smuzhiyun # low memory 0x10000 or higher. 372*4882a593Smuzhiyun 373*4882a593Smuzhiyuninitrd_addr_max: .long 0x7fffffff 374*4882a593Smuzhiyun # (Header version 0x0203 or later) 375*4882a593Smuzhiyun # The highest safe address for 376*4882a593Smuzhiyun # the contents of an initrd 377*4882a593Smuzhiyun # The current kernel allows up to 4 GB, 378*4882a593Smuzhiyun # but leave it at 2 GB to avoid 379*4882a593Smuzhiyun # possible bootloader bugs. 380*4882a593Smuzhiyun 381*4882a593Smuzhiyunkernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment 382*4882a593Smuzhiyun #required for protected mode 383*4882a593Smuzhiyun #kernel 384*4882a593Smuzhiyun#ifdef CONFIG_RELOCATABLE 385*4882a593Smuzhiyunrelocatable_kernel: .byte 1 386*4882a593Smuzhiyun#else 387*4882a593Smuzhiyunrelocatable_kernel: .byte 0 388*4882a593Smuzhiyun#endif 389*4882a593Smuzhiyunmin_alignment: .byte MIN_KERNEL_ALIGN_LG2 # minimum alignment 390*4882a593Smuzhiyun 391*4882a593Smuzhiyunxloadflags: 392*4882a593Smuzhiyun#ifdef CONFIG_X86_64 393*4882a593Smuzhiyun# define XLF0 XLF_KERNEL_64 /* 64-bit kernel */ 394*4882a593Smuzhiyun#else 395*4882a593Smuzhiyun# define XLF0 0 396*4882a593Smuzhiyun#endif 397*4882a593Smuzhiyun 398*4882a593Smuzhiyun#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64) 399*4882a593Smuzhiyun /* kernel/boot_param/ramdisk could be loaded above 4g */ 400*4882a593Smuzhiyun# define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G 401*4882a593Smuzhiyun#else 402*4882a593Smuzhiyun# define XLF1 0 403*4882a593Smuzhiyun#endif 404*4882a593Smuzhiyun 405*4882a593Smuzhiyun#ifdef CONFIG_EFI_STUB 406*4882a593Smuzhiyun# ifdef CONFIG_EFI_MIXED 407*4882a593Smuzhiyun# define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64) 408*4882a593Smuzhiyun# else 409*4882a593Smuzhiyun# ifdef CONFIG_X86_64 410*4882a593Smuzhiyun# define XLF23 XLF_EFI_HANDOVER_64 /* 64-bit EFI handover ok */ 411*4882a593Smuzhiyun# else 412*4882a593Smuzhiyun# define XLF23 XLF_EFI_HANDOVER_32 /* 32-bit EFI handover ok */ 413*4882a593Smuzhiyun# endif 414*4882a593Smuzhiyun# endif 415*4882a593Smuzhiyun#else 416*4882a593Smuzhiyun# define XLF23 0 417*4882a593Smuzhiyun#endif 418*4882a593Smuzhiyun 419*4882a593Smuzhiyun#if defined(CONFIG_X86_64) && defined(CONFIG_EFI) && defined(CONFIG_KEXEC_CORE) 420*4882a593Smuzhiyun# define XLF4 XLF_EFI_KEXEC 421*4882a593Smuzhiyun#else 422*4882a593Smuzhiyun# define XLF4 0 423*4882a593Smuzhiyun#endif 424*4882a593Smuzhiyun 425*4882a593Smuzhiyun#ifdef CONFIG_X86_64 426*4882a593Smuzhiyun#ifdef CONFIG_X86_5LEVEL 427*4882a593Smuzhiyun#define XLF56 (XLF_5LEVEL|XLF_5LEVEL_ENABLED) 428*4882a593Smuzhiyun#else 429*4882a593Smuzhiyun#define XLF56 XLF_5LEVEL 430*4882a593Smuzhiyun#endif 431*4882a593Smuzhiyun#else 432*4882a593Smuzhiyun#define XLF56 0 433*4882a593Smuzhiyun#endif 434*4882a593Smuzhiyun 435*4882a593Smuzhiyun .word XLF0 | XLF1 | XLF23 | XLF4 | XLF56 436*4882a593Smuzhiyun 437*4882a593Smuzhiyuncmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, 438*4882a593Smuzhiyun #added with boot protocol 439*4882a593Smuzhiyun #version 2.06 440*4882a593Smuzhiyun 441*4882a593Smuzhiyunhardware_subarch: .long 0 # subarchitecture, added with 2.07 442*4882a593Smuzhiyun # default to 0 for normal x86 PC 443*4882a593Smuzhiyun 444*4882a593Smuzhiyunhardware_subarch_data: .quad 0 445*4882a593Smuzhiyun 446*4882a593Smuzhiyunpayload_offset: .long ZO_input_data 447*4882a593Smuzhiyunpayload_length: .long ZO_z_input_len 448*4882a593Smuzhiyun 449*4882a593Smuzhiyunsetup_data: .quad 0 # 64-bit physical pointer to 450*4882a593Smuzhiyun # single linked list of 451*4882a593Smuzhiyun # struct setup_data 452*4882a593Smuzhiyun 453*4882a593Smuzhiyunpref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr 454*4882a593Smuzhiyun 455*4882a593Smuzhiyun# 456*4882a593Smuzhiyun# Getting to provably safe in-place decompression is hard. Worst case 457*4882a593Smuzhiyun# behaviours need to be analyzed. Here let's take the decompression of 458*4882a593Smuzhiyun# a gzip-compressed kernel as example, to illustrate it: 459*4882a593Smuzhiyun# 460*4882a593Smuzhiyun# The file layout of gzip compressed kernel is: 461*4882a593Smuzhiyun# 462*4882a593Smuzhiyun# magic[2] 463*4882a593Smuzhiyun# method[1] 464*4882a593Smuzhiyun# flags[1] 465*4882a593Smuzhiyun# timestamp[4] 466*4882a593Smuzhiyun# extraflags[1] 467*4882a593Smuzhiyun# os[1] 468*4882a593Smuzhiyun# compressed data blocks[N] 469*4882a593Smuzhiyun# crc[4] orig_len[4] 470*4882a593Smuzhiyun# 471*4882a593Smuzhiyun# ... resulting in +18 bytes overhead of uncompressed data. 472*4882a593Smuzhiyun# 473*4882a593Smuzhiyun# (For more information, please refer to RFC 1951 and RFC 1952.) 474*4882a593Smuzhiyun# 475*4882a593Smuzhiyun# Files divided into blocks 476*4882a593Smuzhiyun# 1 bit (last block flag) 477*4882a593Smuzhiyun# 2 bits (block type) 478*4882a593Smuzhiyun# 479*4882a593Smuzhiyun# 1 block occurs every 32K -1 bytes or when there 50% compression 480*4882a593Smuzhiyun# has been achieved. The smallest block type encoding is always used. 481*4882a593Smuzhiyun# 482*4882a593Smuzhiyun# stored: 483*4882a593Smuzhiyun# 32 bits length in bytes. 484*4882a593Smuzhiyun# 485*4882a593Smuzhiyun# fixed: 486*4882a593Smuzhiyun# magic fixed tree. 487*4882a593Smuzhiyun# symbols. 488*4882a593Smuzhiyun# 489*4882a593Smuzhiyun# dynamic: 490*4882a593Smuzhiyun# dynamic tree encoding. 491*4882a593Smuzhiyun# symbols. 492*4882a593Smuzhiyun# 493*4882a593Smuzhiyun# 494*4882a593Smuzhiyun# The buffer for decompression in place is the length of the uncompressed 495*4882a593Smuzhiyun# data, plus a small amount extra to keep the algorithm safe. The 496*4882a593Smuzhiyun# compressed data is placed at the end of the buffer. The output pointer 497*4882a593Smuzhiyun# is placed at the start of the buffer and the input pointer is placed 498*4882a593Smuzhiyun# where the compressed data starts. Problems will occur when the output 499*4882a593Smuzhiyun# pointer overruns the input pointer. 500*4882a593Smuzhiyun# 501*4882a593Smuzhiyun# The output pointer can only overrun the input pointer if the input 502*4882a593Smuzhiyun# pointer is moving faster than the output pointer. A condition only 503*4882a593Smuzhiyun# triggered by data whose compressed form is larger than the uncompressed 504*4882a593Smuzhiyun# form. 505*4882a593Smuzhiyun# 506*4882a593Smuzhiyun# The worst case at the block level is a growth of the compressed data 507*4882a593Smuzhiyun# of 5 bytes per 32767 bytes. 508*4882a593Smuzhiyun# 509*4882a593Smuzhiyun# The worst case internal to a compressed block is very hard to figure. 510*4882a593Smuzhiyun# The worst case can at least be bounded by having one bit that represents 511*4882a593Smuzhiyun# 32764 bytes and then all of the rest of the bytes representing the very 512*4882a593Smuzhiyun# very last byte. 513*4882a593Smuzhiyun# 514*4882a593Smuzhiyun# All of which is enough to compute an amount of extra data that is required 515*4882a593Smuzhiyun# to be safe. To avoid problems at the block level allocating 5 extra bytes 516*4882a593Smuzhiyun# per 32767 bytes of data is sufficient. To avoid problems internal to a 517*4882a593Smuzhiyun# block adding an extra 32767 bytes (the worst case uncompressed block size) 518*4882a593Smuzhiyun# is sufficient, to ensure that in the worst case the decompressed data for 519*4882a593Smuzhiyun# block will stop the byte before the compressed data for a block begins. 520*4882a593Smuzhiyun# To avoid problems with the compressed data's meta information an extra 18 521*4882a593Smuzhiyun# bytes are needed. Leading to the formula: 522*4882a593Smuzhiyun# 523*4882a593Smuzhiyun# extra_bytes = (uncompressed_size >> 12) + 32768 + 18 524*4882a593Smuzhiyun# 525*4882a593Smuzhiyun# Adding 8 bytes per 32K is a bit excessive but much easier to calculate. 526*4882a593Smuzhiyun# Adding 32768 instead of 32767 just makes for round numbers. 527*4882a593Smuzhiyun# 528*4882a593Smuzhiyun# Above analysis is for decompressing gzip compressed kernel only. Up to 529*4882a593Smuzhiyun# now 6 different decompressor are supported all together. And among them 530*4882a593Smuzhiyun# xz stores data in chunks and has maximum chunk of 64K. Hence safety 531*4882a593Smuzhiyun# margin should be updated to cover all decompressors so that we don't 532*4882a593Smuzhiyun# need to deal with each of them separately. Please check 533*4882a593Smuzhiyun# the description in lib/decompressor_xxx.c for specific information. 534*4882a593Smuzhiyun# 535*4882a593Smuzhiyun# extra_bytes = (uncompressed_size >> 12) + 65536 + 128 536*4882a593Smuzhiyun# 537*4882a593Smuzhiyun# LZ4 is even worse: data that cannot be further compressed grows by 0.4%, 538*4882a593Smuzhiyun# or one byte per 256 bytes. OTOH, we can safely get rid of the +128 as 539*4882a593Smuzhiyun# the size-dependent part now grows so fast. 540*4882a593Smuzhiyun# 541*4882a593Smuzhiyun# extra_bytes = (uncompressed_size >> 8) + 65536 542*4882a593Smuzhiyun# 543*4882a593Smuzhiyun# ZSTD compressed data grows by at most 3 bytes per 128K, and only has a 22 544*4882a593Smuzhiyun# byte fixed overhead but has a maximum block size of 128K, so it needs a 545*4882a593Smuzhiyun# larger margin. 546*4882a593Smuzhiyun# 547*4882a593Smuzhiyun# extra_bytes = (uncompressed_size >> 8) + 131072 548*4882a593Smuzhiyun 549*4882a593Smuzhiyun#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 131072) 550*4882a593Smuzhiyun#if ZO_z_output_len > ZO_z_input_len 551*4882a593Smuzhiyun# define ZO_z_extract_offset (ZO_z_output_len + ZO_z_extra_bytes - \ 552*4882a593Smuzhiyun ZO_z_input_len) 553*4882a593Smuzhiyun#else 554*4882a593Smuzhiyun# define ZO_z_extract_offset ZO_z_extra_bytes 555*4882a593Smuzhiyun#endif 556*4882a593Smuzhiyun 557*4882a593Smuzhiyun/* 558*4882a593Smuzhiyun * The extract_offset has to be bigger than ZO head section. Otherwise when 559*4882a593Smuzhiyun * the head code is running to move ZO to the end of the buffer, it will 560*4882a593Smuzhiyun * overwrite the head code itself. 561*4882a593Smuzhiyun */ 562*4882a593Smuzhiyun#if (ZO__ehead - ZO_startup_32) > ZO_z_extract_offset 563*4882a593Smuzhiyun# define ZO_z_min_extract_offset ((ZO__ehead - ZO_startup_32 + 4095) & ~4095) 564*4882a593Smuzhiyun#else 565*4882a593Smuzhiyun# define ZO_z_min_extract_offset ((ZO_z_extract_offset + 4095) & ~4095) 566*4882a593Smuzhiyun#endif 567*4882a593Smuzhiyun 568*4882a593Smuzhiyun#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_min_extract_offset) 569*4882a593Smuzhiyun 570*4882a593Smuzhiyun#define VO_INIT_SIZE (VO__end - VO__text) 571*4882a593Smuzhiyun#if ZO_INIT_SIZE > VO_INIT_SIZE 572*4882a593Smuzhiyun# define INIT_SIZE ZO_INIT_SIZE 573*4882a593Smuzhiyun#else 574*4882a593Smuzhiyun# define INIT_SIZE VO_INIT_SIZE 575*4882a593Smuzhiyun#endif 576*4882a593Smuzhiyun 577*4882a593Smuzhiyuninit_size: .long INIT_SIZE # kernel initialization size 578*4882a593Smuzhiyunhandover_offset: .long 0 # Filled in by build.c 579*4882a593Smuzhiyunkernel_info_offset: .long 0 # Filled in by build.c 580*4882a593Smuzhiyun 581*4882a593Smuzhiyun# End of setup header ##################################################### 582*4882a593Smuzhiyun 583*4882a593Smuzhiyun .section ".entrytext", "ax" 584*4882a593Smuzhiyunstart_of_setup: 585*4882a593Smuzhiyun# Force %es = %ds 586*4882a593Smuzhiyun movw %ds, %ax 587*4882a593Smuzhiyun movw %ax, %es 588*4882a593Smuzhiyun cld 589*4882a593Smuzhiyun 590*4882a593Smuzhiyun# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds, 591*4882a593Smuzhiyun# which happened to work by accident for the old code. Recalculate the stack 592*4882a593Smuzhiyun# pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the 593*4882a593Smuzhiyun# stack behind its own code, so we can't blindly put it directly past the heap. 594*4882a593Smuzhiyun 595*4882a593Smuzhiyun movw %ss, %dx 596*4882a593Smuzhiyun cmpw %ax, %dx # %ds == %ss? 597*4882a593Smuzhiyun movw %sp, %dx 598*4882a593Smuzhiyun je 2f # -> assume %sp is reasonably set 599*4882a593Smuzhiyun 600*4882a593Smuzhiyun # Invalid %ss, make up a new stack 601*4882a593Smuzhiyun movw $_end, %dx 602*4882a593Smuzhiyun testb $CAN_USE_HEAP, loadflags 603*4882a593Smuzhiyun jz 1f 604*4882a593Smuzhiyun movw heap_end_ptr, %dx 605*4882a593Smuzhiyun1: addw $STACK_SIZE, %dx 606*4882a593Smuzhiyun jnc 2f 607*4882a593Smuzhiyun xorw %dx, %dx # Prevent wraparound 608*4882a593Smuzhiyun 609*4882a593Smuzhiyun2: # Now %dx should point to the end of our stack space 610*4882a593Smuzhiyun andw $~3, %dx # dword align (might as well...) 611*4882a593Smuzhiyun jnz 3f 612*4882a593Smuzhiyun movw $0xfffc, %dx # Make sure we're not zero 613*4882a593Smuzhiyun3: movw %ax, %ss 614*4882a593Smuzhiyun movzwl %dx, %esp # Clear upper half of %esp 615*4882a593Smuzhiyun sti # Now we should have a working stack 616*4882a593Smuzhiyun 617*4882a593Smuzhiyun# We will have entered with %cs = %ds+0x20, normalize %cs so 618*4882a593Smuzhiyun# it is on par with the other segments. 619*4882a593Smuzhiyun pushw %ds 620*4882a593Smuzhiyun pushw $6f 621*4882a593Smuzhiyun lretw 622*4882a593Smuzhiyun6: 623*4882a593Smuzhiyun 624*4882a593Smuzhiyun# Check signature at end of setup 625*4882a593Smuzhiyun cmpl $0x5a5aaa55, setup_sig 626*4882a593Smuzhiyun jne setup_bad 627*4882a593Smuzhiyun 628*4882a593Smuzhiyun# Zero the bss 629*4882a593Smuzhiyun movw $__bss_start, %di 630*4882a593Smuzhiyun movw $_end+3, %cx 631*4882a593Smuzhiyun xorl %eax, %eax 632*4882a593Smuzhiyun subw %di, %cx 633*4882a593Smuzhiyun shrw $2, %cx 634*4882a593Smuzhiyun rep; stosl 635*4882a593Smuzhiyun 636*4882a593Smuzhiyun# Jump to C code (should not return) 637*4882a593Smuzhiyun calll main 638*4882a593Smuzhiyun 639*4882a593Smuzhiyun# Setup corrupt somehow... 640*4882a593Smuzhiyunsetup_bad: 641*4882a593Smuzhiyun movl $setup_corrupt, %eax 642*4882a593Smuzhiyun calll puts 643*4882a593Smuzhiyun # Fall through... 644*4882a593Smuzhiyun 645*4882a593Smuzhiyun .globl die 646*4882a593Smuzhiyun .type die, @function 647*4882a593Smuzhiyundie: 648*4882a593Smuzhiyun hlt 649*4882a593Smuzhiyun jmp die 650*4882a593Smuzhiyun 651*4882a593Smuzhiyun .size die, .-die 652*4882a593Smuzhiyun 653*4882a593Smuzhiyun .section ".initdata", "a" 654*4882a593Smuzhiyunsetup_corrupt: 655*4882a593Smuzhiyun .byte 7 656*4882a593Smuzhiyun .string "No setup signature found...\n" 657