xref: /reactos/ntoskrnl/vdm/vdmmain.c (revision 34593d93)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:         ReactOS Kernel
3c2c66affSColin Finck  * LICENSE:         GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:            ntoskrnl/vdm/vdmmain.c
5c2c66affSColin Finck  * PURPOSE:         VDM Support Services
6c2c66affSColin Finck  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7c2c66affSColin Finck  *                  Aleksey Bragin (aleksey@reactos.org)
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck /* INCLUDES ******************************************************************/
11c2c66affSColin Finck 
12c2c66affSColin Finck #include <ntoskrnl.h>
13c2c66affSColin Finck #define NDEBUG
14c2c66affSColin Finck #include <debug.h>
15c2c66affSColin Finck 
16c2c66affSColin Finck /* GLOBALS *******************************************************************/
17c2c66affSColin Finck 
18c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/
19c2c66affSColin Finck 
20*5c7ce447SVictor Perevertkin CODE_SEG("INIT")
21c2c66affSColin Finck VOID
22c2c66affSColin Finck NTAPI
Ki386VdmEnablePentiumExtentions(IN BOOLEAN Enable)23c2c66affSColin Finck Ki386VdmEnablePentiumExtentions(IN BOOLEAN Enable)
24c2c66affSColin Finck {
25c2c66affSColin Finck     ULONG EFlags, Cr4;
26c2c66affSColin Finck 
27c2c66affSColin Finck     /* Save interrupt state and disable them */
28c2c66affSColin Finck     EFlags = __readeflags();
29c2c66affSColin Finck     _disable();
30c2c66affSColin Finck 
31c2c66affSColin Finck     /* Enable or disable VME as required */
32c2c66affSColin Finck     Cr4 = __readcr4();
33c2c66affSColin Finck     __writecr4(Enable ? Cr4 | CR4_VME : Cr4 & ~CR4_VME);
34c2c66affSColin Finck 
35c2c66affSColin Finck     /* Restore interrupt state */
36c2c66affSColin Finck     __writeeflags(EFlags);
37c2c66affSColin Finck }
38c2c66affSColin Finck 
39*5c7ce447SVictor Perevertkin CODE_SEG("INIT")
40c2c66affSColin Finck VOID
41c2c66affSColin Finck NTAPI
KeI386VdmInitialize(VOID)42c2c66affSColin Finck KeI386VdmInitialize(VOID)
43c2c66affSColin Finck {
44c2c66affSColin Finck     NTSTATUS Status;
45c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
46c2c66affSColin Finck     HANDLE RegHandle;
47c2c66affSColin Finck     UNICODE_STRING Name;
48c2c66affSColin Finck     UCHAR KeyValueInfo[sizeof(KEY_VALUE_BASIC_INFORMATION) + 30];
49c2c66affSColin Finck     ULONG ReturnLength;
50c2c66affSColin Finck 
51c2c66affSColin Finck     /* Make sure that there is a WOW key */
52c2c66affSColin Finck     RtlInitUnicodeString(&Name,
53c2c66affSColin Finck                          L"\\Registry\\Machine\\System\\CurrentControlSet\\"
54c2c66affSColin Finck                          L"Control\\Wow");
55c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
56c2c66affSColin Finck                                &Name,
57c2c66affSColin Finck                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
58c2c66affSColin Finck                                NULL,
59c2c66affSColin Finck                                NULL);
60c2c66affSColin Finck     Status = ZwOpenKey(&RegHandle, KEY_READ, &ObjectAttributes);
61c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return;
62c2c66affSColin Finck 
63c2c66affSColin Finck     /* Check if VME is enabled */
64c2c66affSColin Finck     RtlInitUnicodeString(&Name, L"DisableVme");
65c2c66affSColin Finck     Status = ZwQueryValueKey(RegHandle,
66c2c66affSColin Finck                              &Name,
67c2c66affSColin Finck                              KeyValueBasicInformation,
68c2c66affSColin Finck                              &KeyValueInfo,
69c2c66affSColin Finck                              sizeof(KeyValueInfo),
70c2c66affSColin Finck                              &ReturnLength);
71c2c66affSColin Finck     if (!NT_SUCCESS(Status))
72c2c66affSColin Finck     {
73c2c66affSColin Finck         /* Not present, so check if the CPU supports VME */
74c2c66affSColin Finck         if (KeGetPcr()->Prcb->FeatureBits & KF_V86_VIS)
75c2c66affSColin Finck         {
76c2c66affSColin Finck             /* Enable them. FIXME: Use IPI */
77c2c66affSColin Finck             Ki386VdmEnablePentiumExtentions(TRUE);
78c2c66affSColin Finck             KeI386VirtualIntExtensions = TRUE;
79c2c66affSColin Finck         }
80c2c66affSColin Finck     }
81c2c66affSColin Finck 
82c2c66affSColin Finck     /* Close the key */
83c2c66affSColin Finck     ZwClose(RegHandle);
84c2c66affSColin Finck }
85c2c66affSColin Finck 
86c2c66affSColin Finck NTSTATUS
87c2c66affSColin Finck NTAPI
VdmpInitialize(PVOID ControlData)88c2c66affSColin Finck VdmpInitialize(PVOID ControlData)
89c2c66affSColin Finck {
90c2c66affSColin Finck     OBJECT_ATTRIBUTES ObjectAttributes;
91c2c66affSColin Finck     UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory");
92c2c66affSColin Finck     NTSTATUS Status;
93c2c66affSColin Finck     HANDLE PhysMemHandle;
94c2c66affSColin Finck     PVOID BaseAddress;
95c2c66affSColin Finck     volatile PVOID NullAddress = NULL;
96c2c66affSColin Finck     LARGE_INTEGER Offset;
97c2c66affSColin Finck     ULONG ViewSize;
98c2c66affSColin Finck 
99c2c66affSColin Finck     /* Open the physical memory section */
100c2c66affSColin Finck     InitializeObjectAttributes(&ObjectAttributes,
101c2c66affSColin Finck                                &PhysMemName,
102c2c66affSColin Finck                                OBJ_KERNEL_HANDLE,
103c2c66affSColin Finck                                NULL,
104c2c66affSColin Finck                                NULL);
105c2c66affSColin Finck     Status = ZwOpenSection(&PhysMemHandle,
106c2c66affSColin Finck                            SECTION_ALL_ACCESS,
107c2c66affSColin Finck                            &ObjectAttributes);
108c2c66affSColin Finck     if (!NT_SUCCESS(Status))
109c2c66affSColin Finck     {
110c2c66affSColin Finck         DPRINT1("Couldn't open \\Device\\PhysicalMemory\n");
111c2c66affSColin Finck         return Status;
112c2c66affSColin Finck     }
113c2c66affSColin Finck 
114c2c66affSColin Finck     /* Map the BIOS and device registers into the address space */
115c2c66affSColin Finck     Offset.QuadPart = 0;
116c2c66affSColin Finck     ViewSize = PAGE_SIZE;
117c2c66affSColin Finck     BaseAddress = 0;
118c2c66affSColin Finck     Status = ZwMapViewOfSection(PhysMemHandle,
119c2c66affSColin Finck                                 NtCurrentProcess(),
120c2c66affSColin Finck                                 &BaseAddress,
121c2c66affSColin Finck                                 0,
122c2c66affSColin Finck                                 ViewSize,
123c2c66affSColin Finck                                 &Offset,
124c2c66affSColin Finck                                 &ViewSize,
125c2c66affSColin Finck                                 ViewUnmap,
126c2c66affSColin Finck                                 0,
127c2c66affSColin Finck                                 PAGE_READWRITE);
128c2c66affSColin Finck     if (!NT_SUCCESS(Status))
129c2c66affSColin Finck     {
130c2c66affSColin Finck         DPRINT1("Couldn't map physical memory (%x)\n", Status);
131c2c66affSColin Finck         ZwClose(PhysMemHandle);
132c2c66affSColin Finck         return Status;
133c2c66affSColin Finck     }
134c2c66affSColin Finck 
135c2c66affSColin Finck     /* Enter SEH */
136c2c66affSColin Finck     _SEH2_TRY
137c2c66affSColin Finck     {
138c2c66affSColin Finck         /* Copy the first physical page into the first virtual page */
139c2c66affSColin Finck         RtlMoveMemory(NullAddress, BaseAddress, ViewSize);
140c2c66affSColin Finck     }
141c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
142c2c66affSColin Finck     {
143c2c66affSColin Finck         /* Fail */
144c2c66affSColin Finck         DPRINT1("Couldn't copy first page (%x)\n", Status);
145c2c66affSColin Finck         ZwClose(PhysMemHandle);
146c2c66affSColin Finck         ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
147c2c66affSColin Finck         _SEH2_YIELD(return _SEH2_GetExceptionCode());
148c2c66affSColin Finck     }
149c2c66affSColin Finck     _SEH2_END;
150c2c66affSColin Finck 
151c2c66affSColin Finck     /* Close physical memory section handle */
152c2c66affSColin Finck     ZwClose(PhysMemHandle);
153c2c66affSColin Finck 
154c2c66affSColin Finck     /* Unmap the section */
155c2c66affSColin Finck     Status = ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
156c2c66affSColin Finck 
157c2c66affSColin Finck     if (!NT_SUCCESS(Status))
158c2c66affSColin Finck     {
159c2c66affSColin Finck         DPRINT1("Couldn't unmap the section (%x)\n", Status);
160c2c66affSColin Finck         return Status;
161c2c66affSColin Finck     }
162c2c66affSColin Finck 
163c2c66affSColin Finck     return STATUS_SUCCESS;
164c2c66affSColin Finck }
165c2c66affSColin Finck 
166c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/
167c2c66affSColin Finck 
168c2c66affSColin Finck /*
169c2c66affSColin Finck  * @implemented
170c2c66affSColin Finck  */
171c2c66affSColin Finck NTSTATUS
172c2c66affSColin Finck NTAPI
NtVdmControl(IN ULONG ControlCode,IN PVOID ControlData)173c2c66affSColin Finck NtVdmControl(IN ULONG ControlCode,
174c2c66affSColin Finck              IN PVOID ControlData)
175c2c66affSColin Finck {
176c2c66affSColin Finck     NTSTATUS Status;
177c2c66affSColin Finck     PAGED_CODE();
178c2c66affSColin Finck 
179c2c66affSColin Finck     /* Check which control code this is */
180c2c66affSColin Finck     switch (ControlCode)
181c2c66affSColin Finck     {
182c2c66affSColin Finck         /* VDM Execution start */
183c2c66affSColin Finck         case VdmStartExecution:
184c2c66affSColin Finck 
185c2c66affSColin Finck             /* Call the sub-function */
186c2c66affSColin Finck             Status = VdmpStartExecution();
187c2c66affSColin Finck             break;
188c2c66affSColin Finck 
189c2c66affSColin Finck         case VdmInitialize:
190c2c66affSColin Finck 
191c2c66affSColin Finck             /* Call the init sub-function */
192c2c66affSColin Finck             Status = VdmpInitialize(ControlData);
193c2c66affSColin Finck             break;
194c2c66affSColin Finck 
195c2c66affSColin Finck         default:
196c2c66affSColin Finck 
197c2c66affSColin Finck             /* Unsupported */
198c2c66affSColin Finck             DPRINT1("Unknown VDM call: %lx\n", ControlCode);
199c2c66affSColin Finck             Status = STATUS_INVALID_PARAMETER;
200c2c66affSColin Finck     }
201c2c66affSColin Finck 
202c2c66affSColin Finck     /* Return the status */
203c2c66affSColin Finck     return Status;
204c2c66affSColin Finck }
205