ACPICA: Add subsystem option to force copy of DSDT to local memory
authorLin Ming <ming.m.lin@intel.com>
Thu, 1 Apr 2010 03:14:12 +0000 (11:14 +0800)
committerLen Brown <len.brown@intel.com>
Tue, 20 Apr 2010 14:43:16 +0000 (10:43 -0400)
Optionally copy the entire DSDT to local memory (instead of
simply mapping it.) There are some BIOSs that corrupt or replace
the original DSDT, creating the need for this option. Default is
FALSE, do not copy the DSDT.

https://bugzilla.kernel.org/show_bug.cgi?id=14679

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

index a419fe98a5fcdad77811ac7d7b0b6ab4055d47dc..e3813d290b4f06d4251d4903d542024cd8f1ae18 100644 (file)
@@ -117,6 +117,14 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
  */
 u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_aml_debug_object, FALSE);
 
+/*
+ * Optionally copy the entire DSDT to local memory (instead of simply
+ * mapping it.) There are some BIOSs that corrupt or replace the original
+ * DSDT, creating the need for this option. Default is FALSE, do not copy
+ * the DSDT.
+ */
+u8 ACPI_INIT_GLOBAL(acpi_gbl_copy_dsdt_locally, FALSE);
+
 /* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
 
 struct acpi_table_fadt acpi_gbl_FADT;
index fc52b6f2d69c6a29904908edb3e8452aac1fb790..b7197bf4af0b4881d231dcb6d140bc3c38160a41 100644 (file)
@@ -109,6 +109,8 @@ acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length);
 
 void acpi_tb_check_dsdt_header(void);
 
+void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc);
+
 void
 acpi_tb_install_table(acpi_physical_address address,
                      char *signature, u32 table_index);
index 67e7ad51705143e135a42cc91795da8ce983cb09..c42f067cff9dfc811f611c07dd7af4c04ad197b9 100644 (file)
@@ -46,6 +46,7 @@
 #include "acparser.h"
 #include "acdispat.h"
 #include "acinterp.h"
+#include "actables.h"
 #include "amlcode.h"
 
 #define _COMPONENT          ACPI_PARSER
index 07bc7437f82bca5cd8bc5e1ee569cd8efbae5321..1efb0940e8b20ede860a63fc2c6ab118497cd686 100644 (file)
@@ -385,6 +385,41 @@ void acpi_tb_check_dsdt_header(void)
        }
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_copy_dsdt
+ *
+ * PARAMETERS:  table_desc          - Installed table to copy
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
+ *              Some very bad BIOSs are known to either corrupt the DSDT or
+ *              install a new, bad DSDT. This copy works around the problem.
+ *
+ ******************************************************************************/
+
+void acpi_tb_copy_dsdt(struct acpi_table_desc *table_desc)
+{
+       struct acpi_table_header *new_table;
+
+       new_table = ACPI_ALLOCATE(table_desc->length);
+       if (!new_table) {
+               ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X",
+                           table_desc->length));
+               return;
+       }
+
+       ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length);
+       acpi_tb_delete_table(table_desc);
+       table_desc->pointer = new_table;
+       table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED;
+
+       ACPI_INFO((AE_INFO,
+                  "Forced DSDT copy: length 0x%05X copied locally, original unmapped",
+                  new_table->length));
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_tb_install_table
index 30565100b94c0bb843ebd4e307eeb210a64c2436..f5378fc302b39e4de8e7f27bdeb14d99cbd20cbb 100644 (file)
@@ -531,6 +531,16 @@ static acpi_status acpi_tb_load_namespace(void)
                goto unlock_and_exit;
        }
 
+       /*
+        * Optionally copy the entire DSDT to local memory (instead of simply
+        * mapping it.) There are some BIOSs that corrupt or replace the original
+        * DSDT, creating the need for this option. Default is FALSE, do not copy
+        * the DSDT.
+        */
+       if (acpi_gbl_copy_dsdt_locally) {
+               acpi_tb_copy_dsdt(acpi_gbl_DSDT);
+       }
+
        /*
         * Save the original DSDT header for detection of table corruption
         * and/or replacement of the DSDT from outside the OS.
index f753222d5cfad108cf9a0c617449a783367c2e6a..fd815f605426c58aa103ba935cf21aaafc189963 100644 (file)
@@ -68,6 +68,7 @@ extern u8 acpi_gbl_use_default_register_widths;
 extern acpi_name acpi_gbl_trace_method_name;
 extern u32 acpi_gbl_trace_flags;
 extern u8 acpi_gbl_enable_aml_debug_object;
+extern u8 acpi_gbl_copy_dsdt_locally;
 
 extern u32 acpi_current_gpe_count;
 extern struct acpi_table_fadt acpi_gbl_FADT;