1/* 2 * header.S 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 * 6 * Based on bootsect.S and setup.S 7 * modified by more people than can be counted 8 * 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 segment 12 * addresses must be multiplied by 16 to obtain their respective linear 13 * addresses. To avoid confusion, linear addresses are written using leading 14 * hex while segment addresses are written as segment:offset. 15 * 16 */ 17 18#include <asm/segment.h> 19#include <generated/utsrelease.h> 20#include <asm/boot.h> 21#include <asm/e820.h> 22#include <asm/page_types.h> 23#include <asm/setup.h> 24#include "boot.h" 25#include "voffset.h" 26#include "zoffset.h" 27 28BOOTSEG = 0x07C0 /* original address of boot-sector */ 29SYSSEG = 0x1000 /* historical load address >> 4 */ 30 31#ifndef SVGA_MODE 32#define SVGA_MODE ASK_VGA 33#endif 34 35#ifndef ROOT_RDONLY 36#define ROOT_RDONLY 1 37#endif 38 39 .code16 40 .section ".bstext", "ax" 41 42 .global bootsect_start 43bootsect_start: 44#ifdef CONFIG_EFI_STUB 45 # "MZ", MS-DOS header 46 .byte 0x4d 47 .byte 0x5a 48#endif 49 50 # Normalize the start address 51 ljmp $BOOTSEG, $start2 52 53start2: 54 movw %cs, %ax 55 movw %ax, %ds 56 movw %ax, %es 57 movw %ax, %ss 58 xorw %sp, %sp 59 sti 60 cld 61 62 movw $bugger_off_msg, %si 63 64msg_loop: 65 lodsb 66 andb %al, %al 67 jz bs_die 68 movb $0xe, %ah 69 movw $7, %bx 70 int $0x10 71 jmp msg_loop 72 73bs_die: 74 # Allow the user to press a key, then reboot 75 xorw %ax, %ax 76 int $0x16 77 int $0x19 78 79 # int 0x19 should never return. In case it does anyway, 80 # invoke the BIOS reset code... 81 ljmp $0xf000,$0xfff0 82 83#ifdef CONFIG_EFI_STUB 84 .org 0x3c 85 # 86 # Offset to the PE header. 87 # 88 .long pe_header 89#endif /* CONFIG_EFI_STUB */ 90 91 .section ".bsdata", "a" 92bugger_off_msg: 93 .ascii "Direct floppy boot is not supported. " 94 .ascii "Use a boot loader program instead.\r\n" 95 .ascii "\n" 96 .ascii "Remove disk and press any key to reboot ...\r\n" 97 .byte 0 98 99#ifdef CONFIG_EFI_STUB 100pe_header: 101 .ascii "PE" 102 .word 0 103 104coff_header: 105#ifdef CONFIG_X86_32 106 .word 0x14c # i386 107#else 108 .word 0x8664 # x86-64 109#endif 110 .word 3 # nr_sections 111 .long 0 # TimeDateStamp 112 .long 0 # PointerToSymbolTable 113 .long 1 # NumberOfSymbols 114 .word section_table - optional_header # SizeOfOptionalHeader 115#ifdef CONFIG_X86_32 116 .word 0x306 # Characteristics. 117 # IMAGE_FILE_32BIT_MACHINE | 118 # IMAGE_FILE_DEBUG_STRIPPED | 119 # IMAGE_FILE_EXECUTABLE_IMAGE | 120 # IMAGE_FILE_LINE_NUMS_STRIPPED 121#else 122 .word 0x206 # Characteristics 123 # IMAGE_FILE_DEBUG_STRIPPED | 124 # IMAGE_FILE_EXECUTABLE_IMAGE | 125 # IMAGE_FILE_LINE_NUMS_STRIPPED 126#endif 127 128optional_header: 129#ifdef CONFIG_X86_32 130 .word 0x10b # PE32 format 131#else 132 .word 0x20b # PE32+ format 133#endif 134 .byte 0x02 # MajorLinkerVersion 135 .byte 0x14 # MinorLinkerVersion 136 137 # Filled in by build.c 138 .long 0 # SizeOfCode 139 140 .long 0 # SizeOfInitializedData 141 .long 0 # SizeOfUninitializedData 142 143 # Filled in by build.c 144 .long 0x0000 # AddressOfEntryPoint 145 146 .long 0x0200 # BaseOfCode 147#ifdef CONFIG_X86_32 148 .long 0 # data 149#endif 150 151extra_header_fields: 152#ifdef CONFIG_X86_32 153 .long 0 # ImageBase 154#else 155 .quad 0 # ImageBase 156#endif 157 .long 0x20 # SectionAlignment 158 .long 0x20 # FileAlignment 159 .word 0 # MajorOperatingSystemVersion 160 .word 0 # MinorOperatingSystemVersion 161 .word 0 # MajorImageVersion 162 .word 0 # MinorImageVersion 163 .word 0 # MajorSubsystemVersion 164 .word 0 # MinorSubsystemVersion 165 .long 0 # Win32VersionValue 166 167 # 168 # The size of the bzImage is written in tools/build.c 169 # 170 .long 0 # SizeOfImage 171 172 .long 0x200 # SizeOfHeaders 173 .long 0 # CheckSum 174 .word 0xa # Subsystem (EFI application) 175 .word 0 # DllCharacteristics 176#ifdef CONFIG_X86_32 177 .long 0 # SizeOfStackReserve 178 .long 0 # SizeOfStackCommit 179 .long 0 # SizeOfHeapReserve 180 .long 0 # SizeOfHeapCommit 181#else 182 .quad 0 # SizeOfStackReserve 183 .quad 0 # SizeOfStackCommit 184 .quad 0 # SizeOfHeapReserve 185 .quad 0 # SizeOfHeapCommit 186#endif 187 .long 0 # LoaderFlags 188 .long 0x6 # NumberOfRvaAndSizes 189 190 .quad 0 # ExportTable 191 .quad 0 # ImportTable 192 .quad 0 # ResourceTable 193 .quad 0 # ExceptionTable 194 .quad 0 # CertificationTable 195 .quad 0 # BaseRelocationTable 196 197 # Section table 198section_table: 199 # 200 # The offset & size fields are filled in by build.c. 201 # 202 .ascii ".setup" 203 .byte 0 204 .byte 0 205 .long 0 206 .long 0x0 # startup_{32,64} 207 .long 0 # Size of initialized data 208 # on disk 209 .long 0x0 # startup_{32,64} 210 .long 0 # PointerToRelocations 211 .long 0 # PointerToLineNumbers 212 .word 0 # NumberOfRelocations 213 .word 0 # NumberOfLineNumbers 214 .long 0x60500020 # Characteristics (section flags) 215 216 # 217 # The EFI application loader requires a relocation section 218 # because EFI applications must be relocatable. The .reloc 219 # offset & size fields are filled in by build.c. 220 # 221 .ascii ".reloc" 222 .byte 0 223 .byte 0 224 .long 0 225 .long 0 226 .long 0 # SizeOfRawData 227 .long 0 # PointerToRawData 228 .long 0 # PointerToRelocations 229 .long 0 # PointerToLineNumbers 230 .word 0 # NumberOfRelocations 231 .word 0 # NumberOfLineNumbers 232 .long 0x42100040 # Characteristics (section flags) 233 234 # 235 # The offset & size fields are filled in by build.c. 236 # 237 .ascii ".text" 238 .byte 0 239 .byte 0 240 .byte 0 241 .long 0 242 .long 0x0 # startup_{32,64} 243 .long 0 # Size of initialized data 244 # on disk 245 .long 0x0 # startup_{32,64} 246 .long 0 # PointerToRelocations 247 .long 0 # PointerToLineNumbers 248 .word 0 # NumberOfRelocations 249 .word 0 # NumberOfLineNumbers 250 .long 0x60500020 # Characteristics (section flags) 251 252#endif /* CONFIG_EFI_STUB */ 253 254 # Kernel attributes; used by setup. This is part 1 of the 255 # header, from the old boot sector. 256 257 .section ".header", "a" 258 .globl hdr 259hdr: 260setup_sects: .byte 0 /* Filled in by build.c */ 261root_flags: .word ROOT_RDONLY 262syssize: .long 0 /* Filled in by build.c */ 263ram_size: .word 0 /* Obsolete */ 264vid_mode: .word SVGA_MODE 265root_dev: .word 0 /* Filled in by build.c */ 266boot_flag: .word 0xAA55 267 268 # offset 512, entry point 269 270 .globl _start 271_start: 272 # Explicitly enter this as bytes, or the assembler 273 # tries to generate a 3-byte jump here, which causes 274 # everything else to push off to the wrong offset. 275 .byte 0xeb # short (2-byte) jump 276 .byte start_of_setup-1f 2771: 278 279 # Part 2 of the header, from the old setup.S 280 281 .ascii "HdrS" # header signature 282 .word 0x020b # header version number (>= 0x0105) 283 # or else old loadlin-1.5 will fail) 284 .globl realmode_swtch 285realmode_swtch: .word 0, 0 # default_switch, SETUPSEG 286start_sys_seg: .word SYSSEG # obsolete and meaningless, but just 287 # in case something decided to "use" it 288 .word kernel_version-512 # pointing to kernel version string 289 # above section of header is compatible 290 # with loadlin-1.5 (header v1.5). Don't 291 # change it. 292 293type_of_loader: .byte 0 # 0 means ancient bootloader, newer 294 # bootloaders know to change this. 295 # See Documentation/x86/boot.txt for 296 # assigned ids 297 298# flags, unused bits must be zero (RFU) bit within loadflags 299loadflags: 300LOADED_HIGH = 1 # If set, the kernel is loaded high 301CAN_USE_HEAP = 0x80 # If set, the loader also has set 302 # heap_end_ptr to tell how much 303 # space behind setup.S can be used for 304 # heap purposes. 305 # Only the loader knows what is free 306 .byte LOADED_HIGH 307 308setup_move_size: .word 0x8000 # size to move, when setup is not 309 # loaded at 0x90000. We will move setup 310 # to 0x90000 then just before jumping 311 # into the kernel. However, only the 312 # loader knows how much data behind 313 # us also needs to be loaded. 314 315code32_start: # here loaders can put a different 316 # start address for 32-bit code. 317 .long 0x100000 # 0x100000 = default for big kernel 318 319ramdisk_image: .long 0 # address of loaded ramdisk image 320 # Here the loader puts the 32-bit 321 # address where it loaded the image. 322 # This only will be read by the kernel. 323 324ramdisk_size: .long 0 # its size in bytes 325 326bootsect_kludge: 327 .long 0 # obsolete 328 329heap_end_ptr: .word _end+STACK_SIZE-512 330 # (Header version 0x0201 or later) 331 # space from here (exclusive) down to 332 # end of setup code can be used by setup 333 # for local heap purposes. 334 335ext_loader_ver: 336 .byte 0 # Extended boot loader version 337ext_loader_type: 338 .byte 0 # Extended boot loader type 339 340cmd_line_ptr: .long 0 # (Header version 0x0202 or later) 341 # If nonzero, a 32-bit pointer 342 # to the kernel command line. 343 # The command line should be 344 # located between the start of 345 # setup and the end of low 346 # memory (0xa0000), or it may 347 # get overwritten before it 348 # gets read. If this field is 349 # used, there is no longer 350 # anything magical about the 351 # 0x90000 segment; the setup 352 # can be located anywhere in 353 # low memory 0x10000 or higher. 354 355ramdisk_max: .long 0x7fffffff 356 # (Header version 0x0203 or later) 357 # The highest safe address for 358 # the contents of an initrd 359 # The current kernel allows up to 4 GB, 360 # but leave it at 2 GB to avoid 361 # possible bootloader bugs. 362 363kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment 364 #required for protected mode 365 #kernel 366#ifdef CONFIG_RELOCATABLE 367relocatable_kernel: .byte 1 368#else 369relocatable_kernel: .byte 0 370#endif 371min_alignment: .byte MIN_KERNEL_ALIGN_LG2 # minimum alignment 372pad3: .word 0 373 374cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, 375 #added with boot protocol 376 #version 2.06 377 378hardware_subarch: .long 0 # subarchitecture, added with 2.07 379 # default to 0 for normal x86 PC 380 381hardware_subarch_data: .quad 0 382 383payload_offset: .long ZO_input_data 384payload_length: .long ZO_z_input_len 385 386setup_data: .quad 0 # 64-bit physical pointer to 387 # single linked list of 388 # struct setup_data 389 390pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr 391 392#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset) 393#define VO_INIT_SIZE (VO__end - VO__text) 394#if ZO_INIT_SIZE > VO_INIT_SIZE 395#define INIT_SIZE ZO_INIT_SIZE 396#else 397#define INIT_SIZE VO_INIT_SIZE 398#endif 399init_size: .long INIT_SIZE # kernel initialization size 400handover_offset: .long 0x30 # offset to the handover 401 # protocol entry point 402 403# End of setup header ##################################################### 404 405 .section ".entrytext", "ax" 406start_of_setup: 407# Force %es = %ds 408 movw %ds, %ax 409 movw %ax, %es 410 cld 411 412# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds, 413# which happened to work by accident for the old code. Recalculate the stack 414# pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the 415# stack behind its own code, so we can't blindly put it directly past the heap. 416 417 movw %ss, %dx 418 cmpw %ax, %dx # %ds == %ss? 419 movw %sp, %dx 420 je 2f # -> assume %sp is reasonably set 421 422 # Invalid %ss, make up a new stack 423 movw $_end, %dx 424 testb $CAN_USE_HEAP, loadflags 425 jz 1f 426 movw heap_end_ptr, %dx 4271: addw $STACK_SIZE, %dx 428 jnc 2f 429 xorw %dx, %dx # Prevent wraparound 430 4312: # Now %dx should point to the end of our stack space 432 andw $~3, %dx # dword align (might as well...) 433 jnz 3f 434 movw $0xfffc, %dx # Make sure we're not zero 4353: movw %ax, %ss 436 movzwl %dx, %esp # Clear upper half of %esp 437 sti # Now we should have a working stack 438 439# We will have entered with %cs = %ds+0x20, normalize %cs so 440# it is on par with the other segments. 441 pushw %ds 442 pushw $6f 443 lretw 4446: 445 446# Check signature at end of setup 447 cmpl $0x5a5aaa55, setup_sig 448 jne setup_bad 449 450# Zero the bss 451 movw $__bss_start, %di 452 movw $_end+3, %cx 453 xorl %eax, %eax 454 subw %di, %cx 455 shrw $2, %cx 456 rep; stosl 457 458# Jump to C code (should not return) 459 calll main 460 461# Setup corrupt somehow... 462setup_bad: 463 movl $setup_corrupt, %eax 464 calll puts 465 # Fall through... 466 467 .globl die 468 .type die, @function 469die: 470 hlt 471 jmp die 472 473 .size die, .-die 474 475 .section ".initdata", "a" 476setup_corrupt: 477 .byte 7 478 .string "No setup signature found...\n" 479