diff options
author | Michael Brown | 2008-10-23 05:16:31 +0200 |
---|---|---|
committer | Michael Brown | 2008-10-23 05:20:45 +0200 |
commit | bcc70d6b9986d9bb7227a915681c83c46ab46134 (patch) | |
tree | 525e567cc65d0737d18b64035df4e96a84bf47cd | |
parent | [settings] Avoid returning uninitialised data on error in fetch_xxx_setting() (diff) | |
download | ipxe-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.S | 8 | ||||
-rw-r--r-- | src/arch/i386/firmware/pcbios/memmap.c | 6 |
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" ); |