/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009,2010 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
/* The code segment of the protected mode. */
/* The data segment of the protected mode. */
#include "relocator_common.S"
/* Update other registers. */
#ifdef __x86_64__
/* Disable amd64. */
#endif
/* Turn off PAE. */
/* Update other registers. */
/* jump to a 16 bit segment */
/* clear the PE bit of CR0 */
/* flush prefetch queue, reload %cs */
/* ljmp */
.byte 0xea
.word 0
/* movw imm16, %ax. */
.byte 0xb8
.word 0
/* first of all, test if already in a good state */
/* second, try a BIOS call */
int $0x15
/*
* In macbook, the keyboard test would hang the machine, so we move
* this forward.
*/
/* fourth, try the system control port A */
inb $0x92
outb $0x92
/* When turning off Gate A20, do not check the state strictly,
because a failure is not fatal usually, and Gate A20 is always
on some modern machines. */
/* iterate the checking for a while */
1:
call 3f
jz 2f
loop 1b
2:
3:
/* compare the byte at ADDR with that at 0x100000 + ADDR */
/* save the original byte in DL */
/* try to set one less value at ADDR */
/* serialize */
/* obtain the value at 0x100000 + ADDR in CH */
/* this result is 1 if A20 is on or 0 if it is off */
/* restore the original */
/* we are in real mode now
* set up the real mode segment registers : DS, SS, ES
*/
/* movw imm16, %ax. */
.byte 0xb8
.word 0
/* movw imm16, %ax. */
.byte 0xb8
.word 0
/* movw imm16, %ax. */
.byte 0xb8
.word 0
/* movw imm16, %ax. */
.byte 0xb8
.word 0
/* movw imm16, %ax. */
.byte 0xb8
.word 0
/* movw imm16, %ax. */
.byte 0xb8
.word 0
/* movw imm32, %eax. */
.long 0
/* movw imm32, %edx. */
.long 0
/* movw imm32, %ebx. */
.long 0
/* Cleared direction flag is of no problem with any current
payload and makes this implementation easier. */
/* ljmp */
.byte 0xea
.word 0
.word 0
.p2align 4
.word 0, 0
.byte 0, 0, 0, 0
/* -- code segment --
* base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present
*/
.word 0xFFFF, 0
/* -- data segment --
* base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present
*/
.word 0xFFFF, 0
/* -- 16 bit real mode CS --
* base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
* type = 16 bit code execute/read only/conforming, DPL = 0
*/
.word 0xFFFF
.word 0
.byte 0
.byte 0x9E, 0, 0
/* -- 16 bit real mode DS --
* base = 0x00000000, limit 0x0FFFF (1 B Granularity), present
*/
.word 0xFFFF, 0
.byte 0, 0x92, 0, 0