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