]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
2005-07-16 Yoshinori K. Okuji <okuji@enbug.org>
authorokuji <okuji@localhost>
Sat, 16 Jul 2005 09:32:52 +0000 (09:32 +0000)
committerokuji <okuji@localhost>
Sat, 16 Jul 2005 09:32:52 +0000 (09:32 +0000)
* 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.

ChangeLog
include/grub/i386/pc/kernel.h
kern/i386/pc/startup.S

index acc598b1156ca1cda68e703ccf75074c19c35f24..2ba78b61d7fbea88dba5bdffd524b10f4d37ece8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
 
        * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): dprintf the
index 24d1cc9f8c63a92ee7482026352a3b654f2f1250..0496e9645ab532ac2f16c99ba4d76e088b06680e 100644 (file)
@@ -39,7 +39,7 @@
 #define GRUB_KERNEL_MACHINE_PREFIX             0x1c
 
 /* 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
 
index b84320f974c2b946a28fcff28819c0d1f676a702..3385e2ca254e4e82168c53702b84c5e079c22938 100644 (file)
@@ -125,7 +125,7 @@ codestart:
 
        /* reset disk system (%ah = 0) */
        int     $0x13
-
+       
        /* transition to protected mode */
        DATA32  call real_to_prot
 
@@ -134,7 +134,7 @@ codestart:
 
        incl    %eax
        call    EXT_C(grub_gate_a20)
-
+       
        /* decompress the compressed part and put the result at 1MB */
        movl    $0x100000, %esi
        movl    $(START_SYMBOL + GRUB_KERNEL_MACHINE_RAW_SIZE), %edi
@@ -384,51 +384,132 @@ realcseg:
  */
 
 FUNCTION(grub_gate_a20)
-       movl    %eax, %ecx
+       movl    %eax, %edx
+
+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)
 
-       call    gloop1
+       .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
        outb    $0x64
-
-gloopint1:
+4:     
        inb     $0x64
        andb    $0x02, %al
-       jnz     gloopint1
+       jnz     4b
 
        movb    $0xdd, %al
-       testl   %ecx, %ecx
-       jz      gdoit
-
+       testb   %dl, %dl
+       jz      5f
        orb     $0x02, %al
-gdoit:
-       outb    $0x60
-
-       call    gloop1
+5:     outb    $0x60
+       call    gate_a20_flush_keyboard_buffer
 
        /* output a dummy command (USB keyboard hack) */
        movb    $0xff, %al
        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
 
-gloop1:
-       inb     $0x64
-       andb    $0x02, %al
-       jnz     gloop1
-
-gloop2:
-       inb     $0x64
-       andb    $0x01, %al
-       jz      gloop2ret
-       inb     $0x60
-       jmp     gloop2
-
-gloop2ret:
+gate_a20_try_system_control_port_a:
+       /* fourth, try the system control port A */
+       inb     $0x92
+       andb    $(~0x03), %al
+       testb   %dl, %dl
+       jz      6f
+       orb     $0x02, %al
+6:     outb    $0x92
+       
+       call    gate_a20_check_state
+       cmpb    %al, %dl
+       /* everything failed, so restart from the beginning */
+       jnz     gate_a20_try_bios
        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"