Package: grub-legacy
Severity: important
Tags: patch

I installed debian on /dev/sda1 and Windows 7 on /dev/sda2. 
Installed and configured grub corretly, but the computer rebooted when selected 
Windows 7. 
I did a lof of research and found the opensuse version of the grub can boot 
windows 7, but the debian (and the unpatched 0.97 version can't). 
I started to test the opensuse patches and found the patch, waht makes grub to 
work with win7. It's an A20 gate patch(called 14_grub-a20.diff), 
but it's strange, because this patch is used for some keyboard problem. 

My computer config: Interl 915GUX chipset, pentium 4 3GHz CPU, 1GB RAM. 80GB 
SATA HDD.
Your description is a bit long; please enter a shorter subject. (An empty 
response will retain the existing subject.)

I also have this reboot problem with grub2,'m trin' to investigate that too. 
Windows XP, MAC OSX Snow leopard and Linux boots without any problem.

Windows 7 is on NTFS partition, the partition is MBR style.

-- System Information:
Debian Release: 6.0
  APT prefers stable
  APT policy: (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 2.6.26-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
--- grub-0.97/stage2/asm.S.orig 2007-08-24 13:03:39.000000000 +0200
+++ grub-0.97/stage2/asm.S      2007-08-24 13:08:37.000000000 +0200
@@ -1620,42 +1620,85 @@ ENTRY(set_vbe_mode)
  *
  * Gate address-line 20 for high memory.
  *
- * This routine is probably overconservative in what it does, but so what?
- *
- * It also eats any keystrokes in the keyboard buffer.  :-(
+ * Try to disable the A20 gate by all means. (The argument is ignored)
+ * On success (the memory world is free), a -1 is returned,  0 on failure.
+ * It may also eat any keystrokes in the keyboard buffer.  :-(
  */
 
 ENTRY(gateA20)
+       pushl   %ebx
+       pushl   %edx
+       pushl   %ebp
+       call    testA20
+       jnz     1f
+       call    A20_BIOS
+       call    testA20
+       jnz     1f
+       call    A20_PORT92
+       call    testA20
+       jnz     1f
+       call    A20_KBDCTL
+       call    testA20
+       jnz     1f
+       movl    $0,%eax
+       jmp     2f
+1:     movl    $-1,%eax
+2:     popl    %ebp
+       popl    %edx
+       popl    %ebx
+       ret
+
+testA20:
+       movl    0x500,%eax
+       movl    0x100500,%ebx
+       notl    %eax
+       movl    %eax,0x100500
+       cmpl    %eax,0x500
+       pushfl
+       movl    %ebx,0x100500
+       notl    %eax
+       movl    %eax,0x500
+       popfl
+       ret
+
+A20_BIOS:      
        /* first, try a BIOS call */
-       pushl   %ebp
-       movl    8(%esp), %edx
        
        call    EXT_C(prot_to_real)
        
        .code16
-       movw    $0x2400, %ax
-       testw   %dx, %dx
-       jz      1f
-       incw    %ax
+       movw    $0x2401, %ax
 1:     stc
        int     $0x15
-       jnc     2f
-
-       /* set non-zero if failed */
-       movb    $1, %ah
-
-       /* save the status */
-2:     movb    %ah, %dl
 
        DATA32  call    EXT_C(real_to_prot)
        .code32
-
-       popl    %ebp
-       testb   %dl, %dl
-       jnz     3f
        ret
 
-3:     /* use keyboard controller */
+
+A20_PORT92:
+       /*
+        * try to switch gateA20 using PORT92, the "Fast A20 and Init"
+        * register
+        */
+       mov     $0x92, %dx
+       inb     %dx, %al
+       /* skip the port92 code if it's unimplemented (read returns 0xff) */
+       cmpb    $0xff, %al
+       jz      6f
+
+       /* set bit1, the ALT_A20_GATE bit */
+       orb     $2, %al
+/*     and     $0xfd, %al */
+
+       /* clear the INIT_NOW bit; don't accidently reset the machine */
+       and     $0xfe, %al
+       outb    %al, %dx
+6:     ret
+
+
+A20_KBDCTL:    
+       /* use keyboard controller */
        pushl   %eax
 
        call    gloop1
@@ -1669,11 +1710,7 @@ gloopint1:
        jnz     gloopint1
 
        movb    $KB_OUTPUT_MASK, %al
-       cmpb    $0, 0x8(%esp)
-       jz      gdoit
-
        orb     $KB_A20_ENABLE, %al
-gdoit:
        outb    $K_RDWR
 
        call    gloop1
--- grub-0.97/stage2/asm.S.orig 2007-08-24 13:03:39.000000000 +0200
+++ grub-0.97/stage2/asm.S      2007-08-24 13:08:37.000000000 +0200
@@ -1620,42 +1620,85 @@ ENTRY(set_vbe_mode)
  *
  * Gate address-line 20 for high memory.
  *
- * This routine is probably overconservative in what it does, but so what?
- *
- * It also eats any keystrokes in the keyboard buffer.  :-(
+ * Try to disable the A20 gate by all means. (The argument is ignored)
+ * On success (the memory world is free), a -1 is returned,  0 on failure.
+ * It may also eat any keystrokes in the keyboard buffer.  :-(
  */
 
 ENTRY(gateA20)
+       pushl   %ebx
+       pushl   %edx
+       pushl   %ebp
+       call    testA20
+       jnz     1f
+       call    A20_BIOS
+       call    testA20
+       jnz     1f
+       call    A20_PORT92
+       call    testA20
+       jnz     1f
+       call    A20_KBDCTL
+       call    testA20
+       jnz     1f
+       movl    $0,%eax
+       jmp     2f
+1:     movl    $-1,%eax
+2:     popl    %ebp
+       popl    %edx
+       popl    %ebx
+       ret
+
+testA20:
+       movl    0x500,%eax
+       movl    0x100500,%ebx
+       notl    %eax
+       movl    %eax,0x100500
+       cmpl    %eax,0x500
+       pushfl
+       movl    %ebx,0x100500
+       notl    %eax
+       movl    %eax,0x500
+       popfl
+       ret
+
+A20_BIOS:      
        /* first, try a BIOS call */
-       pushl   %ebp
-       movl    8(%esp), %edx
        
        call    EXT_C(prot_to_real)
        
        .code16
-       movw    $0x2400, %ax
-       testw   %dx, %dx
-       jz      1f
-       incw    %ax
+       movw    $0x2401, %ax
 1:     stc
        int     $0x15
-       jnc     2f
-
-       /* set non-zero if failed */
-       movb    $1, %ah
-
-       /* save the status */
-2:     movb    %ah, %dl
 
        DATA32  call    EXT_C(real_to_prot)
        .code32
-
-       popl    %ebp
-       testb   %dl, %dl
-       jnz     3f
        ret
 
-3:     /* use keyboard controller */
+
+A20_PORT92:
+       /*
+        * try to switch gateA20 using PORT92, the "Fast A20 and Init"
+        * register
+        */
+       mov     $0x92, %dx
+       inb     %dx, %al
+       /* skip the port92 code if it's unimplemented (read returns 0xff) */
+       cmpb    $0xff, %al
+       jz      6f
+
+       /* set bit1, the ALT_A20_GATE bit */
+       orb     $2, %al
+/*     and     $0xfd, %al */
+
+       /* clear the INIT_NOW bit; don't accidently reset the machine */
+       and     $0xfe, %al
+       outb    %al, %dx
+6:     ret
+
+
+A20_KBDCTL:    
+       /* use keyboard controller */
        pushl   %eax
 
        call    gloop1
@@ -1669,11 +1710,7 @@ gloopint1:
        jnz     gloopint1
 
        movb    $KB_OUTPUT_MASK, %al
-       cmpb    $0, 0x8(%esp)
-       jz      gdoit
-
        orb     $KB_A20_ENABLE, %al
-gdoit:
        outb    $K_RDWR
 
        call    gloop1

Reply via email to