Home | History | Annotate | Line # | Download | only in tables
tbinstal.c revision 1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: tbinstal - ACPI table installation and removal
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2014, 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 #define __TBINSTAL_C__
     45 
     46 #include "acpi.h"
     47 #include "accommon.h"
     48 #include "actables.h"
     49 
     50 #define _COMPONENT          ACPI_TABLES
     51         ACPI_MODULE_NAME    ("tbinstal")
     52 
     53 /* Local prototypes */
     54 
     55 static BOOLEAN
     56 AcpiTbCompareTables (
     57     ACPI_TABLE_DESC         *TableDesc,
     58     UINT32                  TableIndex);
     59 
     60 
     61 /*******************************************************************************
     62  *
     63  * FUNCTION:    AcpiTbCompareTables
     64  *
     65  * PARAMETERS:  TableDesc           - Table 1 descriptor to be compared
     66  *              TableIndex          - Index of table 2 to be compared
     67  *
     68  * RETURN:      TRUE if both tables are identical.
     69  *
     70  * DESCRIPTION: This function compares a table with another table that has
     71  *              already been installed in the root table list.
     72  *
     73  ******************************************************************************/
     74 
     75 static BOOLEAN
     76 AcpiTbCompareTables (
     77     ACPI_TABLE_DESC         *TableDesc,
     78     UINT32                  TableIndex)
     79 {
     80     ACPI_STATUS             Status = AE_OK;
     81     BOOLEAN                 IsIdentical;
     82     ACPI_TABLE_HEADER       *Table;
     83     UINT32                  TableLength;
     84     UINT8                   TableFlags;
     85 
     86 
     87     Status = AcpiTbAcquireTable (&AcpiGbl_RootTableList.Tables[TableIndex],
     88                 &Table, &TableLength, &TableFlags);
     89     if (ACPI_FAILURE (Status))
     90     {
     91         return (FALSE);
     92     }
     93 
     94     /*
     95      * Check for a table match on the entire table length,
     96      * not just the header.
     97      */
     98     IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength ||
     99         ACPI_MEMCMP (TableDesc->Pointer, Table, TableLength)) ?
    100         FALSE : TRUE);
    101 
    102     /* Release the acquired table */
    103 
    104     AcpiTbReleaseTable (Table, TableLength, TableFlags);
    105     return (IsIdentical);
    106 }
    107 
    108 
    109 /*******************************************************************************
    110  *
    111  * FUNCTION:    AcpiTbInstallTableWithOverride
    112  *
    113  * PARAMETERS:  TableIndex              - Index into root table array
    114  *              NewTableDesc            - New table descriptor to install
    115  *              Override                - Whether override should be performed
    116  *
    117  * RETURN:      None
    118  *
    119  * DESCRIPTION: Install an ACPI table into the global data structure. The
    120  *              table override mechanism is called to allow the host
    121  *              OS to replace any table before it is installed in the root
    122  *              table array.
    123  *
    124  ******************************************************************************/
    125 
    126 void
    127 AcpiTbInstallTableWithOverride (
    128     UINT32                  TableIndex,
    129     ACPI_TABLE_DESC         *NewTableDesc,
    130     BOOLEAN                 Override)
    131 {
    132 
    133     if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
    134     {
    135         return;
    136     }
    137 
    138     /*
    139      * ACPI Table Override:
    140      *
    141      * Before we install the table, let the host OS override it with a new
    142      * one if desired. Any table within the RSDT/XSDT can be replaced,
    143      * including the DSDT which is pointed to by the FADT.
    144      */
    145     if (Override)
    146     {
    147         AcpiTbOverrideTable (NewTableDesc);
    148     }
    149 
    150     AcpiTbInitTableDescriptor (&AcpiGbl_RootTableList.Tables[TableIndex],
    151         NewTableDesc->Address, NewTableDesc->Flags, NewTableDesc->Pointer);
    152 
    153     AcpiTbPrintTableHeader (NewTableDesc->Address, NewTableDesc->Pointer);
    154 
    155     /* Set the global integer width (based upon revision of the DSDT) */
    156 
    157     if (TableIndex == ACPI_TABLE_INDEX_DSDT)
    158     {
    159         AcpiUtSetIntegerWidth (NewTableDesc->Pointer->Revision);
    160     }
    161 }
    162 
    163 
    164 /*******************************************************************************
    165  *
    166  * FUNCTION:    AcpiTbInstallFixedTable
    167  *
    168  * PARAMETERS:  Address                 - Physical address of DSDT or FACS
    169  *              Signature               - Table signature, NULL if no need to
    170  *                                        match
    171  *              TableIndex              - Index into root table array
    172  *
    173  * RETURN:      Status
    174  *
    175  * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data
    176  *              structure.
    177  *
    178  ******************************************************************************/
    179 
    180 ACPI_STATUS
    181 AcpiTbInstallFixedTable (
    182     ACPI_PHYSICAL_ADDRESS   Address,
    183     const char              *Signature,
    184     UINT32                  TableIndex)
    185 {
    186     ACPI_TABLE_DESC         NewTableDesc;
    187     ACPI_STATUS             Status;
    188 
    189 
    190     ACPI_FUNCTION_TRACE (TbInstallFixedTable);
    191 
    192 
    193     if (!Address)
    194     {
    195         ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]",
    196             Signature));
    197         return (AE_NO_MEMORY);
    198     }
    199 
    200     /* Fill a table descriptor for validation */
    201 
    202     Status = AcpiTbAcquireTempTable (&NewTableDesc, Address,
    203                 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
    204     if (ACPI_FAILURE (Status))
    205     {
    206         ACPI_ERROR ((AE_INFO, "Could not acquire table length at %p",
    207             ACPI_CAST_PTR (void, Address)));
    208         return_ACPI_STATUS (Status);
    209     }
    210 
    211     /* Validate and verify a table before installation */
    212 
    213     Status = AcpiTbVerifyTempTable (&NewTableDesc, Signature);
    214     if (ACPI_FAILURE (Status))
    215     {
    216         goto ReleaseAndExit;
    217     }
    218 
    219     AcpiTbInstallTableWithOverride (TableIndex, &NewTableDesc, TRUE);
    220 
    221 ReleaseAndExit:
    222 
    223     /* Release the temporary table descriptor */
    224 
    225     AcpiTbReleaseTempTable (&NewTableDesc);
    226     return_ACPI_STATUS (Status);
    227 }
    228 
    229 
    230 /*******************************************************************************
    231  *
    232  * FUNCTION:    AcpiTbInstallStandardTable
    233  *
    234  * PARAMETERS:  Address             - Address of the table (might be a virtual
    235  *                                    address depending on the TableFlags)
    236  *              Flags               - Flags for the table
    237  *              Reload              - Whether reload should be performed
    238  *              Override            - Whether override should be performed
    239  *              TableIndex          - Where the table index is returned
    240  *
    241  * RETURN:      Status
    242  *
    243  * DESCRIPTION: This function is called to install an ACPI table that is
    244  *              neither DSDT nor FACS (a "standard" table.)
    245  *              When this function is called by "Load" or "LoadTable" opcodes,
    246  *              or by AcpiLoadTable() API, the "Reload" parameter is set.
    247  *              After sucessfully returning from this function, table is
    248  *              "INSTALLED" but not "VALIDATED".
    249  *
    250  ******************************************************************************/
    251 
    252 ACPI_STATUS
    253 AcpiTbInstallStandardTable (
    254     ACPI_PHYSICAL_ADDRESS   Address,
    255     UINT8                   Flags,
    256     BOOLEAN                 Reload,
    257     BOOLEAN                 Override,
    258     UINT32                  *TableIndex)
    259 {
    260     UINT32                  i;
    261     ACPI_STATUS             Status = AE_OK;
    262     ACPI_TABLE_DESC         NewTableDesc;
    263 
    264 
    265     ACPI_FUNCTION_TRACE (TbInstallStandardTable);
    266 
    267 
    268     /* Acquire a temporary table descriptor for validation */
    269 
    270     Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags);
    271     if (ACPI_FAILURE (Status))
    272     {
    273         ACPI_ERROR ((AE_INFO, "Could not acquire table length at %p",
    274             ACPI_CAST_PTR (void, Address)));
    275         return_ACPI_STATUS (Status);
    276     }
    277 
    278     /*
    279      * Optionally do not load any SSDTs from the RSDT/XSDT. This can
    280      * be useful for debugging ACPI problems on some machines.
    281      */
    282     if (!Reload &&
    283         AcpiGbl_DisableSsdtTableInstall &&
    284         ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT))
    285     {
    286         ACPI_INFO ((AE_INFO, "Ignoring installation of %4.4s at %p",
    287             NewTableDesc.Signature.Ascii, ACPI_CAST_PTR (void, Address)));
    288         goto ReleaseAndExit;
    289     }
    290 
    291     /* Validate and verify a table before installation */
    292 
    293     Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL);
    294     if (ACPI_FAILURE (Status))
    295     {
    296         goto ReleaseAndExit;
    297     }
    298 
    299     if (Reload)
    300     {
    301         /*
    302          * Validate the incoming table signature.
    303          *
    304          * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
    305          * 2) We added support for OEMx tables, signature "OEM".
    306          * 3) Valid tables were encountered with a null signature, so we just
    307          *    gave up on validating the signature, (05/2008).
    308          * 4) We encountered non-AML tables such as the MADT, which caused
    309          *    interpreter errors and kernel faults. So now, we once again allow
    310          *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
    311          */
    312         if ((NewTableDesc.Signature.Ascii[0] != 0x00) &&
    313            (!ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) &&
    314            (ACPI_STRNCMP (NewTableDesc.Signature.Ascii, "OEM", 3)))
    315         {
    316             ACPI_BIOS_ERROR ((AE_INFO,
    317                 "Table has invalid signature [%4.4s] (0x%8.8X), "
    318                 "must be SSDT or OEMx",
    319                 AcpiUtValidAcpiName (NewTableDesc.Signature.Ascii) ?
    320                     NewTableDesc.Signature.Ascii : "????",
    321                 NewTableDesc.Signature.Integer));
    322 
    323             Status = AE_BAD_SIGNATURE;
    324             goto ReleaseAndExit;
    325         }
    326 
    327         /* Check if table is already registered */
    328 
    329         for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
    330         {
    331             /*
    332              * Check for a table match on the entire table length,
    333              * not just the header.
    334              */
    335             if (!AcpiTbCompareTables (&NewTableDesc, i))
    336             {
    337                 continue;
    338             }
    339 
    340             /*
    341              * Note: the current mechanism does not unregister a table if it is
    342              * dynamically unloaded. The related namespace entries are deleted,
    343              * but the table remains in the root table list.
    344              *
    345              * The assumption here is that the number of different tables that
    346              * will be loaded is actually small, and there is minimal overhead
    347              * in just keeping the table in case it is needed again.
    348              *
    349              * If this assumption changes in the future (perhaps on large
    350              * machines with many table load/unload operations), tables will
    351              * need to be unregistered when they are unloaded, and slots in the
    352              * root table list should be reused when empty.
    353              */
    354             if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
    355             {
    356                 /* Table is still loaded, this is an error */
    357 
    358                 Status = AE_ALREADY_EXISTS;
    359                 goto ReleaseAndExit;
    360             }
    361             else
    362             {
    363                 /*
    364                  * Table was unloaded, allow it to be reloaded.
    365                  * As we are going to return AE_OK to the caller, we should
    366                  * take the responsibility of freeing the input descriptor.
    367                  * Refill the input descriptor to ensure
    368                  * AcpiTbInstallTableWithOverride() can be called again to
    369                  * indicate the re-installation.
    370                  */
    371                 AcpiTbUninstallTable (&NewTableDesc);
    372                 *TableIndex = i;
    373                (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    374                 return_ACPI_STATUS (AE_OK);
    375             }
    376         }
    377     }
    378 
    379     /* Add the table to the global root table list */
    380 
    381     Status = AcpiTbGetNextRootIndex (&i);
    382     if (ACPI_FAILURE (Status))
    383     {
    384         goto ReleaseAndExit;
    385     }
    386 
    387     *TableIndex = i;
    388     AcpiTbInstallTableWithOverride (i, &NewTableDesc, Override);
    389 
    390 ReleaseAndExit:
    391 
    392     /* Release the temporary table descriptor */
    393 
    394     AcpiTbReleaseTempTable (&NewTableDesc);
    395     return_ACPI_STATUS (Status);
    396 }
    397 
    398 
    399 /*******************************************************************************
    400  *
    401  * FUNCTION:    AcpiTbOverrideTable
    402  *
    403  * PARAMETERS:  OldTableDesc        - Validated table descriptor to be
    404  *                                    overridden
    405  *
    406  * RETURN:      None
    407  *
    408  * DESCRIPTION: Attempt table override by calling the OSL override functions.
    409  *              Note: If the table is overridden, then the entire new table
    410  *              is acquired and returned by this function.
    411  *              Before/after invocation, the table descriptor is in a state
    412  *              that is "VALIDATED".
    413  *
    414  ******************************************************************************/
    415 
    416 void
    417 AcpiTbOverrideTable (
    418     ACPI_TABLE_DESC         *OldTableDesc)
    419 {
    420     ACPI_STATUS             Status;
    421     const char              *OverrideType;
    422     ACPI_TABLE_DESC         NewTableDesc;
    423     ACPI_TABLE_HEADER       *Table;
    424     ACPI_PHYSICAL_ADDRESS   Address;
    425     UINT32                  Length;
    426 
    427 
    428     /* (1) Attempt logical override (returns a logical address) */
    429 
    430     Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table);
    431     if (ACPI_SUCCESS (Status) && Table)
    432     {
    433         AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table),
    434             ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
    435         OverrideType = "Logical";
    436         goto FinishOverride;
    437     }
    438 
    439     /* (2) Attempt physical override (returns a physical address) */
    440 
    441     Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer,
    442         &Address, &Length);
    443     if (ACPI_SUCCESS (Status) && Address && Length)
    444     {
    445         AcpiTbAcquireTempTable (&NewTableDesc, Address,
    446             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
    447         OverrideType = "Physical";
    448         goto FinishOverride;
    449     }
    450 
    451     return; /* There was no override */
    452 
    453 
    454 FinishOverride:
    455 
    456     /* Validate and verify a table before overriding */
    457 
    458     Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL);
    459     if (ACPI_FAILURE (Status))
    460     {
    461         return;
    462     }
    463 
    464     ACPI_INFO ((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
    465         " %s table override, new table: " ACPI_PRINTF_UINT,
    466         OldTableDesc->Signature.Ascii,
    467         ACPI_FORMAT_TO_UINT (OldTableDesc->Address),
    468         OverrideType, ACPI_FORMAT_TO_UINT (NewTableDesc.Address)));
    469 
    470     /* We can now uninstall the original table */
    471 
    472     AcpiTbUninstallTable (OldTableDesc);
    473 
    474     /*
    475      * Replace the original table descriptor and keep its state as
    476      * "VALIDATED".
    477      */
    478     AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address,
    479         NewTableDesc.Flags, NewTableDesc.Pointer);
    480     AcpiTbValidateTempTable (OldTableDesc);
    481 
    482     /* Release the temporary table descriptor */
    483 
    484     AcpiTbReleaseTempTable (&NewTableDesc);
    485 }
    486 
    487 
    488 /*******************************************************************************
    489  *
    490  * FUNCTION:    AcpiTbStoreTable
    491  *
    492  * PARAMETERS:  Address             - Table address
    493  *              Table               - Table header
    494  *              Length              - Table length
    495  *              Flags               - Install flags
    496  *              TableIndex          - Where the table index is returned
    497  *
    498  * RETURN:      Status and table index.
    499  *
    500  * DESCRIPTION: Add an ACPI table to the global table list
    501  *
    502  ******************************************************************************/
    503 
    504 ACPI_STATUS
    505 AcpiTbStoreTable (
    506     ACPI_PHYSICAL_ADDRESS   Address,
    507     ACPI_TABLE_HEADER       *Table,
    508     UINT32                  Length,
    509     UINT8                   Flags,
    510     UINT32                  *TableIndex)
    511 {
    512     ACPI_STATUS             Status;
    513     ACPI_TABLE_DESC         *TableDesc;
    514 
    515 
    516     Status = AcpiTbGetNextRootIndex (TableIndex);
    517     if (ACPI_FAILURE (Status))
    518     {
    519         return (Status);
    520     }
    521 
    522     /* Initialize added table */
    523 
    524     TableDesc = &AcpiGbl_RootTableList.Tables[*TableIndex];
    525     AcpiTbInitTableDescriptor (TableDesc, Address, Flags, Table);
    526     TableDesc->Pointer = Table;
    527     return (AE_OK);
    528 }
    529 
    530 
    531 /*******************************************************************************
    532  *
    533  * FUNCTION:    AcpiTbUninstallTable
    534  *
    535  * PARAMETERS:  TableDesc           - Table descriptor
    536  *
    537  * RETURN:      None
    538  *
    539  * DESCRIPTION: Delete one internal ACPI table
    540  *
    541  ******************************************************************************/
    542 
    543 void
    544 AcpiTbUninstallTable (
    545     ACPI_TABLE_DESC         *TableDesc)
    546 {
    547 
    548     ACPI_FUNCTION_TRACE (TbUninstallTable);
    549 
    550 
    551     /* Table must be installed */
    552 
    553     if (!TableDesc->Address)
    554     {
    555         return_VOID;
    556     }
    557 
    558     AcpiTbInvalidateTable (TableDesc);
    559 
    560     if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
    561         ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL)
    562     {
    563         ACPI_FREE (ACPI_CAST_PTR (void, TableDesc->Address));
    564     }
    565 
    566     TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL);
    567     return_VOID;
    568 }
    569