xref: /reactos/hal/halx86/generic/misc.c (revision 7eead935)
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