From bcc70d6b9986d9bb7227a915681c83c46ab46134 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 23 Oct 2008 04:16:31 +0100 Subject: [PATCH] [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. --- src/arch/i386/firmware/pcbios/e820mangler.S | 8 ++++++-- 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 7b8d104cb..53e2d7c55 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 9de10a7a5..848979e9e 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" );