tbxfload.c revision 302408
11553Srgrimes/****************************************************************************** 21553Srgrimes * 31553Srgrimes * Module Name: tbxfload - Table load/unload external interfaces 41553Srgrimes * 51553Srgrimes *****************************************************************************/ 61553Srgrimes 71553Srgrimes/* 81553Srgrimes * Copyright (C) 2000 - 2016, Intel Corp. 91553Srgrimes * All rights reserved. 101553Srgrimes * 111553Srgrimes * Redistribution and use in source and binary forms, with or without 121553Srgrimes * modification, are permitted provided that the following conditions 131553Srgrimes * are met: 141553Srgrimes * 1. Redistributions of source code must retain the above copyright 151553Srgrimes * notice, this list of conditions, and the following disclaimer, 161553Srgrimes * without modification. 171553Srgrimes * 2. Redistributions in binary form must reproduce at minimum a disclaimer 181553Srgrimes * substantially similar to the "NO WARRANTY" disclaimer below 191553Srgrimes * ("Disclaimer") and any redistribution must be conditioned upon 201553Srgrimes * including a substantially similar Disclaimer requirement for further 211553Srgrimes * binary redistribution. 221553Srgrimes * 3. Neither the names of the above-listed copyright holders nor the names 231553Srgrimes * of any contributors may be used to endorse or promote products derived 241553Srgrimes * from this software without specific prior written permission. 251553Srgrimes * 261553Srgrimes * Alternatively, this software may be distributed under the terms of the 271553Srgrimes * GNU General Public License ("GPL") version 2 as published by the Free 281553Srgrimes * Software Foundation. 291553Srgrimes * 301553Srgrimes * NO WARRANTY 311553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 321553Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 331553Srgrimes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 341553Srgrimes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3530027Scharnier * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 361553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3730027Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3830027Scharnier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3938020Sbde * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 401553Srgrimes * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 411553Srgrimes * POSSIBILITY OF SUCH DAMAGES. 421553Srgrimes */ 431553Srgrimes 4430027Scharnier#define EXPORT_ACPI_INTERFACES 4530027Scharnier 4630027Scharnier#include <contrib/dev/acpica/include/acpi.h> 471553Srgrimes#include <contrib/dev/acpica/include/accommon.h> 481553Srgrimes#include <contrib/dev/acpica/include/acnamesp.h> 491553Srgrimes#include <contrib/dev/acpica/include/actables.h> 5030027Scharnier#include <contrib/dev/acpica/include/acevents.h> 511553Srgrimes 5230027Scharnier#define _COMPONENT ACPI_TABLES 5330027Scharnier ACPI_MODULE_NAME ("tbxfload") 541553Srgrimes 551553Srgrimes 561553Srgrimes/******************************************************************************* 571553Srgrimes * 581553Srgrimes * FUNCTION: AcpiLoadTables 591553Srgrimes * 601553Srgrimes * PARAMETERS: None 612860Srgrimes * 622860Srgrimes * RETURN: Status 632860Srgrimes * 6436670Speter * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT 651553Srgrimes * 6630027Scharnier ******************************************************************************/ 671553Srgrimes 681553SrgrimesACPI_STATUS 691553SrgrimesAcpiLoadTables ( 701553Srgrimes void) 711553Srgrimes{ 721553Srgrimes ACPI_STATUS Status; 732860Srgrimes 741553Srgrimes 752860Srgrimes ACPI_FUNCTION_TRACE (AcpiLoadTables); 761553Srgrimes 771553Srgrimes 781553Srgrimes /* 791553Srgrimes * Install the default operation region handlers. These are the 801553Srgrimes * handlers that are defined by the ACPI specification to be 811553Srgrimes * "always accessible" -- namely, SystemMemory, SystemIO, and 821553Srgrimes * PCI_Config. This also means that no _REG methods need to be 831553Srgrimes * run for these address spaces. We need to have these handlers 842860Srgrimes * installed before any AML code can be executed, especially any 851553Srgrimes * module-level code (11/2015). 861553Srgrimes * Note that we allow OSPMs to install their own region handlers 871553Srgrimes * between AcpiInitializeSubsystem() and AcpiLoadTables() to use 881553Srgrimes * their customized default region handlers. 891553Srgrimes */ 901553Srgrimes Status = AcpiEvInstallRegionHandlers (); 911553Srgrimes if (ACPI_FAILURE (Status)) 921553Srgrimes { 931553Srgrimes ACPI_EXCEPTION ((AE_INFO, Status, "During Region initialization")); 941553Srgrimes return_ACPI_STATUS (Status); 9530027Scharnier } 962860Srgrimes 972860Srgrimes /* Load the namespace from the tables */ 982860Srgrimes 991553Srgrimes Status = AcpiTbLoadNamespace (); 1001553Srgrimes 1012860Srgrimes /* Don't let single failures abort the load */ 1022860Srgrimes 1032860Srgrimes if (Status == AE_CTRL_TERMINATE) 1042860Srgrimes { 1051553Srgrimes Status = AE_OK; 1062860Srgrimes } 1071553Srgrimes 1081553Srgrimes if (ACPI_FAILURE (Status)) 1092860Srgrimes { 1102860Srgrimes ACPI_EXCEPTION ((AE_INFO, Status, 1112860Srgrimes "While loading namespace from ACPI tables")); 1122860Srgrimes } 1132860Srgrimes 1141553Srgrimes if (!AcpiGbl_GroupModuleLevelCode) 1151553Srgrimes { 1161553Srgrimes /* 1171553Srgrimes * Initialize the objects that remain uninitialized. This 11830027Scharnier * runs the executable AML that may be part of the 1191553Srgrimes * declaration of these objects: 1201553Srgrimes * OperationRegions, BufferFields, Buffers, and Packages. 1211553Srgrimes */ 1222860Srgrimes Status = AcpiNsInitializeObjects (); 1231553Srgrimes if (ACPI_FAILURE (Status)) 1248857Srgrimes { 1251553Srgrimes return_ACPI_STATUS (Status); 1262860Srgrimes } 1271553Srgrimes } 1281553Srgrimes 12930027Scharnier AcpiGbl_NamespaceInitialized = TRUE; 1301553Srgrimes return_ACPI_STATUS (Status); 1311553Srgrimes} 1321553Srgrimes 1332860SrgrimesACPI_EXPORT_SYMBOL_INIT (AcpiLoadTables) 1342860Srgrimes 1351553Srgrimes 1361553Srgrimes/******************************************************************************* 1371553Srgrimes * 1381553Srgrimes * FUNCTION: AcpiTbLoadNamespace 1391553Srgrimes * 1402860Srgrimes * PARAMETERS: None 1411553Srgrimes * 1422860Srgrimes * RETURN: Status 1432860Srgrimes * 1441553Srgrimes * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in 1452860Srgrimes * the RSDT/XSDT. 1461553Srgrimes * 1472860Srgrimes ******************************************************************************/ 1482860Srgrimes 1491553SrgrimesACPI_STATUS 1502860SrgrimesAcpiTbLoadNamespace ( 1511553Srgrimes void) 1522860Srgrimes{ 1532860Srgrimes ACPI_STATUS Status; 1542860Srgrimes UINT32 i; 1552860Srgrimes ACPI_TABLE_HEADER *NewDsdt; 1562860Srgrimes ACPI_TABLE_DESC *Table; 1572860Srgrimes UINT32 TablesLoaded = 0; 1582860Srgrimes UINT32 TablesFailed = 0; 15930027Scharnier 16030027Scharnier 16130027Scharnier ACPI_FUNCTION_TRACE (TbLoadNamespace); 1622860Srgrimes 1632860Srgrimes 1642860Srgrimes (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 1652860Srgrimes 1662860Srgrimes /* 1672860Srgrimes * Load the namespace. The DSDT is required, but any SSDT and 1682860Srgrimes * PSDT tables are optional. Verify the DSDT. 1692860Srgrimes */ 1702860Srgrimes Table = &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex]; 1712860Srgrimes 17230027Scharnier if (!AcpiGbl_RootTableList.CurrentTableCount || 17330027Scharnier !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_DSDT) || 17430027Scharnier ACPI_FAILURE (AcpiTbValidateTable (Table))) 1752860Srgrimes { 1762860Srgrimes Status = AE_NO_ACPI_TABLES; 1772860Srgrimes goto UnlockAndExit; 1782860Srgrimes } 1792860Srgrimes 1801553Srgrimes /* 1812860Srgrimes * Save the DSDT pointer for simple access. This is the mapped memory 1821553Srgrimes * address. We must take care here because the address of the .Tables 1832860Srgrimes * array can change dynamically as tables are loaded at run-time. Note: 1841553Srgrimes * .Pointer field is not validated until after call to AcpiTbValidateTable. 1852860Srgrimes */ 1861553Srgrimes AcpiGbl_DSDT = Table->Pointer; 1872860Srgrimes 18818404Snate /* 18918404Snate * Optionally copy the entire DSDT to local memory (instead of simply 1901553Srgrimes * mapping it.) There are some BIOSs that corrupt or replace the original 1911553Srgrimes * DSDT, creating the need for this option. Default is FALSE, do not copy 1921553Srgrimes * the DSDT. 19330027Scharnier */ 1941553Srgrimes if (AcpiGbl_CopyDsdtLocally) 1952860Srgrimes { 1961553Srgrimes NewDsdt = AcpiTbCopyDsdt (AcpiGbl_DsdtIndex); 1976286Swollman if (NewDsdt) 1989490Sphk { 1996286Swollman AcpiGbl_DSDT = NewDsdt; 2009490Sphk } 2016286Swollman } 20230027Scharnier 2036286Swollman /* 2046286Swollman * Save the original DSDT header for detection of table corruption 2056286Swollman * and/or replacement of the DSDT from outside the OS. 2066286Swollman */ 2071553Srgrimes memcpy (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, 2081553Srgrimes sizeof (ACPI_TABLE_HEADER)); 2092860Srgrimes 2101553Srgrimes (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 2111553Srgrimes 2121553Srgrimes /* Load and parse tables */ 2131553Srgrimes 2141553Srgrimes Status = AcpiNsLoadTable (AcpiGbl_DsdtIndex, AcpiGbl_RootNode); 2151553Srgrimes if (ACPI_FAILURE (Status)) 2161553Srgrimes { 2171553Srgrimes ACPI_EXCEPTION ((AE_INFO, Status, "[DSDT] table load failed")); 2181553Srgrimes TablesFailed++; 2191553Srgrimes } 2201553Srgrimes else 2211553Srgrimes { 2221553Srgrimes TablesLoaded++; 2231553Srgrimes } 2241553Srgrimes 2251553Srgrimes /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ 2261553Srgrimes 2271553Srgrimes (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 2281553Srgrimes for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) 2291553Srgrimes { 2301553Srgrimes Table = &AcpiGbl_RootTableList.Tables[i]; 2312860Srgrimes 2322860Srgrimes if (!AcpiGbl_RootTableList.Tables[i].Address || 2332860Srgrimes (!ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_SSDT) && 2341553Srgrimes !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_PSDT) && 2352877Srgrimes !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_OSDT)) || 2361553Srgrimes ACPI_FAILURE (AcpiTbValidateTable (Table))) 2371553Srgrimes { 2381553Srgrimes continue; 23930027Scharnier } 2401553Srgrimes 2411553Srgrimes /* Ignore errors while loading tables, get as many as possible */ 2421553Srgrimes 2431553Srgrimes (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 2441553Srgrimes Status = AcpiNsLoadTable (i, AcpiGbl_RootNode); 2451553Srgrimes if (ACPI_FAILURE (Status)) 2461553Srgrimes { 2471553Srgrimes ACPI_EXCEPTION ((AE_INFO, Status, "(%4.4s:%8.8s) while loading table", 2481553Srgrimes Table->Signature.Ascii, Table->Pointer->OemTableId)); 2492860Srgrimes 2502860Srgrimes TablesFailed++; 2512860Srgrimes 2522860Srgrimes ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, 2532860Srgrimes "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n", 2542860Srgrimes Table->Signature.Ascii, Table->Pointer->OemTableId)); 2552860Srgrimes } 2562860Srgrimes else 2572860Srgrimes { 2582860Srgrimes TablesLoaded++; 2592860Srgrimes } 2602860Srgrimes 2612860Srgrimes (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 2622860Srgrimes } 2632860Srgrimes 2642860Srgrimes if (!TablesFailed) 2651553Srgrimes { 2661553Srgrimes ACPI_INFO (( 2672860Srgrimes "%u ACPI AML tables successfully acquired and loaded\n", 2682860Srgrimes TablesLoaded)); 2692877Srgrimes } 2702877Srgrimes else 2712860Srgrimes { 2722860Srgrimes ACPI_ERROR ((AE_INFO, 2732860Srgrimes "%u table load failures, %u successful", 2742877Srgrimes TablesFailed, TablesLoaded)); 2752877Srgrimes 2762860Srgrimes /* Indicate at least one failure */ 2772860Srgrimes 2781553Srgrimes Status = AE_CTRL_TERMINATE; 2792860Srgrimes } 2802860Srgrimes 2812860SrgrimesUnlockAndExit: 2822860Srgrimes (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 2832860Srgrimes return_ACPI_STATUS (Status); 28430027Scharnier} 28530027Scharnier 28630027Scharnier 2872860Srgrimes/******************************************************************************* 28838020Sbde * 2892860Srgrimes * FUNCTION: AcpiInstallTable 2902860Srgrimes * 2912860Srgrimes * PARAMETERS: Address - Address of the ACPI table to be installed. 2922860Srgrimes * Physical - Whether the address is a physical table 29330027Scharnier * address or not 29430027Scharnier * 29530027Scharnier * RETURN: Status 2962860Srgrimes * 29738020Sbde * DESCRIPTION: Dynamically install an ACPI table. 2982860Srgrimes * Note: This function should only be invoked after 2992860Srgrimes * AcpiInitializeTables() and before AcpiLoadTables(). 3002860Srgrimes * 3012860Srgrimes ******************************************************************************/ 3022860Srgrimes 3032860SrgrimesACPI_STATUS 3042860SrgrimesAcpiInstallTable ( 3052860Srgrimes ACPI_PHYSICAL_ADDRESS Address, 3062860Srgrimes BOOLEAN Physical) 3071553Srgrimes{ 3081553Srgrimes ACPI_STATUS Status; 3091553Srgrimes UINT8 Flags; 3101553Srgrimes UINT32 TableIndex; 3111553Srgrimes 3121553Srgrimes 3131553Srgrimes ACPI_FUNCTION_TRACE (AcpiInstallTable); 3141553Srgrimes 3151553Srgrimes 3161553Srgrimes if (Physical) 3171553Srgrimes { 3181553Srgrimes Flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; 3191553Srgrimes } 3201553Srgrimes else 3211553Srgrimes { 3221553Srgrimes Flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; 3231553Srgrimes } 3241553Srgrimes 3251553Srgrimes Status = AcpiTbInstallStandardTable (Address, Flags, 3261553Srgrimes FALSE, FALSE, &TableIndex); 3271553Srgrimes 3281553Srgrimes return_ACPI_STATUS (Status); 3291553Srgrimes} 3302860Srgrimes 3311553SrgrimesACPI_EXPORT_SYMBOL_INIT (AcpiInstallTable) 3322860Srgrimes 3332860Srgrimes 3341553Srgrimes/******************************************************************************* 3351553Srgrimes * 3361553Srgrimes * FUNCTION: AcpiLoadTable 3371553Srgrimes * 3381553Srgrimes * PARAMETERS: Table - Pointer to a buffer containing the ACPI 3391553Srgrimes * table to be loaded. 3401553Srgrimes * 3411553Srgrimes * RETURN: Status 3421553Srgrimes * 3431553Srgrimes * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must 3441553Srgrimes * be a valid ACPI table with a valid ACPI table header. 3451553Srgrimes * Note1: Mainly intended to support hotplug addition of SSDTs. 3461553Srgrimes * Note2: Does not copy the incoming table. User is responsible 3471553Srgrimes * to ensure that the table is not deleted or unmapped. 3481553Srgrimes * 3491553Srgrimes ******************************************************************************/ 3502860Srgrimes 3512860SrgrimesACPI_STATUS 3521553SrgrimesAcpiLoadTable ( 3531553Srgrimes ACPI_TABLE_HEADER *Table) 3541553Srgrimes{ 355 ACPI_STATUS Status; 356 UINT32 TableIndex; 357 358 359 ACPI_FUNCTION_TRACE (AcpiLoadTable); 360 361 362 /* Parameter validation */ 363 364 if (!Table) 365 { 366 return_ACPI_STATUS (AE_BAD_PARAMETER); 367 } 368 369 /* Must acquire the interpreter lock during this operation */ 370 371 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 372 if (ACPI_FAILURE (Status)) 373 { 374 return_ACPI_STATUS (Status); 375 } 376 377 /* Install the table and load it into the namespace */ 378 379 ACPI_INFO (("Host-directed Dynamic ACPI Table Load:")); 380 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 381 382 Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table), 383 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, TRUE, FALSE, 384 &TableIndex); 385 386 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 387 if (ACPI_FAILURE (Status)) 388 { 389 goto UnlockAndExit; 390 } 391 392 /* 393 * Note: Now table is "INSTALLED", it must be validated before 394 * using. 395 */ 396 Status = AcpiTbValidateTable ( 397 &AcpiGbl_RootTableList.Tables[TableIndex]); 398 if (ACPI_FAILURE (Status)) 399 { 400 goto UnlockAndExit; 401 } 402 403 Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode); 404 405 /* Invoke table handler if present */ 406 407 if (AcpiGbl_TableHandler) 408 { 409 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 410 AcpiGbl_TableHandlerContext); 411 } 412 413UnlockAndExit: 414 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 415 return_ACPI_STATUS (Status); 416} 417 418ACPI_EXPORT_SYMBOL (AcpiLoadTable) 419 420 421/******************************************************************************* 422 * 423 * FUNCTION: AcpiUnloadParentTable 424 * 425 * PARAMETERS: Object - Handle to any namespace object owned by 426 * the table to be unloaded 427 * 428 * RETURN: Status 429 * 430 * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads 431 * the table and deletes all namespace objects associated with 432 * that table. Unloading of the DSDT is not allowed. 433 * Note: Mainly intended to support hotplug removal of SSDTs. 434 * 435 ******************************************************************************/ 436 437ACPI_STATUS 438AcpiUnloadParentTable ( 439 ACPI_HANDLE Object) 440{ 441 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); 442 ACPI_STATUS Status = AE_NOT_EXIST; 443 ACPI_OWNER_ID OwnerId; 444 UINT32 i; 445 446 447 ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); 448 449 450 /* Parameter validation */ 451 452 if (!Object) 453 { 454 return_ACPI_STATUS (AE_BAD_PARAMETER); 455 } 456 457 /* 458 * The node OwnerId is currently the same as the parent table ID. 459 * However, this could change in the future. 460 */ 461 OwnerId = Node->OwnerId; 462 if (!OwnerId) 463 { 464 /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ 465 466 return_ACPI_STATUS (AE_TYPE); 467 } 468 469 /* Must acquire the interpreter lock during this operation */ 470 471 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 472 if (ACPI_FAILURE (Status)) 473 { 474 return_ACPI_STATUS (Status); 475 } 476 477 /* Find the table in the global table list */ 478 479 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 480 { 481 if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) 482 { 483 continue; 484 } 485 486 /* 487 * Allow unload of SSDT and OEMx tables only. Do not allow unload 488 * of the DSDT. No other types of tables should get here, since 489 * only these types can contain AML and thus are the only types 490 * that can create namespace objects. 491 */ 492 if (ACPI_COMPARE_NAME ( 493 AcpiGbl_RootTableList.Tables[i].Signature.Ascii, 494 ACPI_SIG_DSDT)) 495 { 496 Status = AE_TYPE; 497 break; 498 } 499 500 /* Ensure the table is actually loaded */ 501 502 if (!AcpiTbIsTableLoaded (i)) 503 { 504 Status = AE_NOT_EXIST; 505 break; 506 } 507 508 /* Invoke table handler if present */ 509 510 if (AcpiGbl_TableHandler) 511 { 512 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, 513 AcpiGbl_RootTableList.Tables[i].Pointer, 514 AcpiGbl_TableHandlerContext); 515 } 516 517 /* 518 * Delete all namespace objects owned by this table. Note that 519 * these objects can appear anywhere in the namespace by virtue 520 * of the AML "Scope" operator. Thus, we need to track ownership 521 * by an ID, not simply a position within the hierarchy. 522 */ 523 Status = AcpiTbDeleteNamespaceByOwner (i); 524 if (ACPI_FAILURE (Status)) 525 { 526 break; 527 } 528 529 Status = AcpiTbReleaseOwnerId (i); 530 AcpiTbSetTableLoadedFlag (i, FALSE); 531 break; 532 } 533 534 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 535 return_ACPI_STATUS (Status); 536} 537 538ACPI_EXPORT_SYMBOL (AcpiUnloadParentTable) 539