* 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:
parent
b5c1f9bf41
commit
215c90cb82
4 changed files with 90 additions and 80 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
1
include/grub/i386/relocator_private.h
Normal file
1
include/grub/i386/relocator_private.h
Normal file
|
@ -0,0 +1 @@
|
|||
#define GRUB_RELOCATOR16_STACK_SIZE 4096
|
Loading…
Reference in a new issue