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