xref: /reactos/subsystems/mvdm/ntvdm/cpu/callback.c (revision 5cb06151)
1 /*
2  * COPYRIGHT:       GPL - See COPYING in the top level directory
3  * PROJECT:         ReactOS Virtual DOS Machine
4  * FILE:            subsystems/mvdm/ntvdm/cpu/callback.c
5  * PURPOSE:         16 and 32-bit Callbacks Support
6  * PROGRAMMERS:     Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7  *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8  */
9 
10 /******************************************************************************\
11 |   WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!
12 |
13 |   Callbacks support supposes implicitly that the callbacks are used
14 |   in the SAME thread as the CPU thread, otherwise messing in parallel
15 |   with the CPU registers is 100% prone to bugs!!
16 \******************************************************************************/
17 
18 /* INCLUDES *******************************************************************/
19 
20 #include "ntvdm.h"
21 
22 #define NDEBUG
23 #include <debug.h>
24 
25 #include "emulator.h"
26 #include "callback.h"
27 
28 #include "cpu.h"
29 #include "bop.h"
30 #include <isvbop.h>
31 
32 /* PRIVATE VARIABLES **********************************************************/
33 
34 #if 0
35 /* FIXME: Are we going to use this somewhere? */
36 static BYTE Yield[] =
37 {
38     0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
39     0x90, 0x90, 0x90, 0x90, 0x90, 0x90,         // 13x nop
40     BOP(BOP_UNSIMULATE),                        // UnSimulate16 BOP
41 };
42 C_ASSERT(sizeof(Yield) == 16 * sizeof(BYTE));
43 #endif
44 
45 /* PUBLIC FUNCTIONS ***********************************************************/
46 
47 VOID
InitializeContextEx(IN PCALLBACK16 Context,IN ULONG TrampolineSize,IN USHORT Segment,IN USHORT Offset)48 InitializeContextEx(IN PCALLBACK16 Context,
49                     IN ULONG       TrampolineSize,
50                     IN USHORT      Segment,
51                     IN USHORT      Offset)
52 {
53     Context->TrampolineFarPtr = MAKELONG(Offset, Segment);
54     Context->TrampolineSize   = max(TRAMPOLINE_SIZE, TrampolineSize);
55     Context->Segment          = Segment;
56     Context->NextOffset       = Offset + Context->TrampolineSize;
57 }
58 
59 VOID
InitializeContext(IN PCALLBACK16 Context,IN USHORT Segment,IN USHORT Offset)60 InitializeContext(IN PCALLBACK16 Context,
61                   IN USHORT      Segment,
62                   IN USHORT      Offset)
63 {
64     InitializeContextEx(Context,
65                         TRAMPOLINE_SIZE,
66                         Segment,
67                         Offset);
68 }
69 
70 VOID
Call16(IN USHORT Segment,IN USHORT Offset)71 Call16(IN USHORT Segment,
72        IN USHORT Offset)
73 {
74     /* Save CS:IP */
75     USHORT OrgCS = getCS();
76     USHORT OrgIP = getIP();
77 
78     /* Set the new CS:IP */
79     setCS(Segment);
80     setIP(Offset);
81 
82     DPRINT("Call16(%04X:%04X)\n", Segment, Offset);
83 
84     /* Start CPU simulation */
85     CpuSimulate();
86 
87     /* Restore CS:IP */
88     setCS(OrgCS);
89     setIP(OrgIP);
90 }
91 
92 VOID
RunCallback16(IN PCALLBACK16 Context,IN ULONG FarPtr)93 RunCallback16(IN PCALLBACK16 Context,
94               IN ULONG       FarPtr)
95 {
96     PUCHAR TrampolineBase = (PUCHAR)FAR_POINTER(Context->TrampolineFarPtr);
97     PUCHAR Trampoline     = TrampolineBase;
98     UCHAR  OldTrampoline[TRAMPOLINE_SIZE];
99 
100     /* Save the old trampoline */
101     ((PULONGLONG)&OldTrampoline)[0] = ((PULONGLONG)TrampolineBase)[0];
102 
103     DPRINT("RunCallback16(0x%p)\n", FarPtr);
104 
105     /* Build the generic entry-point for 16-bit far calls */
106     *Trampoline++ = 0x9A; // Call far seg:off
107     *(PULONG)Trampoline = FarPtr;
108     Trampoline += sizeof(ULONG);
109     UnSimulate16(Trampoline);
110 
111     /* Perform the call */
112     Call16(HIWORD(Context->TrampolineFarPtr),
113            LOWORD(Context->TrampolineFarPtr));
114 
115     /* Restore the old trampoline */
116     ((PULONGLONG)TrampolineBase)[0] = ((PULONGLONG)&OldTrampoline)[0];
117 }
118 
119 ULONG
RegisterCallback16(IN ULONG FarPtr,IN LPBYTE CallbackCode,IN SIZE_T CallbackSize,OUT PSIZE_T CodeSize OPTIONAL)120 RegisterCallback16(IN  ULONG   FarPtr,
121                    IN  LPBYTE  CallbackCode,
122                    IN  SIZE_T  CallbackSize,
123                    OUT PSIZE_T CodeSize OPTIONAL)
124 {
125     LPBYTE CodeStart = (LPBYTE)FAR_POINTER(FarPtr);
126     LPBYTE Code      = CodeStart;
127 
128     SIZE_T OurCodeSize = CallbackSize;
129 
130     if (CallbackCode == NULL) CallbackSize = 0;
131 
132     if (CallbackCode)
133     {
134         /* 16-bit interrupt code */
135         RtlCopyMemory(Code, CallbackCode, CallbackSize);
136         Code += CallbackSize;
137     }
138 
139     /* Return the real size of the code if needed */
140     if (CodeSize) *CodeSize = OurCodeSize; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart;
141 
142     // /* Return the entry-point address for 32-bit calls */
143     // return (ULONG_PTR)(CodeStart + CallbackSize);
144     return OurCodeSize;
145 }
146 
147 /* EOF */
148