1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: hal/halx86/acpi/halacpi.c
5 * PURPOSE: HAL ACPI Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ********************************************************************/
16
17 LIST_ENTRY HalpAcpiTableCacheList;
18 FAST_MUTEX HalpAcpiTableCacheLock;
19
20 BOOLEAN HalpProcessedACPIPhase0;
21 BOOLEAN HalpPhysicalMemoryMayAppearAbove4GB;
22
23 FADT HalpFixedAcpiDescTable;
24 PDEBUG_PORT_TABLE HalpDebugPortTable;
25 PACPI_SRAT HalpAcpiSrat;
26 PBOOT_TABLE HalpSimpleBootFlagTable;
27
28 PHYSICAL_ADDRESS HalpMaxHotPlugMemoryAddress;
29 PHYSICAL_ADDRESS HalpLowStubPhysicalAddress;
30 PHARDWARE_PTE HalpPteForFlush;
31 PVOID HalpVirtAddrForFlush;
32 PVOID HalpLowStub;
33
34 PACPI_BIOS_MULTI_NODE HalpAcpiMultiNode;
35
36 LIST_ENTRY HalpAcpiTableMatchList;
37
38 ULONG HalpInvalidAcpiTable;
39
40 ULONG HalpPicVectorRedirect[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15};
41
42 /* This determines the HAL type */
43 BOOLEAN HalDisableFirmwareMapper = TRUE;
44 PWCHAR HalHardwareIdString = L"acpipic_up";
45 PWCHAR HalName = L"ACPI Compatible Eisa/Isa HAL";
46
47 /* PRIVATE FUNCTIONS **********************************************************/
48
49 PDESCRIPTION_HEADER
50 NTAPI
HalpAcpiGetCachedTable(IN ULONG Signature)51 HalpAcpiGetCachedTable(IN ULONG Signature)
52 {
53 PLIST_ENTRY ListHead, NextEntry;
54 PACPI_CACHED_TABLE CachedTable;
55
56 /* Loop cached tables */
57 ListHead = &HalpAcpiTableCacheList;
58 NextEntry = ListHead->Flink;
59 while (NextEntry != ListHead)
60 {
61 /* Get the table */
62 CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links);
63
64 /* Compare signatures */
65 if (CachedTable->Header.Signature == Signature) return &CachedTable->Header;
66
67 /* Keep going */
68 NextEntry = NextEntry->Flink;
69 }
70
71 /* Nothing found */
72 return NULL;
73 }
74
75 VOID
76 NTAPI
HalpAcpiCacheTable(IN PDESCRIPTION_HEADER TableHeader)77 HalpAcpiCacheTable(IN PDESCRIPTION_HEADER TableHeader)
78 {
79 PACPI_CACHED_TABLE CachedTable;
80
81 /* Get the cached table and link it */
82 CachedTable = CONTAINING_RECORD(TableHeader, ACPI_CACHED_TABLE, Header);
83 InsertTailList(&HalpAcpiTableCacheList, &CachedTable->Links);
84 }
85
86 PVOID
87 NTAPI
HalpAcpiCopyBiosTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,IN PDESCRIPTION_HEADER TableHeader)88 HalpAcpiCopyBiosTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
89 IN PDESCRIPTION_HEADER TableHeader)
90 {
91 ULONG Size;
92 PFN_COUNT PageCount;
93 PHYSICAL_ADDRESS PhysAddress;
94 PACPI_CACHED_TABLE CachedTable;
95 PDESCRIPTION_HEADER CopiedTable;
96
97 /* Size we'll need for the cached table */
98 Size = TableHeader->Length + FIELD_OFFSET(ACPI_CACHED_TABLE, Header);
99 if (LoaderBlock)
100 {
101 /* Phase 0: Convert to pages and use the HAL heap */
102 PageCount = BYTES_TO_PAGES(Size);
103 PhysAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock,
104 0x1000000,
105 PageCount,
106 FALSE);
107 if (PhysAddress.QuadPart)
108 {
109 /* Map it */
110 CachedTable = HalpMapPhysicalMemory64(PhysAddress, PageCount);
111 }
112 else
113 {
114 /* No memory, so nothing to map */
115 CachedTable = NULL;
116 }
117 }
118 else
119 {
120 /* Use Mm pool */
121 CachedTable = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HAL);
122 }
123
124 /* Do we have the cached table? */
125 if (CachedTable)
126 {
127 /* Copy the data */
128 CopiedTable = &CachedTable->Header;
129 RtlCopyMemory(CopiedTable, TableHeader, TableHeader->Length);
130 }
131 else
132 {
133 /* Nothing to return */
134 CopiedTable = NULL;
135 }
136
137 /* Return the table */
138 return CopiedTable;
139 }
140
141 PVOID
142 NTAPI
HalpAcpiGetTableFromBios(IN PLOADER_PARAMETER_BLOCK LoaderBlock,IN ULONG Signature)143 HalpAcpiGetTableFromBios(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
144 IN ULONG Signature)
145 {
146 PHYSICAL_ADDRESS PhysicalAddress;
147 PXSDT Xsdt;
148 PRSDT Rsdt;
149 PFADT Fadt;
150 PDESCRIPTION_HEADER Header = NULL;
151 ULONG TableLength;
152 CHAR CheckSum = 0;
153 ULONG Offset;
154 ULONG EntryCount, CurrentEntry;
155 PCHAR CurrentByte;
156 PFN_COUNT PageCount;
157
158 /* Should not query the RSDT/XSDT by itself */
159 if ((Signature == RSDT_SIGNATURE) || (Signature == XSDT_SIGNATURE)) return NULL;
160
161 /* Special case request for DSDT, because the FADT points to it */
162 if (Signature == DSDT_SIGNATURE)
163 {
164 /* Grab the FADT */
165 Fadt = HalpAcpiGetTable(LoaderBlock, FADT_SIGNATURE);
166 if (Fadt)
167 {
168 /* Grab the DSDT address and assume 2 pages */
169 PhysicalAddress.HighPart = 0;
170 PhysicalAddress.LowPart = Fadt->dsdt;
171 TableLength = 2 * PAGE_SIZE;
172
173 /* Map it */
174 if (LoaderBlock)
175 {
176 /* Phase 0, use HAL heap */
177 Header = HalpMapPhysicalMemory64(PhysicalAddress, 2u);
178 }
179 else
180 {
181 /* Phase 1, use Mm */
182 Header = MmMapIoSpace(PhysicalAddress, 2 * PAGE_SIZE, 0);
183 }
184
185 /* Fail if we couldn't map it */
186 if (!Header)
187 {
188 DPRINT1("HAL: Failed to map ACPI table.\n");
189 return NULL;
190 }
191
192 /* Validate the signature */
193 if (Header->Signature != DSDT_SIGNATURE)
194 {
195 /* Fail and unmap */
196 if (LoaderBlock)
197 {
198 /* Using HAL heap */
199 HalpUnmapVirtualAddress(Header, 2);
200 }
201 else
202 {
203 /* Using Mm */
204 MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
205 }
206
207 /* Didn't find anything */
208 return NULL;
209 }
210 }
211 else
212 {
213 /* Couldn't find it */
214 return NULL;
215 }
216 }
217 else
218 {
219 /* To find tables, we need the RSDT */
220 Rsdt = HalpAcpiGetTable(LoaderBlock, RSDT_SIGNATURE);
221 if (Rsdt)
222 {
223 /* Won't be using the XSDT */
224 Xsdt = NULL;
225 }
226 else
227 {
228 /* Only other choice is to use the XSDT */
229 Xsdt = HalpAcpiGetTable(LoaderBlock, XSDT_SIGNATURE);
230 if (!Xsdt) return NULL;
231
232 /* Won't be using the RSDT */
233 Rsdt = NULL;
234 }
235
236 /* Smallest RSDT/XSDT is one without table entries */
237 Offset = FIELD_OFFSET(RSDT, Tables);
238 if (Xsdt)
239 {
240 /* Figure out total size of table and the offset */
241 TableLength = Xsdt->Header.Length;
242 if (TableLength < Offset) Offset = Xsdt->Header.Length;
243
244 /* The entries are each 64-bits, so count them */
245 EntryCount = (TableLength - Offset) / sizeof(PHYSICAL_ADDRESS);
246 }
247 else
248 {
249 /* Figure out total size of table and the offset */
250 TableLength = Rsdt->Header.Length;
251 if (TableLength < Offset) Offset = Rsdt->Header.Length;
252
253 /* The entries are each 32-bits, so count them */
254 EntryCount = (TableLength - Offset) / sizeof(ULONG);
255 }
256
257 /* Start at the beginning of the array and loop it */
258 for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++)
259 {
260 /* Are we using the XSDT? */
261 if (!Xsdt)
262 {
263 /* Read the 32-bit physical address */
264 PhysicalAddress.LowPart = Rsdt->Tables[CurrentEntry];
265 PhysicalAddress.HighPart = 0;
266 }
267 else
268 {
269 /* Read the 64-bit physical address */
270 PhysicalAddress = Xsdt->Tables[CurrentEntry];
271 }
272
273 /* Had we already mapped a table? */
274 if (Header)
275 {
276 /* Yes, unmap it */
277 if (LoaderBlock)
278 {
279 /* Using HAL heap */
280 HalpUnmapVirtualAddress(Header, 2);
281 }
282 else
283 {
284 /* Using Mm */
285 MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
286 }
287 }
288
289 /* Now map this table */
290 if (!LoaderBlock)
291 {
292 /* Phase 1: Use HAL heap */
293 Header = MmMapIoSpace(PhysicalAddress, 2 * PAGE_SIZE, MmNonCached);
294 }
295 else
296 {
297 /* Phase 0: Use Mm */
298 Header = HalpMapPhysicalMemory64(PhysicalAddress, 2);
299 }
300
301 /* Check if we mapped it */
302 if (!Header)
303 {
304 /* Game over */
305 DPRINT1("HAL: Failed to map ACPI table.\n");
306 return NULL;
307 }
308
309 /* We found it, break out */
310 DPRINT("Found ACPI table %c%c%c%c at 0x%p\n",
311 Header->Signature & 0xFF,
312 (Header->Signature & 0xFF00) >> 8,
313 (Header->Signature & 0xFF0000) >> 16,
314 (Header->Signature & 0xFF000000) >> 24,
315 Header);
316 if (Header->Signature == Signature) break;
317 }
318
319 /* Did we end up here back at the last entry? */
320 if (CurrentEntry == EntryCount)
321 {
322 /* Yes, unmap the last table we processed */
323 if (LoaderBlock)
324 {
325 /* Using HAL heap */
326 HalpUnmapVirtualAddress(Header, 2);
327 }
328 else
329 {
330 /* Using Mm */
331 MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
332 }
333
334 /* Didn't find anything */
335 return NULL;
336 }
337 }
338
339 /* Past this point, we assume something was found */
340 ASSERT(Header);
341
342 /* How many pages do we need? */
343 PageCount = BYTES_TO_PAGES(Header->Length);
344 if (PageCount != 2)
345 {
346 /* We assumed two, but this is not the case, free the current mapping */
347 if (LoaderBlock)
348 {
349 /* Using HAL heap */
350 HalpUnmapVirtualAddress(Header, 2);
351 }
352 else
353 {
354 /* Using Mm */
355 MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
356 }
357
358 /* Now map this table using its correct size */
359 if (!LoaderBlock)
360 {
361 /* Phase 1: Use HAL heap */
362 Header = MmMapIoSpace(PhysicalAddress, PageCount << PAGE_SHIFT, MmNonCached);
363 }
364 else
365 {
366 /* Phase 0: Use Mm */
367 Header = HalpMapPhysicalMemory64(PhysicalAddress, PageCount);
368 }
369 }
370
371 /* Fail if the remapped failed */
372 if (!Header) return NULL;
373
374 /* All tables in ACPI 3.0 other than the FACP should have correct checksum */
375 if ((Header->Signature != FADT_SIGNATURE) || (Header->Revision > 2))
376 {
377 /* Go to the end of the table */
378 CheckSum = 0;
379 CurrentByte = (PCHAR)Header + Header->Length;
380 while (CurrentByte-- != (PCHAR)Header)
381 {
382 /* Add this byte */
383 CheckSum += *CurrentByte;
384 }
385
386 /* The correct checksum is always 0, anything else is illegal */
387 if (CheckSum)
388 {
389 HalpInvalidAcpiTable = Header->Signature;
390 DPRINT1("Checksum failed on ACPI table %c%c%c%c\n",
391 (Signature & 0xFF),
392 (Signature & 0xFF00) >> 8,
393 (Signature & 0xFF0000) >> 16,
394 (Signature & 0xFF000000) >> 24);
395 }
396 }
397
398 /* Return the table */
399 return Header;
400 }
401
402 PVOID
403 NTAPI
HalpAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,IN ULONG Signature)404 HalpAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
405 IN ULONG Signature)
406 {
407 PFN_COUNT PageCount;
408 PDESCRIPTION_HEADER TableAddress, BiosCopy;
409
410 /* See if we have a cached table? */
411 TableAddress = HalpAcpiGetCachedTable(Signature);
412 if (!TableAddress)
413 {
414 /* No cache, search the BIOS */
415 TableAddress = HalpAcpiGetTableFromBios(LoaderBlock, Signature);
416 if (TableAddress)
417 {
418 /* Found it, copy it into our own memory */
419 BiosCopy = HalpAcpiCopyBiosTable(LoaderBlock, TableAddress);
420
421 /* Get the pages, and unmap the BIOS copy */
422 PageCount = BYTES_TO_PAGES(TableAddress->Length);
423 if (LoaderBlock)
424 {
425 /* Phase 0, use the HAL heap */
426 HalpUnmapVirtualAddress(TableAddress, PageCount);
427 }
428 else
429 {
430 /* Phase 1, use Mm */
431 MmUnmapIoSpace(TableAddress, PageCount << PAGE_SHIFT);
432 }
433
434 /* Cache the bios copy */
435 TableAddress = BiosCopy;
436 if (BiosCopy) HalpAcpiCacheTable(BiosCopy);
437 }
438 }
439
440 /* Return the table */
441 return TableAddress;
442 }
443
444 PVOID
445 NTAPI
HalAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,IN ULONG Signature)446 HalAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
447 IN ULONG Signature)
448 {
449 PDESCRIPTION_HEADER TableHeader;
450
451 /* Is this phase0 */
452 if (LoaderBlock)
453 {
454 /* Initialize the cache first */
455 if (!NT_SUCCESS(HalpAcpiTableCacheInit(LoaderBlock))) return NULL;
456 }
457 else
458 {
459 /* Lock the cache */
460 ExAcquireFastMutex(&HalpAcpiTableCacheLock);
461 }
462
463 /* Get the table */
464 TableHeader = HalpAcpiGetTable(LoaderBlock, Signature);
465
466 /* Release the lock in phase 1 */
467 if (!LoaderBlock) ExReleaseFastMutex(&HalpAcpiTableCacheLock);
468
469 /* Return the table */
470 return TableHeader;
471 }
472
473 VOID
474 NTAPI
HalpNumaInitializeStaticConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)475 HalpNumaInitializeStaticConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
476 {
477 PACPI_SRAT SratTable;
478
479 /* Get the SRAT, bail out if it doesn't exist */
480 SratTable = HalAcpiGetTable(LoaderBlock, SRAT_SIGNATURE);
481 HalpAcpiSrat = SratTable;
482 if (!SratTable) return;
483 }
484
485 VOID
486 NTAPI
HalpGetHotPlugMemoryInfo(IN PLOADER_PARAMETER_BLOCK LoaderBlock)487 HalpGetHotPlugMemoryInfo(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
488 {
489 PACPI_SRAT SratTable;
490
491 /* Get the SRAT, bail out if it doesn't exist */
492 SratTable = HalAcpiGetTable(LoaderBlock, SRAT_SIGNATURE);
493 HalpAcpiSrat = SratTable;
494 if (!SratTable) return;
495 }
496
497 VOID
498 NTAPI
HalpDynamicSystemResourceConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)499 HalpDynamicSystemResourceConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
500 {
501 /* For this HAL, it means to get hot plug memory information */
502 HalpGetHotPlugMemoryInfo(LoaderBlock);
503 }
504
505 VOID
506 NTAPI
HalpAcpiDetectMachineSpecificActions(IN PLOADER_PARAMETER_BLOCK LoaderBlock,IN PFADT DescriptionTable)507 HalpAcpiDetectMachineSpecificActions(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
508 IN PFADT DescriptionTable)
509 {
510 /* Does this HAL specify something? */
511 if (HalpAcpiTableMatchList.Flink)
512 {
513 /* Great, but we don't support it */
514 DPRINT1("WARNING: Your HAL has specific ACPI hacks to apply!\n");
515 }
516 }
517
518 VOID
519 NTAPI
HalpInitBootTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock)520 HalpInitBootTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
521 {
522 PBOOT_TABLE BootTable;
523
524 /* Get the boot table */
525 BootTable = HalAcpiGetTable(LoaderBlock, BOOT_SIGNATURE);
526 HalpSimpleBootFlagTable = BootTable;
527
528 /* Validate it */
529 if ((BootTable) &&
530 (BootTable->Header.Length >= sizeof(BOOT_TABLE)) &&
531 (BootTable->CMOSIndex >= 9))
532 {
533 DPRINT1("ACPI Boot table found, but not supported!\n");
534 }
535 else
536 {
537 /* Invalid or doesn't exist, ignore it */
538 HalpSimpleBootFlagTable = 0;
539 }
540
541 /* Install the end of boot handler */
542 // HalEndOfBoot = HalpEndOfBoot;
543 }
544
545 NTSTATUS
546 NTAPI
HalpAcpiFindRsdtPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock,OUT PACPI_BIOS_MULTI_NODE * AcpiMultiNode)547 HalpAcpiFindRsdtPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
548 OUT PACPI_BIOS_MULTI_NODE* AcpiMultiNode)
549 {
550 PCONFIGURATION_COMPONENT_DATA ComponentEntry;
551 PCONFIGURATION_COMPONENT_DATA Next = NULL;
552 PCM_PARTIAL_RESOURCE_LIST ResourceList;
553 PACPI_BIOS_MULTI_NODE NodeData;
554 SIZE_T NodeLength;
555 PFN_COUNT PageCount;
556 PVOID MappedAddress;
557 PHYSICAL_ADDRESS PhysicalAddress;
558
559 /* Did we already do this once? */
560 if (HalpAcpiMultiNode)
561 {
562 /* Return what we know */
563 *AcpiMultiNode = HalpAcpiMultiNode;
564 return STATUS_SUCCESS;
565 }
566
567 /* Assume failure */
568 *AcpiMultiNode = NULL;
569
570 /* Find the multi function adapter key */
571 ComponentEntry = KeFindConfigurationNextEntry(LoaderBlock->ConfigurationRoot,
572 AdapterClass,
573 MultiFunctionAdapter,
574 0,
575 &Next);
576 while (ComponentEntry)
577 {
578 /* Find the ACPI BIOS key */
579 if (!_stricmp(ComponentEntry->ComponentEntry.Identifier, "ACPI BIOS"))
580 {
581 /* Found it */
582 break;
583 }
584
585 /* Keep searching */
586 Next = ComponentEntry;
587 ComponentEntry = KeFindConfigurationNextEntry(LoaderBlock->ConfigurationRoot,
588 AdapterClass,
589 MultiFunctionAdapter,
590 NULL,
591 &Next);
592 }
593
594 /* Make sure we found it */
595 if (!ComponentEntry)
596 {
597 DPRINT1("**** HalpAcpiFindRsdtPhase0: did NOT find RSDT\n");
598 return STATUS_NOT_FOUND;
599 }
600
601 /* The configuration data is a resource list, and the BIOS node follows */
602 ResourceList = ComponentEntry->ConfigurationData;
603 NodeData = (PACPI_BIOS_MULTI_NODE)(ResourceList + 1);
604
605 /* How many E820 memory entries are there? */
606 NodeLength = sizeof(ACPI_BIOS_MULTI_NODE) +
607 (NodeData->Count - 1) * sizeof(ACPI_E820_ENTRY);
608
609 /* Convert to pages */
610 PageCount = (PFN_COUNT)BYTES_TO_PAGES(NodeLength);
611
612 /* Allocate the memory */
613 PhysicalAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock,
614 0x1000000,
615 PageCount,
616 FALSE);
617 if (PhysicalAddress.QuadPart)
618 {
619 /* Map it if the allocation worked */
620 MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, PageCount);
621 }
622 else
623 {
624 /* Otherwise we'll have to fail */
625 MappedAddress = NULL;
626 }
627
628 /* Save the multi node, bail out if we didn't find it */
629 HalpAcpiMultiNode = MappedAddress;
630 if (!MappedAddress) return STATUS_INSUFFICIENT_RESOURCES;
631
632 /* Copy the multi-node data */
633 RtlCopyMemory(MappedAddress, NodeData, NodeLength);
634
635 /* Return the data */
636 *AcpiMultiNode = HalpAcpiMultiNode;
637 return STATUS_SUCCESS;
638 }
639
640 NTSTATUS
641 NTAPI
HalpAcpiTableCacheInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock)642 HalpAcpiTableCacheInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
643 {
644 PACPI_BIOS_MULTI_NODE AcpiMultiNode;
645 NTSTATUS Status = STATUS_SUCCESS;
646 PHYSICAL_ADDRESS PhysicalAddress;
647 PVOID MappedAddress;
648 ULONG TableLength;
649 PRSDT Rsdt;
650 PLOADER_PARAMETER_EXTENSION LoaderExtension;
651
652 /* Only initialize once */
653 if (HalpAcpiTableCacheList.Flink) return Status;
654
655 /* Setup the lock and table */
656 ExInitializeFastMutex(&HalpAcpiTableCacheLock);
657 InitializeListHead(&HalpAcpiTableCacheList);
658
659 /* Find the RSDT */
660 Status = HalpAcpiFindRsdtPhase0(LoaderBlock, &AcpiMultiNode);
661 if (!NT_SUCCESS(Status)) return Status;
662
663 PhysicalAddress.QuadPart = AcpiMultiNode->RsdtAddress.QuadPart;
664
665 /* Map the RSDT */
666 if (LoaderBlock)
667 {
668 /* Phase0: Use HAL Heap to map the RSDT, we assume it's about 2 pages */
669 MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, 2);
670 }
671 else
672 {
673 /* Use an I/O map */
674 MappedAddress = MmMapIoSpace(PhysicalAddress, PAGE_SIZE * 2, MmNonCached);
675 }
676
677 /* Get the RSDT */
678 Rsdt = MappedAddress;
679 if (!MappedAddress)
680 {
681 /* Fail, no memory */
682 DPRINT1("HAL: Failed to map RSDT\n");
683 return STATUS_INSUFFICIENT_RESOURCES;
684 }
685
686 /* Validate it */
687 if ((Rsdt->Header.Signature != RSDT_SIGNATURE) &&
688 (Rsdt->Header.Signature != XSDT_SIGNATURE))
689 {
690 /* Very bad: crash */
691 HalDisplayString("Bad RSDT pointer\r\n");
692 KeBugCheckEx(MISMATCHED_HAL, 4, __LINE__, 0, 0);
693 }
694
695 /* We assumed two pages -- do we need less or more? */
696 TableLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(PhysicalAddress.LowPart,
697 Rsdt->Header.Length);
698 if (TableLength != 2)
699 {
700 /* Are we in phase 0 or 1? */
701 if (!LoaderBlock)
702 {
703 /* Unmap the old table, remap the new one, using Mm I/O space */
704 MmUnmapIoSpace(MappedAddress, 2 * PAGE_SIZE);
705 MappedAddress = MmMapIoSpace(PhysicalAddress,
706 TableLength << PAGE_SHIFT,
707 MmNonCached);
708 }
709 else
710 {
711 /* Unmap the old table, remap the new one, using HAL heap */
712 HalpUnmapVirtualAddress(MappedAddress, 2);
713 MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, TableLength);
714 }
715
716 /* Get the remapped table */
717 Rsdt = MappedAddress;
718 if (!MappedAddress)
719 {
720 /* Fail, no memory */
721 DPRINT1("HAL: Couldn't remap RSDT\n");
722 return STATUS_INSUFFICIENT_RESOURCES;
723 }
724 }
725
726 /* Now take the BIOS copy and make our own local copy */
727 Rsdt = HalpAcpiCopyBiosTable(LoaderBlock, &Rsdt->Header);
728 if (!Rsdt)
729 {
730 /* Fail, no memory */
731 DPRINT1("HAL: Couldn't remap RSDT\n");
732 return STATUS_INSUFFICIENT_RESOURCES;
733 }
734
735 /* Get rid of the BIOS mapping */
736 if (LoaderBlock)
737 {
738 /* Use HAL heap */
739 HalpUnmapVirtualAddress(MappedAddress, TableLength);
740
741 LoaderExtension = LoaderBlock->Extension;
742 }
743 else
744 {
745 /* Use Mm */
746 MmUnmapIoSpace(MappedAddress, TableLength << PAGE_SHIFT);
747
748 LoaderExtension = NULL;
749 }
750
751 /* Cache the RSDT */
752 HalpAcpiCacheTable(&Rsdt->Header);
753
754 /* Check for compatible loader block extension */
755 if (LoaderExtension && (LoaderExtension->Size >= 0x58))
756 {
757 /* Compatible loader: did it provide an ACPI table override? */
758 if ((LoaderExtension->AcpiTable) && (LoaderExtension->AcpiTableSize))
759 {
760 /* Great, because we don't support it! */
761 DPRINT1("ACPI Table Overrides Not Supported!\n");
762 }
763 }
764
765 /* Done */
766 return Status;
767 }
768
769 VOID
770 NTAPI
HaliAcpiTimerInit(IN ULONG TimerPort,IN ULONG TimerValExt)771 HaliAcpiTimerInit(IN ULONG TimerPort,
772 IN ULONG TimerValExt)
773 {
774 PAGED_CODE();
775
776 /* Is this in the init phase? */
777 if (!TimerPort)
778 {
779 /* Get the data from the FADT */
780 TimerPort = HalpFixedAcpiDescTable.pm_tmr_blk_io_port;
781 TimerValExt = HalpFixedAcpiDescTable.flags & ACPI_TMR_VAL_EXT;
782 DPRINT1("ACPI Timer at: %lXh (EXT: %lu)\n", TimerPort, TimerValExt);
783 }
784
785 /* FIXME: Now proceed to the timer initialization */
786 //HalaAcpiTimerInit(TimerPort, TimerValExt);
787 }
788
789 CODE_SEG("INIT")
790 NTSTATUS
791 NTAPI
HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)792 HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
793 {
794 NTSTATUS Status;
795 PFADT Fadt;
796 ULONG TableLength;
797 PHYSICAL_ADDRESS PhysicalAddress;
798
799 /* Only do this once */
800 if (HalpProcessedACPIPhase0) return STATUS_SUCCESS;
801
802 /* Setup the ACPI table cache */
803 Status = HalpAcpiTableCacheInit(LoaderBlock);
804 if (!NT_SUCCESS(Status)) return Status;
805
806 /* Grab the FADT */
807 Fadt = HalAcpiGetTable(LoaderBlock, FADT_SIGNATURE);
808 if (!Fadt)
809 {
810 /* Fail */
811 DPRINT1("HAL: Didn't find the FACP\n");
812 return STATUS_NOT_FOUND;
813 }
814
815 /* Assume typical size, otherwise whatever the descriptor table says */
816 TableLength = sizeof(FADT);
817 if (Fadt->Header.Length < sizeof(FADT)) TableLength = Fadt->Header.Length;
818
819 /* Copy it in the HAL static buffer */
820 RtlCopyMemory(&HalpFixedAcpiDescTable, Fadt, TableLength);
821
822 /* Anything special this HAL needs to do? */
823 HalpAcpiDetectMachineSpecificActions(LoaderBlock, &HalpFixedAcpiDescTable);
824
825 /* Get the debug table for KD */
826 HalpDebugPortTable = HalAcpiGetTable(LoaderBlock, DBGP_SIGNATURE);
827
828 /* Initialize NUMA through the SRAT */
829 HalpNumaInitializeStaticConfiguration(LoaderBlock);
830
831 /* Initialize hotplug through the SRAT */
832 HalpDynamicSystemResourceConfiguration(LoaderBlock);
833 if (HalpAcpiSrat)
834 {
835 DPRINT1("Your machine has a SRAT, but NUMA/HotPlug are not supported!\n");
836 }
837
838 /* Can there be memory higher than 4GB? */
839 if (HalpMaxHotPlugMemoryAddress.HighPart >= 1)
840 {
841 /* We'll need this for DMA later */
842 HalpPhysicalMemoryMayAppearAbove4GB = TRUE;
843 }
844
845 /* Setup the ACPI timer */
846 HaliAcpiTimerInit(0, 0);
847
848 /* Do we have a low stub address yet? */
849 if (!HalpLowStubPhysicalAddress.QuadPart)
850 {
851 /* Allocate it */
852 HalpLowStubPhysicalAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock,
853 0x100000,
854 HALP_LOW_STUB_SIZE_IN_PAGES,
855 FALSE);
856 if (HalpLowStubPhysicalAddress.QuadPart)
857 {
858 /* Map it */
859 HalpLowStub = HalpMapPhysicalMemory64(HalpLowStubPhysicalAddress, HALP_LOW_STUB_SIZE_IN_PAGES);
860 }
861 }
862
863 /* Grab a page for flushes */
864 PhysicalAddress.QuadPart = 0x100000;
865 HalpVirtAddrForFlush = HalpMapPhysicalMemory64(PhysicalAddress, 1);
866 HalpPteForFlush = HalAddressToPte(HalpVirtAddrForFlush);
867
868 /* Don't do this again */
869 HalpProcessedACPIPhase0 = TRUE;
870
871 /* Setup the boot table */
872 HalpInitBootTable(LoaderBlock);
873
874 /* Debugging code */
875 {
876 PLIST_ENTRY ListHead, NextEntry;
877 PACPI_CACHED_TABLE CachedTable;
878
879 /* Loop cached tables */
880 ListHead = &HalpAcpiTableCacheList;
881 NextEntry = ListHead->Flink;
882 while (NextEntry != ListHead)
883 {
884 /* Get the table */
885 CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links);
886
887 /* Compare signatures */
888 if ((CachedTable->Header.Signature == RSDT_SIGNATURE) ||
889 (CachedTable->Header.Signature == XSDT_SIGNATURE))
890 {
891 DPRINT1("ACPI %u.0 Detected. Tables:", CachedTable->Header.Revision + 1);
892 }
893
894 DbgPrint(" [%c%c%c%c]",
895 CachedTable->Header.Signature & 0x000000FF,
896 (CachedTable->Header.Signature & 0x0000FF00) >> 8,
897 (CachedTable->Header.Signature & 0x00FF0000) >> 16,
898 (CachedTable->Header.Signature & 0xFF000000) >> 24);
899
900 /* Keep going */
901 NextEntry = NextEntry->Flink;
902 }
903 DbgPrint("\n");
904 }
905
906 /* Return success */
907 return STATUS_SUCCESS;
908 }
909
910 CODE_SEG("INIT")
911 VOID
912 NTAPI
HalpInitializePciBus(VOID)913 HalpInitializePciBus(VOID)
914 {
915 /* Setup the PCI stub support */
916 HalpInitializePciStubs();
917
918 /* Set the NMI crash flag */
919 HalpGetNMICrashFlag();
920 }
921
922 VOID
923 NTAPI
HalpInitNonBusHandler(VOID)924 HalpInitNonBusHandler(VOID)
925 {
926 /* These should be written by the PCI driver later, but we give defaults */
927 HalPciTranslateBusAddress = HalpTranslateBusAddress;
928 HalPciAssignSlotResources = HalpAssignSlotResources;
929 HalFindBusAddressTranslation = HalpFindBusAddressTranslation;
930 }
931
932 CODE_SEG("INIT")
933 VOID
934 NTAPI
HalpInitBusHandlers(VOID)935 HalpInitBusHandlers(VOID)
936 {
937 /* On ACPI, we only have a fake PCI bus to worry about */
938 HalpInitNonBusHandler();
939 }
940
941 CODE_SEG("INIT")
942 VOID
943 NTAPI
HalpBuildAddressMap(VOID)944 HalpBuildAddressMap(VOID)
945 {
946 /* ACPI is magic baby */
947 }
948
949 CODE_SEG("INIT")
950 BOOLEAN
951 NTAPI
HalpGetDebugPortTable(VOID)952 HalpGetDebugPortTable(VOID)
953 {
954 return ((HalpDebugPortTable) &&
955 (HalpDebugPortTable->BaseAddress.AddressSpaceID == 1));
956 }
957
958 CODE_SEG("INIT")
959 ULONG
960 NTAPI
HalpIs16BitPortDecodeSupported(VOID)961 HalpIs16BitPortDecodeSupported(VOID)
962 {
963 /* All ACPI systems are at least "EISA" so they support this */
964 return CM_RESOURCE_PORT_16_BIT_DECODE;
965 }
966
967 VOID
968 NTAPI
HalpAcpiDetectResourceListSize(OUT PULONG ListSize)969 HalpAcpiDetectResourceListSize(OUT PULONG ListSize)
970 {
971 PAGED_CODE();
972
973 /* One element if there is a SCI */
974 *ListSize = HalpFixedAcpiDescTable.sci_int_vector ? 1: 0;
975 }
976
977 NTSTATUS
978 NTAPI
HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList)979 HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList)
980 {
981 ULONG Interrupt;
982 PAGED_CODE();
983 ASSERT(ResourceList != NULL);
984
985 /* Initialize the list */
986 ResourceList->BusNumber = -1;
987 ResourceList->AlternativeLists = 1;
988 ResourceList->InterfaceType = PNPBus;
989 ResourceList->List[0].Version = 1;
990 ResourceList->List[0].Revision = 1;
991 ResourceList->List[0].Count = 0;
992
993 /* Is there a SCI? */
994 if (HalpFixedAcpiDescTable.sci_int_vector)
995 {
996 /* Fill out the entry for it */
997 ResourceList->List[0].Descriptors[0].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
998 ResourceList->List[0].Descriptors[0].Type = CmResourceTypeInterrupt;
999 ResourceList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared;
1000
1001 /* Get the interrupt number */
1002 Interrupt = HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector];
1003 ResourceList->List[0].Descriptors[0].u.Interrupt.MinimumVector = Interrupt;
1004 ResourceList->List[0].Descriptors[0].u.Interrupt.MaximumVector = Interrupt;
1005
1006 /* One more */
1007 ++ResourceList->List[0].Count;
1008 }
1009
1010 /* All good */
1011 return STATUS_SUCCESS;
1012 }
1013
1014 NTSTATUS
1015 NTAPI
HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST * Requirements)1016 HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements)
1017 {
1018 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
1019 ULONG Count, ListSize;
1020 NTSTATUS Status;
1021
1022 PAGED_CODE();
1023
1024 /* Get ACPI resources */
1025 HalpAcpiDetectResourceListSize(&Count);
1026 DPRINT("Resource count: %lu\n", Count);
1027
1028 /* Compute size of the list and allocate it */
1029 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors) +
1030 (Count * sizeof(IO_RESOURCE_DESCRIPTOR));
1031 DPRINT("Resource list size: %lu\n", ListSize);
1032 RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, TAG_HAL);
1033 if (RequirementsList)
1034 {
1035 /* Initialize it */
1036 RtlZeroMemory(RequirementsList, ListSize);
1037 RequirementsList->ListSize = ListSize;
1038
1039 /* Build it */
1040 Status = HalpBuildAcpiResourceList(RequirementsList);
1041 if (NT_SUCCESS(Status))
1042 {
1043 /* It worked, return it */
1044 *Requirements = RequirementsList;
1045
1046 /* Validate the list */
1047 ASSERT(RequirementsList->List[0].Count == Count);
1048 }
1049 else
1050 {
1051 /* Fail */
1052 ExFreePoolWithTag(RequirementsList, TAG_HAL);
1053 Status = STATUS_NO_SUCH_DEVICE;
1054 }
1055 }
1056 else
1057 {
1058 /* Not enough memory */
1059 Status = STATUS_INSUFFICIENT_RESOURCES;
1060 }
1061
1062 /* Return the status */
1063 return Status;
1064 }
1065
1066 /*
1067 * @implemented
1068 */
1069 CODE_SEG("INIT")
1070 VOID
1071 NTAPI
HalReportResourceUsage(VOID)1072 HalReportResourceUsage(VOID)
1073 {
1074 INTERFACE_TYPE InterfaceType;
1075 UNICODE_STRING HalString;
1076
1077 /* FIXME: Initialize DMA 64-bit support */
1078
1079 /* FIXME: Initialize MCA bus */
1080
1081 /* Initialize PCI bus. */
1082 HalpInitializePciBus();
1083
1084 /* What kind of bus is this? */
1085 switch (HalpBusType)
1086 {
1087 /* ISA Machine */
1088 case MACHINE_TYPE_ISA:
1089 InterfaceType = Isa;
1090 break;
1091
1092 /* EISA Machine */
1093 case MACHINE_TYPE_EISA:
1094 InterfaceType = Eisa;
1095 break;
1096
1097 /* MCA Machine */
1098 case MACHINE_TYPE_MCA:
1099 InterfaceType = MicroChannel;
1100 break;
1101
1102 /* Unknown */
1103 default:
1104 InterfaceType = Internal;
1105 break;
1106 }
1107
1108 /* Build HAL usage */
1109 RtlInitUnicodeString(&HalString, HalName);
1110 HalpReportResourceUsage(&HalString, InterfaceType);
1111
1112 /* Setup PCI debugging and Hibernation */
1113 HalpRegisterPciDebuggingDeviceInfo();
1114 }
1115
1116 /* EOF */
1117