[NTOS]
[reactos.git] / reactos / ntoskrnl / ke / i386 / v86vdm.c
index 9189cc7..503f413 100644 (file)
@@ -53,38 +53,40 @@ KiVdmOpcodePUSHF(IN PKTRAP_FRAME TrapFrame,
 {
     ULONG Esp, V86EFlags, TrapEFlags;
     
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
+
     /* Get current V8086 flags and mask out interrupt flag */
-    DbgPrint("VDM: Handling PUSHF (PREFIX [0x%lx])\n", KiVdmGetPrefixFlags(Flags));
     V86EFlags = *KiNtVdmState;
     V86EFlags &= ~EFLAGS_INTERRUPT_MASK;
-    
+
     /* Get trap frame EFLags and leave only align, nested task and interrupt */
     TrapEFlags = TrapFrame->EFlags;
-    TrapEFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK);
-    
+    V86EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK);
+
     /* Add in those flags if they exist, and add in the IOPL flag */
     V86EFlags |= TrapEFlags;
     V86EFlags |= EFLAGS_IOPL;
     
     /* Build flat ESP */
     Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
-    Esp -= 2;
     
     /* Check for OPER32 */
     if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32)
     {
         /* Save EFlags */
-        Esp -= 2;
-        *(PULONG)(Esp - 2) = V86EFlags;
+        Esp -= 4;
+        *(PULONG)Esp = V86EFlags;
     }
     else
     {
         /* Save EFLags */
+        Esp -= 2;
         *(PUSHORT)Esp = (USHORT)V86EFlags;
     }
     
     /* Set new ESP and EIP */
-    TrapFrame->HardwareEsp = (USHORT)Esp;
+    TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4);
     TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
     
     /* We're done */
@@ -99,23 +101,24 @@ KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame,
     ULONG Esp, V86EFlags, EFlags, TrapEFlags;
     
     /* Build flat ESP */
-    DbgPrint("VDM: Handling POPF (PREFIX [0x%lx])\n", KiVdmGetPrefixFlags(Flags));
     Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
     
-    /* Read EFlags */
-    EFlags = *(PULONG)Esp;
-    Esp += 4;
-    
     /* Check for OPER32 */
-    if (!(KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32))
+    if (KiVdmGetPrefixFlags(Flags) & PFX_FLAG_OPER32)
     {
-        /* Read correct flags and use correct stack address */
-        Esp -= 2;
-        EFlags &= 0xFFFF;
+        /* Read EFlags */
+        EFlags = *(PULONG)Esp;
+        Esp += 4;
+    }
+    else
+    {
+        /* Read EFlags */
+        EFlags = *(PUSHORT)Esp;
+        Esp += 2;
     }
     
     /* Set new ESP */
-    TrapFrame->HardwareEsp = Esp;
+    TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4);
     
     /* Mask out IOPL from the flags */
     EFlags &= ~EFLAGS_IOPL;
@@ -126,15 +129,18 @@ KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame,
     /* Now leave only alignment, nested task and interrupt flag */
     EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_NESTED_TASK | EFLAGS_INTERRUPT_MASK);
     
-    /* FIXME: Check for VME support */
-    
+    /* Get trap EFlags */
+    TrapEFlags = TrapFrame->EFlags;
+                
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
+
     /* Add V86 and Interrupt flag */
     V86EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK;
-    
+
     /* Update EFlags in trap frame */
-    TrapEFlags = TrapFrame->EFlags;
-    TrapFrame->EFlags = (TrapFrame->EFlags & EFLAGS_VIP) | V86EFlags;
-    
+    TrapFrame->EFlags = V86EFlags;
+
     /* Check if ESP0 needs to be fixed up */
     if (TrapEFlags & EFLAGS_V86_MASK) Ki386AdjustEsp0(TrapFrame);
     
@@ -168,7 +174,8 @@ KiVdmOpcodeINTnn(IN PKTRAP_FRAME TrapFrame,
     /* Keep only alignment and interrupt flag from the V8086 state */
     V86EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_INTERRUPT_MASK);
     
-    /* FIXME: Support VME */
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
     
     /* Mask in the relevant V86 EFlags into the trap flags */
     V86EFlags |= (TrapEFlags & ~EFLAGS_INTERRUPT_MASK);
@@ -205,7 +212,6 @@ KiVdmOpcodeINTnn(IN PKTRAP_FRAME TrapFrame,
     
     /* Now read the interrupt number */
     Interrupt = *(PUCHAR)Eip;
-    DbgPrint("VDM: Handling INT [0x%lx]\n", Interrupt);
         
     /* Read the EIP from its IVT entry */
     Interrupt = *(PULONG)(Interrupt * 4);
@@ -248,7 +254,6 @@ KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame,
     ULONG Esp, V86EFlags, EFlags, TrapEFlags, Eip;
 
     /* Build flat ESP */
-    DbgPrint("VDM: Handling IRET (PREFIX [0x%lx])\n", KiVdmGetPrefixFlags(Flags));
     Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp;
     
     /* Check for OPER32 */
@@ -281,7 +286,8 @@ KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame,
     EFlags &= ~(EFLAGS_IOPL + EFLAGS_VIF + EFLAGS_NESTED_TASK + EFLAGS_VIP);
     V86EFlags = EFlags;
     
-    /* FIXME: Check for VME support */
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
     
     /* Add V86 and Interrupt flag */
     EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK;
@@ -299,7 +305,6 @@ KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame,
     
     /* Build flat EIP and check if this is the BOP instruction */
     Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
-    DbgPrint("VDM: Handling IRET EIP @ 0x%p [OPCODE: %lx]\n", Eip, *(PUSHORT)Eip);
     if (*(PUSHORT)Eip == 0xC4C4)
     {
         /* Dispatch the BOP */
@@ -308,6 +313,7 @@ KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame,
     else
     {
         /* FIXME: Check for VDM interrupts */
+       DPRINT("FIXME: Check for VDM interrupts\n");
     }
     
     /* We're done */
@@ -319,10 +325,10 @@ FASTCALL
 KiVdmOpcodeCLI(IN PKTRAP_FRAME TrapFrame,
                IN ULONG Flags)
 {       
-    /* FIXME: Support VME */
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
 
     /* Disable interrupts */
-    DbgPrint("VDM: Handling CLI\n");
     KiVdmClearVdmEFlags(EFLAGS_INTERRUPT_MASK);
     
     /* Skip instruction */
@@ -337,10 +343,10 @@ FASTCALL
 KiVdmOpcodeSTI(IN PKTRAP_FRAME TrapFrame,
                IN ULONG Flags)
 {
-    /* FIXME: Support VME */
+    /* Check for VME support */
+    ASSERT(KeI386VirtualIntExtensions == FALSE);
 
     /* Enable interrupts */
-    DbgPrint("VDM: Handling STI\n");
     KiVdmSetVdmEFlags(EFLAGS_INTERRUPT_MASK);
     
     /* Skip instruction */
@@ -361,7 +367,6 @@ KiVdmHandleOpcode(IN PKTRAP_FRAME TrapFrame,
     
     /* Get flat EIP of the *current* instruction (not the original EIP) */
     Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
-    DbgPrint("VDM: Handling Opcode @ 0x%p\n", Eip);
     Eip += KiVdmGetInstructionSize(Flags) - 1;
     
     /* Read the opcode entry */
@@ -420,7 +425,6 @@ KiVdmOpcodePrefix(IN PKTRAP_FRAME TrapFrame,
                   IN ULONG Flags)
 {
     /* Increase instruction size */
-    DbgPrint("VDM: Handling PREFIX [%lx] Opcode @ 0x%p\n", KiVdmGetPrefixFlags(Flags), TrapFrame->Eip);
     Flags++;
     
     /* Handle the next opcode */
@@ -470,7 +474,7 @@ KiExitV86Mode(IN PKTRAP_FRAME TrapFrame)
 
     /* Restore TEB addresses */
     Thread->Teb = V86Frame->ThreadTeb;
-    KeGetPcr()->Tib.Self = V86Frame->PcrTeb;
+    KeGetPcr()->NtTib.Self = V86Frame->PcrTeb;
     
     /* Setup real TEB descriptor */
     GdtEntry = &((PKIPCR)KeGetPcr())->GDT[KGDT_R3_TEB / sizeof(KGDTENTRY)];
@@ -478,9 +482,9 @@ KiExitV86Mode(IN PKTRAP_FRAME TrapFrame)
     GdtEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Thread->Teb >> 16);
     GdtEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Thread->Teb >> 24);
 
-    /* Enable interrupts and get back to protected mode */
+    /* Enable interrupts and return a pointer to the trap frame */
     _enable();
-    return TrapFrame->Edi;
+    return (ULONG)PmTrapFrame;
 }
 
 VOID
@@ -504,7 +508,7 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
     
     /* Save TEB addresses */
     V86Frame->ThreadTeb = Thread->Teb;
-    V86Frame->PcrTeb = KeGetPcr()->Tib.Self;
+    V86Frame->PcrTeb = KeGetPcr()->NtTib.Self;
     
     /* Save return EIP */
     TrapFrame->Eip = (ULONG_PTR)Ki386BiosCallReturnAddress;
@@ -532,7 +536,7 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
     RtlCopyMemory(NpxFrame, V86Frame->ThreadStack, sizeof(FX_SAVE_AREA));
     
     /* Clear exception list */
-    KeGetPcr()->Tib.ExceptionList = EXCEPTION_CHAIN_END;
+    KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
     
     /* Set new ESP0 */
     KeGetPcr()->TSS->Esp0 = (ULONG_PTR)&TrapFrame->V86Es;
@@ -542,7 +546,7 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
         
     /* Set VDM TEB */
     Thread->Teb = (PTEB)TRAMPOLINE_TEB;
-    KeGetPcr()->Tib.Self = (PVOID)TRAMPOLINE_TEB;
+    KeGetPcr()->NtTib.Self = (PVOID)TRAMPOLINE_TEB;
     
     /* Setup VDM TEB descriptor */
     GdtEntry = &((PKIPCR)KeGetPcr())->GDT[KGDT_R3_TEB / sizeof(KGDTENTRY)];
@@ -635,9 +639,7 @@ Ke386CallBios(IN ULONG Int,
     Tss->IoMapBase = (USHORT)IOPM_OFFSET;
 
     /* Switch stacks and work the magic */
-    DbgPrint("VDM: Entering V8086 Mode\n");
     Ki386SetupAndExitToV86Mode(VdmTeb);
-    DbgPrint("VDM: Exiting V8086 Mode\n");
 
     /* Restore IOPM */
     RtlCopyMemory(&Tss->IoMaps[0].IoMap, Ki386IopmSaveArea, PAGE_SIZE * 2);
@@ -660,37 +662,87 @@ Ke386CallBios(IN ULONG Int,
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOLEAN
 NTAPI
 Ke386IoSetAccessProcess(IN PKPROCESS Process,
-                        IN ULONG Flag)
+                        IN ULONG MapNumber)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    USHORT MapOffset;
+    PKPRCB Prcb;
+    KAFFINITY TargetProcessors;
+
+    if(MapNumber > IOPM_COUNT)
+        return FALSE;
+
+    MapOffset = KiComputeIopmOffset(MapNumber);
+
+    Process->IopmOffset = MapOffset;
+
+    TargetProcessors = Process->ActiveProcessors;
+    Prcb = KeGetCurrentPrcb();
+    if (TargetProcessors & Prcb->SetMember)
+        KeGetPcr()->TSS->IoMapBase = MapOffset;
+
+    return TRUE;
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOLEAN
 NTAPI
-Ke386SetIoAccessMap(IN ULONG Flag,
-                    IN PVOID IopmBuffer)
+Ke386SetIoAccessMap(IN ULONG MapNumber,
+                    IN PKIO_ACCESS_MAP IopmBuffer)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    PKPROCESS CurrentProcess;
+    PKPRCB Prcb;
+    PVOID pt;
+
+    if ((MapNumber > IOPM_COUNT) || (MapNumber == IO_ACCESS_MAP_NONE))
+        return FALSE;
+
+    Prcb = KeGetCurrentPrcb();
+
+    // Copy the IOP map and load the map for the current process.
+    pt = &(KeGetPcr()->TSS->IoMaps[MapNumber-1].IoMap);
+    RtlMoveMemory(pt, (PVOID)IopmBuffer, IOPM_SIZE);
+    CurrentProcess = Prcb->CurrentThread->ApcState.Process;
+    KeGetPcr()->TSS->IoMapBase = CurrentProcess->IopmOffset;
+
+    return TRUE;
 }
 
 /*
- * @unimplemented
+ * @implemented
  */
 BOOLEAN
 NTAPI
-Ke386QueryIoAccessMap(IN ULONG Flag,
-                      IN PVOID IopmBuffer)
+Ke386QueryIoAccessMap(IN ULONG MapNumber,
+                      IN PKIO_ACCESS_MAP IopmBuffer)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    ULONG i;
+    PVOID Map;
+    PUCHAR p;
+
+    if (MapNumber > IOPM_COUNT)
+        return FALSE;
+
+    if (MapNumber == IO_ACCESS_MAP_NONE)
+    {
+        // no access, simply return a map of all 1s
+        p = (PUCHAR)IopmBuffer;
+        for (i = 0; i < IOPM_SIZE; i++) {
+            p[i] = (UCHAR)-1;
+        }
+    }
+    else
+    {
+        // copy the bits
+        Map = (PVOID)&(KeGetPcr()->TSS->IoMaps[MapNumber-1].IoMap);
+        RtlMoveMemory((PVOID)IopmBuffer, Map, IOPM_SIZE);
+    }
+
+    return TRUE;
 }