196ae6ea0SThomas Gleixner/* 296ae6ea0SThomas Gleixner * header.S 396ae6ea0SThomas Gleixner * 496ae6ea0SThomas Gleixner * Copyright (C) 1991, 1992 Linus Torvalds 596ae6ea0SThomas Gleixner * 696ae6ea0SThomas Gleixner * Based on bootsect.S and setup.S 796ae6ea0SThomas Gleixner * modified by more people than can be counted 896ae6ea0SThomas Gleixner * 996ae6ea0SThomas Gleixner * Rewritten as a common file by H. Peter Anvin (Apr 2007) 1096ae6ea0SThomas Gleixner * 1196ae6ea0SThomas Gleixner * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment 1296ae6ea0SThomas Gleixner * addresses must be multiplied by 16 to obtain their respective linear 1396ae6ea0SThomas Gleixner * addresses. To avoid confusion, linear addresses are written using leading 1496ae6ea0SThomas Gleixner * hex while segment addresses are written as segment:offset. 1596ae6ea0SThomas Gleixner * 1696ae6ea0SThomas Gleixner */ 1796ae6ea0SThomas Gleixner 1896ae6ea0SThomas Gleixner#include <asm/segment.h> 1996ae6ea0SThomas Gleixner#include <linux/utsrelease.h> 2096ae6ea0SThomas Gleixner#include <asm/boot.h> 2196ae6ea0SThomas Gleixner#include <asm/e820.h> 220341c14dSJeremy Fitzhardinge#include <asm/page_types.h> 2396ae6ea0SThomas Gleixner#include <asm/setup.h> 2496ae6ea0SThomas Gleixner#include "boot.h" 25099e1377SIan Campbell#include "offsets.h" 2696ae6ea0SThomas Gleixner 2796ae6ea0SThomas GleixnerBOOTSEG = 0x07C0 /* original address of boot-sector */ 285e47c478SH. Peter AnvinSYSSEG = 0x1000 /* historical load address >> 4 */ 2996ae6ea0SThomas Gleixner 3096ae6ea0SThomas Gleixner#ifndef SVGA_MODE 3196ae6ea0SThomas Gleixner#define SVGA_MODE ASK_VGA 3296ae6ea0SThomas Gleixner#endif 3396ae6ea0SThomas Gleixner 3496ae6ea0SThomas Gleixner#ifndef RAMDISK 3596ae6ea0SThomas Gleixner#define RAMDISK 0 3696ae6ea0SThomas Gleixner#endif 3796ae6ea0SThomas Gleixner 3896ae6ea0SThomas Gleixner#ifndef ROOT_RDONLY 3996ae6ea0SThomas Gleixner#define ROOT_RDONLY 1 4096ae6ea0SThomas Gleixner#endif 4196ae6ea0SThomas Gleixner 4296ae6ea0SThomas Gleixner .code16 4396ae6ea0SThomas Gleixner .section ".bstext", "ax" 4496ae6ea0SThomas Gleixner 4596ae6ea0SThomas Gleixner .global bootsect_start 4696ae6ea0SThomas Gleixnerbootsect_start: 4796ae6ea0SThomas Gleixner 4896ae6ea0SThomas Gleixner # Normalize the start address 4996ae6ea0SThomas Gleixner ljmp $BOOTSEG, $start2 5096ae6ea0SThomas Gleixner 5196ae6ea0SThomas Gleixnerstart2: 5296ae6ea0SThomas Gleixner movw %cs, %ax 5396ae6ea0SThomas Gleixner movw %ax, %ds 5496ae6ea0SThomas Gleixner movw %ax, %es 5596ae6ea0SThomas Gleixner movw %ax, %ss 5696ae6ea0SThomas Gleixner xorw %sp, %sp 5796ae6ea0SThomas Gleixner sti 5896ae6ea0SThomas Gleixner cld 5996ae6ea0SThomas Gleixner 6096ae6ea0SThomas Gleixner movw $bugger_off_msg, %si 6196ae6ea0SThomas Gleixner 6296ae6ea0SThomas Gleixnermsg_loop: 6396ae6ea0SThomas Gleixner lodsb 6496ae6ea0SThomas Gleixner andb %al, %al 6596ae6ea0SThomas Gleixner jz bs_die 6696ae6ea0SThomas Gleixner movb $0xe, %ah 6796ae6ea0SThomas Gleixner movw $7, %bx 6896ae6ea0SThomas Gleixner int $0x10 6996ae6ea0SThomas Gleixner jmp msg_loop 7096ae6ea0SThomas Gleixner 7196ae6ea0SThomas Gleixnerbs_die: 7296ae6ea0SThomas Gleixner # Allow the user to press a key, then reboot 7396ae6ea0SThomas Gleixner xorw %ax, %ax 7496ae6ea0SThomas Gleixner int $0x16 7596ae6ea0SThomas Gleixner int $0x19 7696ae6ea0SThomas Gleixner 7796ae6ea0SThomas Gleixner # int 0x19 should never return. In case it does anyway, 7896ae6ea0SThomas Gleixner # invoke the BIOS reset code... 7996ae6ea0SThomas Gleixner ljmp $0xf000,$0xfff0 8096ae6ea0SThomas Gleixner 8196ae6ea0SThomas Gleixner .section ".bsdata", "a" 8296ae6ea0SThomas Gleixnerbugger_off_msg: 8396ae6ea0SThomas Gleixner .ascii "Direct booting from floppy is no longer supported.\r\n" 8496ae6ea0SThomas Gleixner .ascii "Please use a boot loader program instead.\r\n" 8596ae6ea0SThomas Gleixner .ascii "\n" 8696ae6ea0SThomas Gleixner .ascii "Remove disk and press any key to reboot . . .\r\n" 8796ae6ea0SThomas Gleixner .byte 0 8896ae6ea0SThomas Gleixner 8996ae6ea0SThomas Gleixner 9096ae6ea0SThomas Gleixner # Kernel attributes; used by setup. This is part 1 of the 9196ae6ea0SThomas Gleixner # header, from the old boot sector. 9296ae6ea0SThomas Gleixner 9396ae6ea0SThomas Gleixner .section ".header", "a" 9496ae6ea0SThomas Gleixner .globl hdr 9596ae6ea0SThomas Gleixnerhdr: 965e47c478SH. Peter Anvinsetup_sects: .byte 0 /* Filled in by build.c */ 9796ae6ea0SThomas Gleixnerroot_flags: .word ROOT_RDONLY 985e47c478SH. Peter Anvinsyssize: .long 0 /* Filled in by build.c */ 995e47c478SH. Peter Anvinram_size: .word 0 /* Obsolete */ 10096ae6ea0SThomas Gleixnervid_mode: .word SVGA_MODE 1015e47c478SH. Peter Anvinroot_dev: .word 0 /* Filled in by build.c */ 10296ae6ea0SThomas Gleixnerboot_flag: .word 0xAA55 10396ae6ea0SThomas Gleixner 10496ae6ea0SThomas Gleixner # offset 512, entry point 10596ae6ea0SThomas Gleixner 10696ae6ea0SThomas Gleixner .globl _start 10796ae6ea0SThomas Gleixner_start: 10896ae6ea0SThomas Gleixner # Explicitly enter this as bytes, or the assembler 10996ae6ea0SThomas Gleixner # tries to generate a 3-byte jump here, which causes 11096ae6ea0SThomas Gleixner # everything else to push off to the wrong offset. 11196ae6ea0SThomas Gleixner .byte 0xeb # short (2-byte) jump 11296ae6ea0SThomas Gleixner .byte start_of_setup-1f 11396ae6ea0SThomas Gleixner1: 11496ae6ea0SThomas Gleixner 11596ae6ea0SThomas Gleixner # Part 2 of the header, from the old setup.S 11696ae6ea0SThomas Gleixner 11796ae6ea0SThomas Gleixner .ascii "HdrS" # header signature 1188b664aa6SHuang, Ying .word 0x0209 # header version number (>= 0x0105) 11996ae6ea0SThomas Gleixner # or else old loadlin-1.5 will fail) 12096ae6ea0SThomas Gleixner .globl realmode_swtch 12196ae6ea0SThomas Gleixnerrealmode_swtch: .word 0, 0 # default_switch, SETUPSEG 1225e47c478SH. Peter Anvinstart_sys_seg: .word SYSSEG # obsolete and meaningless, but just 1235e47c478SH. Peter Anvin # in case something decided to "use" it 12496ae6ea0SThomas Gleixner .word kernel_version-512 # pointing to kernel version string 12596ae6ea0SThomas Gleixner # above section of header is compatible 12696ae6ea0SThomas Gleixner # with loadlin-1.5 (header v1.5). Don't 12796ae6ea0SThomas Gleixner # change it. 12896ae6ea0SThomas Gleixner 1295e47c478SH. Peter Anvintype_of_loader: .byte 0 # 0 means ancient bootloader, newer 1305e47c478SH. Peter Anvin # bootloaders know to change this. 13196ae6ea0SThomas Gleixner # See Documentation/i386/boot.txt for 13296ae6ea0SThomas Gleixner # assigned ids 13396ae6ea0SThomas Gleixner 13496ae6ea0SThomas Gleixner# flags, unused bits must be zero (RFU) bit within loadflags 13596ae6ea0SThomas Gleixnerloadflags: 13696ae6ea0SThomas GleixnerLOADED_HIGH = 1 # If set, the kernel is loaded high 13796ae6ea0SThomas GleixnerCAN_USE_HEAP = 0x80 # If set, the loader also has set 13896ae6ea0SThomas Gleixner # heap_end_ptr to tell how much 13996ae6ea0SThomas Gleixner # space behind setup.S can be used for 14096ae6ea0SThomas Gleixner # heap purposes. 14196ae6ea0SThomas Gleixner # Only the loader knows what is free 14296ae6ea0SThomas Gleixner .byte LOADED_HIGH 14396ae6ea0SThomas Gleixner 14496ae6ea0SThomas Gleixnersetup_move_size: .word 0x8000 # size to move, when setup is not 14596ae6ea0SThomas Gleixner # loaded at 0x90000. We will move setup 14696ae6ea0SThomas Gleixner # to 0x90000 then just before jumping 14796ae6ea0SThomas Gleixner # into the kernel. However, only the 14896ae6ea0SThomas Gleixner # loader knows how much data behind 14996ae6ea0SThomas Gleixner # us also needs to be loaded. 15096ae6ea0SThomas Gleixner 15196ae6ea0SThomas Gleixnercode32_start: # here loaders can put a different 15296ae6ea0SThomas Gleixner # start address for 32-bit code. 15396ae6ea0SThomas Gleixner .long 0x100000 # 0x100000 = default for big kernel 15496ae6ea0SThomas Gleixner 15596ae6ea0SThomas Gleixnerramdisk_image: .long 0 # address of loaded ramdisk image 15696ae6ea0SThomas Gleixner # Here the loader puts the 32-bit 15796ae6ea0SThomas Gleixner # address where it loaded the image. 15896ae6ea0SThomas Gleixner # This only will be read by the kernel. 15996ae6ea0SThomas Gleixner 16096ae6ea0SThomas Gleixnerramdisk_size: .long 0 # its size in bytes 16196ae6ea0SThomas Gleixner 16296ae6ea0SThomas Gleixnerbootsect_kludge: 16396ae6ea0SThomas Gleixner .long 0 # obsolete 16496ae6ea0SThomas Gleixner 1656b6815c6SH. Peter Anvinheap_end_ptr: .word _end+STACK_SIZE-512 1666b6815c6SH. Peter Anvin # (Header version 0x0201 or later) 16796ae6ea0SThomas Gleixner # space from here (exclusive) down to 16896ae6ea0SThomas Gleixner # end of setup code can be used by setup 16996ae6ea0SThomas Gleixner # for local heap purposes. 17096ae6ea0SThomas Gleixner 17196ae6ea0SThomas Gleixnerpad1: .word 0 17296ae6ea0SThomas Gleixnercmd_line_ptr: .long 0 # (Header version 0x0202 or later) 17396ae6ea0SThomas Gleixner # If nonzero, a 32-bit pointer 17496ae6ea0SThomas Gleixner # to the kernel command line. 17596ae6ea0SThomas Gleixner # The command line should be 17696ae6ea0SThomas Gleixner # located between the start of 17796ae6ea0SThomas Gleixner # setup and the end of low 17896ae6ea0SThomas Gleixner # memory (0xa0000), or it may 17996ae6ea0SThomas Gleixner # get overwritten before it 18096ae6ea0SThomas Gleixner # gets read. If this field is 18196ae6ea0SThomas Gleixner # used, there is no longer 18296ae6ea0SThomas Gleixner # anything magical about the 18396ae6ea0SThomas Gleixner # 0x90000 segment; the setup 18496ae6ea0SThomas Gleixner # can be located anywhere in 18596ae6ea0SThomas Gleixner # low memory 0x10000 or higher. 18696ae6ea0SThomas Gleixner 187cf8fa920SH. Peter Anvinramdisk_max: .long 0x7fffffff 18896ae6ea0SThomas Gleixner # (Header version 0x0203 or later) 18996ae6ea0SThomas Gleixner # The highest safe address for 19096ae6ea0SThomas Gleixner # the contents of an initrd 191cf8fa920SH. Peter Anvin # The current kernel allows up to 4 GB, 192cf8fa920SH. Peter Anvin # but leave it at 2 GB to avoid 193cf8fa920SH. Peter Anvin # possible bootloader bugs. 19496ae6ea0SThomas Gleixner 19596ae6ea0SThomas Gleixnerkernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment 19696ae6ea0SThomas Gleixner #required for protected mode 19796ae6ea0SThomas Gleixner #kernel 19896ae6ea0SThomas Gleixner#ifdef CONFIG_RELOCATABLE 19996ae6ea0SThomas Gleixnerrelocatable_kernel: .byte 1 20096ae6ea0SThomas Gleixner#else 20196ae6ea0SThomas Gleixnerrelocatable_kernel: .byte 0 20296ae6ea0SThomas Gleixner#endif 20396ae6ea0SThomas Gleixnerpad2: .byte 0 20496ae6ea0SThomas Gleixnerpad3: .word 0 20596ae6ea0SThomas Gleixner 20696ae6ea0SThomas Gleixnercmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, 20796ae6ea0SThomas Gleixner #added with boot protocol 20896ae6ea0SThomas Gleixner #version 2.06 20996ae6ea0SThomas Gleixner 210a24e7851SRusty Russellhardware_subarch: .long 0 # subarchitecture, added with 2.07 211a24e7851SRusty Russell # default to 0 for normal x86 PC 212a24e7851SRusty Russell 213a24e7851SRusty Russellhardware_subarch_data: .quad 0 214a24e7851SRusty Russell 21587253d1bSIan Campbellpayload_offset: .long input_data 21687253d1bSIan Campbellpayload_length: .long input_data_end-input_data 217099e1377SIan Campbell 2188b664aa6SHuang, Yingsetup_data: .quad 0 # 64-bit physical pointer to 2198b664aa6SHuang, Ying # single linked list of 2208b664aa6SHuang, Ying # struct setup_data 2218b664aa6SHuang, Ying 22296ae6ea0SThomas Gleixner# End of setup header ##################################################### 22396ae6ea0SThomas Gleixner 22496ae6ea0SThomas Gleixner .section ".inittext", "ax" 22596ae6ea0SThomas Gleixnerstart_of_setup: 22696ae6ea0SThomas Gleixner#ifdef SAFE_RESET_DISK_CONTROLLER 22796ae6ea0SThomas Gleixner# Reset the disk controller. 22896ae6ea0SThomas Gleixner movw $0x0000, %ax # Reset disk controller 22996ae6ea0SThomas Gleixner movb $0x80, %dl # All disks 23096ae6ea0SThomas Gleixner int $0x13 23196ae6ea0SThomas Gleixner#endif 23296ae6ea0SThomas Gleixner 23396ae6ea0SThomas Gleixner# Force %es = %ds 23496ae6ea0SThomas Gleixner movw %ds, %ax 23596ae6ea0SThomas Gleixner movw %ax, %es 23696ae6ea0SThomas Gleixner cld 23796ae6ea0SThomas Gleixner 23816252da6SJens Rottmann# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds, 23916252da6SJens Rottmann# which happened to work by accident for the old code. Recalculate the stack 24016252da6SJens Rottmann# pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the 24116252da6SJens Rottmann# stack behind its own code, so we can't blindly put it directly past the heap. 2426b6815c6SH. Peter Anvin 2436b6815c6SH. Peter Anvin movw %ss, %dx 2446b6815c6SH. Peter Anvin cmpw %ax, %dx # %ds == %ss? 2456b6815c6SH. Peter Anvin movw %sp, %dx 24616252da6SJens Rottmann je 2f # -> assume %sp is reasonably set 2476b6815c6SH. Peter Anvin 24816252da6SJens Rottmann # Invalid %ss, make up a new stack 24916252da6SJens Rottmann movw $_end, %dx 25016252da6SJens Rottmann testb $CAN_USE_HEAP, loadflags 25116252da6SJens Rottmann jz 1f 25216252da6SJens Rottmann movw heap_end_ptr, %dx 25316252da6SJens Rottmann1: addw $STACK_SIZE, %dx 25416252da6SJens Rottmann jnc 2f 25516252da6SJens Rottmann xorw %dx, %dx # Prevent wraparound 25616252da6SJens Rottmann 25716252da6SJens Rottmann2: # Now %dx should point to the end of our stack space 2586b6815c6SH. Peter Anvin andw $~3, %dx # dword align (might as well...) 2596b6815c6SH. Peter Anvin jnz 3f 2606b6815c6SH. Peter Anvin movw $0xfffc, %dx # Make sure we're not zero 26116252da6SJens Rottmann3: movw %ax, %ss 2626b6815c6SH. Peter Anvin movzwl %dx, %esp # Clear upper half of %esp 2636b6815c6SH. Peter Anvin sti # Now we should have a working stack 2646b6815c6SH. Peter Anvin 2656b6815c6SH. Peter Anvin# We will have entered with %cs = %ds+0x20, normalize %cs so 2666b6815c6SH. Peter Anvin# it is on par with the other segments. 2676b6815c6SH. Peter Anvin pushw %ds 2686b6815c6SH. Peter Anvin pushw $6f 2696b6815c6SH. Peter Anvin lretw 2706b6815c6SH. Peter Anvin6: 27196ae6ea0SThomas Gleixner 27296ae6ea0SThomas Gleixner# Check signature at end of setup 27396ae6ea0SThomas Gleixner cmpl $0x5a5aaa55, setup_sig 27496ae6ea0SThomas Gleixner jne setup_bad 27596ae6ea0SThomas Gleixner 27696ae6ea0SThomas Gleixner# Zero the bss 27796ae6ea0SThomas Gleixner movw $__bss_start, %di 27896ae6ea0SThomas Gleixner movw $_end+3, %cx 27996ae6ea0SThomas Gleixner xorl %eax, %eax 28096ae6ea0SThomas Gleixner subw %di, %cx 28196ae6ea0SThomas Gleixner shrw $2, %cx 28296ae6ea0SThomas Gleixner rep; stosl 28396ae6ea0SThomas Gleixner 28496ae6ea0SThomas Gleixner# Jump to C code (should not return) 28596ae6ea0SThomas Gleixner calll main 28696ae6ea0SThomas Gleixner 28796ae6ea0SThomas Gleixner# Setup corrupt somehow... 28896ae6ea0SThomas Gleixnersetup_bad: 28996ae6ea0SThomas Gleixner movl $setup_corrupt, %eax 29096ae6ea0SThomas Gleixner calll puts 29196ae6ea0SThomas Gleixner # Fall through... 29296ae6ea0SThomas Gleixner 29396ae6ea0SThomas Gleixner .globl die 29496ae6ea0SThomas Gleixner .type die, @function 29596ae6ea0SThomas Gleixnerdie: 29696ae6ea0SThomas Gleixner hlt 29796ae6ea0SThomas Gleixner jmp die 29896ae6ea0SThomas Gleixner 29996ae6ea0SThomas Gleixner .size die, .-die 30096ae6ea0SThomas Gleixner 30196ae6ea0SThomas Gleixner .section ".initdata", "a" 30296ae6ea0SThomas Gleixnersetup_corrupt: 30396ae6ea0SThomas Gleixner .byte 7 30496ae6ea0SThomas Gleixner .string "No setup signature found...\n" 305