[HAL/x64] Fix x86BiosCall

Use an INT call stub and exit on the address after the stub instead or using iret (some BIOS code uses int / iret internally). This fixes the messed up display when trying to switch modes.
This commit is contained in:
Timo Kreuzer 2022-08-14 14:41:53 +02:00
parent 38fc6e1274
commit 3381bf39db

View file

@ -412,12 +412,8 @@ x86BiosCall(
_In_ ULONG InterruptNumber, _In_ ULONG InterruptNumber,
_Inout_ PX86_BIOS_REGISTERS Registers) _Inout_ PX86_BIOS_REGISTERS Registers)
{ {
const ULONG StackBase = 0x2000;
FAST486_STATE EmulatorContext; FAST486_STATE EmulatorContext;
struct
{
USHORT Ip;
USHORT SegCs;
} *Ivt;
ULONG FlatIp; ULONG FlatIp;
PUCHAR InstructionPointer; PUCHAR InstructionPointer;
@ -432,8 +428,6 @@ x86BiosCall(
NULL, // FpuCallback, NULL, // FpuCallback,
NULL); // Tlb NULL); // Tlb
//RegisterBop(BOP_UNSIMULATE, CpuUnsimulateBop);
/* Copy the registers */ /* Copy the registers */
EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long = Registers->Eax; EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long = Registers->Eax;
EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long = Registers->Ebx; EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long = Registers->Ebx;
@ -449,36 +443,41 @@ x86BiosCall(
EmulatorContext.Flags.AlwaysSet = 1; EmulatorContext.Flags.AlwaysSet = 1;
EmulatorContext.Flags.If = 1; EmulatorContext.Flags.If = 1;
/* Set the stack pointer */ /* Set up the INT stub */
Fast486SetStack(&EmulatorContext, 0, 0x2000 - 2); // FIXME FlatIp = StackBase - 4;
InstructionPointer = x86BiosMemoryMapping + FlatIp;
InstructionPointer[0] = 0xCD; // INT instruction
InstructionPointer[1] = (UCHAR)InterruptNumber;
InstructionPointer[2] = 0x90; // NOP. We will stop at this address.
/* Set CS:EIP from the IVT entry */ /* Set the stack pointer */
Ivt = (PVOID)x86BiosMemoryMapping; Fast486SetStack(&EmulatorContext, 0, StackBase - 8);
Fast486ExecuteAt(&EmulatorContext,
Ivt[InterruptNumber].SegCs, /* Start execution at the INT stub */
Ivt[InterruptNumber].Ip); Fast486ExecuteAt(&EmulatorContext, 0x00, FlatIp);
while (TRUE) while (TRUE)
{ {
/* Step one instruction */ /* Get the current flat IP */
Fast486StepInto(&EmulatorContext);
/* Check for iret */
FlatIp = (EmulatorContext.SegmentRegs[FAST486_REG_CS].Selector << 4) + FlatIp = (EmulatorContext.SegmentRegs[FAST486_REG_CS].Selector << 4) +
EmulatorContext.InstPtr.Long; EmulatorContext.InstPtr.Long;
/* Make sure we haven't left the allowed memory range */
if (FlatIp >= 0x100000) if (FlatIp >= 0x100000)
{ {
DPRINT1("x86BiosCall: invalid IP (0x%lx) during BIOS execution", FlatIp); DPRINT1("x86BiosCall: invalid IP (0x%lx) during BIOS execution", FlatIp);
return FALSE; return FALSE;
} }
/* Read the next instruction and check if it's IRET */ /* Check if we returned from our int stub */
InstructionPointer = x86BiosMemoryMapping + FlatIp; if (FlatIp == (StackBase - 2))
if (*InstructionPointer == 0xCF)
{ {
/* We are done! */ /* We are done! */
break; break;
} }
/* Emulate one instruction */
Fast486StepInto(&EmulatorContext);
} }
/* Copy the registers back */ /* Copy the registers back */