* 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>
|
2012-02-05 Vladimir Serbinenko <phcoder@gmail.com>
|
||||||
|
|
||||||
* grub-core/commands/minicmd.c (GRUB_MOD_INIT): Add missing SIZE
|
* grub-core/commands/minicmd.c (GRUB_MOD_INIT): Add missing SIZE
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <grub/i386/relocator.h>
|
#include <grub/i386/relocator.h>
|
||||||
#include <grub/relocator_private.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_start;
|
||||||
extern grub_uint8_t grub_relocator_forward_end;
|
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. */
|
/* Put it higher than the byte it checks for A20 check. */
|
||||||
err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010,
|
err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010,
|
||||||
0xa0000 - RELOCATOR_SIZEOF (16),
|
0xa0000 - RELOCATOR_SIZEOF (16)
|
||||||
RELOCATOR_SIZEOF (16), 16,
|
- GRUB_RELOCATOR16_STACK_SIZE,
|
||||||
|
RELOCATOR_SIZEOF (16)
|
||||||
|
+ GRUB_RELOCATOR16_STACK_SIZE, 16,
|
||||||
GRUB_RELOCATOR_PREFERENCE_NONE);
|
GRUB_RELOCATOR_PREFERENCE_NONE);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#define PSEUDO_REAL_DSEG 0x20
|
#define PSEUDO_REAL_DSEG 0x20
|
||||||
|
|
||||||
|
#include <grub/cpu/relocator_private.h>
|
||||||
|
|
||||||
#include "relocator_common.S"
|
#include "relocator_common.S"
|
||||||
|
|
||||||
.p2align 4 /* force 16-byte alignment */
|
.p2align 4 /* force 16-byte alignment */
|
||||||
|
@ -63,84 +65,6 @@ VARIABLE(grub_relocator16_start)
|
||||||
andl $(~GRUB_MEMORY_CPU_CR4_PAE_ON), %eax
|
andl $(~GRUB_MEMORY_CPU_CR4_PAE_ON), %eax
|
||||||
movl %eax, %cr4
|
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. */
|
/* Update other registers. */
|
||||||
movl $PSEUDO_REAL_DSEG, %eax
|
movl $PSEUDO_REAL_DSEG, %eax
|
||||||
movl %eax, %ds
|
movl %eax, %ds
|
||||||
|
@ -172,6 +96,80 @@ LOCAL(segment):
|
||||||
|
|
||||||
LOCAL(cont3):
|
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
|
/* we are in real mode now
|
||||||
* set up the real mode segment registers : DS, SS, ES
|
* 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