summaryrefslogtreecommitdiff
path: root/gpxe/src/arch/i386/firmware/pcbios/memmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'gpxe/src/arch/i386/firmware/pcbios/memmap.c')
-rw-r--r--gpxe/src/arch/i386/firmware/pcbios/memmap.c20
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" );