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