]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[libflat] Test A20 gate without switching to flat real mode
authorMichael Brown <mcb30@ipxe.org>
Fri, 3 Dec 2010 04:44:10 +0000 (04:44 +0000)
committerMichael Brown <mcb30@ipxe.org>
Fri, 3 Dec 2010 05:41:09 +0000 (05:41 +0000)
Use the real-mode address ffff:0010 to access the linear address
0x100000, and so test whether or not the A20 gate is enabled without
requiring a switch into flat real mode (or some other addressing
mode).

This speeds up CPU mode transitions, and also avoids breaking the NBP
from IBM's Tivoli Provisioning Manager for Operating System
Deployment.  This NBP makes some calls to iPXE in VM86 mode rather
than true real mode and does not correctly emulate our transition into
flat real mode.

Interestingly, Tivoli's VMM *does* allow us to switch into protected
mode (though it patches our GDT so that we execute in ring 1 rather
than ring 0).  However, paging is still disabled and we have a 4GB
segment limit.  Being in ring 1 does not, therefore, restrict us in
any meaningful way; this has been verified by deliberately writing
garbage over Tivoli's own GDT (at address 0x02201010) during a
nominally VM86-mode PXE API call.  It's unclear precisely what
protection this VMM is supposed to be offering.

Suggested-by: Joshua Oreman <oremanj@rwcr.net>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/i386/transitions/libflat.S

index 5e5f7b9958b838466dfabb5697179ab0d347352e..98f6f4df6c7a1a5fb8ca37c818ccd9184cae8394 100644 (file)
@@ -165,14 +165,23 @@ test_a20_long:
        pushl   %ecx
        movl    $TEST_A20_LONG_MAX_RETRIES, %ecx
 1:     pushw   %ax
+       pushw   %ds
+       pushw   %es
 
-       /* Flatten real mode so we can access the test pattern's 1MB offset */
-       call    flatten_real_mode
+       /* Set up segment registers for access across the 1MB boundary */
+       xorw    %ax, %ax
+       movw    %ax, %ds
+       decw    %ax
+       movw    %ax, %es
 
 2:     /* Modify and check test pattern; succeed if we see a difference */
-       incw    %cs:test_a20_data
-       addr32 movw %cs:(test_a20_data + 0x100000 ), %ax
-       cmpw    %cs:test_a20_data, %ax
+       pushfw
+       cli
+       xchgw   %ds:0, %cx
+       movw    %es:0x10, %ax
+       xchgw   %ds:0, %cx
+       popfw
+       cmpw    %ax, %cx
        clc
        jnz     99f
 
@@ -182,17 +191,13 @@ test_a20_long:
        stc
 
 99:    /* Restore registers and return */
+       popw    %es
+       popw    %ds
        popw    %ax
        popl    %ecx
        ret
        .size   test_a20_long, . - test_a20_long
 
-       .section ".text16.early.data", "aw", @progbits
-       .align  2
-test_a20_data:
-       .word   0xdead
-       .size   test_a20_data, . - test_a20_data
-
 /****************************************************************************
  * enable_a20_bios
  *
@@ -414,6 +419,7 @@ enable_a20_method:
 access_highmem:
        /* Enable A20 line */
        call    enable_a20
-       /* CPU will be in flat real mode as a result of this call */
+       /* Set up 4GB limits */
+       call    flatten_real_mode
        lret
        .size   access_highmem, . - access_highmem