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