From 215c90cb822c1704d3b529b300a0835c4e026cd6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 7 Feb 2012 22:31:14 +0100 Subject: [PATCH] * 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. --- ChangeLog | 8 ++ grub-core/lib/i386/relocator.c | 7 +- grub-core/lib/i386/relocator16.S | 154 +++++++++++++------------- include/grub/i386/relocator_private.h | 1 + 4 files changed, 90 insertions(+), 80 deletions(-) create mode 100644 include/grub/i386/relocator_private.h diff --git a/ChangeLog b/ChangeLog index 313d135aa..ede7f8e1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2012-02-07 Vladimir Serbinenko + + * 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 * grub-core/commands/minicmd.c (GRUB_MOD_INIT): Add missing SIZE diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index 1f0aa0dd1..ac7d4ca4c 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -25,6 +25,7 @@ #include #include +#include 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; diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index 8500c2f94..d6c5fe5f8 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -26,6 +26,8 @@ #define PSEUDO_REAL_DSEG 0x20 +#include + #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 */ diff --git a/include/grub/i386/relocator_private.h b/include/grub/i386/relocator_private.h new file mode 100644 index 000000000..b7c96a664 --- /dev/null +++ b/include/grub/i386/relocator_private.h @@ -0,0 +1 @@ +#define GRUB_RELOCATOR16_STACK_SIZE 4096