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