a24e785111
This patch uses the updated boot protocol to do paravirtualized boot. If the boot version is >= 2.07, then it will do two things: 1. Check the bootparams loadflags to see if we should reload the segment registers and clear interrupts. This is appropriate for normal native boot and some paravirtualized environments, but inapproprate for others. 2. Check the hardware architecture, and dispatch to the appropriate kernel entrypoint. If the bootloader doesn't set this, then we simply do the normal boot sequence. Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> Acked-by: H. Peter Anvin <hpa@zytor.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Vivek Goyal <vgoyal@in.ibm.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Cc: Zachary Amsden <zach@vmware.com> Cc: Andi Kleen <ak@suse.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
289 lines
7.1 KiB
ArmAsm
289 lines
7.1 KiB
ArmAsm
/*
|
|
* 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 <linux/utsrelease.h>
|
|
#include <asm/boot.h>
|
|
#include <asm/e820.h>
|
|
#include <asm/page.h>
|
|
#include <asm/setup.h>
|
|
#include "boot.h"
|
|
|
|
SETUPSECTS = 4 /* default nr of setup-sectors */
|
|
BOOTSEG = 0x07C0 /* original address of boot-sector */
|
|
SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */
|
|
SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */
|
|
/* to be loaded */
|
|
ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */
|
|
SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */
|
|
|
|
#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 SETUPSECTS
|
|
root_flags: .word ROOT_RDONLY
|
|
syssize: .long SYSSIZE
|
|
ram_size: .word RAMDISK
|
|
vid_mode: .word SVGA_MODE
|
|
root_dev: .word ROOT_DEV
|
|
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 0x0207 # 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
|
|
.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, old one (LILO, Loadlin,
|
|
# Bootlin, SYSLX, bootsect...)
|
|
# 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
|
|
#ifndef __BIG_KERNEL__
|
|
.byte 0
|
|
#else
|
|
.byte LOADED_HIGH
|
|
#endif
|
|
|
|
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.
|
|
#ifndef __BIG_KERNEL__
|
|
.long 0x1000 # 0x1000 = default for zImage
|
|
#else
|
|
.long 0x100000 # 0x100000 = default for big kernel
|
|
#endif
|
|
|
|
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+1024 # (Header version 0x0201 or later)
|
|
# space from here (exclusive) down to
|
|
# end of setup code can be used by setup
|
|
# for local heap purposes.
|
|
|
|
pad1: .word 0
|
|
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 (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
|
|
# (Header version 0x0203 or later)
|
|
# The highest safe address for
|
|
# the contents of an initrd
|
|
|
|
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
|
|
pad2: .byte 0
|
|
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
|
|
|
|
# End of setup header #####################################################
|
|
|
|
.section ".inittext", "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
|
|
|
|
# We will have entered with %cs = %ds+0x20, normalize %cs so
|
|
# it is on par with the other segments.
|
|
pushw %ds
|
|
pushw $setup2
|
|
lretw
|
|
|
|
setup2:
|
|
# Force %es = %ds
|
|
movw %ds, %ax
|
|
movw %ax, %es
|
|
cld
|
|
|
|
# Stack paranoia: align the stack and make sure it is good
|
|
# for both 16- and 32-bit references. In particular, if we
|
|
# were meant to have been using the full 16-bit segment, the
|
|
# caller might have set %sp to zero, which breaks %esp-based
|
|
# references.
|
|
andw $~3, %sp # dword align (might as well...)
|
|
jnz 1f
|
|
movw $0xfffc, %sp # Make sure we're not zero
|
|
1: movzwl %sp, %esp # Clear upper half of %esp
|
|
sti
|
|
|
|
# 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"
|