linux/arch/x86/boot/header.S
<<
>>
Prefs
   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 <asm/bootparam.h>
  25#include "boot.h"
  26#include "voffset.h"
  27#include "zoffset.h"
  28
  29BOOTSEG         = 0x07C0                /* original address of boot-sector */
  30SYSSEG          = 0x1000                /* historical load address >> 4 */
  31
  32#ifndef SVGA_MODE
  33#define SVGA_MODE ASK_VGA
  34#endif
  35
  36#ifndef ROOT_RDONLY
  37#define ROOT_RDONLY 1
  38#endif
  39
  40        .code16
  41        .section ".bstext", "ax"
  42
  43        .global bootsect_start
  44bootsect_start:
  45#ifdef CONFIG_EFI_STUB
  46        # "MZ", MS-DOS header
  47        .byte 0x4d
  48        .byte 0x5a
  49#endif
  50
  51        # Normalize the start address
  52        ljmp    $BOOTSEG, $start2
  53
  54start2:
  55        movw    %cs, %ax
  56        movw    %ax, %ds
  57        movw    %ax, %es
  58        movw    %ax, %ss
  59        xorw    %sp, %sp
  60        sti
  61        cld
  62
  63        movw    $bugger_off_msg, %si
  64
  65msg_loop:
  66        lodsb
  67        andb    %al, %al
  68        jz      bs_die
  69        movb    $0xe, %ah
  70        movw    $7, %bx
  71        int     $0x10
  72        jmp     msg_loop
  73
  74bs_die:
  75        # Allow the user to press a key, then reboot
  76        xorw    %ax, %ax
  77        int     $0x16
  78        int     $0x19
  79
  80        # int 0x19 should never return.  In case it does anyway,
  81        # invoke the BIOS reset code...
  82        ljmp    $0xf000,$0xfff0
  83
  84#ifdef CONFIG_EFI_STUB
  85        .org    0x3c
  86        #
  87        # Offset to the PE header.
  88        #
  89        .long   pe_header
  90#endif /* CONFIG_EFI_STUB */
  91
  92        .section ".bsdata", "a"
  93bugger_off_msg:
  94        .ascii  "Use a boot loader.\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   4                               # 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   CONFIG_PHYSICAL_ALIGN           # 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        #
 253        # The offset & size fields are filled in by build.c.
 254        #
 255        .ascii  ".bss"
 256        .byte   0
 257        .byte   0
 258        .byte   0
 259        .byte   0
 260        .long   0
 261        .long   0x0
 262        .long   0                               # Size of initialized data
 263                                                # on disk
 264        .long   0x0
 265        .long   0                               # PointerToRelocations
 266        .long   0                               # PointerToLineNumbers
 267        .word   0                               # NumberOfRelocations
 268        .word   0                               # NumberOfLineNumbers
 269        .long   0xc8000080                      # Characteristics (section flags)
 270
 271#endif /* CONFIG_EFI_STUB */
 272
 273        # Kernel attributes; used by setup.  This is part 1 of the
 274        # header, from the old boot sector.
 275
 276        .section ".header", "a"
 277        .globl  sentinel
 278sentinel:       .byte 0xff, 0xff        /* Used to detect broken loaders */
 279
 280        .globl  hdr
 281hdr:
 282setup_sects:    .byte 0                 /* Filled in by build.c */
 283root_flags:     .word ROOT_RDONLY
 284syssize:        .long 0                 /* Filled in by build.c */
 285ram_size:       .word 0                 /* Obsolete */
 286vid_mode:       .word SVGA_MODE
 287root_dev:       .word 0                 /* Filled in by build.c */
 288boot_flag:      .word 0xAA55
 289
 290        # offset 512, entry point
 291
 292        .globl  _start
 293_start:
 294                # Explicitly enter this as bytes, or the assembler
 295                # tries to generate a 3-byte jump here, which causes
 296                # everything else to push off to the wrong offset.
 297                .byte   0xeb            # short (2-byte) jump
 298                .byte   start_of_setup-1f
 2991:
 300
 301        # Part 2 of the header, from the old setup.S
 302
 303                .ascii  "HdrS"          # header signature
 304                .word   0x020d          # header version number (>= 0x0105)
 305                                        # or else old loadlin-1.5 will fail)
 306                .globl realmode_swtch
 307realmode_swtch: .word   0, 0            # default_switch, SETUPSEG
 308start_sys_seg:  .word   SYSSEG          # obsolete and meaningless, but just
 309                                        # in case something decided to "use" it
 310                .word   kernel_version-512 # pointing to kernel version string
 311                                        # above section of header is compatible
 312                                        # with loadlin-1.5 (header v1.5). Don't
 313                                        # change it.
 314
 315type_of_loader: .byte   0               # 0 means ancient bootloader, newer
 316                                        # bootloaders know to change this.
 317                                        # See Documentation/x86/boot.txt for
 318                                        # assigned ids
 319
 320# flags, unused bits must be zero (RFU) bit within loadflags
 321loadflags:
 322                .byte   LOADED_HIGH     # The kernel is to be loaded high
 323
 324setup_move_size: .word  0x8000          # size to move, when setup is not
 325                                        # loaded at 0x90000. We will move setup
 326                                        # to 0x90000 then just before jumping
 327                                        # into the kernel. However, only the
 328                                        # loader knows how much data behind
 329                                        # us also needs to be loaded.
 330
 331code32_start:                           # here loaders can put a different
 332                                        # start address for 32-bit code.
 333                .long   0x100000        # 0x100000 = default for big kernel
 334
 335ramdisk_image:  .long   0               # address of loaded ramdisk image
 336                                        # Here the loader puts the 32-bit
 337                                        # address where it loaded the image.
 338                                        # This only will be read by the kernel.
 339
 340ramdisk_size:   .long   0               # its size in bytes
 341
 342bootsect_kludge:
 343                .long   0               # obsolete
 344
 345heap_end_ptr:   .word   _end+STACK_SIZE-512
 346                                        # (Header version 0x0201 or later)
 347                                        # space from here (exclusive) down to
 348                                        # end of setup code can be used by setup
 349                                        # for local heap purposes.
 350
 351ext_loader_ver:
 352                .byte   0               # Extended boot loader version
 353ext_loader_type:
 354                .byte   0               # Extended boot loader type
 355
 356cmd_line_ptr:   .long   0               # (Header version 0x0202 or later)
 357                                        # If nonzero, a 32-bit pointer
 358                                        # to the kernel command line.
 359                                        # The command line should be
 360                                        # located between the start of
 361                                        # setup and the end of low
 362                                        # memory (0xa0000), or it may
 363                                        # get overwritten before it
 364                                        # gets read.  If this field is
 365                                        # used, there is no longer
 366                                        # anything magical about the
 367                                        # 0x90000 segment; the setup
 368                                        # can be located anywhere in
 369                                        # low memory 0x10000 or higher.
 370
 371initrd_addr_max: .long 0x7fffffff
 372                                        # (Header version 0x0203 or later)
 373                                        # The highest safe address for
 374                                        # the contents of an initrd
 375                                        # The current kernel allows up to 4 GB,
 376                                        # but leave it at 2 GB to avoid
 377                                        # possible bootloader bugs.
 378
 379kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN  #physical addr alignment
 380                                                #required for protected mode
 381                                                #kernel
 382#ifdef CONFIG_RELOCATABLE
 383relocatable_kernel:    .byte 1
 384#else
 385relocatable_kernel:    .byte 0
 386#endif
 387min_alignment:          .byte MIN_KERNEL_ALIGN_LG2      # minimum alignment
 388
 389xloadflags:
 390#ifdef CONFIG_X86_64
 391# define XLF0 XLF_KERNEL_64                     /* 64-bit kernel */
 392#else
 393# define XLF0 0
 394#endif
 395
 396#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64)
 397   /* kernel/boot_param/ramdisk could be loaded above 4g */
 398# define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G
 399#else
 400# define XLF1 0
 401#endif
 402
 403#ifdef CONFIG_EFI_STUB
 404# ifdef CONFIG_EFI_MIXED
 405#  define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64)
 406# else
 407#  ifdef CONFIG_X86_64
 408#   define XLF23 XLF_EFI_HANDOVER_64            /* 64-bit EFI handover ok */
 409#  else
 410#   define XLF23 XLF_EFI_HANDOVER_32            /* 32-bit EFI handover ok */
 411#  endif
 412# endif
 413#else
 414# define XLF23 0
 415#endif
 416
 417#if defined(CONFIG_X86_64) && defined(CONFIG_EFI) && defined(CONFIG_KEXEC_CORE)
 418# define XLF4 XLF_EFI_KEXEC
 419#else
 420# define XLF4 0
 421#endif
 422
 423                        .word XLF0 | XLF1 | XLF23 | XLF4
 424
 425cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
 426                                                #added with boot protocol
 427                                                #version 2.06
 428
 429hardware_subarch:       .long 0                 # subarchitecture, added with 2.07
 430                                                # default to 0 for normal x86 PC
 431
 432hardware_subarch_data:  .quad 0
 433
 434payload_offset:         .long ZO_input_data
 435payload_length:         .long ZO_z_input_len
 436
 437setup_data:             .quad 0                 # 64-bit physical pointer to
 438                                                # single linked list of
 439                                                # struct setup_data
 440
 441pref_address:           .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 442
 443#define ZO_INIT_SIZE    (ZO__end - ZO_startup_32 + ZO_z_extract_offset)
 444#define VO_INIT_SIZE    (VO__end - VO__text)
 445#if ZO_INIT_SIZE > VO_INIT_SIZE
 446#define INIT_SIZE ZO_INIT_SIZE
 447#else
 448#define INIT_SIZE VO_INIT_SIZE
 449#endif
 450init_size:              .long INIT_SIZE         # kernel initialization size
 451handover_offset:        .long 0                 # Filled in by build.c
 452
 453# End of setup header #####################################################
 454
 455        .section ".entrytext", "ax"
 456start_of_setup:
 457# Force %es = %ds
 458        movw    %ds, %ax
 459        movw    %ax, %es
 460        cld
 461
 462# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds,
 463# which happened to work by accident for the old code.  Recalculate the stack
 464# pointer if %ss is invalid.  Otherwise leave it alone, LOADLIN sets up the
 465# stack behind its own code, so we can't blindly put it directly past the heap.
 466
 467        movw    %ss, %dx
 468        cmpw    %ax, %dx        # %ds == %ss?
 469        movw    %sp, %dx
 470        je      2f              # -> assume %sp is reasonably set
 471
 472        # Invalid %ss, make up a new stack
 473        movw    $_end, %dx
 474        testb   $CAN_USE_HEAP, loadflags
 475        jz      1f
 476        movw    heap_end_ptr, %dx
 4771:      addw    $STACK_SIZE, %dx
 478        jnc     2f
 479        xorw    %dx, %dx        # Prevent wraparound
 480
 4812:      # Now %dx should point to the end of our stack space
 482        andw    $~3, %dx        # dword align (might as well...)
 483        jnz     3f
 484        movw    $0xfffc, %dx    # Make sure we're not zero
 4853:      movw    %ax, %ss
 486        movzwl  %dx, %esp       # Clear upper half of %esp
 487        sti                     # Now we should have a working stack
 488
 489# We will have entered with %cs = %ds+0x20, normalize %cs so
 490# it is on par with the other segments.
 491        pushw   %ds
 492        pushw   $6f
 493        lretw
 4946:
 495
 496# Check signature at end of setup
 497        cmpl    $0x5a5aaa55, setup_sig
 498        jne     setup_bad
 499
 500# Zero the bss
 501        movw    $__bss_start, %di
 502        movw    $_end+3, %cx
 503        xorl    %eax, %eax
 504        subw    %di, %cx
 505        shrw    $2, %cx
 506        rep; stosl
 507
 508# Jump to C code (should not return)
 509        calll   main
 510
 511# Setup corrupt somehow...
 512setup_bad:
 513        movl    $setup_corrupt, %eax
 514        calll   puts
 515        # Fall through...
 516
 517        .globl  die
 518        .type   die, @function
 519die:
 520        hlt
 521        jmp     die
 522
 523        .size   die, .-die
 524
 525        .section ".initdata", "a"
 526setup_corrupt:
 527        .byte   7
 528        .string "No setup signature found...\n"
 529