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