diff options
Diffstat (limited to 'gpxe/src/arch/i386/firmware/pcbios/memmap.c')
-rw-r--r-- | gpxe/src/arch/i386/firmware/pcbios/memmap.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/gpxe/src/arch/i386/firmware/pcbios/memmap.c b/gpxe/src/arch/i386/firmware/pcbios/memmap.c index 9de10a7a..2e9627c0 100644 --- a/gpxe/src/arch/i386/firmware/pcbios/memmap.c +++ b/gpxe/src/arch/i386/firmware/pcbios/memmap.c @@ -158,7 +158,7 @@ static int meme820 ( struct memory_map *memmap ) { uint32_t smap; size_t size; unsigned int flags; - unsigned int discard_d, discard_D; + unsigned int discard_D; /* Clear the E820 buffer. Do this once before starting, * rather than on each call; some BIOSes rely on the contents @@ -167,18 +167,24 @@ static int meme820 ( struct memory_map *memmap ) { memset ( &e820buf, 0, sizeof ( e820buf ) ); do { - __asm__ __volatile__ ( REAL_CODE ( "stc\n\t" + /* Some BIOSes corrupt %esi for fun. Guard against + * this by telling gcc that all non-output registers + * may be corrupted. + */ + __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" + "stc\n\t" "int $0x15\n\t" "pushfw\n\t" - "popw %w0\n\t" ) - : "=r" ( flags ), "=a" ( smap ), - "=b" ( next ), "=D" ( discard_D ), - "=c" ( size ), "=d" ( discard_d ) + "popw %%dx\n\t" + "popl %%ebp\n\t" ) + : "=a" ( smap ), "=b" ( next ), + "=c" ( size ), "=d" ( flags ), + "=D" ( discard_D ) : "a" ( 0xe820 ), "b" ( next ), "D" ( __from_data16 ( &e820buf ) ), "c" ( sizeof ( e820buf ) ), "d" ( SMAP ) - : "memory" ); + : "esi", "memory" ); if ( smap != SMAP ) { DBG ( "INT 15,e820 failed SMAP signature check\n" ); |