123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- /*
- * header.S
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * Based on bootsect.S and setup.S
- * modified by more people than can be counted
- *
- * Rewritten as a common file by H. Peter Anvin (Apr 2007)
- *
- * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment
- * addresses must be multiplied by 16 to obtain their respective linear
- * addresses. To avoid confusion, linear addresses are written using leading
- * hex while segment addresses are written as segment:offset.
- *
- */
- #include <asm/segment.h>
- #include <generated/utsrelease.h>
- #include <asm/boot.h>
- #include <asm/e820.h>
- #include <asm/page_types.h>
- #include <asm/setup.h>
- #include "boot.h"
- #include "voffset.h"
- #include "zoffset.h"
- BOOTSEG = 0x07C0 /* original address of boot-sector */
- SYSSEG = 0x1000 /* historical load address >> 4 */
- #ifndef SVGA_MODE
- #define SVGA_MODE ASK_VGA
- #endif
- #ifndef RAMDISK
- #define RAMDISK 0
- #endif
- #ifndef ROOT_RDONLY
- #define ROOT_RDONLY 1
- #endif
- .code16
- .section ".bstext", "ax"
- .global bootsect_start
- bootsect_start:
- # Normalize the start address
- ljmp $BOOTSEG, $start2
- start2:
- movw %cs, %ax
- movw %ax, %ds
- movw %ax, %es
- movw %ax, %ss
- xorw %sp, %sp
- sti
- cld
- movw $bugger_off_msg, %si
- msg_loop:
- lodsb
- andb %al, %al
- jz bs_die
- movb $0xe, %ah
- movw $7, %bx
- int $0x10
- jmp msg_loop
- bs_die:
- # Allow the user to press a key, then reboot
- xorw %ax, %ax
- int $0x16
- int $0x19
- # int 0x19 should never return. In case it does anyway,
- # invoke the BIOS reset code...
- ljmp $0xf000,$0xfff0
- .section ".bsdata", "a"
- bugger_off_msg:
- .ascii "Direct booting from floppy is no longer supported.\r\n"
- .ascii "Please use a boot loader program instead.\r\n"
- .ascii "\n"
- .ascii "Remove disk and press any key to reboot . . .\r\n"
- .byte 0
- # Kernel attributes; used by setup. This is part 1 of the
- # header, from the old boot sector.
- .section ".header", "a"
- .globl hdr
- hdr:
- setup_sects: .byte 0 /* Filled in by build.c */
- root_flags: .word ROOT_RDONLY
- syssize: .long 0 /* Filled in by build.c */
- ram_size: .word 0 /* Obsolete */
- vid_mode: .word SVGA_MODE
- root_dev: .word 0 /* Filled in by build.c */
- boot_flag: .word 0xAA55
- # offset 512, entry point
- .globl _start
- _start:
- # Explicitly enter this as bytes, or the assembler
- # tries to generate a 3-byte jump here, which causes
- # everything else to push off to the wrong offset.
- .byte 0xeb # short (2-byte) jump
- .byte start_of_setup-1f
- 1:
- # Part 2 of the header, from the old setup.S
- .ascii "HdrS" # header signature
- .word 0x020a # header version number (>= 0x0105)
- # or else old loadlin-1.5 will fail)
- .globl realmode_swtch
- realmode_swtch: .word 0, 0 # default_switch, SETUPSEG
- start_sys_seg: .word SYSSEG # obsolete and meaningless, but just
- # in case something decided to "use" it
- .word kernel_version-512 # pointing to kernel version string
- # above section of header is compatible
- # with loadlin-1.5 (header v1.5). Don't
- # change it.
- type_of_loader: .byte 0 # 0 means ancient bootloader, newer
- # bootloaders know to change this.
- # See Documentation/i386/boot.txt for
- # assigned ids
- # flags, unused bits must be zero (RFU) bit within loadflags
- loadflags:
- LOADED_HIGH = 1 # If set, the kernel is loaded high
- CAN_USE_HEAP = 0x80 # If set, the loader also has set
- # heap_end_ptr to tell how much
- # space behind setup.S can be used for
- # heap purposes.
- # Only the loader knows what is free
- .byte LOADED_HIGH
- setup_move_size: .word 0x8000 # size to move, when setup is not
- # loaded at 0x90000. We will move setup
- # to 0x90000 then just before jumping
- # into the kernel. However, only the
- # loader knows how much data behind
- # us also needs to be loaded.
- code32_start: # here loaders can put a different
- # start address for 32-bit code.
- .long 0x100000 # 0x100000 = default for big kernel
- ramdisk_image: .long 0 # address of loaded ramdisk image
- # Here the loader puts the 32-bit
- # address where it loaded the image.
- # This only will be read by the kernel.
- ramdisk_size: .long 0 # its size in bytes
- bootsect_kludge:
- .long 0 # obsolete
- heap_end_ptr: .word _end+STACK_SIZE-512
- # (Header version 0x0201 or later)
- # space from here (exclusive) down to
- # end of setup code can be used by setup
- # for local heap purposes.
- ext_loader_ver:
- .byte 0 # Extended boot loader version
- ext_loader_type:
- .byte 0 # Extended boot loader type
- cmd_line_ptr: .long 0 # (Header version 0x0202 or later)
- # If nonzero, a 32-bit pointer
- # to the kernel command line.
- # The command line should be
- # located between the start of
- # setup and the end of low
- # memory (0xa0000), or it may
- # get overwritten before it
- # gets read. If this field is
- # used, there is no longer
- # anything magical about the
- # 0x90000 segment; the setup
- # can be located anywhere in
- # low memory 0x10000 or higher.
- ramdisk_max: .long 0x7fffffff
- # (Header version 0x0203 or later)
- # The highest safe address for
- # the contents of an initrd
- # The current kernel allows up to 4 GB,
- # but leave it at 2 GB to avoid
- # possible bootloader bugs.
- kernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment
- #required for protected mode
- #kernel
- #ifdef CONFIG_RELOCATABLE
- relocatable_kernel: .byte 1
- #else
- relocatable_kernel: .byte 0
- #endif
- min_alignment: .byte MIN_KERNEL_ALIGN_LG2 # minimum alignment
- pad3: .word 0
- cmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line,
- #added with boot protocol
- #version 2.06
- hardware_subarch: .long 0 # subarchitecture, added with 2.07
- # default to 0 for normal x86 PC
- hardware_subarch_data: .quad 0
- payload_offset: .long ZO_input_data
- payload_length: .long ZO_z_input_len
- setup_data: .quad 0 # 64-bit physical pointer to
- # single linked list of
- # struct setup_data
- pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr
- #define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_z_extract_offset)
- #define VO_INIT_SIZE (VO__end - VO__text)
- #if ZO_INIT_SIZE > VO_INIT_SIZE
- #define INIT_SIZE ZO_INIT_SIZE
- #else
- #define INIT_SIZE VO_INIT_SIZE
- #endif
- init_size: .long INIT_SIZE # kernel initialization size
- # End of setup header #####################################################
- .section ".entrytext", "ax"
- start_of_setup:
- #ifdef SAFE_RESET_DISK_CONTROLLER
- # Reset the disk controller.
- movw $0x0000, %ax # Reset disk controller
- movb $0x80, %dl # All disks
- int $0x13
- #endif
- # Force %es = %ds
- movw %ds, %ax
- movw %ax, %es
- cld
- # Apparently some ancient versions of LILO invoked the kernel with %ss != %ds,
- # which happened to work by accident for the old code. Recalculate the stack
- # pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the
- # stack behind its own code, so we can't blindly put it directly past the heap.
- movw %ss, %dx
- cmpw %ax, %dx # %ds == %ss?
- movw %sp, %dx
- je 2f # -> assume %sp is reasonably set
- # Invalid %ss, make up a new stack
- movw $_end, %dx
- testb $CAN_USE_HEAP, loadflags
- jz 1f
- movw heap_end_ptr, %dx
- 1: addw $STACK_SIZE, %dx
- jnc 2f
- xorw %dx, %dx # Prevent wraparound
- 2: # Now %dx should point to the end of our stack space
- andw $~3, %dx # dword align (might as well...)
- jnz 3f
- movw $0xfffc, %dx # Make sure we're not zero
- 3: movw %ax, %ss
- movzwl %dx, %esp # Clear upper half of %esp
- sti # Now we should have a working stack
- # We will have entered with %cs = %ds+0x20, normalize %cs so
- # it is on par with the other segments.
- pushw %ds
- pushw $6f
- lretw
- 6:
- # Check signature at end of setup
- cmpl $0x5a5aaa55, setup_sig
- jne setup_bad
- # Zero the bss
- movw $__bss_start, %di
- movw $_end+3, %cx
- xorl %eax, %eax
- subw %di, %cx
- shrw $2, %cx
- rep; stosl
- # Jump to C code (should not return)
- calll main
- # Setup corrupt somehow...
- setup_bad:
- movl $setup_corrupt, %eax
- calll puts
- # Fall through...
- .globl die
- .type die, @function
- die:
- hlt
- jmp die
- .size die, .-die
- .section ".initdata", "a"
- setup_corrupt:
- .byte 7
- .string "No setup signature found...\n"
|