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 */ 1109