summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2008-10-23 05:16:31 +0200
committerMichael Brown2008-10-23 05:20:45 +0200
commitbcc70d6b9986d9bb7227a915681c83c46ab46134 (patch)
tree525e567cc65d0737d18b64035df4e96a84bf47cd
parent[settings] Avoid returning uninitialised data on error in fetch_xxx_setting() (diff)
downloadipxe-bcc70d6b9986d9bb7227a915681c83c46ab46134.tar.gz
ipxe-bcc70d6b9986d9bb7227a915681c83c46ab46134.tar.xz
ipxe-bcc70d6b9986d9bb7227a915681c83c46ab46134.zip
[pcbios] Guard against register corruption in INT 15,e820 implementations
Someone at Dell must have a full-time job designing ways to screw up implementations of INT 15,e820. This latest gem is courtesy of a Dell Xanadu system, which arbitrarily decides to obliterate the contents of %esi. Preserve %esi, %edi and %ebp across calls to INT 15,e820, in case someone tries a variation on this trick in future.
-rw-r--r--src/arch/i386/firmware/pcbios/e820mangler.S8
-rw-r--r--src/arch/i386/firmware/pcbios/memmap.c6
2 files changed, 11 insertions, 3 deletions
diff --git a/src/arch/i386/firmware/pcbios/e820mangler.S b/src/arch/i386/firmware/pcbios/e820mangler.S
index 7b8d104c..53e2d7c5 100644
--- a/src/arch/i386/firmware/pcbios/e820mangler.S
+++ b/src/arch/i386/firmware/pcbios/e820mangler.S
@@ -268,8 +268,10 @@ get_underlying_e820:
pushl %ebx
pushl %ecx
pushl %edx
+ pushl %esi /* Some implementations corrupt %esi, so we */
+ pushl %edi /* preserve %esi, %edi and %ebp to be paranoid */
+ pushl %ebp
pushw %es
- pushw %di
pushw %ds
popw %es
movw $underlying_e820_cache, %di
@@ -280,8 +282,10 @@ get_underlying_e820:
stc
pushfw
lcall *%cs:int15_vector
- popw %di
popw %es
+ popl %ebp
+ popl %edi
+ popl %esi
/* Check for error return from underlying e820 call */
jc 2f /* CF set: error */
cmpl $SMAP, %eax
diff --git a/src/arch/i386/firmware/pcbios/memmap.c b/src/arch/i386/firmware/pcbios/memmap.c
index 9de10a7a..848979e9 100644
--- a/src/arch/i386/firmware/pcbios/memmap.c
+++ b/src/arch/i386/firmware/pcbios/memmap.c
@@ -167,6 +167,10 @@ static int meme820 ( struct memory_map *memmap ) {
memset ( &e820buf, 0, sizeof ( e820buf ) );
do {
+ /* Some BIOSes corrupt %esi for fun. Guard against
+ * this by telling gcc that all non-output registers
+ * may be corrupted.
+ */
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
"int $0x15\n\t"
"pushfw\n\t"
@@ -178,7 +182,7 @@ static int meme820 ( struct memory_map *memmap ) {
"D" ( __from_data16 ( &e820buf ) ),
"c" ( sizeof ( e820buf ) ),
"d" ( SMAP )
- : "memory" );
+ : "esi", "memory" );
if ( smap != SMAP ) {
DBG ( "INT 15,e820 failed SMAP signature check\n" );