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