Back to home page

LXR

 
 

    


0001 /*
0002  *  header.S
0003  *
0004  *  Copyright (C) 1991, 1992 Linus Torvalds
0005  *
0006  *  Based on bootsect.S and setup.S
0007  *  modified by more people than can be counted
0008  *
0009  *  Rewritten as a common file by H. Peter Anvin (Apr 2007)
0010  *
0011  * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
0012  * addresses must be multiplied by 16 to obtain their respective linear
0013  * addresses. To avoid confusion, linear addresses are written using leading
0014  * hex while segment addresses are written as segment:offset.
0015  *
0016  */
0017 
0018 #include <asm/segment.h>
0019 #include <generated/utsrelease.h>
0020 #include <asm/boot.h>
0021 #include <asm/e820.h>
0022 #include <asm/page_types.h>
0023 #include <asm/setup.h>
0024 #include <asm/bootparam.h>
0025 #include "boot.h"
0026 #include "voffset.h"
0027 #include "zoffset.h"
0028 
0029 BOOTSEG     = 0x07C0        /* original address of boot-sector */
0030 SYSSEG      = 0x1000        /* historical load address >> 4 */
0031 
0032 #ifndef SVGA_MODE
0033 #define SVGA_MODE ASK_VGA
0034 #endif
0035 
0036 #ifndef ROOT_RDONLY
0037 #define ROOT_RDONLY 1
0038 #endif
0039 
0040     .code16
0041     .section ".bstext", "ax"
0042 
0043     .global bootsect_start
0044 bootsect_start:
0045 #ifdef CONFIG_EFI_STUB
0046     # "MZ", MS-DOS header
0047     .byte 0x4d
0048     .byte 0x5a
0049 #endif
0050 
0051     # Normalize the start address
0052     ljmp    $BOOTSEG, $start2
0053 
0054 start2:
0055     movw    %cs, %ax
0056     movw    %ax, %ds
0057     movw    %ax, %es
0058     movw    %ax, %ss
0059     xorw    %sp, %sp
0060     sti
0061     cld
0062 
0063     movw    $bugger_off_msg, %si
0064 
0065 msg_loop:
0066     lodsb
0067     andb    %al, %al
0068     jz  bs_die
0069     movb    $0xe, %ah
0070     movw    $7, %bx
0071     int $0x10
0072     jmp msg_loop
0073 
0074 bs_die:
0075     # Allow the user to press a key, then reboot
0076     xorw    %ax, %ax
0077     int $0x16
0078     int $0x19
0079 
0080     # int 0x19 should never return.  In case it does anyway,
0081     # invoke the BIOS reset code...
0082     ljmp    $0xf000,$0xfff0
0083 
0084 #ifdef CONFIG_EFI_STUB
0085     .org    0x3c
0086     #
0087     # Offset to the PE header.
0088     #
0089     .long   pe_header
0090 #endif /* CONFIG_EFI_STUB */
0091 
0092     .section ".bsdata", "a"
0093 bugger_off_msg:
0094     .ascii  "Use a boot loader.\r\n"
0095     .ascii  "\n"
0096     .ascii  "Remove disk and press any key to reboot...\r\n"
0097     .byte   0
0098 
0099 #ifdef CONFIG_EFI_STUB
0100 pe_header:
0101     .ascii  "PE"
0102     .word   0
0103 
0104 coff_header:
0105 #ifdef CONFIG_X86_32
0106     .word   0x14c               # i386
0107 #else
0108     .word   0x8664              # x86-64
0109 #endif
0110     .word   4               # nr_sections
0111     .long   0               # TimeDateStamp
0112     .long   0               # PointerToSymbolTable
0113     .long   1               # NumberOfSymbols
0114     .word   section_table - optional_header # SizeOfOptionalHeader
0115 #ifdef CONFIG_X86_32
0116     .word   0x306               # Characteristics.
0117                         # IMAGE_FILE_32BIT_MACHINE |
0118                         # IMAGE_FILE_DEBUG_STRIPPED |
0119                         # IMAGE_FILE_EXECUTABLE_IMAGE |
0120                         # IMAGE_FILE_LINE_NUMS_STRIPPED
0121 #else
0122     .word   0x206               # Characteristics
0123                         # IMAGE_FILE_DEBUG_STRIPPED |
0124                         # IMAGE_FILE_EXECUTABLE_IMAGE |
0125                         # IMAGE_FILE_LINE_NUMS_STRIPPED
0126 #endif
0127 
0128 optional_header:
0129 #ifdef CONFIG_X86_32
0130     .word   0x10b               # PE32 format
0131 #else
0132     .word   0x20b               # PE32+ format
0133 #endif
0134     .byte   0x02                # MajorLinkerVersion
0135     .byte   0x14                # MinorLinkerVersion
0136 
0137     # Filled in by build.c
0138     .long   0               # SizeOfCode
0139 
0140     .long   0               # SizeOfInitializedData
0141     .long   0               # SizeOfUninitializedData
0142 
0143     # Filled in by build.c
0144     .long   0x0000              # AddressOfEntryPoint
0145 
0146     .long   0x0200              # BaseOfCode
0147 #ifdef CONFIG_X86_32
0148     .long   0               # data
0149 #endif
0150 
0151 extra_header_fields:
0152 #ifdef CONFIG_X86_32
0153     .long   0               # ImageBase
0154 #else
0155     .quad   0               # ImageBase
0156 #endif
0157     .long   0x20                # SectionAlignment
0158     .long   0x20                # FileAlignment
0159     .word   0               # MajorOperatingSystemVersion
0160     .word   0               # MinorOperatingSystemVersion
0161     .word   0               # MajorImageVersion
0162     .word   0               # MinorImageVersion
0163     .word   0               # MajorSubsystemVersion
0164     .word   0               # MinorSubsystemVersion
0165     .long   0               # Win32VersionValue
0166 
0167     #
0168     # The size of the bzImage is written in tools/build.c
0169     #
0170     .long   0               # SizeOfImage
0171 
0172     .long   0x200               # SizeOfHeaders
0173     .long   0               # CheckSum
0174     .word   0xa             # Subsystem (EFI application)
0175     .word   0               # DllCharacteristics
0176 #ifdef CONFIG_X86_32
0177     .long   0               # SizeOfStackReserve
0178     .long   0               # SizeOfStackCommit
0179     .long   0               # SizeOfHeapReserve
0180     .long   0               # SizeOfHeapCommit
0181 #else
0182     .quad   0               # SizeOfStackReserve
0183     .quad   0               # SizeOfStackCommit
0184     .quad   0               # SizeOfHeapReserve
0185     .quad   0               # SizeOfHeapCommit
0186 #endif
0187     .long   0               # LoaderFlags
0188     .long   0x6             # NumberOfRvaAndSizes
0189 
0190     .quad   0               # ExportTable
0191     .quad   0               # ImportTable
0192     .quad   0               # ResourceTable
0193     .quad   0               # ExceptionTable
0194     .quad   0               # CertificationTable
0195     .quad   0               # BaseRelocationTable
0196 
0197     # Section table
0198 section_table:
0199     #
0200     # The offset & size fields are filled in by build.c.
0201     #
0202     .ascii  ".setup"
0203     .byte   0
0204     .byte   0
0205     .long   0
0206     .long   0x0             # startup_{32,64}
0207     .long   0               # Size of initialized data
0208                         # on disk
0209     .long   0x0             # startup_{32,64}
0210     .long   0               # PointerToRelocations
0211     .long   0               # PointerToLineNumbers
0212     .word   0               # NumberOfRelocations
0213     .word   0               # NumberOfLineNumbers
0214     .long   0x60500020          # Characteristics (section flags)
0215 
0216     #
0217     # The EFI application loader requires a relocation section
0218     # because EFI applications must be relocatable. The .reloc
0219     # offset & size fields are filled in by build.c.
0220     #
0221     .ascii  ".reloc"
0222     .byte   0
0223     .byte   0
0224     .long   0
0225     .long   0
0226     .long   0               # SizeOfRawData
0227     .long   0               # PointerToRawData
0228     .long   0               # PointerToRelocations
0229     .long   0               # PointerToLineNumbers
0230     .word   0               # NumberOfRelocations
0231     .word   0               # NumberOfLineNumbers
0232     .long   0x42100040          # Characteristics (section flags)
0233 
0234     #
0235     # The offset & size fields are filled in by build.c.
0236     #
0237     .ascii  ".text"
0238     .byte   0
0239     .byte   0
0240     .byte   0
0241     .long   0
0242     .long   0x0             # startup_{32,64}
0243     .long   0               # Size of initialized data
0244                         # on disk
0245     .long   0x0             # startup_{32,64}
0246     .long   0               # PointerToRelocations
0247     .long   0               # PointerToLineNumbers
0248     .word   0               # NumberOfRelocations
0249     .word   0               # NumberOfLineNumbers
0250     .long   0x60500020          # Characteristics (section flags)
0251 
0252     #
0253     # The offset & size fields are filled in by build.c.
0254     #
0255     .ascii  ".bss"
0256     .byte   0
0257     .byte   0
0258     .byte   0
0259     .byte   0
0260     .long   0
0261     .long   0x0
0262     .long   0               # Size of initialized data
0263                         # on disk
0264     .long   0x0
0265     .long   0               # PointerToRelocations
0266     .long   0               # PointerToLineNumbers
0267     .word   0               # NumberOfRelocations
0268     .word   0               # NumberOfLineNumbers
0269     .long   0xc8000080          # Characteristics (section flags)
0270 
0271 #endif /* CONFIG_EFI_STUB */
0272 
0273     # Kernel attributes; used by setup.  This is part 1 of the
0274     # header, from the old boot sector.
0275 
0276     .section ".header", "a"
0277     .globl  sentinel
0278 sentinel:   .byte 0xff, 0xff        /* Used to detect broken loaders */
0279 
0280     .globl  hdr
0281 hdr:
0282 setup_sects:    .byte 0         /* Filled in by build.c */
0283 root_flags: .word ROOT_RDONLY
0284 syssize:    .long 0         /* Filled in by build.c */
0285 ram_size:   .word 0         /* Obsolete */
0286 vid_mode:   .word SVGA_MODE
0287 root_dev:   .word 0         /* Filled in by build.c */
0288 boot_flag:  .word 0xAA55
0289 
0290     # offset 512, entry point
0291 
0292     .globl  _start
0293 _start:
0294         # Explicitly enter this as bytes, or the assembler
0295         # tries to generate a 3-byte jump here, which causes
0296         # everything else to push off to the wrong offset.
0297         .byte   0xeb        # short (2-byte) jump
0298         .byte   start_of_setup-1f
0299 1:
0300 
0301     # Part 2 of the header, from the old setup.S
0302 
0303         .ascii  "HdrS"      # header signature
0304         .word   0x020d      # header version number (>= 0x0105)
0305                     # or else old loadlin-1.5 will fail)
0306         .globl realmode_swtch
0307 realmode_swtch: .word   0, 0        # default_switch, SETUPSEG
0308 start_sys_seg:  .word   SYSSEG      # obsolete and meaningless, but just
0309                     # in case something decided to "use" it
0310         .word   kernel_version-512 # pointing to kernel version string
0311                     # above section of header is compatible
0312                     # with loadlin-1.5 (header v1.5). Don't
0313                     # change it.
0314 
0315 type_of_loader: .byte   0       # 0 means ancient bootloader, newer
0316                     # bootloaders know to change this.
0317                     # See Documentation/x86/boot.txt for
0318                     # assigned ids
0319 
0320 # flags, unused bits must be zero (RFU) bit within loadflags
0321 loadflags:
0322         .byte   LOADED_HIGH # The kernel is to be loaded high
0323 
0324 setup_move_size: .word  0x8000      # size to move, when setup is not
0325                     # loaded at 0x90000. We will move setup
0326                     # to 0x90000 then just before jumping
0327                     # into the kernel. However, only the
0328                     # loader knows how much data behind
0329                     # us also needs to be loaded.
0330 
0331 code32_start:               # here loaders can put a different
0332                     # start address for 32-bit code.
0333         .long   0x100000    # 0x100000 = default for big kernel
0334 
0335 ramdisk_image:  .long   0       # address of loaded ramdisk image
0336                     # Here the loader puts the 32-bit
0337                     # address where it loaded the image.
0338                     # This only will be read by the kernel.
0339 
0340 ramdisk_size:   .long   0       # its size in bytes
0341 
0342 bootsect_kludge:
0343         .long   0       # obsolete
0344 
0345 heap_end_ptr:   .word   _end+STACK_SIZE-512
0346                     # (Header version 0x0201 or later)
0347                     # space from here (exclusive) down to
0348                     # end of setup code can be used by setup
0349                     # for local heap purposes.
0350 
0351 ext_loader_ver:
0352         .byte   0       # Extended boot loader version
0353 ext_loader_type:
0354         .byte   0       # Extended boot loader type
0355 
0356 cmd_line_ptr:   .long   0       # (Header version 0x0202 or later)
0357                     # If nonzero, a 32-bit pointer
0358                     # to the kernel command line.
0359                     # The command line should be
0360                     # located between the start of
0361                     # setup and the end of low
0362                     # memory (0xa0000), or it may
0363                     # get overwritten before it
0364                     # gets read.  If this field is
0365                     # used, there is no longer
0366                     # anything magical about the
0367                     # 0x90000 segment; the setup
0368                     # can be located anywhere in
0369                     # low memory 0x10000 or higher.
0370 
0371 initrd_addr_max: .long 0x7fffffff
0372                     # (Header version 0x0203 or later)
0373                     # The highest safe address for
0374                     # the contents of an initrd
0375                     # The current kernel allows up to 4 GB,
0376                     # but leave it at 2 GB to avoid
0377                     # possible bootloader bugs.
0378 
0379 kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN  #physical addr alignment
0380                         #required for protected mode
0381                         #kernel
0382 #ifdef CONFIG_RELOCATABLE
0383 relocatable_kernel:    .byte 1
0384 #else
0385 relocatable_kernel:    .byte 0
0386 #endif
0387 min_alignment:      .byte MIN_KERNEL_ALIGN_LG2  # minimum alignment
0388 
0389 xloadflags:
0390 #ifdef CONFIG_X86_64
0391 # define XLF0 XLF_KERNEL_64         /* 64-bit kernel */
0392 #else
0393 # define XLF0 0
0394 #endif
0395 
0396 #if defined(CONFIG_RELOCATABLE) && defined(CONFIG_X86_64)
0397    /* kernel/boot_param/ramdisk could be loaded above 4g */
0398 # define XLF1 XLF_CAN_BE_LOADED_ABOVE_4G
0399 #else
0400 # define XLF1 0
0401 #endif
0402 
0403 #ifdef CONFIG_EFI_STUB
0404 # ifdef CONFIG_EFI_MIXED
0405 #  define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64)
0406 # else
0407 #  ifdef CONFIG_X86_64
0408 #   define XLF23 XLF_EFI_HANDOVER_64        /* 64-bit EFI handover ok */
0409 #  else
0410 #   define XLF23 XLF_EFI_HANDOVER_32        /* 32-bit EFI handover ok */
0411 #  endif
0412 # endif
0413 #else
0414 # define XLF23 0
0415 #endif
0416 
0417 #if defined(CONFIG_X86_64) && defined(CONFIG_EFI) && defined(CONFIG_KEXEC_CORE)
0418 # define XLF4 XLF_EFI_KEXEC
0419 #else
0420 # define XLF4 0
0421 #endif
0422 
0423             .word XLF0 | XLF1 | XLF23 | XLF4
0424 
0425 cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
0426                                                 #added with boot protocol
0427                                                 #version 2.06
0428 
0429 hardware_subarch:   .long 0         # subarchitecture, added with 2.07
0430                         # default to 0 for normal x86 PC
0431 
0432 hardware_subarch_data:  .quad 0
0433 
0434 payload_offset:     .long ZO_input_data
0435 payload_length:     .long ZO_z_input_len
0436 
0437 setup_data:     .quad 0         # 64-bit physical pointer to
0438                         # single linked list of
0439                         # struct setup_data
0440 
0441 pref_address:       .quad LOAD_PHYSICAL_ADDR    # preferred load addr
0442 
0443 #
0444 # Getting to provably safe in-place decompression is hard. Worst case
0445 # behaviours need to be analyzed. Here let's take the decompression of
0446 # a gzip-compressed kernel as example, to illustrate it:
0447 #
0448 # The file layout of gzip compressed kernel is:
0449 #
0450 #    magic[2]
0451 #    method[1]
0452 #    flags[1]
0453 #    timestamp[4]
0454 #    extraflags[1]
0455 #    os[1]
0456 #    compressed data blocks[N]
0457 #    crc[4] orig_len[4]
0458 #
0459 # ... resulting in +18 bytes overhead of uncompressed data.
0460 #
0461 # (For more information, please refer to RFC 1951 and RFC 1952.)
0462 #
0463 # Files divided into blocks
0464 # 1 bit (last block flag)
0465 # 2 bits (block type)
0466 #
0467 # 1 block occurs every 32K -1 bytes or when there 50% compression
0468 # has been achieved. The smallest block type encoding is always used.
0469 #
0470 # stored:
0471 #    32 bits length in bytes.
0472 #
0473 # fixed:
0474 #    magic fixed tree.
0475 #    symbols.
0476 #
0477 # dynamic:
0478 #    dynamic tree encoding.
0479 #    symbols.
0480 #
0481 #
0482 # The buffer for decompression in place is the length of the uncompressed
0483 # data, plus a small amount extra to keep the algorithm safe. The
0484 # compressed data is placed at the end of the buffer.  The output pointer
0485 # is placed at the start of the buffer and the input pointer is placed
0486 # where the compressed data starts. Problems will occur when the output
0487 # pointer overruns the input pointer.
0488 #
0489 # The output pointer can only overrun the input pointer if the input
0490 # pointer is moving faster than the output pointer.  A condition only
0491 # triggered by data whose compressed form is larger than the uncompressed
0492 # form.
0493 #
0494 # The worst case at the block level is a growth of the compressed data
0495 # of 5 bytes per 32767 bytes.
0496 #
0497 # The worst case internal to a compressed block is very hard to figure.
0498 # The worst case can at least be bounded by having one bit that represents
0499 # 32764 bytes and then all of the rest of the bytes representing the very
0500 # very last byte.
0501 #
0502 # All of which is enough to compute an amount of extra data that is required
0503 # to be safe.  To avoid problems at the block level allocating 5 extra bytes
0504 # per 32767 bytes of data is sufficient.  To avoid problems internal to a
0505 # block adding an extra 32767 bytes (the worst case uncompressed block size)
0506 # is sufficient, to ensure that in the worst case the decompressed data for
0507 # block will stop the byte before the compressed data for a block begins.
0508 # To avoid problems with the compressed data's meta information an extra 18
0509 # bytes are needed.  Leading to the formula:
0510 #
0511 # extra_bytes = (uncompressed_size >> 12) + 32768 + 18
0512 #
0513 # Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
0514 # Adding 32768 instead of 32767 just makes for round numbers.
0515 #
0516 # Above analysis is for decompressing gzip compressed kernel only. Up to
0517 # now 6 different decompressor are supported all together. And among them
0518 # xz stores data in chunks and has maximum chunk of 64K. Hence safety
0519 # margin should be updated to cover all decompressors so that we don't
0520 # need to deal with each of them separately. Please check
0521 # the description in lib/decompressor_xxx.c for specific information.
0522 #
0523 # extra_bytes = (uncompressed_size >> 12) + 65536 + 128
0524 
0525 #define ZO_z_extra_bytes    ((ZO_z_output_len >> 12) + 65536 + 128)
0526 #if ZO_z_output_len > ZO_z_input_len
0527 # define ZO_z_extract_offset    (ZO_z_output_len + ZO_z_extra_bytes - \
0528                  ZO_z_input_len)
0529 #else
0530 # define ZO_z_extract_offset    ZO_z_extra_bytes
0531 #endif
0532 
0533 /*
0534  * The extract_offset has to be bigger than ZO head section. Otherwise when
0535  * the head code is running to move ZO to the end of the buffer, it will
0536  * overwrite the head code itself.
0537  */
0538 #if (ZO__ehead - ZO_startup_32) > ZO_z_extract_offset
0539 # define ZO_z_min_extract_offset ((ZO__ehead - ZO_startup_32 + 4095) & ~4095)
0540 #else
0541 # define ZO_z_min_extract_offset ((ZO_z_extract_offset + 4095) & ~4095)
0542 #endif
0543 
0544 #define ZO_INIT_SIZE    (ZO__end - ZO_startup_32 + ZO_z_min_extract_offset)
0545 
0546 #define VO_INIT_SIZE    (VO__end - VO__text)
0547 #if ZO_INIT_SIZE > VO_INIT_SIZE
0548 # define INIT_SIZE ZO_INIT_SIZE
0549 #else
0550 # define INIT_SIZE VO_INIT_SIZE
0551 #endif
0552 
0553 init_size:      .long INIT_SIZE     # kernel initialization size
0554 handover_offset:    .long 0         # Filled in by build.c
0555 
0556 # End of setup header #####################################################
0557 
0558     .section ".entrytext", "ax"
0559 start_of_setup:
0560 # Force %es = %ds
0561     movw    %ds, %ax
0562     movw    %ax, %es
0563     cld
0564 
0565 # Apparently some ancient versions of LILO invoked the kernel with %ss != %ds,
0566 # which happened to work by accident for the old code.  Recalculate the stack
0567 # pointer if %ss is invalid.  Otherwise leave it alone, LOADLIN sets up the
0568 # stack behind its own code, so we can't blindly put it directly past the heap.
0569 
0570     movw    %ss, %dx
0571     cmpw    %ax, %dx    # %ds == %ss?
0572     movw    %sp, %dx
0573     je  2f      # -> assume %sp is reasonably set
0574 
0575     # Invalid %ss, make up a new stack
0576     movw    $_end, %dx
0577     testb   $CAN_USE_HEAP, loadflags
0578     jz  1f
0579     movw    heap_end_ptr, %dx
0580 1:  addw    $STACK_SIZE, %dx
0581     jnc 2f
0582     xorw    %dx, %dx    # Prevent wraparound
0583 
0584 2:  # Now %dx should point to the end of our stack space
0585     andw    $~3, %dx    # dword align (might as well...)
0586     jnz 3f
0587     movw    $0xfffc, %dx    # Make sure we're not zero
0588 3:  movw    %ax, %ss
0589     movzwl  %dx, %esp   # Clear upper half of %esp
0590     sti         # Now we should have a working stack
0591 
0592 # We will have entered with %cs = %ds+0x20, normalize %cs so
0593 # it is on par with the other segments.
0594     pushw   %ds
0595     pushw   $6f
0596     lretw
0597 6:
0598 
0599 # Check signature at end of setup
0600     cmpl    $0x5a5aaa55, setup_sig
0601     jne setup_bad
0602 
0603 # Zero the bss
0604     movw    $__bss_start, %di
0605     movw    $_end+3, %cx
0606     xorl    %eax, %eax
0607     subw    %di, %cx
0608     shrw    $2, %cx
0609     rep; stosl
0610 
0611 # Jump to C code (should not return)
0612     calll   main
0613 
0614 # Setup corrupt somehow...
0615 setup_bad:
0616     movl    $setup_corrupt, %eax
0617     calll   puts
0618     # Fall through...
0619 
0620     .globl  die
0621     .type   die, @function
0622 die:
0623     hlt
0624     jmp die
0625 
0626     .size   die, .-die
0627 
0628     .section ".initdata", "a"
0629 setup_corrupt:
0630     .byte   7
0631     .string "No setup signature found...\n"