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