* grub-core/lib/i386/relocator16.S: Revert moving A20 code into PM

part. Instead setup the correct stack in RM.
	* grub-core/lib/i386/relocator.c (grub_relocator16_boot): Reserve place
	for stack.
	* include/grub/i386/relocator_private.h: New file.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-02-07 22:31:14 +01:00
parent b5c1f9bf41
commit 215c90cb82
4 changed files with 90 additions and 80 deletions

View file

@ -1,3 +1,11 @@
2012-02-07 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/lib/i386/relocator16.S: Revert moving A20 code into PM
part. Instead setup the correct stack in RM.
* grub-core/lib/i386/relocator.c (grub_relocator16_boot): Reserve place
for stack.
* include/grub/i386/relocator_private.h: New file.
2012-02-05 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/commands/minicmd.c (GRUB_MOD_INIT): Add missing SIZE

View file

@ -25,6 +25,7 @@
#include <grub/i386/relocator.h>
#include <grub/relocator_private.h>
#include <grub/cpu/relocator_private.h>
extern grub_uint8_t grub_relocator_forward_start;
extern grub_uint8_t grub_relocator_forward_end;
@ -200,8 +201,10 @@ grub_relocator16_boot (struct grub_relocator *rel,
/* Put it higher than the byte it checks for A20 check. */
err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010,
0xa0000 - RELOCATOR_SIZEOF (16),
RELOCATOR_SIZEOF (16), 16,
0xa0000 - RELOCATOR_SIZEOF (16)
- GRUB_RELOCATOR16_STACK_SIZE,
RELOCATOR_SIZEOF (16)
+ GRUB_RELOCATOR16_STACK_SIZE, 16,
GRUB_RELOCATOR_PREFERENCE_NONE);
if (err)
return err;

View file

@ -26,6 +26,8 @@
#define PSEUDO_REAL_DSEG 0x20
#include <grub/cpu/relocator_private.h>
#include "relocator_common.S"
.p2align 4 /* force 16-byte alignment */
@ -63,84 +65,6 @@ VARIABLE(grub_relocator16_start)
andl $(~GRUB_MEMORY_CPU_CR4_PAE_ON), %eax
movl %eax, %cr4
/* movw imm16, %ax. */
.byte 0xb8
VARIABLE(grub_relocator16_keep_a20_enabled)
.word 0
test %ax, %ax
jnz LOCAL(gate_a20_done)
/* first of all, test if already in a good state */
call LOCAL(gate_a20_check_state)
testb %al, %al
jz LOCAL(gate_a20_done)
/* second, try a BIOS call */
movw $0x2400, %ax
int $0x15
call LOCAL(gate_a20_check_state)
testb %al, %al
jz LOCAL(gate_a20_done)
/*
* 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
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. */
jmp LOCAL(gate_a20_done)
LOCAL(gate_a20_check_state):
/* iterate the checking for a while */
movw $100, %cx
1:
call 3f
testb %al, %al
jz 2f
loop 1b
2:
ret
3:
xorw %ax, %ax
movw %ax, %ds
decw %ax
movw %ax, %es
xorw %ax, %ax
movw $0x8000, %ax
/* compare the byte at ADDR with that at 0x100000 + ADDR */
movw %ax, %si
addw $0x10, %ax
movw %ax, %di
/* save the original byte in DL */
movb %ds:(%si), %dl
movb %es:(%di), %al
/* try to set one less value at ADDR */
movb %al, %dh
decb %dh
movb %dh, %ds:(%si)
/* serialize */
outb %al, $0x80
outb %al, $0x80
/* obtain the value at 0x100000 + ADDR in CH */
movb %es:(%di), %dh
/* this result is 1 if A20 is on or 0 if it is off */
subb %dh, %al
xorb $1, %al
/* restore the original */
movb %dl, %es:(%di)
ret
LOCAL(gate_a20_done):
/* Update other registers. */
movl $PSEUDO_REAL_DSEG, %eax
movl %eax, %ds
@ -172,6 +96,80 @@ LOCAL(segment):
LOCAL(cont3):
/* movw imm16, %ax. */
.byte 0xb8
VARIABLE(grub_relocator16_keep_a20_enabled)
.word 0
test %ax, %ax
jnz LOCAL(gate_a20_done)
movw %cs, %ax
movw %ax, %ss
leaw EXT_C(grub_relocator16_end) + GRUB_RELOCATOR16_STACK_SIZE, %sp
/* second, try a BIOS call */
movw $0x2400, %ax
int $0x15
call LOCAL(gate_a20_check_state)
testb %al, %al
jz LOCAL(gate_a20_done)
/*
* 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
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. */
jmp LOCAL(gate_a20_done)
LOCAL(gate_a20_check_state):
/* iterate the checking for a while */
movw $100, %cx
1:
xorw %ax, %ax
movw %ax, %ds
decw %ax
movw %ax, %es
xorw %ax, %ax
movw $0x8000, %ax
/* compare the byte at ADDR with that at 0x100000 + ADDR */
movw %ax, %si
addw $0x10, %ax
movw %ax, %di
/* save the original byte in DL */
movb %ds:(%si), %dl
movb %es:(%di), %al
/* try to set one less value at ADDR */
movb %al, %dh
decb %dh
movb %dh, %ds:(%si)
/* serialize */
outb %al, $0x80
outb %al, $0x80
/* obtain the value at 0x100000 + ADDR in CH */
movb %es:(%di), %dh
/* this result is 1 if A20 is on or 0 if it is off */
subb %dh, %al
xorb $1, %al
/* restore the original */
movb %dl, %ds:(%si)
testb %al, %al
jz LOCAL(gate_a20_done)
loop 1b
2:
ret
LOCAL(gate_a20_done):
/* we are in real mode now
* set up the real mode segment registers : DS, SS, ES
*/

View file

@ -0,0 +1 @@
#define GRUB_RELOCATOR16_STACK_SIZE 4096