[HAL] Improve the FILE header section. Brought to you by Adam Stachowicz. CORE-10114
[reactos.git] / reactos / hal / halx86 / acpi / halacpi.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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: %Xh (EXT: %d)\n", TimerPort, TimerValExt);
783 }
784
785 /* FIXME: Now proceed to the timer initialization */
786 //HalaAcpiTimerInit(TimerPort, TimerValExt);
787 }
788
789 NTSTATUS
790 NTAPI
791 HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
792 {
793 NTSTATUS Status;
794 PFADT Fadt;
795 ULONG TableLength;
796 PHYSICAL_ADDRESS PhysicalAddress;
797
798 /* Only do this once */
799 if (HalpProcessedACPIPhase0) return STATUS_SUCCESS;
800
801 /* Setup the ACPI table cache */
802 Status = HalpAcpiTableCacheInit(LoaderBlock);
803 if (!NT_SUCCESS(Status)) return Status;
804
805 /* Grab the FADT */
806 Fadt = HalAcpiGetTable(LoaderBlock, FADT_SIGNATURE);
807 if (!Fadt)
808 {
809 /* Fail */
810 DPRINT1("HAL: Didn't find the FACP\n");
811 return STATUS_NOT_FOUND;
812 }
813
814 /* Assume typical size, otherwise whatever the descriptor table says */
815 TableLength = sizeof(FADT);
816 if (Fadt->Header.Length < sizeof(FADT)) TableLength = Fadt->Header.Length;
817
818 /* Copy it in the HAL static buffer */
819 RtlCopyMemory(&HalpFixedAcpiDescTable, Fadt, TableLength);
820
821 /* Anything special this HAL needs to do? */
822 HalpAcpiDetectMachineSpecificActions(LoaderBlock, &HalpFixedAcpiDescTable);
823
824 /* Get the debug table for KD */
825 HalpDebugPortTable = HalAcpiGetTable(LoaderBlock, DBGP_SIGNATURE);
826
827 /* Initialize NUMA through the SRAT */
828 HalpNumaInitializeStaticConfiguration(LoaderBlock);
829
830 /* Initialize hotplug through the SRAT */
831 HalpDynamicSystemResourceConfiguration(LoaderBlock);
832 if (HalpAcpiSrat)
833 {
834 DPRINT1("Your machine has a SRAT, but NUMA/HotPlug are not supported!\n");
835 }
836
837 /* Can there be memory higher than 4GB? */
838 if (HalpMaxHotPlugMemoryAddress.HighPart >= 1)
839 {
840 /* We'll need this for DMA later */
841 HalpPhysicalMemoryMayAppearAbove4GB = TRUE;
842 }
843
844 /* Setup the ACPI timer */
845 HaliAcpiTimerInit(0, 0);
846
847 /* Do we have a low stub address yet? */
848 if (!HalpLowStubPhysicalAddress.QuadPart)
849 {
850 /* Allocate it */
851 HalpLowStubPhysicalAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock,
852 0x100000,
853 1,
854 FALSE);
855 if (HalpLowStubPhysicalAddress.QuadPart)
856 {
857 /* Map it */
858 HalpLowStub = HalpMapPhysicalMemory64(HalpLowStubPhysicalAddress, 1);
859 }
860 }
861
862 /* Grab a page for flushes */
863 PhysicalAddress.QuadPart = 0x100000;
864 HalpVirtAddrForFlush = HalpMapPhysicalMemory64(PhysicalAddress, 1);
865 HalpPteForFlush = HalAddressToPte(HalpVirtAddrForFlush);
866
867 /* Don't do this again */
868 HalpProcessedACPIPhase0 = TRUE;
869
870 /* Setup the boot table */
871 HalpInitBootTable(LoaderBlock);
872
873 /* Debugging code */
874 {
875 PLIST_ENTRY ListHead, NextEntry;
876 PACPI_CACHED_TABLE CachedTable;
877
878 /* Loop cached tables */
879 ListHead = &HalpAcpiTableCacheList;
880 NextEntry = ListHead->Flink;
881 while (NextEntry != ListHead)
882 {
883 /* Get the table */
884 CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links);
885
886 /* Compare signatures */
887 if ((CachedTable->Header.Signature == RSDT_SIGNATURE) ||
888 (CachedTable->Header.Signature == XSDT_SIGNATURE))
889 {
890 DPRINT1("ACPI %d.0 Detected. Tables: ", (CachedTable->Header.Revision + 1));
891 }
892
893 DbgPrint("[%c%c%c%c] ",
894 (CachedTable->Header.Signature & 0xFF),
895 (CachedTable->Header.Signature & 0xFF00) >> 8,
896 (CachedTable->Header.Signature & 0xFF0000) >> 16,
897 (CachedTable->Header.Signature & 0xFF000000) >> 24);
898
899 /* Keep going */
900 NextEntry = NextEntry->Flink;
901 }
902 DbgPrint("\n");
903 }
904
905 /* Return success */
906 return STATUS_SUCCESS;
907 }
908
909 VOID
910 NTAPI
911 HalpInitializePciBus(VOID)
912 {
913 /* Setup the PCI stub support */
914 HalpInitializePciStubs();
915
916 /* Set the NMI crash flag */
917 HalpGetNMICrashFlag();
918 }
919
920 VOID
921 NTAPI
922 HalpInitNonBusHandler(VOID)
923 {
924 /* These should be written by the PCI driver later, but we give defaults */
925 HalPciTranslateBusAddress = HalpTranslateBusAddress;
926 HalPciAssignSlotResources = HalpAssignSlotResources;
927 HalFindBusAddressTranslation = HalpFindBusAddressTranslation;
928 }
929
930 VOID
931 NTAPI
932 HalpInitBusHandlers(VOID)
933 {
934 /* On ACPI, we only have a fake PCI bus to worry about */
935 HalpInitNonBusHandler();
936 }
937
938 VOID
939 NTAPI
940 HalpBuildAddressMap(VOID)
941 {
942 /* ACPI is magic baby */
943 }
944
945 BOOLEAN
946 NTAPI
947 HalpGetDebugPortTable(VOID)
948 {
949 return ((HalpDebugPortTable) &&
950 (HalpDebugPortTable->BaseAddress.AddressSpaceID == 1));
951 }
952
953 ULONG
954 NTAPI
955 HalpIs16BitPortDecodeSupported(VOID)
956 {
957 /* All ACPI systems are at least "EISA" so they support this */
958 return CM_RESOURCE_PORT_16_BIT_DECODE;
959 }
960
961 VOID
962 NTAPI
963 HalpAcpiDetectResourceListSize(OUT PULONG ListSize)
964 {
965 PAGED_CODE();
966
967 /* One element if there is a SCI */
968 *ListSize = HalpFixedAcpiDescTable.sci_int_vector ? 1: 0;
969 }
970
971 NTSTATUS
972 NTAPI
973 HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList)
974 {
975 ULONG Interrupt;
976 PAGED_CODE();
977 ASSERT(ResourceList != NULL);
978
979 /* Initialize the list */
980 ResourceList->BusNumber = -1;
981 ResourceList->AlternativeLists = 1;
982 ResourceList->InterfaceType = PNPBus;
983 ResourceList->List[0].Version = 1;
984 ResourceList->List[0].Revision = 1;
985 ResourceList->List[0].Count = 0;
986
987 /* Is there a SCI? */
988 if (HalpFixedAcpiDescTable.sci_int_vector)
989 {
990 /* Fill out the entry for it */
991 ResourceList->List[0].Descriptors[0].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
992 ResourceList->List[0].Descriptors[0].Type = CmResourceTypeInterrupt;
993 ResourceList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared;
994
995 /* Get the interrupt number */
996 Interrupt = HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector];
997 ResourceList->List[0].Descriptors[0].u.Interrupt.MinimumVector = Interrupt;
998 ResourceList->List[0].Descriptors[0].u.Interrupt.MaximumVector = Interrupt;
999
1000 /* One more */
1001 ++ResourceList->List[0].Count;
1002 }
1003
1004 /* All good */
1005 return STATUS_SUCCESS;
1006 }
1007
1008 NTSTATUS
1009 NTAPI
1010 HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements)
1011 {
1012 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
1013 ULONG Count = 0, ListSize;
1014 NTSTATUS Status;
1015 PAGED_CODE();
1016
1017 /* Get ACPI resources */
1018 HalpAcpiDetectResourceListSize(&Count);
1019 DPRINT("Resource count: %d\n", Count);
1020
1021 /* Compute size of the list and allocate it */
1022 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors) +
1023 (Count * sizeof(IO_RESOURCE_DESCRIPTOR));
1024 DPRINT("Resource list size: %d\n", ListSize);
1025 RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, TAG_HAL);
1026 if (RequirementsList)
1027 {
1028 /* Initialize it */
1029 RtlZeroMemory(RequirementsList, ListSize);
1030 RequirementsList->ListSize = ListSize;
1031
1032 /* Build it */
1033 Status = HalpBuildAcpiResourceList(RequirementsList);
1034 if (NT_SUCCESS(Status))
1035 {
1036 /* It worked, return it */
1037 *Requirements = RequirementsList;
1038
1039 /* Validate the list */
1040 ASSERT(RequirementsList->List[0].Count == Count);
1041 }
1042 else
1043 {
1044 /* Fail */
1045 ExFreePoolWithTag(RequirementsList, TAG_HAL);
1046 Status = STATUS_NO_SUCH_DEVICE;
1047 }
1048 }
1049 else
1050 {
1051 /* Not enough memory */
1052 Status = STATUS_INSUFFICIENT_RESOURCES;
1053 }
1054
1055 /* Return the status */
1056 return Status;
1057 }
1058
1059 /*
1060 * @implemented
1061 */
1062 VOID
1063 NTAPI
1064 HalReportResourceUsage(VOID)
1065 {
1066 INTERFACE_TYPE InterfaceType;
1067 UNICODE_STRING HalString;
1068
1069 /* FIXME: Initialize DMA 64-bit support */
1070
1071 /* FIXME: Initialize MCA bus */
1072
1073 /* Initialize PCI bus. */
1074 HalpInitializePciBus();
1075
1076 /* What kind of bus is this? */
1077 switch (HalpBusType)
1078 {
1079 /* ISA Machine */
1080 case MACHINE_TYPE_ISA:
1081 InterfaceType = Isa;
1082 break;
1083
1084 /* EISA Machine */
1085 case MACHINE_TYPE_EISA:
1086 InterfaceType = Eisa;
1087 break;
1088
1089 /* MCA Machine */
1090 case MACHINE_TYPE_MCA:
1091 InterfaceType = MicroChannel;
1092 break;
1093
1094 /* Unknown */
1095 default:
1096 InterfaceType = Internal;
1097 break;
1098 }
1099
1100 /* Build HAL usage */
1101 RtlInitUnicodeString(&HalString, HalName);
1102 HalpReportResourceUsage(&HalString, InterfaceType);
1103
1104 /* Setup PCI debugging and Hibernation */
1105 HalpRegisterPciDebuggingDeviceInfo();
1106 }
1107
1108 /* EOF */