[pcbios] Fetch INT 15,e820 entry directly into our e820 cache
authorMichael Brown <mcb30@etherboot.org>
Thu, 25 Sep 2008 17:45:30 +0000 (18:45 +0100)
committerMichael Brown <mcb30@etherboot.org>
Thu, 25 Sep 2008 17:52:49 +0000 (18:52 +0100)
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).

src/arch/i386/firmware/pcbios/e820mangler.S

index 3c4cf21..ad773f7 100644 (file)
@@ -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