/* SPDX-License-Identifier: GPL-2.0 */1/*2* header.S3*4* Copyright (C) 1991, 1992 Linus Torvalds5*6* Based on bootsect.S and setup.S7* modified by more people than can be counted8*9* Rewritten as a common file by H. Peter Anvin (Apr 2007)10*11* BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment12* addresses must be multiplied by 16 to obtain their respective linear13* addresses. To avoid confusion, linear addresses are written using leading14* hex while segment addresses are written as segment:offset.15*16*/17#include <linux/pe.h>18#include <asm/segment.h>19#include <asm/boot.h>20#include <asm/page_types.h>21#include <asm/setup.h>22#include <asm/bootparam.h>23#include "boot.h"24#include "voffset.h"25#include "zoffset.h"2627BOOTSEG = 0x07C0 /* original address of boot-sector */28SYSSEG = 0x1000 /* historical load address >> 4 */2930#ifndef SVGA_MODE31#define SVGA_MODE ASK_VGA32#endif3334#ifndef ROOT_RDONLY35#define ROOT_RDONLY 136#endif3738.set salign, 0x100039.set falign, 0x2004041.code1642.section ".bstext", "ax"43#ifdef CONFIG_EFI_STUB44# "MZ", MS-DOS header45.word IMAGE_DOS_SIGNATURE46.org 0x3847#48# Offset to the PE header.49#50.long LINUX_PE_MAGIC51.long pe_header52pe_header:53.long IMAGE_NT_SIGNATURE5455coff_header:56#ifdef CONFIG_X86_3257.set image_file_add_flags, IMAGE_FILE_32BIT_MACHINE58.set pe_opt_magic, IMAGE_NT_OPTIONAL_HDR32_MAGIC59.word IMAGE_FILE_MACHINE_I38660#else61.set image_file_add_flags, 062.set pe_opt_magic, IMAGE_NT_OPTIONAL_HDR64_MAGIC63.word IMAGE_FILE_MACHINE_AMD6464#endif65.word section_count # nr_sections66.long 0 # TimeDateStamp67.long 0 # PointerToSymbolTable68.long 1 # NumberOfSymbols69.word section_table - optional_header # SizeOfOptionalHeader70.word IMAGE_FILE_EXECUTABLE_IMAGE | \71image_file_add_flags | \72IMAGE_FILE_DEBUG_STRIPPED | \73IMAGE_FILE_LINE_NUMS_STRIPPED # Characteristics7475optional_header:76.word pe_opt_magic77.byte 0x02 # MajorLinkerVersion78.byte 0x14 # MinorLinkerVersion7980.long ZO__data # SizeOfCode8182.long ZO__end - ZO__data # SizeOfInitializedData83.long 0 # SizeOfUninitializedData8485.long setup_size + ZO_efi_pe_entry # AddressOfEntryPoint8687.long setup_size # BaseOfCode88#ifdef CONFIG_X86_3289.long 0 # data90#endif9192extra_header_fields:93#ifdef CONFIG_X86_3294.long 0 # ImageBase95#else96.quad 0 # ImageBase97#endif98.long salign # SectionAlignment99.long falign # FileAlignment100.word 0 # MajorOperatingSystemVersion101.word 0 # MinorOperatingSystemVersion102.word LINUX_EFISTUB_MAJOR_VERSION # MajorImageVersion103.word LINUX_EFISTUB_MINOR_VERSION # MinorImageVersion104.word 0 # MajorSubsystemVersion105.word 0 # MinorSubsystemVersion106.long 0 # Win32VersionValue107108.long setup_size + ZO__end # SizeOfImage109110.long salign # SizeOfHeaders111.long 0 # CheckSum112.word IMAGE_SUBSYSTEM_EFI_APPLICATION # Subsystem (EFI application)113.word IMAGE_DLLCHARACTERISTICS_NX_COMPAT # DllCharacteristics114#ifdef CONFIG_X86_32115.long 0 # SizeOfStackReserve116.long 0 # SizeOfStackCommit117.long 0 # SizeOfHeapReserve118.long 0 # SizeOfHeapCommit119#else120.quad 0 # SizeOfStackReserve121.quad 0 # SizeOfStackCommit122.quad 0 # SizeOfHeapReserve123.quad 0 # SizeOfHeapCommit124#endif125.long 0 # LoaderFlags126.long (section_table - .) / 8 # NumberOfRvaAndSizes127128.quad 0 # ExportTable129.quad 0 # ImportTable130.quad 0 # ResourceTable131.quad 0 # ExceptionTable132.quad 0 # CertificationTable133.quad 0 # BaseRelocationTable134135# Section table136section_table:137.ascii ".setup"138.byte 0139.byte 0140.long pecompat_fstart - salign # VirtualSize141.long salign # VirtualAddress142.long pecompat_fstart - salign # SizeOfRawData143.long salign # PointerToRawData144145.long 0, 0, 0146.long IMAGE_SCN_CNT_INITIALIZED_DATA | \147IMAGE_SCN_MEM_READ | \148IMAGE_SCN_MEM_DISCARDABLE # Characteristics149150#ifdef CONFIG_EFI_MIXED151.asciz ".compat"152153.long pecompat_fsize # VirtualSize154.long pecompat_fstart # VirtualAddress155.long pecompat_fsize # SizeOfRawData156.long pecompat_fstart # PointerToRawData157158.long 0, 0, 0159.long IMAGE_SCN_CNT_INITIALIZED_DATA | \160IMAGE_SCN_MEM_READ | \161IMAGE_SCN_MEM_DISCARDABLE # Characteristics162163/*164* Put the IA-32 machine type and the associated entry point address in165* the .compat section, so loaders can figure out which other execution166* modes this image supports.167*/168.pushsection ".pecompat", "a", @progbits169.balign salign170.globl pecompat_fstart171pecompat_fstart:172.byte 0x1 # Version173.byte 8 # Size174.word IMAGE_FILE_MACHINE_I386 # PE machine type175.long setup_size + ZO_efi32_pe_entry # Entrypoint176.byte 0x0 # Sentinel177.popsection178#else179.set pecompat_fstart, setup_size180#endif181.ascii ".text\0\0\0"182.long textsize # VirtualSize183.long setup_size # VirtualAddress184.long textsize # SizeOfRawData185.long setup_size # PointerToRawData186.long 0 # PointerToRelocations187.long 0 # PointerToLineNumbers188.word 0 # NumberOfRelocations189.word 0 # NumberOfLineNumbers190.long IMAGE_SCN_CNT_CODE | \191IMAGE_SCN_MEM_READ | \192IMAGE_SCN_MEM_EXECUTE # Characteristics193194#ifdef CONFIG_EFI_SBAT195.ascii ".sbat\0\0\0"196.long ZO__esbat - ZO__sbat # VirtualSize197.long setup_size + ZO__sbat # VirtualAddress198.long ZO__esbat - ZO__sbat # SizeOfRawData199.long setup_size + ZO__sbat # PointerToRawData200201.long 0, 0, 0202.long IMAGE_SCN_CNT_INITIALIZED_DATA | \203IMAGE_SCN_MEM_READ | \204IMAGE_SCN_MEM_DISCARDABLE # Characteristics205206.set textsize, ZO__sbat207#else208.set textsize, ZO__data209#endif210211.ascii ".data\0\0\0"212.long ZO__end - ZO__data # VirtualSize213.long setup_size + ZO__data # VirtualAddress214.long ZO__edata - ZO__data # SizeOfRawData215.long setup_size + ZO__data # PointerToRawData216217.long 0, 0, 0218.long IMAGE_SCN_CNT_INITIALIZED_DATA | \219IMAGE_SCN_MEM_READ | \220IMAGE_SCN_MEM_WRITE # Characteristics221222.set section_count, (. - section_table) / 40223#endif /* CONFIG_EFI_STUB */224225# Kernel attributes; used by setup. This is part 1 of the226# header, from the old boot sector.227228.section ".header", "a"229.globl sentinel230sentinel: .byte 0xff, 0xff /* Used to detect broken loaders */231232.globl hdr233hdr:234.byte setup_sects - 1235root_flags: .word ROOT_RDONLY236syssize: .long ZO__edata / 16237ram_size: .word 0 /* Obsolete */238vid_mode: .word SVGA_MODE239root_dev: .word 0 /* Default to major/minor 0/0 */240boot_flag: .word 0xAA55241242# offset 512, entry point243244.globl _start245_start:246# Explicitly enter this as bytes, or the assembler247# tries to generate a 3-byte jump here, which causes248# everything else to push off to the wrong offset.249.byte 0xeb # short (2-byte) jump250.byte start_of_setup-1f2511:252253# Part 2 of the header, from the old setup.S254255.ascii "HdrS" # header signature256.word 0x020f # header version number (>= 0x0105)257# or else old loadlin-1.5 will fail)258.globl realmode_swtch259realmode_swtch: .word 0, 0 # default_switch, SETUPSEG260start_sys_seg: .word SYSSEG # obsolete and meaningless, but just261# in case something decided to "use" it262.word kernel_version-512 # pointing to kernel version string263# above section of header is compatible264# with loadlin-1.5 (header v1.5). Don't265# change it.266267type_of_loader: .byte 0 # 0 means ancient bootloader, newer268# bootloaders know to change this.269# See Documentation/arch/x86/boot.rst for270# assigned ids271272# flags, unused bits must be zero (RFU) bit within loadflags273loadflags:274.byte LOADED_HIGH # The kernel is to be loaded high275276setup_move_size: .word 0x8000 # size to move, when setup is not277# loaded at 0x90000. We will move setup278# to 0x90000 then just before jumping279# into the kernel. However, only the280# loader knows how much data behind281# us also needs to be loaded.282283code32_start: # here loaders can put a different284# start address for 32-bit code.285.long 0x100000 # 0x100000 = default for big kernel286287ramdisk_image: .long 0 # address of loaded ramdisk image288# Here the loader puts the 32-bit289# address where it loaded the image.290# This only will be read by the kernel.291292ramdisk_size: .long 0 # its size in bytes293294bootsect_kludge:295.long 0 # obsolete296297heap_end_ptr: .word _end+STACK_SIZE-512298# (Header version 0x0201 or later)299# space from here (exclusive) down to300# end of setup code can be used by setup301# for local heap purposes.302303ext_loader_ver:304.byte 0 # Extended boot loader version305ext_loader_type:306.byte 0 # Extended boot loader type307308cmd_line_ptr: .long 0 # (Header version 0x0202 or later)309# If nonzero, a 32-bit pointer310# to the kernel command line.311# The command line should be312# located between the start of313# setup and the end of low314# memory (0xa0000), or it may315# get overwritten before it316# gets read. If this field is317# used, there is no longer318# anything magical about the319# 0x90000 segment; the setup320# can be located anywhere in321# low memory 0x10000 or higher.322323initrd_addr_max: .long 0x7fffffff324# (Header version 0x0203 or later)325# The highest safe address for326# the contents of an initrd327# The current kernel allows up to 4 GB,328# but leave it at 2 GB to avoid329# possible bootloader bugs.330331kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment332#required for protected mode333#kernel334#ifdef CONFIG_RELOCATABLE335relocatable_kernel: .byte 1336#else337relocatable_kernel: .byte 0338#endif339min_alignment: .byte MIN_KERNEL_ALIGN_LG2 # minimum alignment340341xloadflags:342#ifdef CONFIG_X86_64343# define XLF0 XLF_KERNEL_64 /* 64-bit kernel */344#else345# define XLF0 0346#endif347348#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64)349/* kernel/boot_param/ramdisk could be loaded above 4g */350# define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G351#else352# define XLF1 0353#endif354355#ifdef CONFIG_EFI_HANDOVER_PROTOCOL356# ifdef CONFIG_EFI_MIXED357# define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64)358# else359# ifdef CONFIG_X86_64360# define XLF23 XLF_EFI_HANDOVER_64 /* 64-bit EFI handover ok */361# else362# define XLF23 XLF_EFI_HANDOVER_32 /* 32-bit EFI handover ok */363# endif364# endif365#else366# define XLF23 0367#endif368369#if defined(CONFIG_X86_64) && defined(CONFIG_EFI) && defined(CONFIG_KEXEC_CORE)370# define XLF4 XLF_EFI_KEXEC371#else372# define XLF4 0373#endif374375#ifdef CONFIG_X86_64376#define XLF56 (XLF_5LEVEL|XLF_5LEVEL_ENABLED)377#else378#define XLF56 0379#endif380381.word XLF0 | XLF1 | XLF23 | XLF4 | XLF56382383cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line,384#added with boot protocol385#version 2.06386387hardware_subarch: .long 0 # subarchitecture, added with 2.07388# default to 0 for normal x86 PC389390hardware_subarch_data: .quad 0391392payload_offset: .long ZO_input_data393payload_length: .long ZO_z_input_len394395setup_data: .quad 0 # 64-bit physical pointer to396# single linked list of397# struct setup_data398399pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr400401#402# Getting to provably safe in-place decompression is hard. Worst case403# behaviours need to be analyzed. Here let's take the decompression of404# a gzip-compressed kernel as example, to illustrate it:405#406# The file layout of gzip compressed kernel is:407#408# magic[2]409# method[1]410# flags[1]411# timestamp[4]412# extraflags[1]413# os[1]414# compressed data blocks[N]415# crc[4] orig_len[4]416#417# ... resulting in +18 bytes overhead of uncompressed data.418#419# (For more information, please refer to RFC 1951 and RFC 1952.)420#421# Files divided into blocks422# 1 bit (last block flag)423# 2 bits (block type)424#425# 1 block occurs every 32K -1 bytes or when there 50% compression426# has been achieved. The smallest block type encoding is always used.427#428# stored:429# 32 bits length in bytes.430#431# fixed:432# magic fixed tree.433# symbols.434#435# dynamic:436# dynamic tree encoding.437# symbols.438#439#440# The buffer for decompression in place is the length of the uncompressed441# data, plus a small amount extra to keep the algorithm safe. The442# compressed data is placed at the end of the buffer. The output pointer443# is placed at the start of the buffer and the input pointer is placed444# where the compressed data starts. Problems will occur when the output445# pointer overruns the input pointer.446#447# The output pointer can only overrun the input pointer if the input448# pointer is moving faster than the output pointer. A condition only449# triggered by data whose compressed form is larger than the uncompressed450# form.451#452# The worst case at the block level is a growth of the compressed data453# of 5 bytes per 32767 bytes.454#455# The worst case internal to a compressed block is very hard to figure.456# The worst case can at least be bounded by having one bit that represents457# 32764 bytes and then all of the rest of the bytes representing the very458# very last byte.459#460# All of which is enough to compute an amount of extra data that is required461# to be safe. To avoid problems at the block level allocating 5 extra bytes462# per 32767 bytes of data is sufficient. To avoid problems internal to a463# block adding an extra 32767 bytes (the worst case uncompressed block size)464# is sufficient, to ensure that in the worst case the decompressed data for465# block will stop the byte before the compressed data for a block begins.466# To avoid problems with the compressed data's meta information an extra 18467# bytes are needed. Leading to the formula:468#469# extra_bytes = (uncompressed_size >> 12) + 32768 + 18470#471# Adding 8 bytes per 32K is a bit excessive but much easier to calculate.472# Adding 32768 instead of 32767 just makes for round numbers.473#474# Above analysis is for decompressing gzip compressed kernel only. Up to475# now 6 different decompressor are supported all together. And among them476# xz stores data in chunks and has maximum chunk of 64K. Hence safety477# margin should be updated to cover all decompressors so that we don't478# need to deal with each of them separately. Please check479# the description in lib/decompressor_xxx.c for specific information.480#481# extra_bytes = (uncompressed_size >> 12) + 65536 + 128482#483# LZ4 is even worse: data that cannot be further compressed grows by 0.4%,484# or one byte per 256 bytes. OTOH, we can safely get rid of the +128 as485# the size-dependent part now grows so fast.486#487# extra_bytes = (uncompressed_size >> 8) + 65536488#489# ZSTD compressed data grows by at most 3 bytes per 128K, and only has a 22490# byte fixed overhead but has a maximum block size of 128K, so it needs a491# larger margin.492#493# extra_bytes = (uncompressed_size >> 8) + 131072494495#define ZO_z_extra_bytes ((ZO_z_output_len >> 8) + 131072)496#if ZO_z_output_len > ZO_z_input_len497# define ZO_z_extract_offset (ZO_z_output_len + ZO_z_extra_bytes - \498ZO_z_input_len)499#else500# define ZO_z_extract_offset ZO_z_extra_bytes501#endif502503/*504* The extract_offset has to be bigger than ZO head section. Otherwise when505* the head code is running to move ZO to the end of the buffer, it will506* overwrite the head code itself.507*/508#if (ZO__ehead - ZO_startup_32) > ZO_z_extract_offset509# define ZO_z_min_extract_offset ((ZO__ehead - ZO_startup_32 + 4095) & ~4095)510#else511# define ZO_z_min_extract_offset ((ZO_z_extract_offset + 4095) & ~4095)512#endif513514#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_min_extract_offset)515516#define VO_INIT_SIZE (VO__end - VO__text)517#if ZO_INIT_SIZE > VO_INIT_SIZE518# define INIT_SIZE ZO_INIT_SIZE519#else520# define INIT_SIZE VO_INIT_SIZE521#endif522523.macro __handover_offset524#ifndef CONFIG_EFI_HANDOVER_PROTOCOL525.long 0526#elif !defined(CONFIG_X86_64)527.long ZO_efi32_stub_entry528#else529/* Yes, this is really how we defined it :( */530.long ZO_efi64_stub_entry - 0x200531#ifdef CONFIG_EFI_MIXED532.if ZO_efi32_stub_entry != ZO_efi64_stub_entry - 0x200533.error "32-bit and 64-bit EFI entry points do not match"534.endif535#endif536#endif537.endm538539init_size: .long INIT_SIZE # kernel initialization size540handover_offset: __handover_offset541kernel_info_offset: .long ZO_kernel_info542543# End of setup header #####################################################544545.section ".entrytext", "ax"546start_of_setup:547# Force %es = %ds548movw %ds, %ax549movw %ax, %es550cld551552# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds,553# which happened to work by accident for the old code. Recalculate the stack554# pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the555# stack behind its own code, so we can't blindly put it directly past the heap.556557movw %ss, %dx558cmpw %ax, %dx # %ds == %ss?559movw %sp, %dx560je 2f # -> assume %sp is reasonably set561562# Invalid %ss, make up a new stack563movw $_end, %dx564testb $CAN_USE_HEAP, loadflags565jz 1f566movw heap_end_ptr, %dx5671: addw $STACK_SIZE, %dx568jnc 2f569xorw %dx, %dx # Prevent wraparound5705712: # Now %dx should point to the end of our stack space572andw $~3, %dx # dword align (might as well...)573jnz 3f574movw $0xfffc, %dx # Make sure we're not zero5753: movw %ax, %ss576movzwl %dx, %esp # Clear upper half of %esp577sti # Now we should have a working stack578579# We will have entered with %cs = %ds+0x20, normalize %cs so580# it is on par with the other segments.581pushw %ds582pushw $6f583lretw5846:585586# Check signature at end of setup587cmpl $0x5a5aaa55, setup_sig588jne setup_bad589590# Zero the bss591movw $__bss_start, %di592movw $_end+3, %cx593xorl %eax, %eax594subw %di, %cx595shrw $2, %cx596rep stosl597598# Jump to C code (should not return)599calll main600601# Setup corrupt somehow...602setup_bad:603movl $setup_corrupt, %eax604calll puts605# Fall through...606607.globl die608.type die, @function609die:610hlt611jmp die612613.size die, .-die614615.section ".initdata", "a"616setup_corrupt:617.byte 7618.string "No setup signature found...\n"619620621