https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3381bf39db36a2b763c83…
commit 3381bf39db36a2b763c83a9411f69acf7329acfe
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Sun Aug 14 14:41:53 2022 +0200
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Thu Nov 24 21:17:58 2022 +0200
[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.
---
hal/halx86/amd64/x86bios.c | 39 +++++++++++++++++++--------------------
1 file changed, 19 insertions(+), 20 deletions(-)
diff --git a/hal/halx86/amd64/x86bios.c b/hal/halx86/amd64/x86bios.c
index 6d7ce9ae083..80cefebc322 100644
--- a/hal/halx86/amd64/x86bios.c
+++ b/hal/halx86/amd64/x86bios.c
@@ -412,12 +412,8 @@ x86BiosCall(
_In_ ULONG InterruptNumber,
_Inout_ PX86_BIOS_REGISTERS Registers)
{
+ const ULONG StackBase = 0x2000;
FAST486_STATE EmulatorContext;
- struct
- {
- USHORT Ip;
- USHORT SegCs;
- } *Ivt;
ULONG FlatIp;
PUCHAR InstructionPointer;
@@ -432,8 +428,6 @@ x86BiosCall(
NULL, // FpuCallback,
NULL); // Tlb
-//RegisterBop(BOP_UNSIMULATE, CpuUnsimulateBop);
-
/* Copy the registers */
EmulatorContext.GeneralRegs[FAST486_REG_EAX].Long = Registers->Eax;
EmulatorContext.GeneralRegs[FAST486_REG_EBX].Long = Registers->Ebx;
@@ -449,36 +443,41 @@ x86BiosCall(
EmulatorContext.Flags.AlwaysSet = 1;
EmulatorContext.Flags.If = 1;
+ /* Set up the INT stub */
+ 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 the stack pointer */
- Fast486SetStack(&EmulatorContext, 0, 0x2000 - 2); // FIXME
+ Fast486SetStack(&EmulatorContext, 0, StackBase - 8);
- /* Set CS:EIP from the IVT entry */
- Ivt = (PVOID)x86BiosMemoryMapping;
- Fast486ExecuteAt(&EmulatorContext,
- Ivt[InterruptNumber].SegCs,
- Ivt[InterruptNumber].Ip);
+ /* Start execution at the INT stub */
+ Fast486ExecuteAt(&EmulatorContext, 0x00, FlatIp);
while (TRUE)
{
- /* Step one instruction */
- Fast486StepInto(&EmulatorContext);
-
- /* Check for iret */
+ /* Get the current flat IP */
FlatIp = (EmulatorContext.SegmentRegs[FAST486_REG_CS].Selector << 4) +
EmulatorContext.InstPtr.Long;
+
+ /* Make sure we haven't left the allowed memory range */
if (FlatIp >= 0x100000)
{
DPRINT1("x86BiosCall: invalid IP (0x%lx) during BIOS execution",
FlatIp);
return FALSE;
}
- /* Read the next instruction and check if it's IRET */
- InstructionPointer = x86BiosMemoryMapping + FlatIp;
- if (*InstructionPointer == 0xCF)
+ /* Check if we returned from our int stub */
+ if (FlatIp == (StackBase - 2))
{
/* We are done! */
break;
}
+
+ /* Emulate one instruction */
+ Fast486StepInto(&EmulatorContext);
}
/* Copy the registers back */