Home | History | Annotate | Line # | Download | only in tables
tbinstal.c revision 1.12
      1 /******************************************************************************
      2  *
      3  * Module Name: tbinstal - ACPI table installation and removal
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2018, 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 "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  *              Reload              - Whether reload should be performed
    123  *              Override            - Whether override should be performed
    124  *              TableIndex          - Where the table index is returned
    125  *
    126  * RETURN:      Status
    127  *
    128  * DESCRIPTION: This function is called to verify and install an ACPI table.
    129  *              When this function is called by "Load" or "LoadTable" opcodes,
    130  *              or by AcpiLoadTable() API, the "Reload" parameter is set.
    131  *              After sucessfully returning from this function, table is
    132  *              "INSTALLED" but not "VALIDATED".
    133  *
    134  ******************************************************************************/
    135 
    136 ACPI_STATUS
    137 AcpiTbInstallStandardTable (
    138     ACPI_PHYSICAL_ADDRESS   Address,
    139     UINT8                   Flags,
    140     BOOLEAN                 Reload,
    141     BOOLEAN                 Override,
    142     UINT32                  *TableIndex)
    143 {
    144     UINT32                  i;
    145     ACPI_STATUS             Status = AE_OK;
    146     ACPI_TABLE_DESC         NewTableDesc;
    147 
    148 
    149     ACPI_FUNCTION_TRACE (TbInstallStandardTable);
    150 
    151 
    152     /* Acquire a temporary table descriptor for validation */
    153 
    154     Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags);
    155     if (ACPI_FAILURE (Status))
    156     {
    157         ACPI_ERROR ((AE_INFO,
    158             "Could not acquire table length at %8.8X%8.8X",
    159             ACPI_FORMAT_UINT64 (Address)));
    160         return_ACPI_STATUS (Status);
    161     }
    162 
    163     /*
    164      * Optionally do not load any SSDTs from the RSDT/XSDT. This can
    165      * be useful for debugging ACPI problems on some machines.
    166      */
    167     if (!Reload &&
    168         AcpiGbl_DisableSsdtTableInstall &&
    169         ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT))
    170     {
    171         ACPI_INFO ((
    172             "Ignoring installation of %4.4s at %8.8X%8.8X",
    173             NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address)));
    174         goto ReleaseAndExit;
    175     }
    176 
    177     /* Acquire the table lock */
    178 
    179     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
    180 
    181     /* Validate and verify a table before installation */
    182 
    183     Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, &i);
    184     if (ACPI_FAILURE (Status))
    185     {
    186         if (Status == AE_CTRL_TERMINATE)
    187         {
    188             /*
    189              * Table was unloaded, allow it to be reloaded.
    190              * As we are going to return AE_OK to the caller, we should
    191              * take the responsibility of freeing the input descriptor.
    192              * Refill the input descriptor to ensure
    193              * AcpiTbInstallTableWithOverride() can be called again to
    194              * indicate the re-installation.
    195              */
    196             AcpiTbUninstallTable (&NewTableDesc);
    197             (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    198             *TableIndex = i;
    199             return_ACPI_STATUS (AE_OK);
    200         }
    201         goto UnlockAndExit;
    202     }
    203 
    204     /* Add the table to the global root table list */
    205 
    206     AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex);
    207 
    208     /* Invoke table handler */
    209 
    210     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    211     AcpiTbNotifyTable (ACPI_TABLE_EVENT_INSTALL, NewTableDesc.Pointer);
    212     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
    213 
    214 UnlockAndExit:
    215 
    216     /* Release the table lock */
    217 
    218     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
    219 
    220 ReleaseAndExit:
    221 
    222     /* Release the temporary table descriptor */
    223 
    224     AcpiTbReleaseTempTable (&NewTableDesc);
    225     return_ACPI_STATUS (Status);
    226 }
    227 
    228 
    229 /*******************************************************************************
    230  *
    231  * FUNCTION:    AcpiTbOverrideTable
    232  *
    233  * PARAMETERS:  OldTableDesc        - Validated table descriptor to be
    234  *                                    overridden
    235  *
    236  * RETURN:      None
    237  *
    238  * DESCRIPTION: Attempt table override by calling the OSL override functions.
    239  *              Note: If the table is overridden, then the entire new table
    240  *              is acquired and returned by this function.
    241  *              Before/after invocation, the table descriptor is in a state
    242  *              that is "VALIDATED".
    243  *
    244  ******************************************************************************/
    245 
    246 void
    247 AcpiTbOverrideTable (
    248     ACPI_TABLE_DESC         *OldTableDesc)
    249 {
    250     ACPI_STATUS             Status;
    251     ACPI_TABLE_DESC         NewTableDesc;
    252     ACPI_TABLE_HEADER       *Table;
    253     ACPI_PHYSICAL_ADDRESS   Address;
    254     UINT32                  Length;
    255     ACPI_ERROR_ONLY (const char   *OverrideType);
    256 
    257 
    258     /* (1) Attempt logical override (returns a logical address) */
    259 
    260     Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table);
    261     if (ACPI_SUCCESS (Status) && Table)
    262     {
    263         AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table),
    264             ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
    265         ACPI_ERROR_ONLY (OverrideType = "Logical");
    266         goto FinishOverride;
    267     }
    268 
    269     /* (2) Attempt physical override (returns a physical address) */
    270 
    271     Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer,
    272         &Address, &Length);
    273     if (ACPI_SUCCESS (Status) && Address && Length)
    274     {
    275         AcpiTbAcquireTempTable (&NewTableDesc, Address,
    276             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
    277         ACPI_ERROR_ONLY (OverrideType = "Physical");
    278         goto FinishOverride;
    279     }
    280 
    281     return; /* There was no override */
    282 
    283 
    284 FinishOverride:
    285 
    286     /*
    287      * Validate and verify a table before overriding, no nested table
    288      * duplication check as it's too complicated and unnecessary.
    289      */
    290     Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, NULL);
    291     if (ACPI_FAILURE (Status))
    292     {
    293         return;
    294     }
    295 
    296     ACPI_INFO (("%4.4s 0x%8.8X%8.8X"
    297         " %s table override, new table: 0x%8.8X%8.8X",
    298         OldTableDesc->Signature.Ascii,
    299         ACPI_FORMAT_UINT64 (OldTableDesc->Address),
    300         OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address)));
    301 
    302     /* We can now uninstall the original table */
    303 
    304     AcpiTbUninstallTable (OldTableDesc);
    305 
    306     /*
    307      * Replace the original table descriptor and keep its state as
    308      * "VALIDATED".
    309      */
    310     AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address,
    311         NewTableDesc.Flags, NewTableDesc.Pointer);
    312     AcpiTbValidateTempTable (OldTableDesc);
    313 
    314     /* Release the temporary table descriptor */
    315 
    316     AcpiTbReleaseTempTable (&NewTableDesc);
    317 }
    318 
    319 
    320 /*******************************************************************************
    321  *
    322  * FUNCTION:    AcpiTbUninstallTable
    323  *
    324  * PARAMETERS:  TableDesc           - Table descriptor
    325  *
    326  * RETURN:      None
    327  *
    328  * DESCRIPTION: Delete one internal ACPI table
    329  *
    330  ******************************************************************************/
    331 
    332 void
    333 AcpiTbUninstallTable (
    334     ACPI_TABLE_DESC         *TableDesc)
    335 {
    336 
    337     ACPI_FUNCTION_TRACE (TbUninstallTable);
    338 
    339 
    340     /* Table must be installed */
    341 
    342     if (!TableDesc->Address)
    343     {
    344         return_VOID;
    345     }
    346 
    347     AcpiTbInvalidateTable (TableDesc);
    348 
    349     if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
    350         ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL)
    351     {
    352 	void *ptr = ACPI_PHYSADDR_TO_PTR (TableDesc->Address);
    353 	if (ptr)
    354 	{
    355 		ACPI_FREE (ptr);
    356 	}
    357     }
    358 
    359     TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL);
    360     return_VOID;
    361 }
    362