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> 2296ae6ea0SThomas Gleixner#include <asm/page.h> 2396ae6ea0SThomas Gleixner#include <asm/setup.h> 2496ae6ea0SThomas Gleixner#include "boot.h" 2596ae6ea0SThomas Gleixner 2696ae6ea0SThomas GleixnerSETUPSECTS = 4 /* default nr of setup-sectors */ 2796ae6ea0SThomas GleixnerBOOTSEG = 0x07C0 /* original address of boot-sector */ 2896ae6ea0SThomas GleixnerSYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ 2996ae6ea0SThomas GleixnerSYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ 3096ae6ea0SThomas Gleixner /* to be loaded */ 3196ae6ea0SThomas GleixnerROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ 3296ae6ea0SThomas GleixnerSWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ 3396ae6ea0SThomas Gleixner 3496ae6ea0SThomas Gleixner#ifndef SVGA_MODE 3596ae6ea0SThomas Gleixner#define SVGA_MODE ASK_VGA 3696ae6ea0SThomas Gleixner#endif 3796ae6ea0SThomas Gleixner 3896ae6ea0SThomas Gleixner#ifndef RAMDISK 3996ae6ea0SThomas Gleixner#define RAMDISK 0 4096ae6ea0SThomas Gleixner#endif 4196ae6ea0SThomas Gleixner 4296ae6ea0SThomas Gleixner#ifndef ROOT_RDONLY 4396ae6ea0SThomas Gleixner#define ROOT_RDONLY 1 4496ae6ea0SThomas Gleixner#endif 4596ae6ea0SThomas Gleixner 4696ae6ea0SThomas Gleixner .code16 4796ae6ea0SThomas Gleixner .section ".bstext", "ax" 4896ae6ea0SThomas Gleixner 4996ae6ea0SThomas Gleixner .global bootsect_start 5096ae6ea0SThomas Gleixnerbootsect_start: 5196ae6ea0SThomas Gleixner 5296ae6ea0SThomas Gleixner # Normalize the start address 5396ae6ea0SThomas Gleixner ljmp $BOOTSEG, $start2 5496ae6ea0SThomas Gleixner 5596ae6ea0SThomas Gleixnerstart2: 5696ae6ea0SThomas Gleixner movw %cs, %ax 5796ae6ea0SThomas Gleixner movw %ax, %ds 5896ae6ea0SThomas Gleixner movw %ax, %es 5996ae6ea0SThomas Gleixner movw %ax, %ss 6096ae6ea0SThomas Gleixner xorw %sp, %sp 6196ae6ea0SThomas Gleixner sti 6296ae6ea0SThomas Gleixner cld 6396ae6ea0SThomas Gleixner 6496ae6ea0SThomas Gleixner movw $bugger_off_msg, %si 6596ae6ea0SThomas Gleixner 6696ae6ea0SThomas Gleixnermsg_loop: 6796ae6ea0SThomas Gleixner lodsb 6896ae6ea0SThomas Gleixner andb %al, %al 6996ae6ea0SThomas Gleixner jz bs_die 7096ae6ea0SThomas Gleixner movb $0xe, %ah 7196ae6ea0SThomas Gleixner movw $7, %bx 7296ae6ea0SThomas Gleixner int $0x10 7396ae6ea0SThomas Gleixner jmp msg_loop 7496ae6ea0SThomas Gleixner 7596ae6ea0SThomas Gleixnerbs_die: 7696ae6ea0SThomas Gleixner # Allow the user to press a key, then reboot 7796ae6ea0SThomas Gleixner xorw %ax, %ax 7896ae6ea0SThomas Gleixner int $0x16 7996ae6ea0SThomas Gleixner int $0x19 8096ae6ea0SThomas Gleixner 8196ae6ea0SThomas Gleixner # int 0x19 should never return. In case it does anyway, 8296ae6ea0SThomas Gleixner # invoke the BIOS reset code... 8396ae6ea0SThomas Gleixner ljmp $0xf000,$0xfff0 8496ae6ea0SThomas Gleixner 8596ae6ea0SThomas Gleixner .section ".bsdata", "a" 8696ae6ea0SThomas Gleixnerbugger_off_msg: 8796ae6ea0SThomas Gleixner .ascii "Direct booting from floppy is no longer supported.\r\n" 8896ae6ea0SThomas Gleixner .ascii "Please use a boot loader program instead.\r\n" 8996ae6ea0SThomas Gleixner .ascii "\n" 9096ae6ea0SThomas Gleixner .ascii "Remove disk and press any key to reboot . . .\r\n" 9196ae6ea0SThomas Gleixner .byte 0 9296ae6ea0SThomas Gleixner 9396ae6ea0SThomas Gleixner 9496ae6ea0SThomas Gleixner # Kernel attributes; used by setup. This is part 1 of the 9596ae6ea0SThomas Gleixner # header, from the old boot sector. 9696ae6ea0SThomas Gleixner 9796ae6ea0SThomas Gleixner .section ".header", "a" 9896ae6ea0SThomas Gleixner .globl hdr 9996ae6ea0SThomas Gleixnerhdr: 10096ae6ea0SThomas Gleixnersetup_sects: .byte SETUPSECTS 10196ae6ea0SThomas Gleixnerroot_flags: .word ROOT_RDONLY 10296ae6ea0SThomas Gleixnersyssize: .long SYSSIZE 10396ae6ea0SThomas Gleixnerram_size: .word RAMDISK 10496ae6ea0SThomas Gleixnervid_mode: .word SVGA_MODE 10596ae6ea0SThomas Gleixnerroot_dev: .word ROOT_DEV 10696ae6ea0SThomas Gleixnerboot_flag: .word 0xAA55 10796ae6ea0SThomas Gleixner 10896ae6ea0SThomas Gleixner # offset 512, entry point 10996ae6ea0SThomas Gleixner 11096ae6ea0SThomas Gleixner .globl _start 11196ae6ea0SThomas Gleixner_start: 11296ae6ea0SThomas Gleixner # Explicitly enter this as bytes, or the assembler 11396ae6ea0SThomas Gleixner # tries to generate a 3-byte jump here, which causes 11496ae6ea0SThomas Gleixner # everything else to push off to the wrong offset. 11596ae6ea0SThomas Gleixner .byte 0xeb # short (2-byte) jump 11696ae6ea0SThomas Gleixner .byte start_of_setup-1f 11796ae6ea0SThomas Gleixner1: 11896ae6ea0SThomas Gleixner 11996ae6ea0SThomas Gleixner # Part 2 of the header, from the old setup.S 12096ae6ea0SThomas Gleixner 12196ae6ea0SThomas Gleixner .ascii "HdrS" # header signature 122a24e7851SRusty Russell .word 0x0207 # header version number (>= 0x0105) 12396ae6ea0SThomas Gleixner # or else old loadlin-1.5 will fail) 12496ae6ea0SThomas Gleixner .globl realmode_swtch 12596ae6ea0SThomas Gleixnerrealmode_swtch: .word 0, 0 # default_switch, SETUPSEG 12696ae6ea0SThomas Gleixnerstart_sys_seg: .word SYSSEG 12796ae6ea0SThomas Gleixner .word kernel_version-512 # pointing to kernel version string 12896ae6ea0SThomas Gleixner # above section of header is compatible 12996ae6ea0SThomas Gleixner # with loadlin-1.5 (header v1.5). Don't 13096ae6ea0SThomas Gleixner # change it. 13196ae6ea0SThomas Gleixner 13296ae6ea0SThomas Gleixnertype_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, 13396ae6ea0SThomas Gleixner # Bootlin, SYSLX, bootsect...) 13496ae6ea0SThomas Gleixner # See Documentation/i386/boot.txt for 13596ae6ea0SThomas Gleixner # assigned ids 13696ae6ea0SThomas Gleixner 13796ae6ea0SThomas Gleixner# flags, unused bits must be zero (RFU) bit within loadflags 13896ae6ea0SThomas Gleixnerloadflags: 13996ae6ea0SThomas GleixnerLOADED_HIGH = 1 # If set, the kernel is loaded high 14096ae6ea0SThomas GleixnerCAN_USE_HEAP = 0x80 # If set, the loader also has set 14196ae6ea0SThomas Gleixner # heap_end_ptr to tell how much 14296ae6ea0SThomas Gleixner # space behind setup.S can be used for 14396ae6ea0SThomas Gleixner # heap purposes. 14496ae6ea0SThomas Gleixner # Only the loader knows what is free 14596ae6ea0SThomas Gleixner#ifndef __BIG_KERNEL__ 14696ae6ea0SThomas Gleixner .byte 0 14796ae6ea0SThomas Gleixner#else 14896ae6ea0SThomas Gleixner .byte LOADED_HIGH 14996ae6ea0SThomas Gleixner#endif 15096ae6ea0SThomas Gleixner 15196ae6ea0SThomas Gleixnersetup_move_size: .word 0x8000 # size to move, when setup is not 15296ae6ea0SThomas Gleixner # loaded at 0x90000. We will move setup 15396ae6ea0SThomas Gleixner # to 0x90000 then just before jumping 15496ae6ea0SThomas Gleixner # into the kernel. However, only the 15596ae6ea0SThomas Gleixner # loader knows how much data behind 15696ae6ea0SThomas Gleixner # us also needs to be loaded. 15796ae6ea0SThomas Gleixner 15896ae6ea0SThomas Gleixnercode32_start: # here loaders can put a different 15996ae6ea0SThomas Gleixner # start address for 32-bit code. 16096ae6ea0SThomas Gleixner#ifndef __BIG_KERNEL__ 16196ae6ea0SThomas Gleixner .long 0x1000 # 0x1000 = default for zImage 16296ae6ea0SThomas Gleixner#else 16396ae6ea0SThomas Gleixner .long 0x100000 # 0x100000 = default for big kernel 16496ae6ea0SThomas Gleixner#endif 16596ae6ea0SThomas Gleixner 16696ae6ea0SThomas Gleixnerramdisk_image: .long 0 # address of loaded ramdisk image 16796ae6ea0SThomas Gleixner # Here the loader puts the 32-bit 16896ae6ea0SThomas Gleixner # address where it loaded the image. 16996ae6ea0SThomas Gleixner # This only will be read by the kernel. 17096ae6ea0SThomas Gleixner 17196ae6ea0SThomas Gleixnerramdisk_size: .long 0 # its size in bytes 17296ae6ea0SThomas Gleixner 17396ae6ea0SThomas Gleixnerbootsect_kludge: 17496ae6ea0SThomas Gleixner .long 0 # obsolete 17596ae6ea0SThomas Gleixner 1766b6815c6SH. Peter Anvinheap_end_ptr: .word _end+STACK_SIZE-512 1776b6815c6SH. Peter Anvin # (Header version 0x0201 or later) 17896ae6ea0SThomas Gleixner # space from here (exclusive) down to 17996ae6ea0SThomas Gleixner # end of setup code can be used by setup 18096ae6ea0SThomas Gleixner # for local heap purposes. 18196ae6ea0SThomas Gleixner 18296ae6ea0SThomas Gleixnerpad1: .word 0 18396ae6ea0SThomas Gleixnercmd_line_ptr: .long 0 # (Header version 0x0202 or later) 18496ae6ea0SThomas Gleixner # If nonzero, a 32-bit pointer 18596ae6ea0SThomas Gleixner # to the kernel command line. 18696ae6ea0SThomas Gleixner # The command line should be 18796ae6ea0SThomas Gleixner # located between the start of 18896ae6ea0SThomas Gleixner # setup and the end of low 18996ae6ea0SThomas Gleixner # memory (0xa0000), or it may 19096ae6ea0SThomas Gleixner # get overwritten before it 19196ae6ea0SThomas Gleixner # gets read. If this field is 19296ae6ea0SThomas Gleixner # used, there is no longer 19396ae6ea0SThomas Gleixner # anything magical about the 19496ae6ea0SThomas Gleixner # 0x90000 segment; the setup 19596ae6ea0SThomas Gleixner # can be located anywhere in 19696ae6ea0SThomas Gleixner # low memory 0x10000 or higher. 19796ae6ea0SThomas Gleixner 19896ae6ea0SThomas Gleixnerramdisk_max: .long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff 19996ae6ea0SThomas Gleixner # (Header version 0x0203 or later) 20096ae6ea0SThomas Gleixner # The highest safe address for 20196ae6ea0SThomas Gleixner # the contents of an initrd 20296ae6ea0SThomas Gleixner 20396ae6ea0SThomas Gleixnerkernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment 20496ae6ea0SThomas Gleixner #required for protected mode 20596ae6ea0SThomas Gleixner #kernel 20696ae6ea0SThomas Gleixner#ifdef CONFIG_RELOCATABLE 20796ae6ea0SThomas Gleixnerrelocatable_kernel: .byte 1 20896ae6ea0SThomas Gleixner#else 20996ae6ea0SThomas Gleixnerrelocatable_kernel: .byte 0 21096ae6ea0SThomas Gleixner#endif 21196ae6ea0SThomas Gleixnerpad2: .byte 0 21296ae6ea0SThomas Gleixnerpad3: .word 0 21396ae6ea0SThomas Gleixner 21496ae6ea0SThomas Gleixnercmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, 21596ae6ea0SThomas Gleixner #added with boot protocol 21696ae6ea0SThomas Gleixner #version 2.06 21796ae6ea0SThomas Gleixner 218a24e7851SRusty Russellhardware_subarch: .long 0 # subarchitecture, added with 2.07 219a24e7851SRusty Russell # default to 0 for normal x86 PC 220a24e7851SRusty Russell 221a24e7851SRusty Russellhardware_subarch_data: .quad 0 222a24e7851SRusty Russell 22396ae6ea0SThomas Gleixner# End of setup header ##################################################### 22496ae6ea0SThomas Gleixner 22596ae6ea0SThomas Gleixner .section ".inittext", "ax" 22696ae6ea0SThomas Gleixnerstart_of_setup: 22796ae6ea0SThomas Gleixner#ifdef SAFE_RESET_DISK_CONTROLLER 22896ae6ea0SThomas Gleixner# Reset the disk controller. 22996ae6ea0SThomas Gleixner movw $0x0000, %ax # Reset disk controller 23096ae6ea0SThomas Gleixner movb $0x80, %dl # All disks 23196ae6ea0SThomas Gleixner int $0x13 23296ae6ea0SThomas Gleixner#endif 23396ae6ea0SThomas Gleixner 23496ae6ea0SThomas Gleixner# Force %es = %ds 23596ae6ea0SThomas Gleixner movw %ds, %ax 23696ae6ea0SThomas Gleixner movw %ax, %es 23796ae6ea0SThomas Gleixner cld 23896ae6ea0SThomas Gleixner 239*16252da6SJens Rottmann# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds, 240*16252da6SJens Rottmann# which happened to work by accident for the old code. Recalculate the stack 241*16252da6SJens Rottmann# pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the 242*16252da6SJens Rottmann# stack behind its own code, so we can't blindly put it directly past the heap. 2436b6815c6SH. Peter Anvin 2446b6815c6SH. Peter Anvin movw %ss, %dx 2456b6815c6SH. Peter Anvin cmpw %ax, %dx # %ds == %ss? 2466b6815c6SH. Peter Anvin movw %sp, %dx 247*16252da6SJens Rottmann je 2f # -> assume %sp is reasonably set 2486b6815c6SH. Peter Anvin 249*16252da6SJens Rottmann # Invalid %ss, make up a new stack 250*16252da6SJens Rottmann movw $_end, %dx 251*16252da6SJens Rottmann testb $CAN_USE_HEAP, loadflags 252*16252da6SJens Rottmann jz 1f 253*16252da6SJens Rottmann movw heap_end_ptr, %dx 254*16252da6SJens Rottmann1: addw $STACK_SIZE, %dx 255*16252da6SJens Rottmann jnc 2f 256*16252da6SJens Rottmann xorw %dx, %dx # Prevent wraparound 257*16252da6SJens Rottmann 258*16252da6SJens Rottmann2: # Now %dx should point to the end of our stack space 2596b6815c6SH. Peter Anvin andw $~3, %dx # dword align (might as well...) 2606b6815c6SH. Peter Anvin jnz 3f 2616b6815c6SH. Peter Anvin movw $0xfffc, %dx # Make sure we're not zero 262*16252da6SJens Rottmann3: movw %ax, %ss 2636b6815c6SH. Peter Anvin movzwl %dx, %esp # Clear upper half of %esp 2646b6815c6SH. Peter Anvin sti # Now we should have a working stack 2656b6815c6SH. Peter Anvin 2666b6815c6SH. Peter Anvin# We will have entered with %cs = %ds+0x20, normalize %cs so 2676b6815c6SH. Peter Anvin# it is on par with the other segments. 2686b6815c6SH. Peter Anvin pushw %ds 2696b6815c6SH. Peter Anvin pushw $6f 2706b6815c6SH. Peter Anvin lretw 2716b6815c6SH. Peter Anvin6: 27296ae6ea0SThomas Gleixner 27396ae6ea0SThomas Gleixner# Check signature at end of setup 27496ae6ea0SThomas Gleixner cmpl $0x5a5aaa55, setup_sig 27596ae6ea0SThomas Gleixner jne setup_bad 27696ae6ea0SThomas Gleixner 27796ae6ea0SThomas Gleixner# Zero the bss 27896ae6ea0SThomas Gleixner movw $__bss_start, %di 27996ae6ea0SThomas Gleixner movw $_end+3, %cx 28096ae6ea0SThomas Gleixner xorl %eax, %eax 28196ae6ea0SThomas Gleixner subw %di, %cx 28296ae6ea0SThomas Gleixner shrw $2, %cx 28396ae6ea0SThomas Gleixner rep; stosl 28496ae6ea0SThomas Gleixner 28596ae6ea0SThomas Gleixner# Jump to C code (should not return) 28696ae6ea0SThomas Gleixner calll main 28796ae6ea0SThomas Gleixner 28896ae6ea0SThomas Gleixner# Setup corrupt somehow... 28996ae6ea0SThomas Gleixnersetup_bad: 29096ae6ea0SThomas Gleixner movl $setup_corrupt, %eax 29196ae6ea0SThomas Gleixner calll puts 29296ae6ea0SThomas Gleixner # Fall through... 29396ae6ea0SThomas Gleixner 29496ae6ea0SThomas Gleixner .globl die 29596ae6ea0SThomas Gleixner .type die, @function 29696ae6ea0SThomas Gleixnerdie: 29796ae6ea0SThomas Gleixner hlt 29896ae6ea0SThomas Gleixner jmp die 29996ae6ea0SThomas Gleixner 30096ae6ea0SThomas Gleixner .size die, .-die 30196ae6ea0SThomas Gleixner 30296ae6ea0SThomas Gleixner .section ".initdata", "a" 30396ae6ea0SThomas Gleixnersetup_corrupt: 30496ae6ea0SThomas Gleixner .byte 7 30596ae6ea0SThomas Gleixner .string "No setup signature found...\n" 306