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