]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/acpi/acpica/tbutils.c
Merge branch 'omap-pool'
[linux-2.6-omap-h63xx.git] / drivers / acpi / acpica / tbutils.c
index 22ce489857202b73fa13d293367fa35e346f5d7a..ef7d2c2d8f0b0067fabf069e547a456afde52fc9 100644 (file)
@@ -177,19 +177,23 @@ acpi_tb_print_table_header(acpi_physical_address address,
                           struct acpi_table_header *header)
 {
 
+       /*
+        * The reason that the Address is cast to a void pointer is so that we
+        * can use %p which will work properly on both 32-bit and 64-bit hosts.
+        */
        if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) {
 
-               /* FACS only has signature and length fields of common table header */
+               /* FACS only has signature and length fields */
 
-               ACPI_INFO((AE_INFO, "%4.4s %08lX, %04X",
-                          header->signature, (unsigned long)address,
+               ACPI_INFO((AE_INFO, "%4.4s %p %05X",
+                          header->signature, ACPI_CAST_PTR(void, address),
                           header->length));
        } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) {
 
                /* RSDP has no common fields */
 
-               ACPI_INFO((AE_INFO, "RSDP %08lX, %04X (r%d %6.6s)",
-                          (unsigned long)address,
+               ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)",
+                          ACPI_CAST_PTR (void, address),
                           (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
                            revision >
                            0) ? ACPI_CAST_PTR(struct acpi_table_rsdp,
@@ -202,8 +206,8 @@ acpi_tb_print_table_header(acpi_physical_address address,
                /* Standard ACPI table with full common header */
 
                ACPI_INFO((AE_INFO,
-                          "%4.4s %08lX, %04X (r%d %6.6s %8.8s %8X %4.4s %8X)",
-                          header->signature, (unsigned long)address,
+                          "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
+                          header->signature, ACPI_CAST_PTR (void, address),
                           header->length, header->revision, header->oem_id,
                           header->oem_table_id, header->oem_revision,
                           header->asl_compiler_id,
@@ -280,22 +284,28 @@ u8 acpi_tb_checksum(u8 *buffer, u32 length)
  * FUNCTION:    acpi_tb_install_table
  *
  * PARAMETERS:  Address                 - Physical address of DSDT or FACS
- *              Flags                   - Flags
  *              Signature               - Table signature, NULL if no need to
  *                                        match
  *              table_index             - Index into root table array
  *
  * 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.
  *
  ******************************************************************************/
 
 void
 acpi_tb_install_table(acpi_physical_address address,
-                     u8 flags, char *signature, u32 table_index)
+                     char *signature, u32 table_index)
 {
-       struct acpi_table_header *table;
+       u8 flags;
+       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 +316,69 @@ 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;
+               address = ACPI_PTR_TO_PHYSADDR(override_table);
+
+               table_to_install = override_table;
+               flags = ACPI_TABLE_ORIGIN_OVERRIDE;
+       } else {
+               table_to_install = mapped_table;
+               flags = ACPI_TABLE_ORIGIN_MAPPED;
+       }
+
        /* 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));
 }
 
 /*******************************************************************************
@@ -379,7 +417,8 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
        } else {
                /*
                 * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
-                * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, return 64-bit
+                * 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
+                *  return 64-bit
                 */
                ACPI_MOVE_64_TO_64(&address64, table_entry);
 
@@ -389,7 +428,8 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
                        /* Will truncate 64-bit address to 32 bits, issue warning */
 
                        ACPI_WARNING((AE_INFO,
-                                     "64-bit Physical Address in XSDT is too large (%8.8X%8.8X), truncating",
+                                     "64-bit Physical Address in XSDT is too large (%8.8X%8.8X),"
+                                     " truncating",
                                      ACPI_FORMAT_UINT64(address64)));
                }
 #endif
@@ -402,7 +442,6 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
  * FUNCTION:    acpi_tb_parse_root_table
  *
  * PARAMETERS:  Rsdp                    - Pointer to the RSDP
- *              Flags                   - Flags
  *
  * RETURN:      Status
  *
@@ -416,7 +455,7 @@ acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
  ******************************************************************************/
 
 acpi_status __init
-acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
+acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
 {
        struct acpi_table_rsdp *rsdp;
        u32 table_entry_size;
@@ -513,13 +552,12 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
 
        /* Calculate the number of tables described in the root table */
 
-       table_count =
-           (u32) ((table->length -
-                   sizeof(struct acpi_table_header)) / table_entry_size);
-
+       table_count = (u32)((table->length - sizeof(struct acpi_table_header)) /
+                           table_entry_size);
        /*
-        * First two entries in the table array are reserved for the DSDT and FACS,
-        * which are not actually present in the RSDT/XSDT - they come from the FADT
+        * First two entries in the table array are reserved for the DSDT
+        * and FACS, which are not actually present in the RSDT/XSDT - they
+        * come from the FADT
         */
        table_entry =
            ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
@@ -567,14 +605,14 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
         */
        for (i = 2; i < acpi_gbl_root_table_list.count; i++) {
                acpi_tb_install_table(acpi_gbl_root_table_list.tables[i].
-                                     address, flags, NULL, i);
+                                     address, NULL, i);
 
                /* Special case for FADT - get the DSDT and FACS */
 
                if (ACPI_COMPARE_NAME
                    (&acpi_gbl_root_table_list.tables[i].signature,
                     ACPI_SIG_FADT)) {
-                       acpi_tb_parse_fadt(i, flags);
+                       acpi_tb_parse_fadt(i);
                }
        }