*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2014, Intel Corp.
* All rights reserved.
*
* 2. License
*
* 2.1. This is your license from Intel Corp. under its intellectual property
- * rights. You may have additional license terms from the party that provided
+ * rights. You may have additional license terms from the party that provided
* you this software, covering your right to use that party's intellectual
* property rights.
*
* offer to sell, and import the Covered Code and derivative works thereof
* solely to the minimum extent necessary to exercise the above copyright
* license, and in no event shall the patent license extend to any additions
- * to or modifications of the Original Intel Code. No other license or right
+ * to or modifications of the Original Intel Code. No other license or right
* is granted directly or by implication, estoppel or otherwise;
*
* The above copyright and patent license is granted only if the following
* Redistribution of source code of any substantial portion of the Covered
* Code or modification with rights to further distribute source must include
* the above Copyright Notice, the above License, this list of Conditions,
- * and the following Disclaimer and Export Compliance provision. In addition,
+ * and the following Disclaimer and Export Compliance provision. In addition,
* Licensee must cause all Covered Code to which Licensee contributes to
* contain a file documenting the changes Licensee made to create that Covered
- * Code and the date of any change. Licensee must include in that file the
- * documentation of any changes made by any predecessor Licensee. Licensee
+ * Code and the date of any change. Licensee must include in that file the
+ * documentation of any changes made by any predecessor Licensee. Licensee
* must include a prominent statement that the modification is derived,
* directly or indirectly, from Original Intel Code.
*
* Redistribution of source code of any substantial portion of the Covered
* Code or modification without rights to further distribute source must
* include the following Disclaimer and Export Compliance provision in the
- * documentation and/or other materials provided with distribution. In
+ * documentation and/or other materials provided with distribution. In
* addition, Licensee may not authorize further sublicense of source of any
* portion of the Covered Code, and must include terms to the effect that the
* license from Licensee to its licensee is limited to the intellectual
* 4. Disclaimer and Export Compliance
*
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
- * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
- * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
- * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
- * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
+ * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
+ * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
+ * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
+ * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
- * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
+ * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
* LIMITED REMEDY.
*
* 4.3. Licensee shall not export, either directly or indirectly, any of this
* software or system incorporating such software without first obtaining any
* required license or other approval from the U. S. Department of Commerce or
- * any other agency or department of the United States Government. In the
+ * any other agency or department of the United States Government. In the
* event Licensee exports any such software from the United States or
* re-exports any such software from a foreign destination, Licensee shall
* ensure that the distribution and export/re-export of the software is in
*
*****************************************************************************/
-
#define __TBINSTAL_C__
#include "acpi.h"
#include "accommon.h"
-#include "acnamesp.h"
#include "actables.h"
-
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME ("tbinstal")
+/* Local prototypes */
-/******************************************************************************
+static BOOLEAN
+AcpiTbCompareTables (
+ ACPI_TABLE_DESC *TableDesc,
+ UINT32 TableIndex);
+
+
+/*******************************************************************************
*
- * FUNCTION: AcpiTbVerifyTable
+ * FUNCTION: AcpiTbCompareTables
*
- * PARAMETERS: TableDesc - table
+ * PARAMETERS: TableDesc - Table 1 descriptor to be compared
+ * TableIndex - Index of table 2 to be compared
*
- * RETURN: Status
+ * RETURN: TRUE if both tables are identical.
*
- * DESCRIPTION: this function is called to verify and map table
+ * DESCRIPTION: This function compares a table with another table that has
+ * already been installed in the root table list.
*
- *****************************************************************************/
+ ******************************************************************************/
-ACPI_STATUS
-AcpiTbVerifyTable (
- ACPI_TABLE_DESC *TableDesc)
+static BOOLEAN
+AcpiTbCompareTables (
+ ACPI_TABLE_DESC *TableDesc,
+ UINT32 TableIndex)
{
ACPI_STATUS Status = AE_OK;
+ BOOLEAN IsIdentical;
+ ACPI_TABLE_HEADER *Table;
+ UINT32 TableLength;
+ UINT8 TableFlags;
- ACPI_FUNCTION_TRACE (TbVerifyTable);
-
-
- /* Map the table if necessary */
-
- if (!TableDesc->Pointer)
+ Status = AcpiTbAcquireTable (&AcpiGbl_RootTableList.Tables[TableIndex],
+ &Table, &TableLength, &TableFlags);
+ if (ACPI_FAILURE (Status))
{
- if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
- ACPI_TABLE_ORIGIN_MAPPED)
- {
- TableDesc->Pointer = AcpiOsMapMemory (
- TableDesc->Address, TableDesc->Length);
- }
-
- if (!TableDesc->Pointer)
- {
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
+ return (FALSE);
}
- /* FACS is the odd table, has no standard ACPI header and no checksum */
-
- if (!ACPI_COMPARE_NAME (&TableDesc->Signature, ACPI_SIG_FACS))
- {
- /* Always calculate checksum, ignore bad checksum if requested */
+ /*
+ * Check for a table match on the entire table length,
+ * not just the header.
+ */
+ IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength ||
+ ACPI_MEMCMP (TableDesc->Pointer, Table, TableLength)) ?
+ FALSE : TRUE);
- Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
- }
+ /* Release the acquired table */
- return_ACPI_STATUS (Status);
+ AcpiTbReleaseTable (Table, TableLength, TableFlags);
+ return (IsIdentical);
}
/*******************************************************************************
*
- * FUNCTION: AcpiTbAddTable
+ * FUNCTION: AcpiTbInstallTableWithOverride
*
- * PARAMETERS: TableDesc - Table descriptor
- * TableIndex - Where the table index is returned
+ * PARAMETERS: TableIndex - Index into root table array
+ * NewTableDesc - New table descriptor to install
+ * Override - Whether override should be performed
*
- * RETURN: Status
+ * RETURN: None
*
- * DESCRIPTION: This function is called to add an ACPI table. It is used to
- * dynamically load tables via the Load and LoadTable AML
- * operators.
+ * DESCRIPTION: Install an ACPI table into the global data structure. The
+ * table override mechanism is called to allow the host
+ * OS to replace any table before it is installed in the root
+ * table array.
*
******************************************************************************/
-ACPI_STATUS
-AcpiTbAddTable (
- ACPI_TABLE_DESC *TableDesc,
- UINT32 *TableIndex)
+void
+AcpiTbInstallTableWithOverride (
+ UINT32 TableIndex,
+ ACPI_TABLE_DESC *NewTableDesc,
+ BOOLEAN Override)
{
- UINT32 i;
- ACPI_STATUS Status = AE_OK;
- ACPI_TABLE_HEADER *OverrideTable = NULL;
-
-
- ACPI_FUNCTION_TRACE (TbAddTable);
-
- if (!TableDesc->Pointer)
+ if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
{
- Status = AcpiTbVerifyTable (TableDesc);
- if (ACPI_FAILURE (Status) || !TableDesc->Pointer)
- {
- return_ACPI_STATUS (Status);
- }
+ return;
}
/*
- * Validate the incoming table signature.
+ * ACPI Table Override:
*
- * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
- * 2) We added support for OEMx tables, signature "OEM".
- * 3) Valid tables were encountered with a null signature, so we just
- * gave up on validating the signature, (05/2008).
- * 4) We encountered non-AML tables such as the MADT, which caused
- * interpreter errors and kernel faults. So now, we once again allow
- * only "SSDT", "OEMx", and now, also a null signature. (05/2011).
+ * Before we install the table, let the host OS override it with a new
+ * one if desired. Any table within the RSDT/XSDT can be replaced,
+ * including the DSDT which is pointed to by the FADT.
*/
- if ((TableDesc->Pointer->Signature[0] != 0x00) &&
- (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
- (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
+ if (Override)
{
- ACPI_ERROR ((AE_INFO,
- "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
- AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ?
- TableDesc->Pointer->Signature : "????",
- *(UINT32 *) TableDesc->Pointer->Signature));
-
- return_ACPI_STATUS (AE_BAD_SIGNATURE);
- }
-
- (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
-
- /* Check if table is already registered */
-
- for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
- {
- if (!AcpiGbl_RootTableList.Tables[i].Pointer)
- {
- Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
- if (ACPI_FAILURE (Status) ||
- !AcpiGbl_RootTableList.Tables[i].Pointer)
- {
- continue;
- }
- }
-
- /*
- * Check for a table match on the entire table length,
- * not just the header.
- */
- if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length)
- {
- continue;
- }
-
- if (ACPI_MEMCMP (TableDesc->Pointer,
- AcpiGbl_RootTableList.Tables[i].Pointer,
- AcpiGbl_RootTableList.Tables[i].Length))
- {
- continue;
- }
-
- /*
- * Note: the current mechanism does not unregister a table if it is
- * dynamically unloaded. The related namespace entries are deleted,
- * but the table remains in the root table list.
- *
- * The assumption here is that the number of different tables that
- * will be loaded is actually small, and there is minimal overhead
- * in just keeping the table in case it is needed again.
- *
- * If this assumption changes in the future (perhaps on large
- * machines with many table load/unload operations), tables will
- * need to be unregistered when they are unloaded, and slots in the
- * root table list should be reused when empty.
- */
-
- /*
- * Table is already registered.
- * We can delete the table that was passed as a parameter.
- */
- AcpiTbDeleteTable (TableDesc);
- *TableIndex = i;
-
- if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
- {
- /* Table is still loaded, this is an error */
-
- Status = AE_ALREADY_EXISTS;
- goto Release;
- }
- else
- {
- /* Table was unloaded, allow it to be reloaded */
-
- TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer;
- TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address;
- Status = AE_OK;
- goto PrintHeader;
- }
+ AcpiTbOverrideTable (NewTableDesc);
}
- /*
- * ACPI Table Override:
- * Allow the host to override dynamically loaded tables.
- */
- Status = AcpiOsTableOverride (TableDesc->Pointer, &OverrideTable);
- if (ACPI_SUCCESS (Status) && OverrideTable)
- {
- ACPI_INFO ((AE_INFO,
- "%4.4s @ 0x%p Table override, replaced with:",
- TableDesc->Pointer->Signature,
- ACPI_CAST_PTR (void, TableDesc->Address)));
-
- /* We can delete the table that was passed as a parameter */
+ AcpiTbInitTableDescriptor (&AcpiGbl_RootTableList.Tables[TableIndex],
+ NewTableDesc->Address, NewTableDesc->Flags, NewTableDesc->Pointer);
- AcpiTbDeleteTable (TableDesc);
+ AcpiTbPrintTableHeader (NewTableDesc->Address, NewTableDesc->Pointer);
- /* Setup descriptor for the new table */
+ /* Set the global integer width (based upon revision of the DSDT) */
- TableDesc->Address = ACPI_PTR_TO_PHYSADDR (OverrideTable);
- TableDesc->Pointer = OverrideTable;
- TableDesc->Length = OverrideTable->Length;
- TableDesc->Flags = ACPI_TABLE_ORIGIN_OVERRIDE;
- }
-
- /* Add the table to the global root table list */
-
- Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
- TableDesc->Length, TableDesc->Flags, TableIndex);
- if (ACPI_FAILURE (Status))
+ if (TableIndex == ACPI_TABLE_INDEX_DSDT)
{
- goto Release;
+ AcpiUtSetIntegerWidth (NewTableDesc->Pointer->Revision);
}
-
-PrintHeader:
- AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
-
-Release:
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (Status);
}
/*******************************************************************************
*
- * FUNCTION: AcpiTbResizeRootTableList
+ * FUNCTION: AcpiTbInstallFixedTable
*
- * PARAMETERS: None
+ * PARAMETERS: Address - Physical address of DSDT or FACS
+ * Signature - Table signature, NULL if no need to
+ * match
+ * TableIndex - Index into root table array
*
* RETURN: Status
*
- * DESCRIPTION: Expand the size of global table array
+ * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data
+ * structure.
*
******************************************************************************/
ACPI_STATUS
-AcpiTbResizeRootTableList (
- void)
+AcpiTbInstallFixedTable (
+ ACPI_PHYSICAL_ADDRESS Address,
+ char *Signature,
+ UINT32 TableIndex)
{
- ACPI_TABLE_DESC *Tables;
-
+ ACPI_TABLE_DESC NewTableDesc;
+ ACPI_STATUS Status;
- ACPI_FUNCTION_TRACE (TbResizeRootTableList);
+ ACPI_FUNCTION_TRACE (TbInstallFixedTable);
- /* AllowResize flag is a parameter to AcpiInitializeTables */
- if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
+ if (!Address)
{
- ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
- return_ACPI_STATUS (AE_SUPPORT);
+ ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]",
+ Signature));
+ return (AE_NO_MEMORY);
}
- /* Increase the Table Array size */
+ /* Fill a table descriptor for validation */
- Tables = ACPI_ALLOCATE_ZEROED (
- ((ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount +
- ACPI_ROOT_TABLE_SIZE_INCREMENT) *
- sizeof (ACPI_TABLE_DESC));
- if (!Tables)
+ Status = AcpiTbAcquireTempTable (&NewTableDesc, Address,
+ ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
+ if (ACPI_FAILURE (Status))
{
- ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
- return_ACPI_STATUS (AE_NO_MEMORY);
+ ACPI_ERROR ((AE_INFO, "Could not acquire table length at %p",
+ ACPI_CAST_PTR (void, Address)));
+ return_ACPI_STATUS (Status);
}
- /* Copy and free the previous table array */
+ /* Validate and verify a table before installation */
- if (AcpiGbl_RootTableList.Tables)
+ Status = AcpiTbVerifyTable (&NewTableDesc, Signature);
+ if (ACPI_FAILURE (Status))
{
- ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
- (ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount * sizeof (ACPI_TABLE_DESC));
-
- if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
- {
- ACPI_FREE (AcpiGbl_RootTableList.Tables);
- }
+ goto ReleaseAndExit;
}
- AcpiGbl_RootTableList.Tables = Tables;
- AcpiGbl_RootTableList.MaxTableCount += ACPI_ROOT_TABLE_SIZE_INCREMENT;
- AcpiGbl_RootTableList.Flags |= (UINT8) ACPI_ROOT_ORIGIN_ALLOCATED;
+ AcpiTbInstallTableWithOverride (TableIndex, &NewTableDesc, TRUE);
+
+ReleaseAndExit:
+
+ /* Release the temporary table descriptor */
- return_ACPI_STATUS (AE_OK);
+ AcpiTbReleaseTempTable (&NewTableDesc);
+ return_ACPI_STATUS (Status);
}
/*******************************************************************************
*
- * FUNCTION: AcpiTbStoreTable
+ * FUNCTION: AcpiTbInstallStandardTable
*
- * PARAMETERS: Address - Table address
- * Table - Table header
- * Length - Table length
- * Flags - flags
+ * PARAMETERS: Address - Address of the table (might be a virtual
+ * address depending on the TableFlags)
+ * Flags - Flags for the table
+ * Reload - Whether reload should be performed
+ * Override - Whether override should be performed
+ * TableIndex - Where the table index is returned
*
- * RETURN: Status and table index.
+ * RETURN: Status
*
- * DESCRIPTION: Add an ACPI table to the global table list
+ * DESCRIPTION: This function is called to install an ACPI table that is
+ * neither DSDT nor FACS (a "standard" table.)
+ * When this function is called by "Load" or "LoadTable" opcodes,
+ * or by AcpiLoadTable() API, the "Reload" parameter is set.
+ * After sucessfully returning from this function, table is
+ * "INSTALLED" but not "VALIDATED".
*
******************************************************************************/
ACPI_STATUS
-AcpiTbStoreTable (
+AcpiTbInstallStandardTable (
ACPI_PHYSICAL_ADDRESS Address,
- ACPI_TABLE_HEADER *Table,
- UINT32 Length,
UINT8 Flags,
+ BOOLEAN Reload,
+ BOOLEAN Override,
UINT32 *TableIndex)
{
- ACPI_STATUS Status;
- ACPI_TABLE_DESC *NewTable;
+ UINT32 i;
+ ACPI_STATUS Status = AE_OK;
+ ACPI_TABLE_DESC NewTableDesc;
+
+ ACPI_FUNCTION_TRACE (TbInstallStandardTable);
- /* Ensure that there is room for the table in the Root Table List */
- if (AcpiGbl_RootTableList.CurrentTableCount >=
- AcpiGbl_RootTableList.MaxTableCount)
+ /* Acquire a temporary table descriptor for validation */
+
+ Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags);
+ if (ACPI_FAILURE (Status))
{
- Status = AcpiTbResizeRootTableList();
- if (ACPI_FAILURE (Status))
- {
- return (Status);
- }
+ ACPI_ERROR ((AE_INFO, "Could not acquire table length at %p",
+ ACPI_CAST_PTR (void, Address)));
+ return_ACPI_STATUS (Status);
}
- NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
+ /*
+ * Optionally do not load any SSDTs from the RSDT/XSDT. This can
+ * be useful for debugging ACPI problems on some machines.
+ */
+ if (!Reload &&
+ AcpiGbl_DisableSsdtTableInstall &&
+ ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT))
+ {
+ ACPI_INFO ((AE_INFO, "Ignoring installation of %4.4s at %p",
+ NewTableDesc.Signature.Ascii, ACPI_CAST_PTR (void, Address)));
+ goto ReleaseAndExit;
+ }
- /* Initialize added table */
+ /* Validate and verify a table before installation */
- NewTable->Address = Address;
- NewTable->Pointer = Table;
- NewTable->Length = Length;
- NewTable->OwnerId = 0;
- NewTable->Flags = Flags;
+ Status = AcpiTbVerifyTable (&NewTableDesc, NULL);
+ if (ACPI_FAILURE (Status))
+ {
+ goto ReleaseAndExit;
+ }
- ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
+ if (Reload)
+ {
+ /*
+ * Validate the incoming table signature.
+ *
+ * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
+ * 2) We added support for OEMx tables, signature "OEM".
+ * 3) Valid tables were encountered with a null signature, so we just
+ * gave up on validating the signature, (05/2008).
+ * 4) We encountered non-AML tables such as the MADT, which caused
+ * interpreter errors and kernel faults. So now, we once again allow
+ * only "SSDT", "OEMx", and now, also a null signature. (05/2011).
+ */
+ if ((NewTableDesc.Signature.Ascii[0] != 0x00) &&
+ (!ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) &&
+ (ACPI_STRNCMP (NewTableDesc.Signature.Ascii, "OEM", 3)))
+ {
+ ACPI_BIOS_ERROR ((AE_INFO,
+ "Table has invalid signature [%4.4s] (0x%8.8X), "
+ "must be SSDT or OEMx",
+ AcpiUtValidAcpiName (NewTableDesc.Signature.Ascii) ?
+ NewTableDesc.Signature.Ascii : "????",
+ NewTableDesc.Signature.Integer));
+
+ Status = AE_BAD_SIGNATURE;
+ goto ReleaseAndExit;
+ }
- *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
- AcpiGbl_RootTableList.CurrentTableCount++;
- return (AE_OK);
-}
+ /* Check if table is already registered */
+ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
+ {
+ /*
+ * Check for a table match on the entire table length,
+ * not just the header.
+ */
+ if (!AcpiTbCompareTables (&NewTableDesc, i))
+ {
+ continue;
+ }
-/*******************************************************************************
- *
- * FUNCTION: AcpiTbDeleteTable
- *
- * PARAMETERS: TableIndex - Table index
- *
- * RETURN: None
- *
- * DESCRIPTION: Delete one internal ACPI table
- *
- ******************************************************************************/
+ /*
+ * Note: the current mechanism does not unregister a table if it is
+ * dynamically unloaded. The related namespace entries are deleted,
+ * but the table remains in the root table list.
+ *
+ * The assumption here is that the number of different tables that
+ * will be loaded is actually small, and there is minimal overhead
+ * in just keeping the table in case it is needed again.
+ *
+ * If this assumption changes in the future (perhaps on large
+ * machines with many table load/unload operations), tables will
+ * need to be unregistered when they are unloaded, and slots in the
+ * root table list should be reused when empty.
+ */
+ if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
+ {
+ /* Table is still loaded, this is an error */
-void
-AcpiTbDeleteTable (
- ACPI_TABLE_DESC *TableDesc)
-{
+ Status = AE_ALREADY_EXISTS;
+ goto ReleaseAndExit;
+ }
+ else
+ {
+ /*
+ * Table was unloaded, allow it to be reloaded.
+ * As we are going to return AE_OK to the caller, we should
+ * take the responsibility of freeing the input descriptor.
+ * Refill the input descriptor to ensure
+ * AcpiTbInstallTableWithOverride() can be called again to
+ * indicate the re-installation.
+ */
+ AcpiTbUninstallTable (&NewTableDesc);
+ *TableIndex = i;
+ (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
+ return_ACPI_STATUS (AE_OK);
+ }
+ }
+ }
- /* Table must be mapped or allocated */
+ /* Add the table to the global root table list */
- if (!TableDesc->Pointer)
+ Status = AcpiTbGetNextRootIndex (&i);
+ if (ACPI_FAILURE (Status))
{
- return;
+ goto ReleaseAndExit;
}
- switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
- {
- case ACPI_TABLE_ORIGIN_MAPPED:
- AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
- break;
+ *TableIndex = i;
+ AcpiTbInstallTableWithOverride (i, &NewTableDesc, Override);
- case ACPI_TABLE_ORIGIN_ALLOCATED:
- ACPI_FREE (TableDesc->Pointer);
- break;
+ReleaseAndExit:
- default:
- break;
- }
+ /* Release the temporary table descriptor */
- TableDesc->Pointer = NULL;
+ AcpiTbReleaseTempTable (&NewTableDesc);
+ return_ACPI_STATUS (Status);
}
/*******************************************************************************
*
- * FUNCTION: AcpiTbTerminate
+ * FUNCTION: AcpiTbOverrideTable
*
- * PARAMETERS: None
+ * PARAMETERS: OldTableDesc - Validated table descriptor to be
+ * overridden
*
* RETURN: None
*
- * DESCRIPTION: Delete all internal ACPI tables
+ * DESCRIPTION: Attempt table override by calling the OSL override functions.
+ * Note: If the table is overridden, then the entire new table
+ * is acquired and returned by this function.
+ * Before/after invocation, the table descriptor is in a state
+ * that is "VALIDATED".
*
******************************************************************************/
void
-AcpiTbTerminate (
- void)
+AcpiTbOverrideTable (
+ ACPI_TABLE_DESC *OldTableDesc)
{
- UINT32 i;
-
-
- ACPI_FUNCTION_TRACE (TbTerminate);
-
+ ACPI_STATUS Status;
+ char *OverrideType;
+ ACPI_TABLE_DESC NewTableDesc;
+ ACPI_TABLE_HEADER *Table;
+ ACPI_PHYSICAL_ADDRESS Address;
+ UINT32 Length;
- (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- /* Delete the individual tables */
+ /* (1) Attempt logical override (returns a logical address) */
- for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
+ Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table);
+ if (ACPI_SUCCESS (Status) && Table)
{
- AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
+ AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table),
+ ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
+ OverrideType = "Logical";
+ goto FinishOverride;
}
- /*
- * Delete the root table array if allocated locally. Array cannot be
- * mapped, so we don't need to check for that flag.
- */
- if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
+ /* (2) Attempt physical override (returns a physical address) */
+
+ Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer,
+ &Address, &Length);
+ if (ACPI_SUCCESS (Status) && Address && Length)
{
- ACPI_FREE (AcpiGbl_RootTableList.Tables);
+ AcpiTbAcquireTempTable (&NewTableDesc, Address,
+ ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
+ OverrideType = "Physical";
+ goto FinishOverride;
}
- AcpiGbl_RootTableList.Tables = NULL;
- AcpiGbl_RootTableList.Flags = 0;
- AcpiGbl_RootTableList.CurrentTableCount = 0;
+ return; /* There was no override */
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
-}
+FinishOverride:
-/*******************************************************************************
- *
- * FUNCTION: AcpiTbDeleteNamespaceByOwner
- *
- * PARAMETERS: TableIndex - Table index
- *
- * RETURN: Status
- *
- * DESCRIPTION: Delete all namespace objects created when this table was loaded.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiTbDeleteNamespaceByOwner (
- UINT32 TableIndex)
-{
- ACPI_OWNER_ID OwnerId;
- ACPI_STATUS Status;
-
-
- ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
+ /* Validate and verify a table before overriding */
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
+ Status = AcpiTbVerifyTable (&NewTableDesc, NULL);
if (ACPI_FAILURE (Status))
{
- return_ACPI_STATUS (Status);
+ return;
}
- if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
- {
- /* The table index does not exist */
-
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (AE_NOT_EXIST);
- }
+ ACPI_INFO ((AE_INFO, "%4.4s " ACPI_PRINTF_UINT
+ " %s table override, new table: " ACPI_PRINTF_UINT,
+ OldTableDesc->Signature.Ascii,
+ ACPI_FORMAT_TO_UINT (OldTableDesc->Address),
+ OverrideType, ACPI_FORMAT_TO_UINT (NewTableDesc.Address)));
- /* Get the owner ID for this table, used to delete namespace nodes */
+ /* We can now uninstall the original table */
- OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
+ AcpiTbUninstallTable (OldTableDesc);
/*
- * Need to acquire the namespace writer lock to prevent interference
- * with any concurrent namespace walks. The interpreter must be
- * released during the deletion since the acquisition of the deletion
- * lock may block, and also since the execution of a namespace walk
- * must be allowed to use the interpreter.
+ * Replace the original table descriptor and keep its state as
+ * "VALIDATED".
*/
- (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
- Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
+ AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address,
+ NewTableDesc.Flags, NewTableDesc.Pointer);
+ AcpiTbValidateTable (OldTableDesc);
- AcpiNsDeleteNamespaceByOwner (OwnerId);
- if (ACPI_FAILURE (Status))
- {
- return_ACPI_STATUS (Status);
- }
+ /* Release the temporary table descriptor */
- AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
-
- Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
- return_ACPI_STATUS (Status);
+ AcpiTbReleaseTempTable (&NewTableDesc);
}
/*******************************************************************************
*
- * FUNCTION: AcpiTbAllocateOwnerId
+ * FUNCTION: AcpiTbStoreTable
*
- * PARAMETERS: TableIndex - Table index
+ * PARAMETERS: Address - Table address
+ * Table - Table header
+ * Length - Table length
+ * Flags - Install flags
+ * TableIndex - Where the table index is returned
*
- * RETURN: Status
+ * RETURN: Status and table index.
*
- * DESCRIPTION: Allocates OwnerId in TableDesc
+ * DESCRIPTION: Add an ACPI table to the global table list
*
******************************************************************************/
ACPI_STATUS
-AcpiTbAllocateOwnerId (
- UINT32 TableIndex)
+AcpiTbStoreTable (
+ ACPI_PHYSICAL_ADDRESS Address,
+ ACPI_TABLE_HEADER *Table,
+ UINT32 Length,
+ UINT8 Flags,
+ UINT32 *TableIndex)
{
- ACPI_STATUS Status = AE_BAD_PARAMETER;
-
-
- ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
+ ACPI_STATUS Status;
+ ACPI_TABLE_DESC *TableDesc;
- (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
+ Status = AcpiTbGetNextRootIndex (TableIndex);
+ if (ACPI_FAILURE (Status))
{
- Status = AcpiUtAllocateOwnerId
- (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
+ return (Status);
}
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (Status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiTbReleaseOwnerId
- *
- * PARAMETERS: TableIndex - Table index
- *
- * RETURN: Status
- *
- * DESCRIPTION: Releases OwnerId in TableDesc
- *
- ******************************************************************************/
-
-ACPI_STATUS
-AcpiTbReleaseOwnerId (
- UINT32 TableIndex)
-{
- ACPI_STATUS Status = AE_BAD_PARAMETER;
-
-
- ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
-
-
- (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
- {
- AcpiUtReleaseOwnerId (
- &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
- Status = AE_OK;
- }
+ /* Initialize added table */
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (Status);
+ TableDesc = &AcpiGbl_RootTableList.Tables[*TableIndex];
+ AcpiTbInitTableDescriptor (TableDesc, Address, Flags, Table);
+ TableDesc->Pointer = Table;
+ return (AE_OK);
}
/*******************************************************************************
*
- * FUNCTION: AcpiTbGetOwnerId
+ * FUNCTION: AcpiTbUninstallTable
*
- * PARAMETERS: TableIndex - Table index
- * OwnerId - Where the table OwnerId is returned
+ * PARAMETERS: TableDesc - Table descriptor
*
- * RETURN: Status
+ * RETURN: None
*
- * DESCRIPTION: returns OwnerId for the ACPI table
+ * DESCRIPTION: Delete one internal ACPI table
*
******************************************************************************/
-ACPI_STATUS
-AcpiTbGetOwnerId (
- UINT32 TableIndex,
- ACPI_OWNER_ID *OwnerId)
+void
+AcpiTbUninstallTable (
+ ACPI_TABLE_DESC *TableDesc)
{
- ACPI_STATUS Status = AE_BAD_PARAMETER;
-
- ACPI_FUNCTION_TRACE (TbGetOwnerId);
+ ACPI_FUNCTION_TRACE (TbUninstallTable);
- (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
- {
- *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
- Status = AE_OK;
- }
-
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
- return_ACPI_STATUS (Status);
-}
+ /* Table must be installed */
-
-/*******************************************************************************
- *
- * FUNCTION: AcpiTbIsTableLoaded
- *
- * PARAMETERS: TableIndex - Table index
- *
- * RETURN: Table Loaded Flag
- *
- ******************************************************************************/
-
-BOOLEAN
-AcpiTbIsTableLoaded (
- UINT32 TableIndex)
-{
- BOOLEAN IsLoaded = FALSE;
-
-
- (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
+ if (!TableDesc->Address)
{
- IsLoaded = (BOOLEAN)
- (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
- ACPI_TABLE_IS_LOADED);
+ return_VOID;
}
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
- return (IsLoaded);
-}
-
+ AcpiTbInvalidateTable (TableDesc);
-/*******************************************************************************
- *
- * FUNCTION: AcpiTbSetTableLoadedFlag
- *
- * PARAMETERS: TableIndex - Table index
- * IsLoaded - TRUE if table is loaded, FALSE otherwise
- *
- * RETURN: None
- *
- * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
- *
- ******************************************************************************/
-
-void
-AcpiTbSetTableLoadedFlag (
- UINT32 TableIndex,
- BOOLEAN IsLoaded)
-{
-
- (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
- if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
+ if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
+ ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL)
{
- if (IsLoaded)
- {
- AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
- ACPI_TABLE_IS_LOADED;
- }
- else
- {
- AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
- ~ACPI_TABLE_IS_LOADED;
- }
+ ACPI_FREE (ACPI_CAST_PTR (void, TableDesc->Address));
}
- (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
+ TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL);
+ return_VOID;
}
-