summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2008-09-25 19:45:30 +0200
committerMichael Brown2008-09-25 19:52:49 +0200
commit3392cfa7df58a5662417f25226cf75dedabeb750 (patch)
treeb0da133831c28120ee3e037098da490884072f80
parent[arbel] Allocate sufficient space for firmware buffer (diff)
downloadipxe-3392cfa7df58a5662417f25226cf75dedabeb750.tar.gz
ipxe-3392cfa7df58a5662417f25226cf75dedabeb750.tar.xz
ipxe-3392cfa7df58a5662417f25226cf75dedabeb750.zip
[pcbios] Fetch INT 15,e820 entry directly into our e820 cache
Some BIOSes require us to pass in not only the continuation value (in %ebx) as returned by the previous call to INT 15,e820 but also the unmodified buffer (at %es:%di) as returned by the previous call to INT 15,e820. Apparently, someone thought it would be a worthwhile optimisation to fill in only the low dword of the "length" field and the low byte of the "type field", assuming that the buffer would remain unaltered from the previous call. This problem was being triggered by the "peek ahead" logic in get_mangled_e820(), which would read the next entry into a temporary buffer in order to be able to guarantee terminating the map with %ebx=0 rather than CF=1. (Terminating with CF=1 upsets some Windows flavours, despite being documented legal behaviour.) Work around this problem by always fetching directly into our e820 cache; that way we can guarantee that the underlying call always sees the previous buffer contents (and the same buffer address).
-rw-r--r--src/arch/i386/firmware/pcbios/e820mangler.S28
1 files changed, 9 insertions, 19 deletions
diff --git a/src/arch/i386/firmware/pcbios/e820mangler.S b/src/arch/i386/firmware/pcbios/e820mangler.S
index 3c4cf21b..ad773f74 100644
--- a/src/arch/i386/firmware/pcbios/e820mangler.S
+++ b/src/arch/i386/firmware/pcbios/e820mangler.S
@@ -245,10 +245,19 @@ get_underlying_e820:
pushl %ebx
pushl %ecx
pushl %edx
+ pushw %es
+ pushw %di
+ pushw %ds
+ popw %es
+ movw $underlying_e820_cache, %di
+ movl $20, %ecx
movl underlying_e820_ebx, %ebx
stc
pushfw
lcall *%cs:int15_vector
+ popw %di
+ popw %es
+ /* Check for error return from underlying e820 call */
jc 1f /* CF set: error */
cmpl $SMAP, %eax
je 2f /* 'SMAP' missing: error */
@@ -262,25 +271,6 @@ get_underlying_e820:
popl %ecx
popl %ebx
popl %eax
- /* Copy result to cache */
- pushw %es
- pushw %fs
- pushw %si
- pushw %di
- pushw %cx
- pushw %es
- popw %fs
- movw %di, %si
- pushw %ds
- popw %es
- movw $underlying_e820_cache, %di
- movw $20, %cx
- fs rep movsb
- popw %cx
- popw %di
- popw %si
- popw %fs
- popw %es
/* Mark cache as containing this result */
incw underlying_e820_index