Home | History | Annotate | Line # | Download | only in tables
tbinstal.c revision 1.17
      1 /******************************************************************************
      2  *
      3  * Module Name: tbinstal - ACPI table installation and removal
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2021, 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 "actables.h"
     47 
     48 #define _COMPONENT          ACPI_TABLES
     49         ACPI_MODULE_NAME    ("tbinstal")
     50 
     51 
     52 /*******************************************************************************
     53  *
     54  * FUNCTION:    AcpiTbInstallTableWithOverride
     55  *
     56  * PARAMETERS:  NewTableDesc            - New table descriptor to install
     57  *              Override                - Whether override should be performed
     58  *              TableIndex              - Where the table index is returned
     59  *
     60  * RETURN:      None
     61  *
     62  * DESCRIPTION: Install an ACPI table into the global data structure. The
     63  *              table override mechanism is called to allow the host
     64  *              OS to replace any table before it is installed in the root
     65  *              table array.
     66  *
     67  ******************************************************************************/
     68 
     69 void
     70 AcpiTbInstallTableWithOverride (
     71     ACPI_TABLE_DESC         *NewTableDesc,
     72     BOOLEAN                 Override,
     73     UINT32                  *TableIndex)
     74 {
     75     UINT32                  i;
     76     ACPI_STATUS             Status;
     77 
     78 
     79     Status = AcpiTbGetNextTableDescriptor (&i, NULL);
     80     if (ACPI_FAILURE (Status))
     81     {
     82         return;
     83     }
     84 
     85     /*
     86      * ACPI Table Override:
     87      *
     88      * Before we install the table, let the host OS override it with a new
     89      * one if desired. Any table within the RSDT/XSDT can be replaced,
     90      * including the DSDT which is pointed to by the FADT.
     91      */
     92     if (Override)
     93     {
     94         AcpiTbOverrideTable (NewTableDesc);
     95     }
     96 
     97     AcpiTbInitTableDescriptor (&AcpiGbl_RootTableList.Tables[i],
     98         NewTableDesc->Address, NewTableDesc->Flags, NewTableDesc->Pointer);
     99 
    100     AcpiTbPrintTableHeader (NewTableDesc->Address, NewTableDesc->Pointer);
    101 
    102     /* This synchronizes AcpiGbl_DsdtIndex */
    103 
    104     *TableIndex = i;
    105 
    106     /* Set the global integer width (based upon revision of the DSDT) */
    107 
    108     if (i == AcpiGbl_DsdtIndex)
    109     {
    110         AcpiUtSetIntegerWidth (NewTableDesc->Pointer->Revision);
    111     }
    112 }
    113 
    114 
    115 /*******************************************************************************
    116  *
    117  * FUNCTION:    AcpiTbInstallStandardTable
    118  *
    119  * PARAMETERS:  Address             - Address of the table (might be a virtual
    120  *                                    address depending on the TableFlags)
    121  *              Flags               - Flags for the table
    122  *              Table               - Pointer to the table (required for virtual
    123  *                                    origins, optional for physical)
    124  *              Reload              - Whether reload should be performed
    125  *              Override            - Whether override should be performed
    126  *              TableIndex          - Where the table index is returned
    127  *
    128  * RETURN:      Status
    129  *
    130  * DESCRIPTION: This function is called to verify and install an ACPI table.
    131  *              When this function is called by "Load" or "LoadTable" opcodes,
    132  *              or by AcpiLoadTable() API, the "Reload" parameter is set.
    133  *              After successfully returning from this function, table is
    134  *              "INSTALLED" but not "VALIDATED".
    135  *
    136  ******************************************************************************/
    137 
    138 ACPI_STATUS
    139 AcpiTbInstallStandardTable (
    140     ACPI_PHYSICAL_ADDRESS   Address,
    141     UINT8                   Flags,
    142     ACPI_TABLE_HEADER       *Table,
    143     BOOLEAN                 Reload,
    144     BOOLEAN                 Override,
    145     UINT32                  *TableIndex)
    146 {
    147     UINT32                  i;
    148     ACPI_STATUS             Status = AE_OK;
    149     ACPI_TABLE_DESC         NewTableDesc;
    150 
    151 
    152     ACPI_FUNCTION_TRACE (TbInstallStandardTable);
    153 
    154 
    155     /* Acquire a temporary table descriptor for validation */
    156 
    157     Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags, Table);
    158     if (ACPI_FAILURE (Status))
    159     {
    160         ACPI_ERROR ((AE_INFO,
    161             "Could not acquire table length at %8.8X%8.8X",
    162             ACPI_FORMAT_UINT64 (Address)));
    163         return_ACPI_STATUS (Status);
    164     }
    165 
    166     /*
    167      * Optionally do not load any SSDTs from the RSDT/XSDT. This can
    168      * be useful for debugging ACPI problems on some machines.
    169      */
    170     if (!Reload &&
    171         AcpiGbl_DisableSsdtTableInstall &&
    172         ACPI_COMPARE_NAMESEG (&NewTableDesc.Signature, ACPI_SIG_SSDT))
    173     {
    174         ACPI_INFO ((
    175             "Ignoring installation of %4.4s at %8.8X%8.8X",
    176             NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address)));
    177         goto ReleaseAndExit;
    178     }
    179 
    180     /* Acquire the table lock */
    181 
    182     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
    183 
    184     /* Validate and verify a table before installation */
    185 
    186     Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, &i);
    187     if (ACPI_FAILURE (Status))
    188     {
    189         if (Status == AE_CTRL_TERMINATE)
    190         {
    191             /*
    192              * Table was unloaded, allow it to be reloaded.
    193              * As we are going to return AE_OK to the caller, we should
    194              * take the responsibility of freeing the input descriptor.
    195              * Refill the input descriptor to ensure
    196              * AcpiTbInstallTableWithOverride() can be called again to
    197              * indicate the re-installation.
    198              */
    199             AcpiTbUninstallTable (&NewTableDesc);
    200             (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    201             *TableIndex = i;
    202             return_ACPI_STATUS (AE_OK);
    203         }
    204         goto UnlockAndExit;
    205     }
    206 
    207     /* Add the table to the global root table list */
    208 
    209     AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex);
    210 
    211     /* Invoke table handler */
    212 
    213     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    214     AcpiTbNotifyTable (ACPI_TABLE_EVENT_INSTALL, NewTableDesc.Pointer);
    215     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
    216 
    217 UnlockAndExit:
    218 
    219     /* Release the table lock */
    220 
    221     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    222 
    223 ReleaseAndExit:
    224 
    225     /* Release the temporary table descriptor */
    226 
    227     AcpiTbReleaseTempTable (&NewTableDesc);
    228     return_ACPI_STATUS (Status);
    229 }
    230 
    231 
    232 /*******************************************************************************
    233  *
    234  * FUNCTION:    AcpiTbOverrideTable
    235  *
    236  * PARAMETERS:  OldTableDesc        - Validated table descriptor to be
    237  *                                    overridden
    238  *
    239  * RETURN:      None
    240  *
    241  * DESCRIPTION: Attempt table override by calling the OSL override functions.
    242  *              Note: If the table is overridden, then the entire new table
    243  *              is acquired and returned by this function.
    244  *              Before/after invocation, the table descriptor is in a state
    245  *              that is "VALIDATED".
    246  *
    247  ******************************************************************************/
    248 
    249 void
    250 AcpiTbOverrideTable (
    251     ACPI_TABLE_DESC         *OldTableDesc)
    252 {
    253     ACPI_STATUS             Status;
    254     ACPI_TABLE_DESC         NewTableDesc;
    255     ACPI_TABLE_HEADER       *Table;
    256     ACPI_PHYSICAL_ADDRESS   Address;
    257     UINT32                  Length;
    258     ACPI_ERROR_ONLY (const char   *OverrideType);
    259 
    260 
    261     /* (1) Attempt logical override (returns a logical address) */
    262 
    263     Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table);
    264     if (ACPI_SUCCESS (Status) && Table)
    265     {
    266         AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table),
    267             ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, Table);
    268         ACPI_ERROR_ONLY (OverrideType = "Logical");
    269         goto FinishOverride;
    270     }
    271 
    272     /* (2) Attempt physical override (returns a physical address) */
    273 
    274     Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer,
    275         &Address, &Length);
    276     if (ACPI_SUCCESS (Status) && Address && Length)
    277     {
    278         AcpiTbAcquireTempTable (&NewTableDesc, Address,
    279             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL);
    280         ACPI_ERROR_ONLY (OverrideType = "Physical");
    281         goto FinishOverride;
    282     }
    283 
    284     return; /* There was no override */
    285 
    286 
    287 FinishOverride:
    288 
    289     /*
    290      * Validate and verify a table before overriding, no nested table
    291      * duplication check as it's too complicated and unnecessary.
    292      */
    293     Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, NULL);
    294     if (ACPI_FAILURE (Status))
    295     {
    296         return;
    297     }
    298 
    299     ACPI_INFO (("%4.4s 0x%8.8X%8.8X"
    300         " %s table override, new table: 0x%8.8X%8.8X",
    301         OldTableDesc->Signature.Ascii,
    302         ACPI_FORMAT_UINT64 (OldTableDesc->Address),
    303         OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address)));
    304 
    305     /* We can now uninstall the original table */
    306 
    307     AcpiTbUninstallTable (OldTableDesc);
    308 
    309     /*
    310      * Replace the original table descriptor and keep its state as
    311      * "VALIDATED".
    312      */
    313     AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address,
    314         NewTableDesc.Flags, NewTableDesc.Pointer);
    315     AcpiTbValidateTempTable (OldTableDesc);
    316 
    317     /* Release the temporary table descriptor */
    318 
    319     AcpiTbReleaseTempTable (&NewTableDesc);
    320 }
    321 
    322 
    323 /*******************************************************************************
    324  *
    325  * FUNCTION:    AcpiTbUninstallTable
    326  *
    327  * PARAMETERS:  TableDesc           - Table descriptor
    328  *
    329  * RETURN:      None
    330  *
    331  * DESCRIPTION: Delete one internal ACPI table
    332  *
    333  ******************************************************************************/
    334 
    335 void
    336 AcpiTbUninstallTable (
    337     ACPI_TABLE_DESC         *TableDesc)
    338 {
    339 
    340     ACPI_FUNCTION_TRACE (TbUninstallTable);
    341 
    342 
    343     /* Table must be installed */
    344 
    345     if (!TableDesc->Address)
    346     {
    347         return_VOID;
    348     }
    349 
    350     AcpiTbInvalidateTable (TableDesc);
    351 
    352     if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
    353         ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL)
    354     {
    355         ACPI_FREE (TableDesc->Pointer);
    356         TableDesc->Pointer = NULL;
    357     }
    358 
    359     TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL);
    360     return_VOID;
    361 }
    362