1 /****************************************************************************** 2 * 3 * Module Name: tbdata - Table manager data structure functions 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2022, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 #include "acnamesp.h" 47 #include "actables.h" 48 #include "acevents.h" 49 50 #define _COMPONENT ACPI_TABLES 51 ACPI_MODULE_NAME ("tbdata") 52 53 /* Local prototypes */ 54 55 static ACPI_STATUS 56 AcpiTbCheckDuplication ( 57 ACPI_TABLE_DESC *TableDesc, 58 UINT32 *TableIndex); 59 60 static BOOLEAN 61 AcpiTbCompareTables ( 62 ACPI_TABLE_DESC *TableDesc, 63 UINT32 TableIndex); 64 65 66 /******************************************************************************* 67 * 68 * FUNCTION: AcpiTbCompareTables 69 * 70 * PARAMETERS: TableDesc - Table 1 descriptor to be compared 71 * TableIndex - Index of table 2 to be compared 72 * 73 * RETURN: TRUE if both tables are identical. 74 * 75 * DESCRIPTION: This function compares a table with another table that has 76 * already been installed in the root table list. 77 * 78 ******************************************************************************/ 79 80 static BOOLEAN 81 AcpiTbCompareTables ( 82 ACPI_TABLE_DESC *TableDesc, 83 UINT32 TableIndex) 84 { 85 ACPI_STATUS Status = AE_OK; 86 BOOLEAN IsIdentical; 87 ACPI_TABLE_HEADER *Table; 88 UINT32 TableLength; 89 UINT8 TableFlags; 90 91 92 Status = AcpiTbAcquireTable (&AcpiGbl_RootTableList.Tables[TableIndex], 93 &Table, &TableLength, &TableFlags); 94 if (ACPI_FAILURE (Status)) 95 { 96 return (FALSE); 97 } 98 99 /* 100 * Check for a table match on the entire table length, 101 * not just the header. 102 */ 103 IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength || 104 memcmp (TableDesc->Pointer, Table, TableLength)) ? 105 FALSE : TRUE); 106 107 /* Release the acquired table */ 108 109 AcpiTbReleaseTable (Table, TableLength, TableFlags); 110 return (IsIdentical); 111 } 112 113 114 /******************************************************************************* 115 * 116 * FUNCTION: AcpiTbInitTableDescriptor 117 * 118 * PARAMETERS: TableDesc - Table descriptor 119 * Address - Physical address of the table 120 * Flags - Allocation flags of the table 121 * Table - Pointer to the table 122 * 123 * RETURN: None 124 * 125 * DESCRIPTION: Initialize a new table descriptor 126 * 127 ******************************************************************************/ 128 129 void 130 AcpiTbInitTableDescriptor ( 131 ACPI_TABLE_DESC *TableDesc, 132 ACPI_PHYSICAL_ADDRESS Address, 133 UINT8 Flags, 134 ACPI_TABLE_HEADER *Table) 135 { 136 137 /* 138 * Initialize the table descriptor. Set the pointer to NULL for external 139 * tables, since the table is not fully mapped at this time. 140 */ 141 memset (TableDesc, 0, sizeof (ACPI_TABLE_DESC)); 142 TableDesc->Address = Address; 143 TableDesc->Length = Table->Length; 144 TableDesc->Flags = Flags; 145 ACPI_MOVE_32_TO_32 (TableDesc->Signature.Ascii, Table->Signature); 146 147 switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) 148 { 149 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: 150 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: 151 152 TableDesc->Pointer = Table; 153 break; 154 155 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: 156 default: 157 158 break; 159 } 160 } 161 162 163 /******************************************************************************* 164 * 165 * FUNCTION: AcpiTbAcquireTable 166 * 167 * PARAMETERS: TableDesc - Table descriptor 168 * TablePtr - Where table is returned 169 * TableLength - Where table length is returned 170 * TableFlags - Where table allocation flags are returned 171 * 172 * RETURN: Status 173 * 174 * DESCRIPTION: Acquire an ACPI table. It can be used for tables not 175 * maintained in the AcpiGbl_RootTableList. 176 * 177 ******************************************************************************/ 178 179 ACPI_STATUS 180 AcpiTbAcquireTable ( 181 ACPI_TABLE_DESC *TableDesc, 182 ACPI_TABLE_HEADER **TablePtr, 183 UINT32 *TableLength, 184 UINT8 *TableFlags) 185 { 186 ACPI_TABLE_HEADER *Table = NULL; 187 188 189 switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) 190 { 191 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: 192 193 Table = AcpiOsMapMemory (TableDesc->Address, TableDesc->Length); 194 break; 195 196 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: 197 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: 198 199 Table = TableDesc->Pointer; 200 break; 201 202 default: 203 204 break; 205 } 206 207 /* Table is not valid yet */ 208 209 if (!Table) 210 { 211 return (AE_NO_MEMORY); 212 } 213 214 /* Fill the return values */ 215 216 *TablePtr = Table; 217 *TableLength = TableDesc->Length; 218 *TableFlags = TableDesc->Flags; 219 return (AE_OK); 220 } 221 222 223 /******************************************************************************* 224 * 225 * FUNCTION: AcpiTbReleaseTable 226 * 227 * PARAMETERS: Table - Pointer for the table 228 * TableLength - Length for the table 229 * TableFlags - Allocation flags for the table 230 * 231 * RETURN: None 232 * 233 * DESCRIPTION: Release a table. The inverse of AcpiTbAcquireTable(). 234 * 235 ******************************************************************************/ 236 237 void 238 AcpiTbReleaseTable ( 239 ACPI_TABLE_HEADER *Table, 240 UINT32 TableLength, 241 UINT8 TableFlags) 242 { 243 244 switch (TableFlags & ACPI_TABLE_ORIGIN_MASK) 245 { 246 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: 247 248 AcpiOsUnmapMemory (Table, TableLength); 249 break; 250 251 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: 252 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: 253 default: 254 255 break; 256 } 257 } 258 259 260 /******************************************************************************* 261 * 262 * FUNCTION: AcpiTbAcquireTempTable 263 * 264 * PARAMETERS: TableDesc - Table descriptor to be acquired 265 * Address - Address of the table 266 * Flags - Allocation flags of the table 267 * Table - Pointer to the table (required for virtual 268 * origins, optional for physical) 269 * 270 * RETURN: Status 271 * 272 * DESCRIPTION: This function validates the table header to obtain the length 273 * of a table and fills the table descriptor to make its state as 274 * "INSTALLED". Such a table descriptor is only used for verified 275 * installation. 276 * 277 ******************************************************************************/ 278 279 ACPI_STATUS 280 AcpiTbAcquireTempTable ( 281 ACPI_TABLE_DESC *TableDesc, 282 ACPI_PHYSICAL_ADDRESS Address, 283 UINT8 Flags, 284 ACPI_TABLE_HEADER *Table) 285 { 286 BOOLEAN MappedTable = FALSE; 287 288 289 switch (Flags & ACPI_TABLE_ORIGIN_MASK) 290 { 291 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: 292 293 /* Get the length of the full table from the header */ 294 295 if (!Table) 296 { 297 Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 298 if (!Table) 299 { 300 return (AE_NO_MEMORY); 301 } 302 303 MappedTable = TRUE; 304 } 305 306 break; 307 308 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: 309 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: 310 311 if (!Table) 312 { 313 return (AE_BAD_PARAMETER); 314 } 315 316 break; 317 318 default: 319 320 /* Table is not valid yet */ 321 322 return (AE_NO_MEMORY); 323 } 324 325 AcpiTbInitTableDescriptor (TableDesc, Address, Flags, Table); 326 if (MappedTable) 327 { 328 AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); 329 } 330 331 return (AE_OK); 332 } 333 334 335 /******************************************************************************* 336 * 337 * FUNCTION: AcpiTbReleaseTempTable 338 * 339 * PARAMETERS: TableDesc - Table descriptor to be released 340 * 341 * RETURN: Status 342 * 343 * DESCRIPTION: The inverse of AcpiTbAcquireTempTable(). 344 * 345 *****************************************************************************/ 346 347 void 348 AcpiTbReleaseTempTable ( 349 ACPI_TABLE_DESC *TableDesc) 350 { 351 352 /* 353 * Note that the .Address is maintained by the callers of 354 * AcpiTbAcquireTempTable(), thus do not invoke AcpiTbUninstallTable() 355 * where .Address will be freed. 356 */ 357 AcpiTbInvalidateTable (TableDesc); 358 } 359 360 361 /****************************************************************************** 362 * 363 * FUNCTION: AcpiTbValidateTable 364 * 365 * PARAMETERS: TableDesc - Table descriptor 366 * 367 * RETURN: Status 368 * 369 * DESCRIPTION: This function is called to validate the table, the returned 370 * table descriptor is in "VALIDATED" state. 371 * 372 *****************************************************************************/ 373 374 ACPI_STATUS 375 AcpiTbValidateTable ( 376 ACPI_TABLE_DESC *TableDesc) 377 { 378 ACPI_STATUS Status = AE_OK; 379 380 381 ACPI_FUNCTION_TRACE (TbValidateTable); 382 383 384 /* Validate the table if necessary */ 385 386 if (!TableDesc->Pointer) 387 { 388 Status = AcpiTbAcquireTable (TableDesc, &TableDesc->Pointer, 389 &TableDesc->Length, &TableDesc->Flags); 390 if (!TableDesc->Pointer) 391 { 392 Status = AE_NO_MEMORY; 393 } 394 } 395 396 return_ACPI_STATUS (Status); 397 } 398 399 400 /******************************************************************************* 401 * 402 * FUNCTION: AcpiTbInvalidateTable 403 * 404 * PARAMETERS: TableDesc - Table descriptor 405 * 406 * RETURN: None 407 * 408 * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of 409 * AcpiTbValidateTable(). 410 * 411 ******************************************************************************/ 412 413 void 414 AcpiTbInvalidateTable ( 415 ACPI_TABLE_DESC *TableDesc) 416 { 417 418 ACPI_FUNCTION_TRACE (TbInvalidateTable); 419 420 421 /* Table must be validated */ 422 423 if (!TableDesc->Pointer) 424 { 425 return_VOID; 426 } 427 428 AcpiTbReleaseTable (TableDesc->Pointer, TableDesc->Length, 429 TableDesc->Flags); 430 431 switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) 432 { 433 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: 434 435 TableDesc->Pointer = NULL; 436 break; 437 438 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: 439 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: 440 default: 441 442 break; 443 } 444 445 return_VOID; 446 } 447 448 449 /****************************************************************************** 450 * 451 * FUNCTION: AcpiTbValidateTempTable 452 * 453 * PARAMETERS: TableDesc - Table descriptor 454 * 455 * RETURN: Status 456 * 457 * DESCRIPTION: This function is called to validate the table, the returned 458 * table descriptor is in "VALIDATED" state. 459 * 460 *****************************************************************************/ 461 462 ACPI_STATUS 463 AcpiTbValidateTempTable ( 464 ACPI_TABLE_DESC *TableDesc) 465 { 466 467 if (!TableDesc->Pointer && !AcpiGbl_EnableTableValidation) 468 { 469 /* 470 * Only validates the header of the table. 471 * Note that Length contains the size of the mapping after invoking 472 * this work around, this value is required by 473 * AcpiTbReleaseTempTable(). 474 * We can do this because in AcpiInitTableDescriptor(), the Length 475 * field of the installed descriptor is filled with the actual 476 * table length obtaining from the table header. 477 */ 478 TableDesc->Length = sizeof (ACPI_TABLE_HEADER); 479 } 480 481 return (AcpiTbValidateTable (TableDesc)); 482 } 483 484 485 /******************************************************************************* 486 * 487 * FUNCTION: AcpiTbCheckDuplication 488 * 489 * PARAMETERS: TableDesc - Table descriptor 490 * TableIndex - Where the table index is returned 491 * 492 * RETURN: Status 493 * 494 * DESCRIPTION: Avoid installing duplicated tables. However table override and 495 * user aided dynamic table load is allowed, thus comparing the 496 * address of the table is not sufficient, and checking the entire 497 * table content is required. 498 * 499 ******************************************************************************/ 500 501 static ACPI_STATUS 502 AcpiTbCheckDuplication ( 503 ACPI_TABLE_DESC *TableDesc, 504 UINT32 *TableIndex) 505 { 506 UINT32 i; 507 508 509 ACPI_FUNCTION_TRACE (TbCheckDuplication); 510 511 512 /* Check if table is already registered */ 513 514 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) 515 { 516 /* Do not compare with unverified tables */ 517 518 if (!(AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_VERIFIED)) 519 { 520 continue; 521 } 522 523 /* 524 * Check for a table match on the entire table length, 525 * not just the header. 526 */ 527 if (!AcpiTbCompareTables (TableDesc, i)) 528 { 529 continue; 530 } 531 532 /* 533 * Note: the current mechanism does not unregister a table if it is 534 * dynamically unloaded. The related namespace entries are deleted, 535 * but the table remains in the root table list. 536 * 537 * The assumption here is that the number of different tables that 538 * will be loaded is actually small, and there is minimal overhead 539 * in just keeping the table in case it is needed again. 540 * 541 * If this assumption changes in the future (perhaps on large 542 * machines with many table load/unload operations), tables will 543 * need to be unregistered when they are unloaded, and slots in the 544 * root table list should be reused when empty. 545 */ 546 if (AcpiGbl_RootTableList.Tables[i].Flags & 547 ACPI_TABLE_IS_LOADED) 548 { 549 /* Table is still loaded, this is an error */ 550 551 return_ACPI_STATUS (AE_ALREADY_EXISTS); 552 } 553 else 554 { 555 *TableIndex = i; 556 return_ACPI_STATUS (AE_CTRL_TERMINATE); 557 } 558 } 559 560 /* Indicate no duplication to the caller */ 561 562 return_ACPI_STATUS (AE_OK); 563 } 564 565 566 /****************************************************************************** 567 * 568 * FUNCTION: AcpiTbVerifyTempTable 569 * 570 * PARAMETERS: TableDesc - Table descriptor 571 * Signature - Table signature to verify 572 * TableIndex - Where the table index is returned 573 * 574 * RETURN: Status 575 * 576 * DESCRIPTION: This function is called to validate and verify the table, the 577 * returned table descriptor is in "VALIDATED" state. 578 * Note that 'TableIndex' is required to be set to !NULL to 579 * enable duplication check. 580 * 581 *****************************************************************************/ 582 583 ACPI_STATUS 584 AcpiTbVerifyTempTable ( 585 ACPI_TABLE_DESC *TableDesc, 586 const char *Signature, 587 UINT32 *TableIndex) 588 { 589 ACPI_STATUS Status = AE_OK; 590 591 592 ACPI_FUNCTION_TRACE (TbVerifyTempTable); 593 594 595 /* Validate the table */ 596 597 Status = AcpiTbValidateTempTable (TableDesc); 598 if (ACPI_FAILURE (Status)) 599 { 600 return_ACPI_STATUS (AE_NO_MEMORY); 601 } 602 603 /* If a particular signature is expected (DSDT/FACS), it must match */ 604 605 if (Signature && 606 !ACPI_COMPARE_NAMESEG (&TableDesc->Signature, Signature)) 607 { 608 ACPI_BIOS_ERROR ((AE_INFO, 609 "Invalid signature 0x%X for ACPI table, expected [%s]", 610 TableDesc->Signature.Integer, Signature)); 611 Status = AE_BAD_SIGNATURE; 612 goto InvalidateAndExit; 613 } 614 615 if (AcpiGbl_EnableTableValidation) 616 { 617 /* Verify the checksum */ 618 619 Status = AcpiUtVerifyChecksum (TableDesc->Pointer, TableDesc->Length); 620 if (ACPI_FAILURE (Status)) 621 { 622 ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, 623 "%4.4s 0x%8.8X%8.8X" 624 " Attempted table install failed", 625 AcpiUtValidNameseg (TableDesc->Signature.Ascii) ? 626 TableDesc->Signature.Ascii : "????", 627 ACPI_FORMAT_UINT64 (TableDesc->Address))); 628 629 goto InvalidateAndExit; 630 } 631 632 /* Avoid duplications */ 633 634 if (TableIndex) 635 { 636 Status = AcpiTbCheckDuplication (TableDesc, TableIndex); 637 if (ACPI_FAILURE (Status)) 638 { 639 if (Status != AE_CTRL_TERMINATE) 640 { 641 ACPI_EXCEPTION ((AE_INFO, Status, 642 "%4.4s 0x%8.8X%8.8X" 643 " Table is already loaded", 644 AcpiUtValidNameseg (TableDesc->Signature.Ascii) ? 645 TableDesc->Signature.Ascii : "????", 646 ACPI_FORMAT_UINT64 (TableDesc->Address))); 647 } 648 649 goto InvalidateAndExit; 650 } 651 } 652 653 TableDesc->Flags |= ACPI_TABLE_IS_VERIFIED; 654 } 655 656 return_ACPI_STATUS (Status); 657 658 InvalidateAndExit: 659 AcpiTbInvalidateTable (TableDesc); 660 return_ACPI_STATUS (Status); 661 } 662 663 664 /******************************************************************************* 665 * 666 * FUNCTION: AcpiTbResizeRootTableList 667 * 668 * PARAMETERS: None 669 * 670 * RETURN: Status 671 * 672 * DESCRIPTION: Expand the size of global table array 673 * 674 ******************************************************************************/ 675 676 ACPI_STATUS 677 AcpiTbResizeRootTableList ( 678 void) 679 { 680 ACPI_TABLE_DESC *Tables; 681 UINT32 TableCount; 682 UINT32 CurrentTableCount, MaxTableCount; 683 UINT32 i; 684 685 686 ACPI_FUNCTION_TRACE (TbResizeRootTableList); 687 688 689 /* AllowResize flag is a parameter to AcpiInitializeTables */ 690 691 if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE)) 692 { 693 ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed")); 694 return_ACPI_STATUS (AE_SUPPORT); 695 } 696 697 /* Increase the Table Array size */ 698 699 if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) 700 { 701 TableCount = AcpiGbl_RootTableList.MaxTableCount; 702 } 703 else 704 { 705 TableCount = AcpiGbl_RootTableList.CurrentTableCount; 706 } 707 708 MaxTableCount = TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT; 709 Tables = ACPI_ALLOCATE_ZEROED ( 710 ((ACPI_SIZE) MaxTableCount) * sizeof (ACPI_TABLE_DESC)); 711 if (!Tables) 712 { 713 ACPI_ERROR ((AE_INFO, "Could not allocate new root table array")); 714 return_ACPI_STATUS (AE_NO_MEMORY); 715 } 716 717 /* Copy and free the previous table array */ 718 719 CurrentTableCount = 0; 720 if (AcpiGbl_RootTableList.Tables) 721 { 722 for (i = 0; i < TableCount; i++) 723 { 724 if (AcpiGbl_RootTableList.Tables[i].Address) 725 { 726 memcpy (Tables + CurrentTableCount, 727 AcpiGbl_RootTableList.Tables + i, 728 sizeof (ACPI_TABLE_DESC)); 729 CurrentTableCount++; 730 } 731 } 732 733 if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) 734 { 735 ACPI_FREE (AcpiGbl_RootTableList.Tables); 736 } 737 } 738 739 AcpiGbl_RootTableList.Tables = Tables; 740 AcpiGbl_RootTableList.MaxTableCount = MaxTableCount; 741 AcpiGbl_RootTableList.CurrentTableCount = CurrentTableCount; 742 AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED; 743 744 return_ACPI_STATUS (AE_OK); 745 } 746 747 748 /******************************************************************************* 749 * 750 * FUNCTION: AcpiTbGetNextTableDescriptor 751 * 752 * PARAMETERS: TableIndex - Where table index is returned 753 * TableDesc - Where table descriptor is returned 754 * 755 * RETURN: Status and table index/descriptor. 756 * 757 * DESCRIPTION: Allocate a new ACPI table entry to the global table list 758 * 759 ******************************************************************************/ 760 761 ACPI_STATUS 762 AcpiTbGetNextTableDescriptor ( 763 UINT32 *TableIndex, 764 ACPI_TABLE_DESC **TableDesc) 765 { 766 ACPI_STATUS Status; 767 UINT32 i; 768 769 770 /* Ensure that there is room for the table in the Root Table List */ 771 772 if (AcpiGbl_RootTableList.CurrentTableCount >= 773 AcpiGbl_RootTableList.MaxTableCount) 774 { 775 Status = AcpiTbResizeRootTableList(); 776 if (ACPI_FAILURE (Status)) 777 { 778 return (Status); 779 } 780 } 781 782 i = AcpiGbl_RootTableList.CurrentTableCount; 783 AcpiGbl_RootTableList.CurrentTableCount++; 784 785 if (TableIndex) 786 { 787 *TableIndex = i; 788 } 789 if (TableDesc) 790 { 791 *TableDesc = &AcpiGbl_RootTableList.Tables[i]; 792 } 793 794 return (AE_OK); 795 } 796 797 798 /******************************************************************************* 799 * 800 * FUNCTION: AcpiTbTerminate 801 * 802 * PARAMETERS: None 803 * 804 * RETURN: None 805 * 806 * DESCRIPTION: Delete all internal ACPI tables 807 * 808 ******************************************************************************/ 809 810 void 811 AcpiTbTerminate ( 812 void) 813 { 814 UINT32 i; 815 816 817 ACPI_FUNCTION_TRACE (TbTerminate); 818 819 820 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 821 822 /* Delete the individual tables */ 823 824 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 825 { 826 AcpiTbUninstallTable (&AcpiGbl_RootTableList.Tables[i]); 827 } 828 829 /* 830 * Delete the root table array if allocated locally. Array cannot be 831 * mapped, so we don't need to check for that flag. 832 */ 833 if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) 834 { 835 ACPI_FREE (AcpiGbl_RootTableList.Tables); 836 } 837 838 AcpiGbl_RootTableList.Tables = NULL; 839 AcpiGbl_RootTableList.Flags = 0; 840 AcpiGbl_RootTableList.CurrentTableCount = 0; 841 842 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n")); 843 844 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 845 return_VOID; 846 } 847 848 849 /******************************************************************************* 850 * 851 * FUNCTION: AcpiTbDeleteNamespaceByOwner 852 * 853 * PARAMETERS: TableIndex - Table index 854 * 855 * RETURN: Status 856 * 857 * DESCRIPTION: Delete all namespace objects created when this table was loaded. 858 * 859 ******************************************************************************/ 860 861 ACPI_STATUS 862 AcpiTbDeleteNamespaceByOwner ( 863 UINT32 TableIndex) 864 { 865 ACPI_OWNER_ID OwnerId; 866 ACPI_STATUS Status; 867 868 869 ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner); 870 871 872 Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES); 873 if (ACPI_FAILURE (Status)) 874 { 875 return_ACPI_STATUS (Status); 876 } 877 878 if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) 879 { 880 /* The table index does not exist */ 881 882 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 883 return_ACPI_STATUS (AE_NOT_EXIST); 884 } 885 886 /* Get the owner ID for this table, used to delete namespace nodes */ 887 888 OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId; 889 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 890 891 /* 892 * Need to acquire the namespace writer lock to prevent interference 893 * with any concurrent namespace walks. The interpreter must be 894 * released during the deletion since the acquisition of the deletion 895 * lock may block, and also since the execution of a namespace walk 896 * must be allowed to use the interpreter. 897 */ 898 Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock); 899 if (ACPI_FAILURE (Status)) 900 { 901 return_ACPI_STATUS (Status); 902 } 903 904 AcpiNsDeleteNamespaceByOwner (OwnerId); 905 AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock); 906 return_ACPI_STATUS (Status); 907 } 908 909 910 /******************************************************************************* 911 * 912 * FUNCTION: AcpiTbAllocateOwnerId 913 * 914 * PARAMETERS: TableIndex - Table index 915 * 916 * RETURN: Status 917 * 918 * DESCRIPTION: Allocates OwnerId in TableDesc 919 * 920 ******************************************************************************/ 921 922 ACPI_STATUS 923 AcpiTbAllocateOwnerId ( 924 UINT32 TableIndex) 925 { 926 ACPI_STATUS Status = AE_BAD_PARAMETER; 927 928 929 ACPI_FUNCTION_TRACE (TbAllocateOwnerId); 930 931 932 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 933 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) 934 { 935 Status = AcpiUtAllocateOwnerId ( 936 &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId)); 937 } 938 939 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 940 return_ACPI_STATUS (Status); 941 } 942 943 944 /******************************************************************************* 945 * 946 * FUNCTION: AcpiTbReleaseOwnerId 947 * 948 * PARAMETERS: TableIndex - Table index 949 * 950 * RETURN: Status 951 * 952 * DESCRIPTION: Releases OwnerId in TableDesc 953 * 954 ******************************************************************************/ 955 956 ACPI_STATUS 957 AcpiTbReleaseOwnerId ( 958 UINT32 TableIndex) 959 { 960 ACPI_STATUS Status = AE_BAD_PARAMETER; 961 962 963 ACPI_FUNCTION_TRACE (TbReleaseOwnerId); 964 965 966 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 967 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) 968 { 969 AcpiUtReleaseOwnerId ( 970 &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId)); 971 Status = AE_OK; 972 } 973 974 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 975 return_ACPI_STATUS (Status); 976 } 977 978 979 /******************************************************************************* 980 * 981 * FUNCTION: AcpiTbGetOwnerId 982 * 983 * PARAMETERS: TableIndex - Table index 984 * OwnerId - Where the table OwnerId is returned 985 * 986 * RETURN: Status 987 * 988 * DESCRIPTION: returns OwnerId for the ACPI table 989 * 990 ******************************************************************************/ 991 992 ACPI_STATUS 993 AcpiTbGetOwnerId ( 994 UINT32 TableIndex, 995 ACPI_OWNER_ID *OwnerId) 996 { 997 ACPI_STATUS Status = AE_BAD_PARAMETER; 998 999 1000 ACPI_FUNCTION_TRACE (TbGetOwnerId); 1001 1002 1003 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 1004 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) 1005 { 1006 *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId; 1007 Status = AE_OK; 1008 } 1009 1010 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 1011 return_ACPI_STATUS (Status); 1012 } 1013 1014 1015 /******************************************************************************* 1016 * 1017 * FUNCTION: AcpiTbIsTableLoaded 1018 * 1019 * PARAMETERS: TableIndex - Index into the root table 1020 * 1021 * RETURN: Table Loaded Flag 1022 * 1023 ******************************************************************************/ 1024 1025 BOOLEAN 1026 AcpiTbIsTableLoaded ( 1027 UINT32 TableIndex) 1028 { 1029 BOOLEAN IsLoaded = FALSE; 1030 1031 1032 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 1033 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) 1034 { 1035 IsLoaded = (BOOLEAN) 1036 (AcpiGbl_RootTableList.Tables[TableIndex].Flags & 1037 ACPI_TABLE_IS_LOADED); 1038 } 1039 1040 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 1041 return (IsLoaded); 1042 } 1043 1044 1045 /******************************************************************************* 1046 * 1047 * FUNCTION: AcpiTbSetTableLoadedFlag 1048 * 1049 * PARAMETERS: TableIndex - Table index 1050 * IsLoaded - TRUE if table is loaded, FALSE otherwise 1051 * 1052 * RETURN: None 1053 * 1054 * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. 1055 * 1056 ******************************************************************************/ 1057 1058 void 1059 AcpiTbSetTableLoadedFlag ( 1060 UINT32 TableIndex, 1061 BOOLEAN IsLoaded) 1062 { 1063 1064 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 1065 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) 1066 { 1067 if (IsLoaded) 1068 { 1069 AcpiGbl_RootTableList.Tables[TableIndex].Flags |= 1070 ACPI_TABLE_IS_LOADED; 1071 } 1072 else 1073 { 1074 AcpiGbl_RootTableList.Tables[TableIndex].Flags &= 1075 ~ACPI_TABLE_IS_LOADED; 1076 } 1077 } 1078 1079 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 1080 } 1081 1082 1083 /******************************************************************************* 1084 * 1085 * FUNCTION: AcpiTbLoadTable 1086 * 1087 * PARAMETERS: TableIndex - Table index 1088 * ParentNode - Where table index is returned 1089 * 1090 * RETURN: Status 1091 * 1092 * DESCRIPTION: Load an ACPI table 1093 * 1094 ******************************************************************************/ 1095 1096 ACPI_STATUS 1097 AcpiTbLoadTable ( 1098 UINT32 TableIndex, 1099 ACPI_NAMESPACE_NODE *ParentNode) 1100 { 1101 ACPI_TABLE_HEADER *Table; 1102 ACPI_STATUS Status; 1103 ACPI_OWNER_ID OwnerId; 1104 1105 1106 ACPI_FUNCTION_TRACE (TbLoadTable); 1107 1108 1109 /* 1110 * Note: Now table is "INSTALLED", it must be validated before 1111 * using. 1112 */ 1113 Status = AcpiGetTableByIndex (TableIndex, &Table); 1114 if (ACPI_FAILURE (Status)) 1115 { 1116 return_ACPI_STATUS (Status); 1117 } 1118 1119 Status = AcpiNsLoadTable (TableIndex, ParentNode); 1120 if (ACPI_FAILURE (Status)) 1121 { 1122 return_ACPI_STATUS (Status); 1123 } 1124 1125 /* 1126 * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is 1127 * responsible for discovering any new wake GPEs by running _PRW methods 1128 * that may have been loaded by this table. 1129 */ 1130 Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); 1131 if (ACPI_SUCCESS (Status)) 1132 { 1133 AcpiEvUpdateGpes (OwnerId); 1134 } 1135 1136 /* Invoke table handler */ 1137 1138 AcpiTbNotifyTable (ACPI_TABLE_EVENT_LOAD, Table); 1139 return_ACPI_STATUS (Status); 1140 } 1141 1142 1143 /******************************************************************************* 1144 * 1145 * FUNCTION: AcpiTbInstallAndLoadTable 1146 * 1147 * PARAMETERS: Address - Physical address of the table 1148 * Flags - Allocation flags of the table 1149 * Table - Pointer to the table (required for 1150 * virtual origins, optional for 1151 * physical) 1152 * Override - Whether override should be performed 1153 * TableIndex - Where table index is returned 1154 * 1155 * RETURN: Status 1156 * 1157 * DESCRIPTION: Install and load an ACPI table 1158 * 1159 ******************************************************************************/ 1160 1161 ACPI_STATUS 1162 AcpiTbInstallAndLoadTable ( 1163 ACPI_PHYSICAL_ADDRESS Address, 1164 UINT8 Flags, 1165 ACPI_TABLE_HEADER *Table, 1166 BOOLEAN Override, 1167 UINT32 *TableIndex) 1168 { 1169 ACPI_STATUS Status; 1170 UINT32 i; 1171 1172 1173 ACPI_FUNCTION_TRACE (TbInstallAndLoadTable); 1174 1175 1176 /* Install the table and load it into the namespace */ 1177 1178 Status = AcpiTbInstallStandardTable (Address, Flags, Table, TRUE, 1179 Override, &i); 1180 if (ACPI_FAILURE (Status)) 1181 { 1182 goto Exit; 1183 } 1184 1185 Status = AcpiTbLoadTable (i, AcpiGbl_RootNode); 1186 1187 Exit: 1188 *TableIndex = i; 1189 return_ACPI_STATUS (Status); 1190 } 1191 1192 1193 /******************************************************************************* 1194 * 1195 * FUNCTION: AcpiTbUnloadTable 1196 * 1197 * PARAMETERS: TableIndex - Table index 1198 * 1199 * RETURN: Status 1200 * 1201 * DESCRIPTION: Unload an ACPI table 1202 * 1203 ******************************************************************************/ 1204 1205 ACPI_STATUS 1206 AcpiTbUnloadTable ( 1207 UINT32 TableIndex) 1208 { 1209 ACPI_STATUS Status = AE_OK; 1210 ACPI_TABLE_HEADER *Table; 1211 1212 1213 ACPI_FUNCTION_TRACE (TbUnloadTable); 1214 1215 1216 /* Ensure the table is still loaded */ 1217 1218 if (!AcpiTbIsTableLoaded (TableIndex)) 1219 { 1220 return_ACPI_STATUS (AE_NOT_EXIST); 1221 } 1222 1223 /* Invoke table handler */ 1224 1225 Status = AcpiGetTableByIndex (TableIndex, &Table); 1226 if (ACPI_SUCCESS (Status)) 1227 { 1228 AcpiTbNotifyTable (ACPI_TABLE_EVENT_UNLOAD, Table); 1229 } 1230 1231 /* Delete the portion of the namespace owned by this table */ 1232 1233 Status = AcpiTbDeleteNamespaceByOwner (TableIndex); 1234 if (ACPI_FAILURE (Status)) 1235 { 1236 return_ACPI_STATUS (Status); 1237 } 1238 1239 (void) AcpiTbReleaseOwnerId (TableIndex); 1240 AcpiTbSetTableLoadedFlag (TableIndex, FALSE); 1241 return_ACPI_STATUS (Status); 1242 } 1243 1244 1245 /******************************************************************************* 1246 * 1247 * FUNCTION: AcpiTbNotifyTable 1248 * 1249 * PARAMETERS: Event - Table event 1250 * Table - Validated table pointer 1251 * 1252 * RETURN: None 1253 * 1254 * DESCRIPTION: Notify a table event to the users. 1255 * 1256 ******************************************************************************/ 1257 1258 void 1259 AcpiTbNotifyTable ( 1260 UINT32 Event, 1261 void *Table) 1262 { 1263 /* Invoke table handler if present */ 1264 1265 if (AcpiGbl_TableHandler) 1266 { 1267 (void) AcpiGbl_TableHandler (Event, Table, 1268 AcpiGbl_TableHandlerContext); 1269 } 1270 } 1271