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