Sync with trunk r62754.
[reactos.git] / drivers / bus / acpi / acpica / tables / tbinstal.c
index da3ccf4..4560d0f 100644 (file)
@@ -8,13 +8,13 @@
  *
  * 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.
  *
@@ -31,7 +31,7 @@
  * 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.
  *
@@ -55,7 +55,7 @@
  * 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;
 }
-