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" 2577d1a499SH. Peter Anvin#include "voffset.h" 2677d1a499SH. Peter Anvin#include "zoffset.h" 2796ae6ea0SThomas Gleixner 2896ae6ea0SThomas GleixnerBOOTSEG = 0x07C0 /* original address of boot-sector */ 295e47c478SH. Peter AnvinSYSSEG = 0x1000 /* historical load address >> 4 */ 3096ae6ea0SThomas Gleixner 3196ae6ea0SThomas Gleixner#ifndef SVGA_MODE 3296ae6ea0SThomas Gleixner#define SVGA_MODE ASK_VGA 3396ae6ea0SThomas Gleixner#endif 3496ae6ea0SThomas Gleixner 3596ae6ea0SThomas Gleixner#ifndef RAMDISK 3696ae6ea0SThomas Gleixner#define RAMDISK 0 3796ae6ea0SThomas Gleixner#endif 3896ae6ea0SThomas Gleixner 3996ae6ea0SThomas Gleixner#ifndef ROOT_RDONLY 4096ae6ea0SThomas Gleixner#define ROOT_RDONLY 1 4196ae6ea0SThomas Gleixner#endif 4296ae6ea0SThomas Gleixner 4396ae6ea0SThomas Gleixner .code16 4496ae6ea0SThomas Gleixner .section ".bstext", "ax" 4596ae6ea0SThomas Gleixner 4696ae6ea0SThomas Gleixner .global bootsect_start 4796ae6ea0SThomas Gleixnerbootsect_start: 4896ae6ea0SThomas Gleixner 4996ae6ea0SThomas Gleixner # Normalize the start address 5096ae6ea0SThomas Gleixner ljmp $BOOTSEG, $start2 5196ae6ea0SThomas Gleixner 5296ae6ea0SThomas Gleixnerstart2: 5396ae6ea0SThomas Gleixner movw %cs, %ax 5496ae6ea0SThomas Gleixner movw %ax, %ds 5596ae6ea0SThomas Gleixner movw %ax, %es 5696ae6ea0SThomas Gleixner movw %ax, %ss 5796ae6ea0SThomas Gleixner xorw %sp, %sp 5896ae6ea0SThomas Gleixner sti 5996ae6ea0SThomas Gleixner cld 6096ae6ea0SThomas Gleixner 6196ae6ea0SThomas Gleixner movw $bugger_off_msg, %si 6296ae6ea0SThomas Gleixner 6396ae6ea0SThomas Gleixnermsg_loop: 6496ae6ea0SThomas Gleixner lodsb 6596ae6ea0SThomas Gleixner andb %al, %al 6696ae6ea0SThomas Gleixner jz bs_die 6796ae6ea0SThomas Gleixner movb $0xe, %ah 6896ae6ea0SThomas Gleixner movw $7, %bx 6996ae6ea0SThomas Gleixner int $0x10 7096ae6ea0SThomas Gleixner jmp msg_loop 7196ae6ea0SThomas Gleixner 7296ae6ea0SThomas Gleixnerbs_die: 7396ae6ea0SThomas Gleixner # Allow the user to press a key, then reboot 7496ae6ea0SThomas Gleixner xorw %ax, %ax 7596ae6ea0SThomas Gleixner int $0x16 7696ae6ea0SThomas Gleixner int $0x19 7796ae6ea0SThomas Gleixner 7896ae6ea0SThomas Gleixner # int 0x19 should never return. In case it does anyway, 7996ae6ea0SThomas Gleixner # invoke the BIOS reset code... 8096ae6ea0SThomas Gleixner ljmp $0xf000,$0xfff0 8196ae6ea0SThomas Gleixner 8296ae6ea0SThomas Gleixner .section ".bsdata", "a" 8396ae6ea0SThomas Gleixnerbugger_off_msg: 8496ae6ea0SThomas Gleixner .ascii "Direct booting from floppy is no longer supported.\r\n" 8596ae6ea0SThomas Gleixner .ascii "Please use a boot loader program instead.\r\n" 8696ae6ea0SThomas Gleixner .ascii "\n" 8796ae6ea0SThomas Gleixner .ascii "Remove disk and press any key to reboot . . .\r\n" 8896ae6ea0SThomas Gleixner .byte 0 8996ae6ea0SThomas Gleixner 9096ae6ea0SThomas Gleixner 9196ae6ea0SThomas Gleixner # Kernel attributes; used by setup. This is part 1 of the 9296ae6ea0SThomas Gleixner # header, from the old boot sector. 9396ae6ea0SThomas Gleixner 9496ae6ea0SThomas Gleixner .section ".header", "a" 9596ae6ea0SThomas Gleixner .globl hdr 9696ae6ea0SThomas Gleixnerhdr: 975e47c478SH. Peter Anvinsetup_sects: .byte 0 /* Filled in by build.c */ 9896ae6ea0SThomas Gleixnerroot_flags: .word ROOT_RDONLY 995e47c478SH. Peter Anvinsyssize: .long 0 /* Filled in by build.c */ 1005e47c478SH. Peter Anvinram_size: .word 0 /* Obsolete */ 10196ae6ea0SThomas Gleixnervid_mode: .word SVGA_MODE 1025e47c478SH. Peter Anvinroot_dev: .word 0 /* Filled in by build.c */ 10396ae6ea0SThomas Gleixnerboot_flag: .word 0xAA55 10496ae6ea0SThomas Gleixner 10596ae6ea0SThomas Gleixner # offset 512, entry point 10696ae6ea0SThomas Gleixner 10796ae6ea0SThomas Gleixner .globl _start 10896ae6ea0SThomas Gleixner_start: 10996ae6ea0SThomas Gleixner # Explicitly enter this as bytes, or the assembler 11096ae6ea0SThomas Gleixner # tries to generate a 3-byte jump here, which causes 11196ae6ea0SThomas Gleixner # everything else to push off to the wrong offset. 11296ae6ea0SThomas Gleixner .byte 0xeb # short (2-byte) jump 11396ae6ea0SThomas Gleixner .byte start_of_setup-1f 11496ae6ea0SThomas Gleixner1: 11596ae6ea0SThomas Gleixner 11696ae6ea0SThomas Gleixner # Part 2 of the header, from the old setup.S 11796ae6ea0SThomas Gleixner 11896ae6ea0SThomas Gleixner .ascii "HdrS" # header signature 11937ba7ab5SH. Peter Anvin .word 0x020a # header version number (>= 0x0105) 12096ae6ea0SThomas Gleixner # or else old loadlin-1.5 will fail) 12196ae6ea0SThomas Gleixner .globl realmode_swtch 12296ae6ea0SThomas Gleixnerrealmode_swtch: .word 0, 0 # default_switch, SETUPSEG 1235e47c478SH. Peter Anvinstart_sys_seg: .word SYSSEG # obsolete and meaningless, but just 1245e47c478SH. Peter Anvin # in case something decided to "use" it 12596ae6ea0SThomas Gleixner .word kernel_version-512 # pointing to kernel version string 12696ae6ea0SThomas Gleixner # above section of header is compatible 12796ae6ea0SThomas Gleixner # with loadlin-1.5 (header v1.5). Don't 12896ae6ea0SThomas Gleixner # change it. 12996ae6ea0SThomas Gleixner 1305e47c478SH. Peter Anvintype_of_loader: .byte 0 # 0 means ancient bootloader, newer 1315e47c478SH. Peter Anvin # bootloaders know to change this. 13296ae6ea0SThomas Gleixner # See Documentation/i386/boot.txt for 13396ae6ea0SThomas Gleixner # assigned ids 13496ae6ea0SThomas Gleixner 13596ae6ea0SThomas Gleixner# flags, unused bits must be zero (RFU) bit within loadflags 13696ae6ea0SThomas Gleixnerloadflags: 13796ae6ea0SThomas GleixnerLOADED_HIGH = 1 # If set, the kernel is loaded high 13896ae6ea0SThomas GleixnerCAN_USE_HEAP = 0x80 # If set, the loader also has set 13996ae6ea0SThomas Gleixner # heap_end_ptr to tell how much 14096ae6ea0SThomas Gleixner # space behind setup.S can be used for 14196ae6ea0SThomas Gleixner # heap purposes. 14296ae6ea0SThomas Gleixner # Only the loader knows what is free 14396ae6ea0SThomas Gleixner .byte LOADED_HIGH 14496ae6ea0SThomas Gleixner 14596ae6ea0SThomas Gleixnersetup_move_size: .word 0x8000 # size to move, when setup is not 14696ae6ea0SThomas Gleixner # loaded at 0x90000. We will move setup 14796ae6ea0SThomas Gleixner # to 0x90000 then just before jumping 14896ae6ea0SThomas Gleixner # into the kernel. However, only the 14996ae6ea0SThomas Gleixner # loader knows how much data behind 15096ae6ea0SThomas Gleixner # us also needs to be loaded. 15196ae6ea0SThomas Gleixner 15296ae6ea0SThomas Gleixnercode32_start: # here loaders can put a different 15396ae6ea0SThomas Gleixner # start address for 32-bit code. 15496ae6ea0SThomas Gleixner .long 0x100000 # 0x100000 = default for big kernel 15596ae6ea0SThomas Gleixner 15696ae6ea0SThomas Gleixnerramdisk_image: .long 0 # address of loaded ramdisk image 15796ae6ea0SThomas Gleixner # Here the loader puts the 32-bit 15896ae6ea0SThomas Gleixner # address where it loaded the image. 15996ae6ea0SThomas Gleixner # This only will be read by the kernel. 16096ae6ea0SThomas Gleixner 16196ae6ea0SThomas Gleixnerramdisk_size: .long 0 # its size in bytes 16296ae6ea0SThomas Gleixner 16396ae6ea0SThomas Gleixnerbootsect_kludge: 16496ae6ea0SThomas Gleixner .long 0 # obsolete 16596ae6ea0SThomas Gleixner 1666b6815c6SH. Peter Anvinheap_end_ptr: .word _end+STACK_SIZE-512 1676b6815c6SH. Peter Anvin # (Header version 0x0201 or later) 16896ae6ea0SThomas Gleixner # space from here (exclusive) down to 16996ae6ea0SThomas Gleixner # end of setup code can be used by setup 17096ae6ea0SThomas Gleixner # for local heap purposes. 17196ae6ea0SThomas Gleixner 1725031296cSH. Peter Anvinext_loader_ver: 1735031296cSH. Peter Anvin .byte 0 # Extended boot loader version 1745031296cSH. Peter Anvinext_loader_type: 1755031296cSH. Peter Anvin .byte 0 # Extended boot loader type 1765031296cSH. Peter Anvin 17796ae6ea0SThomas Gleixnercmd_line_ptr: .long 0 # (Header version 0x0202 or later) 17896ae6ea0SThomas Gleixner # If nonzero, a 32-bit pointer 17996ae6ea0SThomas Gleixner # to the kernel command line. 18096ae6ea0SThomas Gleixner # The command line should be 18196ae6ea0SThomas Gleixner # located between the start of 18296ae6ea0SThomas Gleixner # setup and the end of low 18396ae6ea0SThomas Gleixner # memory (0xa0000), or it may 18496ae6ea0SThomas Gleixner # get overwritten before it 18596ae6ea0SThomas Gleixner # gets read. If this field is 18696ae6ea0SThomas Gleixner # used, there is no longer 18796ae6ea0SThomas Gleixner # anything magical about the 18896ae6ea0SThomas Gleixner # 0x90000 segment; the setup 18996ae6ea0SThomas Gleixner # can be located anywhere in 19096ae6ea0SThomas Gleixner # low memory 0x10000 or higher. 19196ae6ea0SThomas Gleixner 192cf8fa920SH. Peter Anvinramdisk_max: .long 0x7fffffff 19396ae6ea0SThomas Gleixner # (Header version 0x0203 or later) 19496ae6ea0SThomas Gleixner # The highest safe address for 19596ae6ea0SThomas Gleixner # the contents of an initrd 196cf8fa920SH. Peter Anvin # The current kernel allows up to 4 GB, 197cf8fa920SH. Peter Anvin # but leave it at 2 GB to avoid 198cf8fa920SH. Peter Anvin # possible bootloader bugs. 19996ae6ea0SThomas Gleixner 20096ae6ea0SThomas Gleixnerkernel_alignment: .long CONFIG_PHYSICAL_ALIGN #physical addr alignment 20196ae6ea0SThomas Gleixner #required for protected mode 20296ae6ea0SThomas Gleixner #kernel 20396ae6ea0SThomas Gleixner#ifdef CONFIG_RELOCATABLE 20496ae6ea0SThomas Gleixnerrelocatable_kernel: .byte 1 20596ae6ea0SThomas Gleixner#else 20696ae6ea0SThomas Gleixnerrelocatable_kernel: .byte 0 20796ae6ea0SThomas Gleixner#endif 20837ba7ab5SH. Peter Anvinmin_alignment: .byte MIN_KERNEL_ALIGN_LG2 # minimum alignment 20996ae6ea0SThomas Gleixnerpad3: .word 0 21096ae6ea0SThomas Gleixner 21196ae6ea0SThomas Gleixnercmdline_size: .long COMMAND_LINE_SIZE-1 #length of the command line, 21296ae6ea0SThomas Gleixner #added with boot protocol 21396ae6ea0SThomas Gleixner #version 2.06 21496ae6ea0SThomas Gleixner 215a24e7851SRusty Russellhardware_subarch: .long 0 # subarchitecture, added with 2.07 216a24e7851SRusty Russell # default to 0 for normal x86 PC 217a24e7851SRusty Russell 218a24e7851SRusty Russellhardware_subarch_data: .quad 0 219a24e7851SRusty Russell 22077d1a499SH. Peter Anvinpayload_offset: .long ZO_input_data 22177d1a499SH. Peter Anvinpayload_length: .long ZO_z_input_len 222099e1377SIan Campbell 2238b664aa6SHuang, Yingsetup_data: .quad 0 # 64-bit physical pointer to 2248b664aa6SHuang, Ying # single linked list of 2258b664aa6SHuang, Ying # struct setup_data 2268b664aa6SHuang, Ying 22737ba7ab5SH. Peter Anvinpref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr 22837ba7ab5SH. Peter Anvin 22937ba7ab5SH. Peter Anvin#define ZO_INIT_SIZE (ZO__end - ZO_startup_32 + ZO_extract_offset) 23037ba7ab5SH. Peter Anvin#define VO_INIT_SIZE (VO__end - VO__text) 23137ba7ab5SH. Peter Anvin#if ZO_INIT_SIZE > VO_INIT_SIZE 23237ba7ab5SH. Peter Anvin#define INIT_SIZE ZO_INIT_SIZE 23337ba7ab5SH. Peter Anvin#else 23437ba7ab5SH. Peter Anvin#define INIT_SIZE VO_INIT_SIZE 23537ba7ab5SH. Peter Anvin#endif 23637ba7ab5SH. Peter Anvininit_size: .long INIT_SIZE # kernel initialization size 23737ba7ab5SH. Peter Anvin 23896ae6ea0SThomas Gleixner# End of setup header ##################################################### 23996ae6ea0SThomas Gleixner 24096ae6ea0SThomas Gleixner .section ".inittext", "ax" 24196ae6ea0SThomas Gleixnerstart_of_setup: 24296ae6ea0SThomas Gleixner#ifdef SAFE_RESET_DISK_CONTROLLER 24396ae6ea0SThomas Gleixner# Reset the disk controller. 24496ae6ea0SThomas Gleixner movw $0x0000, %ax # Reset disk controller 24596ae6ea0SThomas Gleixner movb $0x80, %dl # All disks 24696ae6ea0SThomas Gleixner int $0x13 24796ae6ea0SThomas Gleixner#endif 24896ae6ea0SThomas Gleixner 24996ae6ea0SThomas Gleixner# Force %es = %ds 25096ae6ea0SThomas Gleixner movw %ds, %ax 25196ae6ea0SThomas Gleixner movw %ax, %es 25296ae6ea0SThomas Gleixner cld 25396ae6ea0SThomas Gleixner 25416252da6SJens Rottmann# Apparently some ancient versions of LILO invoked the kernel with %ss != %ds, 25516252da6SJens Rottmann# which happened to work by accident for the old code. Recalculate the stack 25616252da6SJens Rottmann# pointer if %ss is invalid. Otherwise leave it alone, LOADLIN sets up the 25716252da6SJens Rottmann# stack behind its own code, so we can't blindly put it directly past the heap. 2586b6815c6SH. Peter Anvin 2596b6815c6SH. Peter Anvin movw %ss, %dx 2606b6815c6SH. Peter Anvin cmpw %ax, %dx # %ds == %ss? 2616b6815c6SH. Peter Anvin movw %sp, %dx 26216252da6SJens Rottmann je 2f # -> assume %sp is reasonably set 2636b6815c6SH. Peter Anvin 26416252da6SJens Rottmann # Invalid %ss, make up a new stack 26516252da6SJens Rottmann movw $_end, %dx 26616252da6SJens Rottmann testb $CAN_USE_HEAP, loadflags 26716252da6SJens Rottmann jz 1f 26816252da6SJens Rottmann movw heap_end_ptr, %dx 26916252da6SJens Rottmann1: addw $STACK_SIZE, %dx 27016252da6SJens Rottmann jnc 2f 27116252da6SJens Rottmann xorw %dx, %dx # Prevent wraparound 27216252da6SJens Rottmann 27316252da6SJens Rottmann2: # Now %dx should point to the end of our stack space 2746b6815c6SH. Peter Anvin andw $~3, %dx # dword align (might as well...) 2756b6815c6SH. Peter Anvin jnz 3f 2766b6815c6SH. Peter Anvin movw $0xfffc, %dx # Make sure we're not zero 27716252da6SJens Rottmann3: movw %ax, %ss 2786b6815c6SH. Peter Anvin movzwl %dx, %esp # Clear upper half of %esp 2796b6815c6SH. Peter Anvin sti # Now we should have a working stack 2806b6815c6SH. Peter Anvin 2816b6815c6SH. Peter Anvin# We will have entered with %cs = %ds+0x20, normalize %cs so 2826b6815c6SH. Peter Anvin# it is on par with the other segments. 2836b6815c6SH. Peter Anvin pushw %ds 2846b6815c6SH. Peter Anvin pushw $6f 2856b6815c6SH. Peter Anvin lretw 2866b6815c6SH. Peter Anvin6: 28796ae6ea0SThomas Gleixner 28896ae6ea0SThomas Gleixner# Check signature at end of setup 28996ae6ea0SThomas Gleixner cmpl $0x5a5aaa55, setup_sig 29096ae6ea0SThomas Gleixner jne setup_bad 29196ae6ea0SThomas Gleixner 29296ae6ea0SThomas Gleixner# Zero the bss 29396ae6ea0SThomas Gleixner movw $__bss_start, %di 29496ae6ea0SThomas Gleixner movw $_end+3, %cx 29596ae6ea0SThomas Gleixner xorl %eax, %eax 29696ae6ea0SThomas Gleixner subw %di, %cx 29796ae6ea0SThomas Gleixner shrw $2, %cx 29896ae6ea0SThomas Gleixner rep; stosl 29996ae6ea0SThomas Gleixner 30096ae6ea0SThomas Gleixner# Jump to C code (should not return) 30196ae6ea0SThomas Gleixner calll main 30296ae6ea0SThomas Gleixner 30396ae6ea0SThomas Gleixner# Setup corrupt somehow... 30496ae6ea0SThomas Gleixnersetup_bad: 30596ae6ea0SThomas Gleixner movl $setup_corrupt, %eax 30696ae6ea0SThomas Gleixner calll puts 30796ae6ea0SThomas Gleixner # Fall through... 30896ae6ea0SThomas Gleixner 30996ae6ea0SThomas Gleixner .globl die 31096ae6ea0SThomas Gleixner .type die, @function 31196ae6ea0SThomas Gleixnerdie: 31296ae6ea0SThomas Gleixner hlt 31396ae6ea0SThomas Gleixner jmp die 31496ae6ea0SThomas Gleixner 31596ae6ea0SThomas Gleixner .size die, .-die 31696ae6ea0SThomas Gleixner 31796ae6ea0SThomas Gleixner .section ".initdata", "a" 31896ae6ea0SThomas Gleixnersetup_corrupt: 31996ae6ea0SThomas Gleixner .byte 7 32096ae6ea0SThomas Gleixner .string "No setup signature found...\n" 321