dprintf(9, "smm cpu ret %x esp=%x\n", regs[3], regs[4]);
memcpy(&smm->cpu, &smm->backup2, sizeof(smm->cpu));
memcpy(&smm->cpu.i32.eax, regs, sizeof(regs));
- set_a20(smm->backup_a20);
+ if (!smm->backup_a20)
+ set_a20(0);
smm->cpu.i32.eip = regs[3];
}
} else if (rev == SMM_REV_I64) {
} else if ((u32)smm->cpu.i64.rcx == CALL32SMM_RETURNID) {
memcpy(&smm->cpu, &smm->backup2, sizeof(smm->cpu));
memcpy(&smm->cpu.i64.rdi, regs, sizeof(regs));
- set_a20(smm->backup_a20);
+ if (!smm->backup_a20)
+ set_a20(0);
smm->cpu.i64.rip = (u32)regs[4];
}
}
if (!CONFIG_CALL32_SMM || method != C16_SMM) {
// Restore a20
- set_a20(GET_LOW(Call16Data.a20));
+ u8 a20 = GET_LOW(Call16Data.a20);
+ if (!a20)
+ set_a20(0);
// Restore gdt and fs/gs
struct descloc_s gdt;
}
static inline u8 set_a20(u8 cond) {
- u8 val = inb(PORT_A20);
- outb((val & ~A20_ENABLE_BIT) | (cond ? A20_ENABLE_BIT : 0), PORT_A20);
- return (val & A20_ENABLE_BIT) != 0;
+ u8 val = inb(PORT_A20), a20_enabled = (val & A20_ENABLE_BIT) != 0;
+ if (a20_enabled != !!cond)
+ outb(val ^ A20_ENABLE_BIT, PORT_A20);
+ return a20_enabled;
}
// x86.c