1 /* 2 * PROJECT: ReactOS Hardware Abstraction Layer (HAL) 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: hal/halx86/generic/misc.c 5 * PURPOSE: NMI, I/O Mapping and x86 Subs 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 /* INCLUDES *******************************************************************/ 10 11 #include <hal.h> 12 #include <drivers/bootvid/display.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 #if defined(ALLOC_PRAGMA) && !defined(_MINIHAL_) 18 #pragma alloc_text(INIT, HalpMarkAcpiHal) 19 #pragma alloc_text(INIT, HalpReportSerialNumber) 20 #endif 21 22 /* GLOBALS *******************************************************************/ 23 24 BOOLEAN HalpNMIInProgress; 25 26 UCHAR HalpSerialLen; 27 CHAR HalpSerialNumber[31]; 28 29 /* PRIVATE FUNCTIONS **********************************************************/ 30 31 #ifndef _MINIHAL_ 32 INIT_FUNCTION 33 VOID 34 NTAPI 35 HalpReportSerialNumber(VOID) 36 { 37 NTSTATUS Status; 38 UNICODE_STRING KeyString; 39 HANDLE Handle; 40 41 /* Make sure there is a serial number */ 42 if (!HalpSerialLen) return; 43 44 /* Open the system key */ 45 RtlInitUnicodeString(&KeyString, L"\\Registry\\Machine\\Hardware\\Description\\System"); 46 Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE); 47 if (NT_SUCCESS(Status)) 48 { 49 /* Add the serial number */ 50 RtlInitUnicodeString(&KeyString, L"Serial Number"); 51 ZwSetValueKey(Handle, 52 &KeyString, 53 0, 54 REG_BINARY, 55 HalpSerialNumber, 56 HalpSerialLen); 57 58 /* Close the handle */ 59 ZwClose(Handle); 60 } 61 } 62 63 INIT_FUNCTION 64 NTSTATUS 65 NTAPI 66 HalpMarkAcpiHal(VOID) 67 { 68 NTSTATUS Status; 69 UNICODE_STRING KeyString; 70 HANDLE KeyHandle; 71 HANDLE Handle; 72 ULONG Value = HalDisableFirmwareMapper ? 1 : 0; 73 74 /* Open the control set key */ 75 RtlInitUnicodeString(&KeyString, 76 L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); 77 Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE); 78 if (NT_SUCCESS(Status)) 79 { 80 /* Open the PNP key */ 81 RtlInitUnicodeString(&KeyString, L"Control\\Pnp"); 82 Status = HalpOpenRegistryKey(&KeyHandle, 83 Handle, 84 &KeyString, 85 KEY_ALL_ACCESS, 86 TRUE); 87 /* Close root key */ 88 ZwClose(Handle); 89 90 /* Check if PNP BIOS key exists */ 91 if (NT_SUCCESS(Status)) 92 { 93 /* Set the disable value to false -- we need the mapper */ 94 RtlInitUnicodeString(&KeyString, L"DisableFirmwareMapper"); 95 Status = ZwSetValueKey(KeyHandle, 96 &KeyString, 97 0, 98 REG_DWORD, 99 &Value, 100 sizeof(Value)); 101 102 /* Close subkey */ 103 ZwClose(KeyHandle); 104 } 105 } 106 107 /* Return status */ 108 return Status; 109 } 110 111 NTSTATUS 112 NTAPI 113 HalpOpenRegistryKey(IN PHANDLE KeyHandle, 114 IN HANDLE RootKey, 115 IN PUNICODE_STRING KeyName, 116 IN ACCESS_MASK DesiredAccess, 117 IN BOOLEAN Create) 118 { 119 NTSTATUS Status; 120 ULONG Disposition; 121 OBJECT_ATTRIBUTES ObjectAttributes; 122 123 /* Setup the attributes we received */ 124 InitializeObjectAttributes(&ObjectAttributes, 125 KeyName, 126 OBJ_CASE_INSENSITIVE, 127 RootKey, 128 NULL); 129 130 /* What to do? */ 131 if ( Create ) 132 { 133 /* Create the key */ 134 Status = ZwCreateKey(KeyHandle, 135 DesiredAccess, 136 &ObjectAttributes, 137 0, 138 NULL, 139 REG_OPTION_VOLATILE, 140 &Disposition); 141 } 142 else 143 { 144 /* Open the key */ 145 Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes); 146 } 147 148 /* We're done */ 149 return Status; 150 } 151 #endif 152 153 VOID 154 NTAPI 155 HalpCheckPowerButton(VOID) 156 { 157 // 158 // Nothing to do on non-ACPI 159 // 160 return; 161 } 162 163 VOID 164 NTAPI 165 HalpFlushTLB(VOID) 166 { 167 ULONG_PTR Flags, Cr4; 168 INT CpuInfo[4]; 169 ULONG_PTR PageDirectory; 170 171 // 172 // Disable interrupts 173 // 174 Flags = __readeflags(); 175 _disable(); 176 177 // 178 // Get page table directory base 179 // 180 PageDirectory = __readcr3(); 181 182 // 183 // Check for CPUID support 184 // 185 if (KeGetCurrentPrcb()->CpuID) 186 { 187 // 188 // Check for global bit in CPU features 189 // 190 __cpuid(CpuInfo, 1); 191 if (CpuInfo[3] & 0x2000) 192 { 193 // 194 // Get current CR4 value 195 // 196 Cr4 = __readcr4(); 197 198 // 199 // Disable global bit 200 // 201 __writecr4(Cr4 & ~CR4_PGE); 202 203 // 204 // Flush TLB and re-enable global bit 205 // 206 __writecr3(PageDirectory); 207 __writecr4(Cr4); 208 209 // 210 // Restore interrupts 211 // 212 __writeeflags(Flags); 213 return; 214 } 215 } 216 217 // 218 // Legacy: just flush TLB 219 // 220 __writecr3(PageDirectory); 221 __writeeflags(Flags); 222 } 223 224 /* FUNCTIONS *****************************************************************/ 225 226 /* 227 * @implemented 228 */ 229 VOID 230 NTAPI 231 HalHandleNMI(IN PVOID NmiInfo) 232 { 233 #ifndef _MINIHAL_ 234 SYSTEM_CONTROL_PORT_B_REGISTER SystemControl; 235 236 // 237 // Don't recurse 238 // 239 if (HalpNMIInProgress++) ERROR_DBGBREAK(); 240 241 // 242 // Read the system control register B 243 // 244 SystemControl.Bits = __inbyte(SYSTEM_CONTROL_PORT_B); 245 246 // 247 // Switch to boot vieo 248 // 249 if (InbvIsBootDriverInstalled()) 250 { 251 // 252 // Acquire ownership 253 // 254 InbvAcquireDisplayOwnership(); 255 InbvResetDisplay(); 256 257 // 258 // Fill the screen 259 // 260 InbvSolidColorFill(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 1); 261 InbvSetScrollRegion(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1); 262 263 // 264 // Enable text 265 // 266 InbvSetTextColor(15); 267 InbvInstallDisplayStringFilter(NULL); 268 InbvEnableDisplayString(TRUE); 269 } 270 271 // 272 // Display NMI failure string 273 // 274 InbvDisplayString("\r\n*** Hardware Malfunction\r\n\r\n"); 275 InbvDisplayString("Call your hardware vendor for support\r\n\r\n"); 276 277 // 278 // Check for parity error 279 // 280 if (SystemControl.ParityCheck) 281 { 282 // 283 // Display message 284 // 285 InbvDisplayString("NMI: Parity Check / Memory Parity Error\r\n"); 286 } 287 288 // 289 // Check for I/O failure 290 // 291 if (SystemControl.ChannelCheck) 292 { 293 // 294 // Display message 295 // 296 InbvDisplayString("NMI: Channel Check / IOCHK\r\n"); 297 } 298 299 // 300 // Check for EISA systems 301 // 302 if (HalpBusType == MACHINE_TYPE_EISA) 303 { 304 // 305 // FIXME: Not supported 306 // 307 UNIMPLEMENTED; 308 } 309 310 // 311 // Halt the system 312 // 313 InbvDisplayString("\r\n*** The system has halted ***\r\n"); 314 315 316 // 317 // Enter the debugger if possible 318 // 319 KiBugCheckData[0] = (ULONG_PTR)KeServiceDescriptorTable; /* NMI Corruption? */ 320 //if (!(KdDebuggerNotPresent) && (KdDebuggerEnabled)) KeEnterKernelDebugger(); 321 #endif 322 // 323 // Freeze the system 324 // 325 while (TRUE); 326 } 327 328 /* 329 * @implemented 330 */ 331 UCHAR 332 FASTCALL 333 HalSystemVectorDispatchEntry(IN ULONG Vector, 334 OUT PKINTERRUPT_ROUTINE **FlatDispatch, 335 OUT PKINTERRUPT_ROUTINE *NoConnection) 336 { 337 // 338 // Not implemented on x86 339 // 340 return 0; 341 } 342 343 /* 344 * @implemented 345 */ 346 VOID 347 NTAPI 348 KeFlushWriteBuffer(VOID) 349 { 350 // 351 // Not implemented on x86 352 // 353 return; 354 } 355 356 #ifdef _M_IX86 357 /* x86 fastcall wrappers */ 358 359 #undef KeRaiseIrql 360 /* 361 * @implemented 362 */ 363 VOID 364 NTAPI 365 KeRaiseIrql(KIRQL NewIrql, 366 PKIRQL OldIrql) 367 { 368 /* Call the fastcall function */ 369 *OldIrql = KfRaiseIrql(NewIrql); 370 } 371 372 #undef KeLowerIrql 373 /* 374 * @implemented 375 */ 376 VOID 377 NTAPI 378 KeLowerIrql(KIRQL NewIrql) 379 { 380 /* Call the fastcall function */ 381 KfLowerIrql(NewIrql); 382 } 383 384 #undef KeAcquireSpinLock 385 /* 386 * @implemented 387 */ 388 VOID 389 NTAPI 390 KeAcquireSpinLock(PKSPIN_LOCK SpinLock, 391 PKIRQL OldIrql) 392 { 393 /* Call the fastcall function */ 394 *OldIrql = KfAcquireSpinLock(SpinLock); 395 } 396 397 #undef KeReleaseSpinLock 398 /* 399 * @implemented 400 */ 401 VOID 402 NTAPI 403 KeReleaseSpinLock(PKSPIN_LOCK SpinLock, 404 KIRQL NewIrql) 405 { 406 /* Call the fastcall function */ 407 KfReleaseSpinLock(SpinLock, NewIrql); 408 } 409 410 #endif 411 412