summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2010-12-03 05:44:10 +0100
committerMichael Brown2010-12-03 06:41:09 +0100
commit87723a0f11425fce10743cb31e0365a8eade4891 (patch)
treebb1798b0abe0cc8cca7e83bff963ed45080f82ff
parent[hermon] Work around hardware stripping of VLAN tags (diff)
downloadipxe-87723a0f11425fce10743cb31e0365a8eade4891.tar.gz
ipxe-87723a0f11425fce10743cb31e0365a8eade4891.tar.xz
ipxe-87723a0f11425fce10743cb31e0365a8eade4891.zip
[libflat] Test A20 gate without switching to flat real mode
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>
-rw-r--r--src/arch/i386/transitions/libflat.S30
1 files changed, 18 insertions, 12 deletions
diff --git a/src/arch/i386/transitions/libflat.S b/src/arch/i386/transitions/libflat.S
index 5e5f7b99..98f6f4df 100644
--- a/src/arch/i386/transitions/libflat.S
+++ b/src/arch/i386/transitions/libflat.S
@@ -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