/* -*- 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 #include #include #include "boot.h" /* be aware of: */ THIS_IS_REALMODE_CODE /* * While we are in flat mode, we can't handle interrupts. But we can't * switch them off for ever in the PIC, because we need them again while * entering real mode code again and again.... */ static void __bootcode realmode_switch_hook(void) { asm volatile("cli"); outb(0x80, 0x70); /* Disable NMI */ io_delay(); } /* * Reset IGNNE# if asserted in the FPU. */ static void __bootcode reset_coprocessor(void) { outb(0, 0xf0); io_delay(); outb(0, 0xf1); io_delay(); } /** * Setup and register the global descriptor table (GDT) * * @note This is for the first time only */ static void __bootcode setup_gdt(void) { /* 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 __bootdata gdt_ptr; gdt_ptr.len = gdt_size - 1; gdt_ptr.ptr = (uint32_t)&gdt + (ds() << 4); asm volatile("lgdtl %0" : : "m" (gdt_ptr)); } static char a20_message[] __bootdata = "A20 gate not responding, unable to boot...\n"; /* * Actual invocation sequence */ void __bootcode start_pre_uboot(void) { /* Hook before leaving real mode, also disables interrupts */ realmode_switch_hook(); /* Enable the A20 gate */ if (enable_a20()) { boot_puts(a20_message); die(); } /* Reset coprocessor (IGNNE#) */ reset_coprocessor(); setup_gdt(); /* Actual transition to protected mode... */ protected_mode_jump(); }