ACPICA: Allow OS override of all ACPI tables
authorBob Moore <robert.moore@intel.com>
Tue, 3 Feb 2009 06:35:25 +0000 (14:35 +0800)
committerLen Brown <len.brown@intel.com>
Thu, 26 Mar 2009 20:38:19 +0000 (16:38 -0400)
Previously, the table override mechanism was implemented for the
DSDT only. Now, any table in the RSDT/XSDT can be replaced by
the host OS. (including the DSDT).

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/tbutils.c
drivers/acpi/acpica/tbxface.c
include/acpi/actbl.h

index ddb40f5c68fc25e35e9cab318fb232c4a9015723..634fb0785e7e0d8933a10732d937440617b4867e 100644 (file)
@@ -371,7 +371,6 @@ ACPI_EXTERN char *acpi_gbl_db_buffer;
 ACPI_EXTERN char *acpi_gbl_db_filename;
 ACPI_EXTERN u32 acpi_gbl_db_debug_level;
 ACPI_EXTERN u32 acpi_gbl_db_console_debug_level;
-ACPI_EXTERN struct acpi_table_header *acpi_gbl_db_table_ptr;
 ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node;
 
 /*
index 22ce489857202b73fa13d293367fa35e346f5d7a..e285bedbb989e5051706195a71a263f87bdd9112 100644 (file)
@@ -287,7 +287,10 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length)
  *
  * RETURN:      None
  *
- * DESCRIPTION: Install an ACPI table into the global data structure.
+ * DESCRIPTION: Install an ACPI table into the global data structure. The
+ *              table override mechanism is implemented here to allow the host
+ *              OS to replace any table before it is installed in the root
+ *              table array.
  *
  ******************************************************************************/
 
@@ -295,7 +298,10 @@ void
 acpi_tb_install_table(acpi_physical_address address,
                      u8 flags, char *signature, u32 table_index)
 {
-       struct acpi_table_header *table;
+       acpi_status status;
+       struct acpi_table_header *table_to_install;
+       struct acpi_table_header *mapped_table;
+       struct acpi_table_header *override_table = NULL;
 
        if (!address) {
                ACPI_ERROR((AE_INFO,
@@ -306,41 +312,68 @@ acpi_tb_install_table(acpi_physical_address address,
 
        /* Map just the table header */
 
-       table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
-       if (!table) {
+       mapped_table =
+           acpi_os_map_memory(address, sizeof(struct acpi_table_header));
+       if (!mapped_table) {
                return;
        }
 
-       /* If a particular signature is expected, signature must match */
+       /* If a particular signature is expected (DSDT/FACS), it must match */
 
-       if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) {
+       if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) {
                ACPI_ERROR((AE_INFO,
-                           "Invalid signature 0x%X for ACPI table [%s]",
-                           *ACPI_CAST_PTR(u32, table->signature), signature));
+                           "Invalid signature 0x%X for ACPI table, expected [%s]",
+                           *ACPI_CAST_PTR(u32, mapped_table->signature),
+                           signature));
                goto unmap_and_exit;
        }
 
+       /*
+        * ACPI Table Override:
+        *
+        * 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.
+        */
+       status = acpi_os_table_override(mapped_table, &override_table);
+       if (ACPI_SUCCESS(status) && override_table) {
+               ACPI_INFO((AE_INFO,
+                          "%4.4s @ 0x%p Table override, replaced with:",
+                          mapped_table->signature, ACPI_CAST_PTR(void,
+                                                                 address)));
+
+               acpi_gbl_root_table_list.tables[table_index].pointer =
+                   override_table;
+               flags = ACPI_TABLE_ORIGIN_OVERRIDE;
+               address = ACPI_PTR_TO_PHYSADDR(override_table);
+
+               table_to_install = override_table;
+       } else {
+               table_to_install = mapped_table;
+       }
+
        /* Initialize the table entry */
 
        acpi_gbl_root_table_list.tables[table_index].address = address;
-       acpi_gbl_root_table_list.tables[table_index].length = table->length;
+       acpi_gbl_root_table_list.tables[table_index].length =
+           table_to_install->length;
        acpi_gbl_root_table_list.tables[table_index].flags = flags;
 
        ACPI_MOVE_32_TO_32(&
                           (acpi_gbl_root_table_list.tables[table_index].
-                           signature), table->signature);
+                           signature), table_to_install->signature);
 
-       acpi_tb_print_table_header(address, table);
+       acpi_tb_print_table_header(address, table_to_install);
 
        if (table_index == ACPI_TABLE_INDEX_DSDT) {
 
                /* Global integer width is based upon revision of the DSDT */
 
-               acpi_ut_set_integer_width(table->revision);
+               acpi_ut_set_integer_width(table_to_install->revision);
        }
 
       unmap_and_exit:
-       acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+       acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));
 }
 
 /*******************************************************************************
index c3e841f3cde924239ce34f94a75818cfc194a211..f3f95e386334e633603c11b8ceeed7d1d250e935 100644 (file)
@@ -491,7 +491,6 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
 static acpi_status acpi_tb_load_namespace(void)
 {
        acpi_status status;
-       struct acpi_table_header *table;
        u32 i;
 
        ACPI_FUNCTION_TRACE(tb_load_namespace);
@@ -515,41 +514,13 @@ static acpi_status acpi_tb_load_namespace(void)
                goto unlock_and_exit;
        }
 
-       /*
-        * Find DSDT table
-        */
-       status =
-           acpi_os_table_override(acpi_gbl_root_table_list.
-                                  tables[ACPI_TABLE_INDEX_DSDT].pointer,
-                                  &table);
-       if (ACPI_SUCCESS(status) && table) {
-               /*
-                * DSDT table has been found
-                */
-               acpi_tb_delete_table(&acpi_gbl_root_table_list.
-                                    tables[ACPI_TABLE_INDEX_DSDT]);
-               acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer =
-                   table;
-               acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length =
-                   table->length;
-               acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags =
-                   ACPI_TABLE_ORIGIN_UNKNOWN;
-
-               ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS"));
-               acpi_tb_print_table_header(0, table);
-
-               if (no_auto_ssdt == 0) {
-                       printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"\n");
-               }
-       }
+       /* A valid DSDT is required */
 
        status =
            acpi_tb_verify_table(&acpi_gbl_root_table_list.
                                 tables[ACPI_TABLE_INDEX_DSDT]);
        if (ACPI_FAILURE(status)) {
 
-               /* A valid DSDT is required */
-
                status = AE_NO_ACPI_TABLES;
                goto unlock_and_exit;
        }
index bf8d4cfd8cf57186a88664685761bd943054dbf3..1f3dfdb1b370bff30b53c5a2eecdea136ca19a99 100644 (file)
@@ -310,8 +310,9 @@ struct acpi_table_desc {
 #define ACPI_TABLE_ORIGIN_UNKNOWN       (0)
 #define ACPI_TABLE_ORIGIN_MAPPED        (1)
 #define ACPI_TABLE_ORIGIN_ALLOCATED     (2)
-#define ACPI_TABLE_ORIGIN_MASK          (3)
-#define ACPI_TABLE_IS_LOADED            (4)
+#define ACPI_TABLE_ORIGIN_OVERRIDE      (4)
+#define ACPI_TABLE_ORIGIN_MASK          (7)
+#define ACPI_TABLE_IS_LOADED            (8)
 
 /*
  * Get the remaining ACPI tables