2005-07-16 Yoshinori K. Okuji <okuji@enbug.org>

* kern/i386/pc/startup.S (grub_gate_a20): Rewritten for
	robustness. This routine now supports a BIOS call and System
	Control Port A to modify the gate A20.

	* include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE):
	Increased to 0x440.
This commit is contained in:
okuji 2005-07-16 09:32:52 +00:00
parent 09f9923fbb
commit 654fc59fe4
3 changed files with 121 additions and 31 deletions

View file

@ -1,3 +1,12 @@
2005-07-16 Yoshinori K. Okuji <okuji@enbug.org>
* kern/i386/pc/startup.S (grub_gate_a20): Rewritten for
robustness. This routine now supports a BIOS call and System
Control Port A to modify the gate A20.
* include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE):
Increased to 0x440.
2005-07-12 Hollis Blanchard <hollis@penguinppc.org> 2005-07-12 Hollis Blanchard <hollis@penguinppc.org>
* disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): dprintf the * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): dprintf the

View file

@ -39,7 +39,7 @@
#define GRUB_KERNEL_MACHINE_PREFIX 0x1c #define GRUB_KERNEL_MACHINE_PREFIX 0x1c
/* The size of the first region which won't be compressed. */ /* The size of the first region which won't be compressed. */
#define GRUB_KERNEL_MACHINE_RAW_SIZE 0x400 #define GRUB_KERNEL_MACHINE_RAW_SIZE 0x440
#ifndef ASM_FILE #ifndef ASM_FILE

View file

@ -384,50 +384,131 @@ realcseg:
*/ */
FUNCTION(grub_gate_a20) FUNCTION(grub_gate_a20)
movl %eax, %ecx movl %eax, %edx
call gloop1 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 EXT_C(prot_to_real)
.code16
movw $0x2400, %ax
testb %dl, %dl
jz 1f
incw %ax
1: int $0x15
DATA32 call EXT_C(real_to_prot)
.code32
popl %ebp
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_keyboard_controller
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 movb $0xd1, %al
outb $0x64 outb $0x64
4:
gloopint1:
inb $0x64 inb $0x64
andb $0x02, %al andb $0x02, %al
jnz gloopint1 jnz 4b
movb $0xdd, %al movb $0xdd, %al
testl %ecx, %ecx testb %dl, %dl
jz gdoit jz 5f
orb $0x02, %al orb $0x02, %al
gdoit: 5: outb $0x60
outb $0x60 call gate_a20_flush_keyboard_buffer
call gloop1
/* output a dummy command (USB keyboard hack) */ /* output a dummy command (USB keyboard hack) */
movb $0xff, %al movb $0xff, %al
outb $0x64 outb $0x64
call gloop1 call gate_a20_flush_keyboard_buffer
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_system_control_port_a
ret ret
gloop1: gate_a20_try_system_control_port_a:
inb $0x64 /* fourth, try the system control port A */
andb $0x02, %al inb $0x92
jnz gloop1 andb $(~0x03), %al
testb %dl, %dl
jz 6f
orb $0x02, %al
6: outb $0x92
gloop2: call gate_a20_check_state
inb $0x64 cmpb %al, %dl
andb $0x01, %al /* everything failed, so restart from the beginning */
jz gloop2ret jnz gate_a20_try_bios
inb $0x60
jmp gloop2
gloop2ret:
ret 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 0x2000 with that at 0x102000 */
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
pushl %ebx
/* save the original byte in CL */
movb (%ebx), %cl
/* store the value at 0x102000 in AL */
addl $0x100000, %ebx
movb (%ebx), %al
/* try to set one less value at 0x2000 */
popl %ebx
movb %al, %ch
decb %ch
movb %ch, (%ebx)
/* serialize */
outb $0x80
outb $0x80
/* store the value at 0x2000 in CH */
movb (%ebx), %ch
/* this result is 1 if A20 is on or 0 if it is off */
subb %ch, %al
/* restore the original */
movb %cl, (%ebx)
popl %ecx
popl %ebx
ret
#include "lzo1x.S" #include "lzo1x.S"