Use decompressors framework on i386-pc. It increases core size

by 46 bytes but improves compatibility and maintainability.

	* grub-core/Makefile.core.def (lzma_decompress): New image.
	(kernel): Add i386_pc_ldflags.
	* grub-core/kern/i386/pc/startup.S: Move intial part to ..
	* grub-core/boot/i386/pc/startup_raw.S: ... here. Pass pointers
	to real_to_prot, prot_to_real and device info.
	* include/grub/offsets.h: Renamed decompressor offsets.
	* util/grub-mkimage.c (grub_compression_t): New cmpression lzma.
	(image_target_desc): Remove raw_size and rename decompressor fields.
	(compress_kernel): Handle lzma.
	(generate_image): Handle decompressors on i386-pc.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-11-12 19:53:25 +01:00
parent e9d3421c05
commit 60240b8bc1
12 changed files with 601 additions and 486 deletions

View file

@ -34,7 +34,7 @@ kernel = {
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
@ -356,6 +356,15 @@ image = {
enable = mips;
};
image = {
name = lzma_decompress;
i386_pc = boot/i386/pc/startup_raw.S;
objcopyflags = '-O binary';
ldflags = '-Wl,-Ttext,0x8200';
enable = i386_pc;
};
image = {
name = fwstart;
mips_loongson = boot/mips/loongson/fwstart.S;

View file

@ -199,12 +199,8 @@ real_code_2:
1:
movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
#else
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
#endif
movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
2:
call LOCAL(move_memory)

View file

@ -0,0 +1,369 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/>.
*/
#include <config.h>
#include <grub/symbol.h>
#include <grub/offsets.h>
#include <grub/machine/boot.h>
#include <grub/machine/memory.h>
#include <grub/machine/kernel.h>
#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
.file "startup_raw.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
.code16
.globl start, _start
start:
_start:
LOCAL (base):
/*
* Guarantee that "main" is loaded at 0x0:0x8200.
*/
#ifdef __APPLE__
ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
#else
ljmp $0, $ABS(LOCAL (codestart))
#endif
/*
* This is a special data area.
*/
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
LOCAL(compressed_size):
.long 0
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
LOCAL(uncompressed_size):
.long 0
. = _start + GRUB_KERNEL_I386_PC_INSTALL_DOS_PART
LOCAL(dos_part):
.long 0xFFFFFFFF
. = _start + GRUB_KERNEL_I386_PC_INSTALL_BSD_PART
LOCAL(bsd_part):
.long 0xFFFFFFFF
. = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
reed_solomon_redundancy:
.long 0
/*
* This is the area for all of the special variables.
*/
LOCAL(boot_drive):
.byte 0
/* the real mode code continues... */
LOCAL (codestart):
cli /* we're not safe here! */
/* set up %ds, %ss, and %es */
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
/* set up the real mode/BIOS stack */
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
movl %ebp, %esp
sti /* we're safe again */
/* save the boot drive */
ADDR32 movb %dl, LOCAL(boot_drive)
/* reset disk system (%ah = 0) */
int $0x13
/* transition to protected mode */
DATA32 call real_to_prot
/* The ".code32" directive takes GAS out of 16-bit mode. */
.code32
incl %eax
call grub_gate_a20
movl LOCAL(compressed_size), %edx
addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx
movl reed_solomon_redundancy, %ecx
leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax
call EXT_C (grub_reed_solomon_recover)
jmp post_reed_solomon
#include <rs_decoder.S>
.text
. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART
/*
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
* This uses the a.out kludge to load raw binary to the area starting at 1MB,
* and relocates itself after loaded.
*/
.p2align 2 /* force 4-byte alignment */
multiboot_header:
/* magic */
.long 0x1BADB002
/* flags */
.long (1 << 16)
/* checksum */
.long -0x1BADB002 - (1 << 16)
/* header addr */
.long multiboot_header - _start + 0x100000 + 0x200
/* load addr */
.long 0x100000
/* load end addr */
.long 0
/* bss end addr */
.long 0
/* entry addr */
.long multiboot_entry - _start + 0x100000 + 0x200
multiboot_entry:
.code32
/* obtain the boot device */
movl 12(%ebx), %edx
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
movl %ebp, %esp
/* relocate the code */
movl $(LOCAL(decompressor_end) + 0x200), %ecx
addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx
movl $0x100000, %esi
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
cld
rep
movsb
/* jump to the real address */
movl $multiboot_trampoline, %eax
jmp *%eax
multiboot_trampoline:
/* fill the boot information */
movl %edx, %eax
shrl $8, %eax
xorl %ebx, %ebx
cmpb $0xFF, %ah
je 1f
movb %ah, %bl
movl %ebx, LOCAL(dos_part)
1:
cmpb $0xFF, %al
je 2f
movb %al, %bl
movl %ebx, LOCAL(bsd_part)
2:
shrl $24, %edx
movb %dl, LOCAL(boot_drive)
movb $0xFF, %dh
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %esp
/* enter the usual booting */
call prot_to_real
.code16
jmp LOCAL (codestart)
.code32
post_reed_solomon:
#ifdef ENABLE_LZMA
movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
movl $LOCAL(decompressor_end), %esi
pushl %edi
movl LOCAL (uncompressed_size), %ecx
leal (%edi, %ecx), %ebx
call _LzmaDecodeA
/* _LzmaDecodeA clears DF, so no need to run cld */
popl %esi
#endif
movb LOCAL(boot_drive), %dl
movl LOCAL(dos_part), %eax
movl LOCAL(bsd_part), %ebx
movl $prot_to_real, %edi
movl $real_to_prot, %ecx
jmp *%esi
#include "../../../kern/i386/realmode.S"
/*
* grub_gate_a20(int on)
*
* Gate address-line 20 for high memory.
*
* This routine is probably overconservative in what it does, but so what?
*
* It also eats any keystrokes in the keyboard buffer. :-(
*/
grub_gate_a20:
movl %eax, %edx
gate_a20_test_current_state:
/* first of all, test if already in a good state */
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_bios
ret
gate_a20_try_bios:
/* second, try a BIOS call */
pushl %ebp
call prot_to_real
.code16
movw $0x2400, %ax
testb %dl, %dl
jz 1f
incw %ax
1: int $0x15
DATA32 call real_to_prot
.code32
popl %ebp
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_system_control_port_a
ret
gate_a20_try_system_control_port_a:
/*
* In macbook, the keyboard test would hang the machine, so we move
* this forward.
*/
/* fourth, try the system control port A */
inb $0x92
andb $(~0x03), %al
testb %dl, %dl
jz 6f
orb $0x02, %al
6: 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. */
testb %dl, %dl
jz 7f
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_keyboard_controller
7: ret
gate_a20_flush_keyboard_buffer:
inb $0x64
andb $0x02, %al
jnz gate_a20_flush_keyboard_buffer
2:
inb $0x64
andb $0x01, %al
jz 3f
inb $0x60
jmp 2b
3:
ret
gate_a20_try_keyboard_controller:
/* third, try the keyboard controller */
call gate_a20_flush_keyboard_buffer
movb $0xd1, %al
outb $0x64
4:
inb $0x64
andb $0x02, %al
jnz 4b
movb $0xdd, %al
testb %dl, %dl
jz 5f
orb $0x02, %al
5: outb $0x60
call gate_a20_flush_keyboard_buffer
/* output a dummy command (USB keyboard hack) */
movb $0xff, %al
outb $0x64
call gate_a20_flush_keyboard_buffer
call gate_a20_check_state
cmpb %al, %dl
/* everything failed, so restart from the beginning */
jnz gate_a20_try_bios
ret
gate_a20_check_state:
/* iterate the checking for a while */
movl $100, %ecx
1:
call 3f
cmpb %al, %dl
jz 2f
loop 1b
2:
ret
3:
pushl %ebx
pushl %ecx
xorl %eax, %eax
/* compare the byte at 0x8000 with that at 0x108000 */
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
pushl %ebx
/* save the original byte in CL */
movb (%ebx), %cl
/* store the value at 0x108000 in AL */
addl $0x100000, %ebx
movb (%ebx), %al
/* try to set one less value at 0x8000 */
popl %ebx
movb %al, %ch
decb %ch
movb %ch, (%ebx)
/* serialize */
outb %al, $0x80
outb %al, $0x80
/* obtain the value at 0x108000 in CH */
pushl %ebx
addl $0x100000, %ebx
movb (%ebx), %ch
/* this result is 1 if A20 is on or 0 if it is off */
subb %ch, %al
xorb $1, %al
/* restore the original */
popl %ebx
movb %cl, (%ebx)
popl %ecx
popl %ebx
ret
#ifdef ENABLE_LZMA
#include "lzma_decode.S"
#endif
.p2align 2
LOCAL(decompressor_end):

View file

@ -38,13 +38,13 @@ start:
bal codestart
nop
base:
. = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
compressed_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
uncompressed_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
uncompressed_addr:
.long 0
codestart:

View file

@ -47,7 +47,7 @@ FUNCTION(grub_bios_interrupt)
movl 24(%edx), %esi
movl 28(%edx), %edx
call prot_to_real
PROT_TO_REAL
.code16
pushf
cli
@ -98,7 +98,7 @@ intno:
movw %ax, LOCAL(bios_register_es)
popf
DATA32 call real_to_prot
REAL_TO_PROT
.code32
popl %eax

View file

@ -156,8 +156,7 @@ grub_machine_init (void)
int grub_lower_mem;
#endif
grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR
+ ((_edata - _start) - GRUB_KERNEL_MACHINE_RAW_SIZE);
grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start);
/* Initialize the console as early as possible. */
grub_console_init ();

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -43,203 +43,30 @@
#include <config.h>
#include <grub/symbol.h>
#include <grub/machine/boot.h>
#include <grub/machine/memory.h>
#include <grub/machine/console.h>
#include <grub/cpu/linux.h>
#include <grub/machine/kernel.h>
#include <grub/term.h>
#include <multiboot.h>
#include <multiboot2.h>
#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
.file "startup.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
.code16
.globl start, _start
start:
_start:
LOCAL (base):
/*
* Guarantee that "main" is loaded at 0x0:0x8200.
*/
#ifdef __APPLE__
ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
#else
ljmp $0, $ABS(LOCAL (codestart))
#endif
/*
* This is a special data area.
*/
. = _start + GRUB_KERNEL_I386_PC_TOTAL_MODULE_SIZE
VARIABLE(grub_total_module_size)
.long 0
. = _start + GRUB_KERNEL_I386_PC_COMPRESSED_SIZE
VARIABLE(grub_compressed_size)
.long 0
. = _start + GRUB_KERNEL_I386_PC_INSTALL_DOS_PART
VARIABLE(grub_install_dos_part)
.long 0xFFFFFFFF
. = _start + GRUB_KERNEL_I386_PC_INSTALL_BSD_PART
VARIABLE(grub_install_bsd_part)
.long 0xFFFFFFFF
. = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
reed_solomon_redundancy:
.long 0
#ifdef APPLE_CC
bss_start:
.long 0
bss_end:
.long 0
#endif
/*
* This is the area for all of the special variables.
*/
VARIABLE(grub_boot_drive)
.byte 0
/* the real mode code continues... */
LOCAL (codestart):
cli /* we're not safe here! */
/* set up %ds, %ss, and %es */
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
/* set up the real mode/BIOS stack */
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
movl %ebp, %esp
sti /* we're safe again */
/* save the boot drive */
ADDR32 movb %dl, EXT_C(grub_boot_drive)
/* reset disk system (%ah = 0) */
int $0x13
/* transition to protected mode */
DATA32 call real_to_prot
/* The ".code32" directive takes GAS out of 16-bit mode. */
.code32
incl %eax
call grub_gate_a20
movl EXT_C(grub_compressed_size), %edx
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART), %edx
movl reed_solomon_redundancy, %ecx
leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax
call EXT_C (grub_reed_solomon_recover)
jmp post_reed_solomon
#include <rs_decoder.S>
.text
. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART
/*
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
* This uses the a.out kludge to load raw binary to the area starting at 1MB,
* and relocates itself after loaded.
*/
.p2align 2 /* force 4-byte alignment */
multiboot_header:
/* magic */
.long 0x1BADB002
/* flags */
.long (1 << 16)
/* checksum */
.long -0x1BADB002 - (1 << 16)
/* header addr */
.long multiboot_header - _start + 0x100000 + 0x200
/* load addr */
.long 0x100000
/* load end addr */
.long 0
/* bss end addr */
.long 0
/* entry addr */
.long multiboot_entry - _start + 0x100000 + 0x200
multiboot_entry:
.code32
/* obtain the boot device */
movl 12(%ebx), %edx
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
movl %ebp, %esp
/* relocate the code */
movl $(GRUB_KERNEL_MACHINE_RAW_SIZE + 0x200), %ecx
addl EXT_C(grub_compressed_size) - _start + 0x100000 + 0x200, %ecx
movl $0x100000, %esi
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
cld
rep
movsb
/* jump to the real address */
movl $multiboot_trampoline, %eax
jmp *%eax
multiboot_trampoline:
/* fill the boot information */
movl %edx, %eax
shrl $8, %eax
xorl %ebx, %ebx
cmpb $0xFF, %ah
je 1f
movb %ah, %bl
movl %ebx, EXT_C(grub_install_dos_part)
1:
cmpb $0xFF, %al
je 2f
movb %al, %bl
movl %ebx, EXT_C(grub_install_bsd_part)
2:
shrl $24, %edx
movb $0xFF, %dh
/* enter the usual booting */
call prot_to_real
jmp LOCAL (codestart)
post_reed_solomon:
#ifdef ENABLE_LZMA
movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
movl $(_start + GRUB_KERNEL_MACHINE_RAW_SIZE), %esi
pushl %edi
pushl %esi
movl $(BSS_START_SYMBOL - _start), %ecx
addl EXT_C(grub_total_module_size), %ecx
subl $GRUB_KERNEL_MACHINE_RAW_SIZE, %ecx
pushl %ecx
leal (%edi, %ecx), %ebx
call _LzmaDecodeA
/* _LzmaDecodeA clears DF, so no need to run cld */
popl %ecx
popl %edi
popl %esi
#endif
movl %ecx, (LOCAL(real_to_prot_addr) - _start) (%esi)
movl %edi, (LOCAL(prot_to_real_addr) - _start) (%esi)
/* copy back the decompressed part (except the modules) */
subl EXT_C(grub_total_module_size), %ecx
movl $(_edata - _start), %ecx
movl $(_start), %edi
rep
movsb
movl $LOCAL (cont), %esi
jmp *%esi
LOCAL(cont):
#if 0
/* copy modules before cleaning out the bss */
movl EXT_C(grub_total_module_size), %ecx
@ -255,24 +82,14 @@ post_reed_solomon:
movsb
#endif
#ifdef APPLE_CC
/* clean out the bss */
bss_start_abs = ABS (bss_start)
bss_end_abs = ABS (bss_end)
movl %eax, %esi
movl bss_start_abs, %edi
/* compute the bss length */
movl bss_end_abs, %ecx
subl %edi, %ecx
#else
/* clean out the bss */
movl $BSS_START_SYMBOL, %edi
/* compute the bss length */
movl $END_SYMBOL, %ecx
subl %edi, %ecx
#endif
/* clean out */
xorl %eax, %eax
@ -280,172 +97,29 @@ post_reed_solomon:
rep
stosb
movl %esi, EXT_C(grub_install_dos_part)
movb %dl, EXT_C(grub_boot_drive)
movl %ebx, EXT_C(grub_install_bsd_part)
/*
* Call the start of main body of C code.
*/
call EXT_C(grub_main)
#include "../realmode.S"
LOCAL(real_to_prot_addr):
.long 0
LOCAL(prot_to_real_addr):
.long 0
/*
* grub_gate_a20(int on)
*
* Gate address-line 20 for high memory.
*
* This routine is probably overconservative in what it does, but so what?
*
* It also eats any keystrokes in the keyboard buffer. :-(
*/
.macro PROT_TO_REAL
movl LOCAL(prot_to_real_addr), %eax
call *%eax
.endm
grub_gate_a20:
movl %eax, %edx
gate_a20_test_current_state:
/* first of all, test if already in a good state */
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_bios
ret
gate_a20_try_bios:
/* second, try a BIOS call */
pushl %ebp
call prot_to_real
.code16
movw $0x2400, %ax
testb %dl, %dl
jz 1f
incw %ax
1: int $0x15
DATA32 call real_to_prot
.code32
popl %ebp
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_system_control_port_a
ret
gate_a20_try_system_control_port_a:
/*
* In macbook, the keyboard test would hang the machine, so we move
* this forward.
*/
/* fourth, try the system control port A */
inb $0x92
andb $(~0x03), %al
testb %dl, %dl
jz 6f
orb $0x02, %al
6: 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. */
testb %dl, %dl
jz 7f
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_keyboard_controller
7: ret
gate_a20_flush_keyboard_buffer:
inb $0x64
andb $0x02, %al
jnz gate_a20_flush_keyboard_buffer
2:
inb $0x64
andb $0x01, %al
jz 3f
inb $0x60
jmp 2b
3:
ret
gate_a20_try_keyboard_controller:
/* third, try the keyboard controller */
call gate_a20_flush_keyboard_buffer
movb $0xd1, %al
outb $0x64
4:
inb $0x64
andb $0x02, %al
jnz 4b
movb $0xdd, %al
testb %dl, %dl
jz 5f
orb $0x02, %al
5: outb $0x60
call gate_a20_flush_keyboard_buffer
/* output a dummy command (USB keyboard hack) */
movb $0xff, %al
outb $0x64
call gate_a20_flush_keyboard_buffer
call gate_a20_check_state
cmpb %al, %dl
/* everything failed, so restart from the beginning */
jnz gate_a20_try_bios
ret
gate_a20_check_state:
/* iterate the checking for a while */
movl $100, %ecx
1:
call 3f
cmpb %al, %dl
jz 2f
loop 1b
2:
ret
3:
pushl %ebx
pushl %ecx
xorl %eax, %eax
/* compare the byte at 0x8000 with that at 0x108000 */
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
pushl %ebx
/* save the original byte in CL */
movb (%ebx), %cl
/* store the value at 0x108000 in AL */
addl $0x100000, %ebx
movb (%ebx), %al
/* try to set one less value at 0x8000 */
popl %ebx
movb %al, %ch
decb %ch
movb %ch, (%ebx)
/* serialize */
outb %al, $0x80
outb %al, $0x80
/* obtain the value at 0x108000 in CH */
pushl %ebx
addl $0x100000, %ebx
movb (%ebx), %ch
/* this result is 1 if A20 is on or 0 if it is off */
subb %ch, %al
xorb $1, %al
/* restore the original */
popl %ebx
movb %cl, (%ebx)
popl %ecx
popl %ebx
ret
#ifdef ENABLE_LZMA
#include "lzma_decode.S"
#endif
/*
* The code beyond this point is compressed. Assert that the uncompressed
* code fits GRUB_KERNEL_MACHINE_RAW_SIZE.
*/
. = _start + GRUB_KERNEL_MACHINE_RAW_SIZE
.macro REAL_TO_PROT
movl LOCAL(real_to_prot_addr), %eax
DATA32 call *%ax
.endm
/*
* grub_exit()
@ -453,7 +127,7 @@ gate_a20_check_state:
* Exit the system.
*/
FUNCTION(grub_exit)
call prot_to_real
PROT_TO_REAL
.code16
/* Tell the BIOS a boot failure. If this does not work, reboot. */
int $0x18
@ -482,7 +156,7 @@ FUNCTION(grub_pxe_call)
shll $16, %edx
addl %eax, %edx
call prot_to_real
PROT_TO_REAL
.code16
pushl %ebx
@ -494,7 +168,7 @@ FUNCTION(grub_pxe_call)
addw $10, %sp
movw %ax, %cx
DATA32 call real_to_prot
REAL_TO_PROT
.code32
movzwl %cx, %eax
@ -506,3 +180,11 @@ FUNCTION(grub_pxe_call)
ret
#include "../int.S"
.bss
VARIABLE(grub_boot_drive)
.byte 0
VARIABLE(grub_install_dos_part)
.long 0xFFFFFFFF
VARIABLE(grub_install_bsd_part)
.long 0xFFFFFFFF

View file

@ -51,6 +51,14 @@
protstack:
.long GRUB_MEMORY_MACHINE_PROT_STACK
.macro PROT_TO_REAL
call prot_to_real
.endm
.macro REAL_TO_PROT
DATA32 call real_to_prot
.endm
/*
* This is the Global Descriptor Table
*
@ -162,6 +170,25 @@ protcseg:
/* return on the old (or initialized) stack! */
ret
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* 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/>.
*/
#include <grub/i386/pc/memory.h>
prot_to_real:
/* just in case, set GDT */