mirror of
https://github.com/ipxe/ipxe
synced 2025-12-22 21:11:03 +03:00
[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.
This commit is contained in:
@@ -268,8 +268,10 @@ get_underlying_e820:
|
|||||||
pushl %ebx
|
pushl %ebx
|
||||||
pushl %ecx
|
pushl %ecx
|
||||||
pushl %edx
|
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 %es
|
||||||
pushw %di
|
|
||||||
pushw %ds
|
pushw %ds
|
||||||
popw %es
|
popw %es
|
||||||
movw $underlying_e820_cache, %di
|
movw $underlying_e820_cache, %di
|
||||||
@@ -280,8 +282,10 @@ get_underlying_e820:
|
|||||||
stc
|
stc
|
||||||
pushfw
|
pushfw
|
||||||
lcall *%cs:int15_vector
|
lcall *%cs:int15_vector
|
||||||
popw %di
|
|
||||||
popw %es
|
popw %es
|
||||||
|
popl %ebp
|
||||||
|
popl %edi
|
||||||
|
popl %esi
|
||||||
/* Check for error return from underlying e820 call */
|
/* Check for error return from underlying e820 call */
|
||||||
jc 2f /* CF set: error */
|
jc 2f /* CF set: error */
|
||||||
cmpl $SMAP, %eax
|
cmpl $SMAP, %eax
|
||||||
|
|||||||
@@ -167,6 +167,10 @@ static int meme820 ( struct memory_map *memmap ) {
|
|||||||
memset ( &e820buf, 0, sizeof ( e820buf ) );
|
memset ( &e820buf, 0, sizeof ( e820buf ) );
|
||||||
|
|
||||||
do {
|
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"
|
__asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
|
||||||
"int $0x15\n\t"
|
"int $0x15\n\t"
|
||||||
"pushfw\n\t"
|
"pushfw\n\t"
|
||||||
@@ -178,7 +182,7 @@ static int meme820 ( struct memory_map *memmap ) {
|
|||||||
"D" ( __from_data16 ( &e820buf ) ),
|
"D" ( __from_data16 ( &e820buf ) ),
|
||||||
"c" ( sizeof ( e820buf ) ),
|
"c" ( sizeof ( e820buf ) ),
|
||||||
"d" ( SMAP )
|
"d" ( SMAP )
|
||||||
: "memory" );
|
: "esi", "memory" );
|
||||||
|
|
||||||
if ( smap != SMAP ) {
|
if ( smap != SMAP ) {
|
||||||
DBG ( "INT 15,e820 failed SMAP signature check\n" );
|
DBG ( "INT 15,e820 failed SMAP signature check\n" );
|
||||||
|
|||||||
Reference in New Issue
Block a user