https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3381bf39db36a2b763c83a9411f69acf7329acfe

commit 3381bf39db36a2b763c83a9411f69acf7329acfe
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Sun Aug 14 14:41:53 2022 +0200
Commit:     Timo Kreuzer <[email protected]>
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 */

Reply via email to