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