forked from Minki/linux
5e47c478b0
Impact: obsolete feature removal The zImage kernel format has been functionally unused for a very long time. It is just barely possible to build a modern kernel that still fits within the zImage size limit, but it is highly unlikely that anyone ever uses it. Furthermore, although it is still supported by most bootloaders, it has been at best poorly tested (or not tested at all); some bootloaders are even known to not support zImage at all and not having even noticed. Also remove some really obsolete constants that no longer have any meaning. LKML-Reference: <49B703D4.1000008@zytor.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
127 lines
3.0 KiB
C
127 lines
3.0 KiB
C
/* -*- linux-c -*- ------------------------------------------------------- *
|
|
*
|
|
* Copyright (C) 1991, 1992 Linus Torvalds
|
|
* Copyright 2007 rPath, Inc. - All Rights Reserved
|
|
*
|
|
* This file is part of the Linux kernel, and is made available under
|
|
* the terms of the GNU General Public License version 2.
|
|
*
|
|
* ----------------------------------------------------------------------- */
|
|
|
|
/*
|
|
* Prepare the machine for transition to protected mode.
|
|
*/
|
|
|
|
#include "boot.h"
|
|
#include <asm/segment.h>
|
|
|
|
/*
|
|
* Invoke the realmode switch hook if present; otherwise
|
|
* disable all interrupts.
|
|
*/
|
|
static void realmode_switch_hook(void)
|
|
{
|
|
if (boot_params.hdr.realmode_swtch) {
|
|
asm volatile("lcallw *%0"
|
|
: : "m" (boot_params.hdr.realmode_swtch)
|
|
: "eax", "ebx", "ecx", "edx");
|
|
} else {
|
|
asm volatile("cli");
|
|
outb(0x80, 0x70); /* Disable NMI */
|
|
io_delay();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Disable all interrupts at the legacy PIC.
|
|
*/
|
|
static void mask_all_interrupts(void)
|
|
{
|
|
outb(0xff, 0xa1); /* Mask all interrupts on the secondary PIC */
|
|
io_delay();
|
|
outb(0xfb, 0x21); /* Mask all but cascade on the primary PIC */
|
|
io_delay();
|
|
}
|
|
|
|
/*
|
|
* Reset IGNNE# if asserted in the FPU.
|
|
*/
|
|
static void reset_coprocessor(void)
|
|
{
|
|
outb(0, 0xf0);
|
|
io_delay();
|
|
outb(0, 0xf1);
|
|
io_delay();
|
|
}
|
|
|
|
/*
|
|
* Set up the GDT
|
|
*/
|
|
|
|
struct gdt_ptr {
|
|
u16 len;
|
|
u32 ptr;
|
|
} __attribute__((packed));
|
|
|
|
static void setup_gdt(void)
|
|
{
|
|
/* There are machines which are known to not boot with the GDT
|
|
being 8-byte unaligned. Intel recommends 16 byte alignment. */
|
|
static const u64 boot_gdt[] __attribute__((aligned(16))) = {
|
|
/* CS: code, read/execute, 4 GB, base 0 */
|
|
[GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
|
|
/* DS: data, read/write, 4 GB, base 0 */
|
|
[GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
|
|
/* TSS: 32-bit tss, 104 bytes, base 4096 */
|
|
/* We only have a TSS here to keep Intel VT happy;
|
|
we don't actually use it for anything. */
|
|
[GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
|
|
};
|
|
/* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead
|
|
of the gdt_ptr contents. Thus, make it static so it will
|
|
stay in memory, at least long enough that we switch to the
|
|
proper kernel GDT. */
|
|
static struct gdt_ptr gdt;
|
|
|
|
gdt.len = sizeof(boot_gdt)-1;
|
|
gdt.ptr = (u32)&boot_gdt + (ds() << 4);
|
|
|
|
asm volatile("lgdtl %0" : : "m" (gdt));
|
|
}
|
|
|
|
/*
|
|
* Set up the IDT
|
|
*/
|
|
static void setup_idt(void)
|
|
{
|
|
static const struct gdt_ptr null_idt = {0, 0};
|
|
asm volatile("lidtl %0" : : "m" (null_idt));
|
|
}
|
|
|
|
/*
|
|
* Actual invocation sequence
|
|
*/
|
|
void go_to_protected_mode(void)
|
|
{
|
|
/* Hook before leaving real mode, also disables interrupts */
|
|
realmode_switch_hook();
|
|
|
|
/* Enable the A20 gate */
|
|
if (enable_a20()) {
|
|
puts("A20 gate not responding, unable to boot...\n");
|
|
die();
|
|
}
|
|
|
|
/* Reset coprocessor (IGNNE#) */
|
|
reset_coprocessor();
|
|
|
|
/* Mask all interrupts in the PIC */
|
|
mask_all_interrupts();
|
|
|
|
/* Actual transition to protected mode... */
|
|
setup_idt();
|
|
setup_gdt();
|
|
protected_mode_jump(boot_params.hdr.code32_start,
|
|
(u32)&boot_params + (ds() << 4));
|
|
}
|