Reactos
fork

Configure Feed

Select the types of activity you want to include in your feed.

at listview 1167 lines 34 kB view raw
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 17LIST_ENTRY HalpAcpiTableCacheList; 18FAST_MUTEX HalpAcpiTableCacheLock; 19 20BOOLEAN HalpProcessedACPIPhase0; 21BOOLEAN HalpPhysicalMemoryMayAppearAbove4GB; 22 23FADT HalpFixedAcpiDescTable; 24PDEBUG_PORT_TABLE HalpDebugPortTable; 25PACPI_SRAT HalpAcpiSrat; 26PBOOT_TABLE HalpSimpleBootFlagTable; 27 28PHYSICAL_ADDRESS HalpMaxHotPlugMemoryAddress; 29PHYSICAL_ADDRESS HalpLowStubPhysicalAddress; 30PHARDWARE_PTE HalpPteForFlush; 31PVOID HalpVirtAddrForFlush; 32PVOID HalpLowStub; 33 34PACPI_BIOS_MULTI_NODE HalpAcpiMultiNode; 35 36LIST_ENTRY HalpAcpiTableMatchList; 37 38ULONG HalpInvalidAcpiTable; 39 40ULONG HalpPicVectorRedirect[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; 41 42/* This determines the HAL type */ 43BOOLEAN HalDisableFirmwareMapper = TRUE; 44PWCHAR HalHardwareIdString = L"acpipic_up"; 45PWCHAR HalName = L"ACPI Compatible Eisa/Isa HAL"; 46 47/* PRIVATE FUNCTIONS **********************************************************/ 48 49PDESCRIPTION_HEADER 50NTAPI 51HalpAcpiGetCachedTable(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 75VOID 76NTAPI 77HalpAcpiCacheTable(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 86PVOID 87NTAPI 88HalpAcpiCopyBiosTable(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 141PVOID 142NTAPI 143HalpAcpiGetTableFromBios(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 402PVOID 403NTAPI 404HalpAcpiGetTable(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 444PVOID 445NTAPI 446HalAcpiGetTable(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 473VOID 474NTAPI 475HalpNumaInitializeStaticConfiguration(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 485VOID 486NTAPI 487HalpGetHotPlugMemoryInfo(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 497VOID 498NTAPI 499HalpDynamicSystemResourceConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 500{ 501 /* For this HAL, it means to get hot plug memory information */ 502 HalpGetHotPlugMemoryInfo(LoaderBlock); 503} 504 505VOID 506NTAPI 507HalpAcpiDetectMachineSpecificActions(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 518VOID 519NTAPI 520HalpInitBootTable(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 545NTSTATUS 546NTAPI 547HalpAcpiFindRsdtPhase0(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 640NTSTATUS 641NTAPI 642HalpAcpiTableCacheInit(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 769VOID 770NTAPI 771HaliAcpiTimerInit(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: %lXh (EXT: %lu)\n", TimerPort, TimerValExt); 783 } 784 785 /* FIXME: Now proceed to the timer initialization */ 786 //HalaAcpiTimerInit(TimerPort, TimerValExt); 787} 788 789CODE_SEG("INIT") 790NTSTATUS 791NTAPI 792HalpSetupAcpiPhase0(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 HALP_LOW_STUB_SIZE_IN_PAGES, 855 FALSE); 856 if (HalpLowStubPhysicalAddress.QuadPart) 857 { 858 /* Map it */ 859 HalpLowStub = HalpMapPhysicalMemory64(HalpLowStubPhysicalAddress, HALP_LOW_STUB_SIZE_IN_PAGES); 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 /* Log some ACPI data */ 875 { 876 PLIST_ENTRY NextEntry; 877 PCSTR AcpiVersion = NULL; 878 879 /* Find the ACPI version (range) out */ 880 // v1.0+: Revision is major version. 881 // v5.1+: minor_revision is minor version. 882 // v6.4+: errata bits are errata version. 883 switch (Fadt->Header.Revision) 884 { 885 case 0: // Should not happen. 886 AcpiVersion = "Unknown_0"; 887 break; 888 case 1: 889 AcpiVersion = "1.0-1.0b"; 890 break; 891 case 2: // Should not happen. 892 AcpiVersion = "Unknown_2"; 893 break; 894 case 3: 895 AcpiVersion = "1.5-2.0_C"; 896 break; 897 case 4: 898 AcpiVersion = "3.0-4.0_A"; 899 break; 900 case 5: 901 if (Fadt->minor_revision == 0) 902 AcpiVersion = "5.0-5.0_B"; 903 else if (Fadt->minor_revision == 1) 904 AcpiVersion = "5.1-5.1_B"; 905 break; 906 case 6: 907 if (Fadt->minor_revision == 0) 908 AcpiVersion = "6.0-6.0_A"; 909 else if (Fadt->minor_revision == 1) 910 AcpiVersion = "6.1-6.1_A"; 911 else if (Fadt->minor_revision == 2) 912 AcpiVersion = "6.2-6.2_B"; 913 else if (Fadt->minor_revision == 3) 914 AcpiVersion = "6.3-6.3_A"; 915 else if ((Fadt->minor_revision & 0x0F) == 0x04) 916 { 917 if ((Fadt->minor_revision & 0xF0) == 0x00) 918 AcpiVersion = "6.4"; 919 else if ((Fadt->minor_revision & 0xF0) == 0x10) 920 AcpiVersion = "6.4_A"; 921 } 922 else if (Fadt->minor_revision == 5) // v6.5_A too is documented as errata=0. 923 AcpiVersion = "6.5-6.6"; 924 break; 925 } 926 927 /* Print the ACPI version */ 928 DPRINT1("ACPI v"); 929 if (AcpiVersion == NULL) 930 { 931 // Unknown past values, or newer than v6.6 (documented as 6.5). 932 DbgPrint("Unknown_%u_%u", Fadt->Header.Revision, Fadt->minor_revision); 933 } 934 else 935 { 936 DbgPrint("%s", AcpiVersion); 937 } 938 DbgPrint(" detected. Tables:"); 939 940 /* List cached tables */ 941 for (NextEntry = HalpAcpiTableCacheList.Flink; 942 NextEntry != &HalpAcpiTableCacheList; 943 NextEntry = NextEntry->Flink) 944 { 945 PACPI_CACHED_TABLE CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links); 946 947 /* Print the table signature */ 948 DbgPrint(" [%c%c%c%c]", 949 CachedTable->Header.Signature & 0x000000FF, 950 (CachedTable->Header.Signature & 0x0000FF00) >> 8, 951 (CachedTable->Header.Signature & 0x00FF0000) >> 16, 952 (CachedTable->Header.Signature & 0xFF000000) >> 24); 953 } 954 DbgPrint("\n"); 955 } 956 957 /* Return success */ 958 return STATUS_SUCCESS; 959} 960 961CODE_SEG("INIT") 962VOID 963NTAPI 964HalpInitializePciBus(VOID) 965{ 966 /* Setup the PCI stub support */ 967 HalpInitializePciStubs(); 968 969 /* Set the NMI crash flag */ 970 HalpGetNMICrashFlag(); 971} 972 973VOID 974NTAPI 975HalpInitNonBusHandler(VOID) 976{ 977 /* These should be written by the PCI driver later, but we give defaults */ 978 HalPciTranslateBusAddress = HalpTranslateBusAddress; 979 HalPciAssignSlotResources = HalpAssignSlotResources; 980 HalFindBusAddressTranslation = HalpFindBusAddressTranslation; 981} 982 983CODE_SEG("INIT") 984VOID 985NTAPI 986HalpInitBusHandlers(VOID) 987{ 988 /* On ACPI, we only have a fake PCI bus to worry about */ 989 HalpInitNonBusHandler(); 990} 991 992CODE_SEG("INIT") 993VOID 994NTAPI 995HalpBuildAddressMap(VOID) 996{ 997 /* ACPI is magic baby */ 998} 999 1000CODE_SEG("INIT") 1001BOOLEAN 1002NTAPI 1003HalpGetDebugPortTable(VOID) 1004{ 1005 return ((HalpDebugPortTable) && 1006 (HalpDebugPortTable->BaseAddress.AddressSpaceID == 1)); 1007} 1008 1009CODE_SEG("INIT") 1010ULONG 1011NTAPI 1012HalpIs16BitPortDecodeSupported(VOID) 1013{ 1014 /* All ACPI systems are at least "EISA" so they support this */ 1015 return CM_RESOURCE_PORT_16_BIT_DECODE; 1016} 1017 1018VOID 1019NTAPI 1020HalpAcpiDetectResourceListSize(OUT PULONG ListSize) 1021{ 1022 PAGED_CODE(); 1023 1024 /* One element if there is a SCI */ 1025 *ListSize = HalpFixedAcpiDescTable.sci_int_vector ? 1: 0; 1026} 1027 1028NTSTATUS 1029NTAPI 1030HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList) 1031{ 1032 ULONG Interrupt; 1033 PAGED_CODE(); 1034 ASSERT(ResourceList != NULL); 1035 1036 /* Initialize the list */ 1037 ResourceList->BusNumber = -1; 1038 ResourceList->AlternativeLists = 1; 1039 ResourceList->InterfaceType = PNPBus; 1040 ResourceList->List[0].Version = 1; 1041 ResourceList->List[0].Revision = 1; 1042 ResourceList->List[0].Count = 0; 1043 1044 /* Is there a SCI? */ 1045 if (HalpFixedAcpiDescTable.sci_int_vector) 1046 { 1047 /* Fill out the entry for it */ 1048 ResourceList->List[0].Descriptors[0].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 1049 ResourceList->List[0].Descriptors[0].Type = CmResourceTypeInterrupt; 1050 ResourceList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared; 1051 1052 /* Get the interrupt number */ 1053 Interrupt = HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector]; 1054 ResourceList->List[0].Descriptors[0].u.Interrupt.MinimumVector = Interrupt; 1055 ResourceList->List[0].Descriptors[0].u.Interrupt.MaximumVector = Interrupt; 1056 1057 /* One more */ 1058 ++ResourceList->List[0].Count; 1059 } 1060 1061 /* All good */ 1062 return STATUS_SUCCESS; 1063} 1064 1065NTSTATUS 1066NTAPI 1067HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements) 1068{ 1069 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 1070 ULONG Count, ListSize; 1071 NTSTATUS Status; 1072 1073 PAGED_CODE(); 1074 1075 /* Get ACPI resources */ 1076 HalpAcpiDetectResourceListSize(&Count); 1077 DPRINT("Resource count: %lu\n", Count); 1078 1079 /* Compute size of the list and allocate it */ 1080 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors) + 1081 (Count * sizeof(IO_RESOURCE_DESCRIPTOR)); 1082 DPRINT("Resource list size: %lu\n", ListSize); 1083 RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, TAG_HAL); 1084 if (RequirementsList) 1085 { 1086 /* Initialize it */ 1087 RtlZeroMemory(RequirementsList, ListSize); 1088 RequirementsList->ListSize = ListSize; 1089 1090 /* Build it */ 1091 Status = HalpBuildAcpiResourceList(RequirementsList); 1092 if (NT_SUCCESS(Status)) 1093 { 1094 /* It worked, return it */ 1095 *Requirements = RequirementsList; 1096 1097 /* Validate the list */ 1098 ASSERT(RequirementsList->List[0].Count == Count); 1099 } 1100 else 1101 { 1102 /* Fail */ 1103 ExFreePoolWithTag(RequirementsList, TAG_HAL); 1104 Status = STATUS_NO_SUCH_DEVICE; 1105 } 1106 } 1107 else 1108 { 1109 /* Not enough memory */ 1110 Status = STATUS_INSUFFICIENT_RESOURCES; 1111 } 1112 1113 /* Return the status */ 1114 return Status; 1115} 1116 1117/* 1118 * @implemented 1119 */ 1120CODE_SEG("INIT") 1121VOID 1122NTAPI 1123HalReportResourceUsage(VOID) 1124{ 1125 INTERFACE_TYPE InterfaceType; 1126 UNICODE_STRING HalString; 1127 1128 /* FIXME: Initialize DMA 64-bit support */ 1129 1130 /* FIXME: Initialize MCA bus */ 1131 1132 /* Initialize PCI bus. */ 1133 HalpInitializePciBus(); 1134 1135 /* What kind of bus is this? */ 1136 switch (HalpBusType) 1137 { 1138 /* ISA Machine */ 1139 case MACHINE_TYPE_ISA: 1140 InterfaceType = Isa; 1141 break; 1142 1143 /* EISA Machine */ 1144 case MACHINE_TYPE_EISA: 1145 InterfaceType = Eisa; 1146 break; 1147 1148 /* MCA Machine */ 1149 case MACHINE_TYPE_MCA: 1150 InterfaceType = MicroChannel; 1151 break; 1152 1153 /* Unknown */ 1154 default: 1155 InterfaceType = Internal; 1156 break; 1157 } 1158 1159 /* Build HAL usage */ 1160 RtlInitUnicodeString(&HalString, HalName); 1161 HalpReportResourceUsage(&HalString, InterfaceType); 1162 1163 /* Setup PCI debugging and Hibernation */ 1164 HalpRegisterPciDebuggingDeviceInfo(); 1165} 1166 1167/* EOF */