fork
Configure Feed
Select the types of activity you want to include in your feed.
Reactos
fork
Configure Feed
Select the types of activity you want to include in your feed.
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
17LIST_ENTRY HalpAcpiTableCacheList;
18FAST_MUTEX HalpAcpiTableCacheLock;
19
20BOOLEAN HalpProcessedACPIPhase0;
21BOOLEAN HalpPhysicalMemoryMayAppearAbove4GB;
22
23FADT HalpFixedAcpiDescTable;
24PDEBUG_PORT_TABLE HalpDebugPortTable;
25PACPI_SRAT HalpAcpiSrat;
26PBOOT_TABLE HalpSimpleBootFlagTable;
27
28PHYSICAL_ADDRESS HalpMaxHotPlugMemoryAddress;
29PHYSICAL_ADDRESS HalpLowStubPhysicalAddress;
30PHARDWARE_PTE HalpPteForFlush;
31PVOID HalpVirtAddrForFlush;
32PVOID HalpLowStub;
33
34PACPI_BIOS_MULTI_NODE HalpAcpiMultiNode;
35
36LIST_ENTRY HalpAcpiTableMatchList;
37
38ULONG HalpInvalidAcpiTable;
39
40ULONG HalpPicVectorRedirect[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
41
42/* This determines the HAL type */
43BOOLEAN HalDisableFirmwareMapper = TRUE;
44PWCHAR HalHardwareIdString = L"acpipic_up";
45PWCHAR HalName = L"ACPI Compatible Eisa/Isa HAL";
46
47/* PRIVATE FUNCTIONS **********************************************************/
48
49PDESCRIPTION_HEADER
50NTAPI
51HalpAcpiGetCachedTable(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
75VOID
76NTAPI
77HalpAcpiCacheTable(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
86PVOID
87NTAPI
88HalpAcpiCopyBiosTable(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
141PVOID
142NTAPI
143HalpAcpiGetTableFromBios(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
402PVOID
403NTAPI
404HalpAcpiGetTable(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
444PVOID
445NTAPI
446HalAcpiGetTable(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
473VOID
474NTAPI
475HalpNumaInitializeStaticConfiguration(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
485VOID
486NTAPI
487HalpGetHotPlugMemoryInfo(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
497VOID
498NTAPI
499HalpDynamicSystemResourceConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
500{
501 /* For this HAL, it means to get hot plug memory information */
502 HalpGetHotPlugMemoryInfo(LoaderBlock);
503}
504
505VOID
506NTAPI
507HalpAcpiDetectMachineSpecificActions(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
518VOID
519NTAPI
520HalpInitBootTable(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
545NTSTATUS
546NTAPI
547HalpAcpiFindRsdtPhase0(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
640NTSTATUS
641NTAPI
642HalpAcpiTableCacheInit(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
769VOID
770NTAPI
771HaliAcpiTimerInit(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
789CODE_SEG("INIT")
790NTSTATUS
791NTAPI
792HalpSetupAcpiPhase0(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 /* Log some ACPI data */
875 {
876 PLIST_ENTRY NextEntry;
877 PCSTR AcpiVersion = NULL;
878
879 /* Find the ACPI version (range) out */
880 // v1.0+: Revision is major version.
881 // v5.1+: minor_revision is minor version.
882 // v6.4+: errata bits are errata version.
883 switch (Fadt->Header.Revision)
884 {
885 case 0: // Should not happen.
886 AcpiVersion = "Unknown_0";
887 break;
888 case 1:
889 AcpiVersion = "1.0-1.0b";
890 break;
891 case 2: // Should not happen.
892 AcpiVersion = "Unknown_2";
893 break;
894 case 3:
895 AcpiVersion = "1.5-2.0_C";
896 break;
897 case 4:
898 AcpiVersion = "3.0-4.0_A";
899 break;
900 case 5:
901 if (Fadt->minor_revision == 0)
902 AcpiVersion = "5.0-5.0_B";
903 else if (Fadt->minor_revision == 1)
904 AcpiVersion = "5.1-5.1_B";
905 break;
906 case 6:
907 if (Fadt->minor_revision == 0)
908 AcpiVersion = "6.0-6.0_A";
909 else if (Fadt->minor_revision == 1)
910 AcpiVersion = "6.1-6.1_A";
911 else if (Fadt->minor_revision == 2)
912 AcpiVersion = "6.2-6.2_B";
913 else if (Fadt->minor_revision == 3)
914 AcpiVersion = "6.3-6.3_A";
915 else if ((Fadt->minor_revision & 0x0F) == 0x04)
916 {
917 if ((Fadt->minor_revision & 0xF0) == 0x00)
918 AcpiVersion = "6.4";
919 else if ((Fadt->minor_revision & 0xF0) == 0x10)
920 AcpiVersion = "6.4_A";
921 }
922 else if (Fadt->minor_revision == 5) // v6.5_A too is documented as errata=0.
923 AcpiVersion = "6.5-6.6";
924 break;
925 }
926
927 /* Print the ACPI version */
928 DPRINT1("ACPI v");
929 if (AcpiVersion == NULL)
930 {
931 // Unknown past values, or newer than v6.6 (documented as 6.5).
932 DbgPrint("Unknown_%u_%u", Fadt->Header.Revision, Fadt->minor_revision);
933 }
934 else
935 {
936 DbgPrint("%s", AcpiVersion);
937 }
938 DbgPrint(" detected. Tables:");
939
940 /* List cached tables */
941 for (NextEntry = HalpAcpiTableCacheList.Flink;
942 NextEntry != &HalpAcpiTableCacheList;
943 NextEntry = NextEntry->Flink)
944 {
945 PACPI_CACHED_TABLE CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links);
946
947 /* Print the table signature */
948 DbgPrint(" [%c%c%c%c]",
949 CachedTable->Header.Signature & 0x000000FF,
950 (CachedTable->Header.Signature & 0x0000FF00) >> 8,
951 (CachedTable->Header.Signature & 0x00FF0000) >> 16,
952 (CachedTable->Header.Signature & 0xFF000000) >> 24);
953 }
954 DbgPrint("\n");
955 }
956
957 /* Return success */
958 return STATUS_SUCCESS;
959}
960
961CODE_SEG("INIT")
962VOID
963NTAPI
964HalpInitializePciBus(VOID)
965{
966 /* Setup the PCI stub support */
967 HalpInitializePciStubs();
968
969 /* Set the NMI crash flag */
970 HalpGetNMICrashFlag();
971}
972
973VOID
974NTAPI
975HalpInitNonBusHandler(VOID)
976{
977 /* These should be written by the PCI driver later, but we give defaults */
978 HalPciTranslateBusAddress = HalpTranslateBusAddress;
979 HalPciAssignSlotResources = HalpAssignSlotResources;
980 HalFindBusAddressTranslation = HalpFindBusAddressTranslation;
981}
982
983CODE_SEG("INIT")
984VOID
985NTAPI
986HalpInitBusHandlers(VOID)
987{
988 /* On ACPI, we only have a fake PCI bus to worry about */
989 HalpInitNonBusHandler();
990}
991
992CODE_SEG("INIT")
993VOID
994NTAPI
995HalpBuildAddressMap(VOID)
996{
997 /* ACPI is magic baby */
998}
999
1000CODE_SEG("INIT")
1001BOOLEAN
1002NTAPI
1003HalpGetDebugPortTable(VOID)
1004{
1005 return ((HalpDebugPortTable) &&
1006 (HalpDebugPortTable->BaseAddress.AddressSpaceID == 1));
1007}
1008
1009CODE_SEG("INIT")
1010ULONG
1011NTAPI
1012HalpIs16BitPortDecodeSupported(VOID)
1013{
1014 /* All ACPI systems are at least "EISA" so they support this */
1015 return CM_RESOURCE_PORT_16_BIT_DECODE;
1016}
1017
1018VOID
1019NTAPI
1020HalpAcpiDetectResourceListSize(OUT PULONG ListSize)
1021{
1022 PAGED_CODE();
1023
1024 /* One element if there is a SCI */
1025 *ListSize = HalpFixedAcpiDescTable.sci_int_vector ? 1: 0;
1026}
1027
1028NTSTATUS
1029NTAPI
1030HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList)
1031{
1032 ULONG Interrupt;
1033 PAGED_CODE();
1034 ASSERT(ResourceList != NULL);
1035
1036 /* Initialize the list */
1037 ResourceList->BusNumber = -1;
1038 ResourceList->AlternativeLists = 1;
1039 ResourceList->InterfaceType = PNPBus;
1040 ResourceList->List[0].Version = 1;
1041 ResourceList->List[0].Revision = 1;
1042 ResourceList->List[0].Count = 0;
1043
1044 /* Is there a SCI? */
1045 if (HalpFixedAcpiDescTable.sci_int_vector)
1046 {
1047 /* Fill out the entry for it */
1048 ResourceList->List[0].Descriptors[0].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1049 ResourceList->List[0].Descriptors[0].Type = CmResourceTypeInterrupt;
1050 ResourceList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared;
1051
1052 /* Get the interrupt number */
1053 Interrupt = HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector];
1054 ResourceList->List[0].Descriptors[0].u.Interrupt.MinimumVector = Interrupt;
1055 ResourceList->List[0].Descriptors[0].u.Interrupt.MaximumVector = Interrupt;
1056
1057 /* One more */
1058 ++ResourceList->List[0].Count;
1059 }
1060
1061 /* All good */
1062 return STATUS_SUCCESS;
1063}
1064
1065NTSTATUS
1066NTAPI
1067HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements)
1068{
1069 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
1070 ULONG Count, ListSize;
1071 NTSTATUS Status;
1072
1073 PAGED_CODE();
1074
1075 /* Get ACPI resources */
1076 HalpAcpiDetectResourceListSize(&Count);
1077 DPRINT("Resource count: %lu\n", Count);
1078
1079 /* Compute size of the list and allocate it */
1080 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors) +
1081 (Count * sizeof(IO_RESOURCE_DESCRIPTOR));
1082 DPRINT("Resource list size: %lu\n", ListSize);
1083 RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, TAG_HAL);
1084 if (RequirementsList)
1085 {
1086 /* Initialize it */
1087 RtlZeroMemory(RequirementsList, ListSize);
1088 RequirementsList->ListSize = ListSize;
1089
1090 /* Build it */
1091 Status = HalpBuildAcpiResourceList(RequirementsList);
1092 if (NT_SUCCESS(Status))
1093 {
1094 /* It worked, return it */
1095 *Requirements = RequirementsList;
1096
1097 /* Validate the list */
1098 ASSERT(RequirementsList->List[0].Count == Count);
1099 }
1100 else
1101 {
1102 /* Fail */
1103 ExFreePoolWithTag(RequirementsList, TAG_HAL);
1104 Status = STATUS_NO_SUCH_DEVICE;
1105 }
1106 }
1107 else
1108 {
1109 /* Not enough memory */
1110 Status = STATUS_INSUFFICIENT_RESOURCES;
1111 }
1112
1113 /* Return the status */
1114 return Status;
1115}
1116
1117/*
1118 * @implemented
1119 */
1120CODE_SEG("INIT")
1121VOID
1122NTAPI
1123HalReportResourceUsage(VOID)
1124{
1125 INTERFACE_TYPE InterfaceType;
1126 UNICODE_STRING HalString;
1127
1128 /* FIXME: Initialize DMA 64-bit support */
1129
1130 /* FIXME: Initialize MCA bus */
1131
1132 /* Initialize PCI bus. */
1133 HalpInitializePciBus();
1134
1135 /* What kind of bus is this? */
1136 switch (HalpBusType)
1137 {
1138 /* ISA Machine */
1139 case MACHINE_TYPE_ISA:
1140 InterfaceType = Isa;
1141 break;
1142
1143 /* EISA Machine */
1144 case MACHINE_TYPE_EISA:
1145 InterfaceType = Eisa;
1146 break;
1147
1148 /* MCA Machine */
1149 case MACHINE_TYPE_MCA:
1150 InterfaceType = MicroChannel;
1151 break;
1152
1153 /* Unknown */
1154 default:
1155 InterfaceType = Internal;
1156 break;
1157 }
1158
1159 /* Build HAL usage */
1160 RtlInitUnicodeString(&HalString, HalName);
1161 HalpReportResourceUsage(&HalString, InterfaceType);
1162
1163 /* Setup PCI debugging and Hibernation */
1164 HalpRegisterPciDebuggingDeviceInfo();
1165}
1166
1167/* EOF */