summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/tables/tbget.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/tables/tbget.c')
-rw-r--r--drivers/acpi/tables/tbget.c303
1 files changed, 292 insertions, 11 deletions
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 19a8f0a2a..2cf8eede7 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: tbget - ACPI Table get* routines
- * $Revision: 22 $
+ * $Revision: 40 $
*
*****************************************************************************/
@@ -32,6 +32,7 @@
#define _COMPONENT TABLE_MANAGER
MODULE_NAME ("tbget")
+#define RSDP_CHECKSUM_LENGTH 20
/*******************************************************************************
*
@@ -127,7 +128,7 @@ acpi_tb_get_table_ptr (
ACPI_STATUS
acpi_tb_get_table (
- void *physical_address,
+ ACPI_PHYSICAL_ADDRESS physical_address,
ACPI_TABLE_HEADER *buffer_ptr,
ACPI_TABLE_DESC *table_info)
{
@@ -239,9 +240,10 @@ acpi_tb_get_all_tables (
MEMSET (&table_info, 0, sizeof (ACPI_TABLE_DESC));
- /* Get the table via the RSDT */
+ /* Get the table via the XSDT */
- status = acpi_tb_get_table ((void *) acpi_gbl_RSDT->table_offset_entry[index],
+ status = acpi_tb_get_table ((ACPI_PHYSICAL_ADDRESS)
+ acpi_gbl_XSDT->table_offset_entry[index],
table_ptr, &table_info);
/* Ignore a table that failed verification */
@@ -266,15 +268,25 @@ acpi_tb_get_all_tables (
* determine if there are enough tables to continue.
*/
- acpi_tb_delete_single_table (&table_info);
+ acpi_tb_uninstall_table (&table_info);
}
}
/*
+ * Convert the FADT to a common format. This allows earlier revisions of the
+ * table to coexist with newer versions, using common access code.
+ */
+ status = acpi_tb_convert_table_fadt ();
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+
+ /*
* Get the minimum set of ACPI tables, namely:
*
- * 1) FACP (via RSDT in loop above)
+ * 1) FADT (via RSDT in loop above)
* 2) FACS
* 3) DSDT
*
@@ -282,8 +294,8 @@ acpi_tb_get_all_tables (
/*
- * Get the FACS (must have the FACP first, from loop above)
- * Acpi_tb_get_table_facs will fail if FACP pointer is not valid
+ * Get the FACS (must have the FADT first, from loop above)
+ * Acpi_tb_get_table_facs will fail if FADT pointer is not valid
*/
status = acpi_tb_get_table_facs (table_ptr, &table_info);
@@ -291,6 +303,7 @@ acpi_tb_get_all_tables (
return (status);
}
+
/* Install the FACS */
status = acpi_tb_install_table (table_ptr, &table_info);
@@ -298,10 +311,22 @@ acpi_tb_get_all_tables (
return (status);
}
+ /*
+ * Create the common FACS pointer table
+ * (Contains pointers to the original table)
+ */
- /* Get the DSDT (We know that the FACP if valid now) */
+ status = acpi_tb_build_common_facs (&table_info);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+
+ /*
+ * Get the DSDT (We know that the FADT is valid now)
+ */
- status = acpi_tb_get_table ((void *) acpi_gbl_FACP->dsdt, table_ptr, &table_info);
+ status = acpi_tb_get_table (acpi_gbl_FADT->Xdsdt, table_ptr, &table_info);
if (ACPI_FAILURE (status)) {
return (status);
}
@@ -321,9 +346,265 @@ acpi_tb_get_all_tables (
* Initialize the capabilities flags.
* Assumes that platform supports ACPI_MODE since we have tables!
*/
-
acpi_gbl_system_flags |= acpi_hw_get_mode_capabilities ();
+
+ /* Always delete the RSDP mapping, we are done with it */
+
+ acpi_tb_delete_acpi_table (ACPI_TABLE_RSDP);
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_tb_verify_rsdp
+ *
+ * PARAMETERS: Number_of_tables - Where the table count is placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_tb_verify_rsdp (
+ ACPI_PHYSICAL_ADDRESS rsdp_physical_address)
+{
+ ACPI_TABLE_DESC table_info;
+ ACPI_STATUS status;
+ u8 *table_ptr;
+
+
+ /*
+ * Obtain access to the RSDP structure
+ */
+ status = acpi_os_map_memory (rsdp_physical_address,
+ sizeof (RSDP_DESCRIPTOR),
+ (void **) &table_ptr);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /*
+ * The signature and checksum must both be correct
+ */
+ if (STRNCMP ((NATIVE_CHAR *) table_ptr, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) {
+ /* Nope, BAD Signature */
+
+ status = AE_BAD_SIGNATURE;
+ goto cleanup;
+ }
+
+ if (acpi_tb_checksum (table_ptr, RSDP_CHECKSUM_LENGTH) != 0) {
+ /* Nope, BAD Checksum */
+
+ status = AE_BAD_CHECKSUM;
+ goto cleanup;
+ }
+
+ /* TBD: Check extended checksum if table version >= 2 */
+
+ /* The RSDP supplied is OK */
+
+ table_info.pointer = (ACPI_TABLE_HEADER *) table_ptr;
+ table_info.length = sizeof (RSDP_DESCRIPTOR);
+ table_info.allocation = ACPI_MEM_MAPPED;
+ table_info.base_pointer = table_ptr;
+
+ /* Save the table pointers and allocation info */
+
+ status = acpi_tb_init_table_descriptor (ACPI_TABLE_RSDP, &table_info);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+
+ /* Save the RSDP in a global for easy access */
+
+ acpi_gbl_RSDP = (RSDP_DESCRIPTOR *) table_info.pointer;
+ return (status);
+
+
+ /* Error exit */
+cleanup:
+
+ acpi_os_unmap_memory (table_ptr, sizeof (RSDP_DESCRIPTOR));
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_tb_get_table_rsdt
+ *
+ * PARAMETERS: Number_of_tables - Where the table count is placed
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Load and validate the RSDP (ptr) and RSDT (table)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_tb_get_table_rsdt (
+ u32 *number_of_tables)
+{
+ ACPI_TABLE_DESC table_info;
+ ACPI_STATUS status = AE_OK;
+ ACPI_PHYSICAL_ADDRESS physical_address;
+ u32 signature_length;
+ char *table_signature;
+
+
+ /*
+ * Get the RSDT from the RSDP
+ */
+
+ /*
+ * For RSDP revision 0 or 1, we use the RSDT.
+ * For RSDP revision 2 (and above), we use the XSDT
+ */
+ if (acpi_gbl_RSDP->revision < 2) {
+#ifdef _IA64
+ /* 0.71 RSDP has 64bit Rsdt address field */
+ physical_address = ((RSDP_DESCRIPTOR_REV071 *)acpi_gbl_RSDP)->rsdt_physical_address;
+#else
+ physical_address = acpi_gbl_RSDP->rsdt_physical_address;
+#endif
+ table_signature = RSDT_SIG;
+ signature_length = sizeof (RSDT_SIG) -1;
+ }
+ else {
+ physical_address = (ACPI_PHYSICAL_ADDRESS) acpi_gbl_RSDP->xsdt_physical_address;
+ table_signature = XSDT_SIG;
+ signature_length = sizeof (XSDT_SIG) -1;
+ }
+
+
+ /* Get the RSDT/XSDT */
+
+ status = acpi_tb_get_table (physical_address, NULL, &table_info);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+
+ /* Check the RSDT or XSDT signature */
+
+ if (STRNCMP ((char *) table_info.pointer, table_signature,
+ signature_length))
+ {
+ /* Invalid RSDT or XSDT signature */
+
+ REPORT_ERROR (("Invalid signature where RSDP indicates %s should be located\n",
+ table_signature));
+
+ return (status);
+ }
+
+
+ /* Valid RSDT signature, verify the checksum */
+
+ status = acpi_tb_verify_table_checksum (table_info.pointer);
+
+
+ /* Convert and/or copy to an XSDT structure */
+
+ status = acpi_tb_convert_to_xsdt (&table_info, number_of_tables);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /* Save the table pointers and allocation info */
+
+ status = acpi_tb_init_table_descriptor (ACPI_TABLE_XSDT, &table_info);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ acpi_gbl_XSDT = (XSDT_DESCRIPTOR *) table_info.pointer;
+
+ return (status);
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION: Acpi_tb_get_table_facs
+ *
+ * PARAMETERS: *Buffer_ptr - If Buffer_ptr is valid, read data from
+ * buffer rather than searching memory
+ * *Table_info - Where the table info is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Returns a pointer to the FACS as defined in FADT. This
+ * function assumes the global variable FADT has been
+ * correctly initialized. The value of FADT->Firmware_ctrl
+ * into a far pointer which is returned.
+ *
+ *****************************************************************************/
+
+ACPI_STATUS
+acpi_tb_get_table_facs (
+ ACPI_TABLE_HEADER *buffer_ptr,
+ ACPI_TABLE_DESC *table_info)
+{
+ void *table_ptr = NULL;
+ u32 size;
+ u8 allocation;
+ ACPI_STATUS status = AE_OK;
+
+
+ /* Must have a valid FADT pointer */
+
+ if (!acpi_gbl_FADT) {
+ return (AE_NO_ACPI_TABLES);
+ }
+
+ size = sizeof (FACS_DESCRIPTOR);
+ if (buffer_ptr) {
+ /*
+ * Getting table from a file -- allocate a buffer and
+ * read the table.
+ */
+ table_ptr = acpi_cm_allocate (size);
+ if(!table_ptr) {
+ return (AE_NO_MEMORY);
+ }
+
+ MEMCPY (table_ptr, buffer_ptr, size);
+
+ /* Save allocation type */
+
+ allocation = ACPI_MEM_ALLOCATED;
+ }
+
+ else {
+ /* Just map the physical memory to our address space */
+
+ status = acpi_tb_map_acpi_table (acpi_gbl_FADT->Xfirmware_ctrl,
+ &size, &table_ptr);
+ if (ACPI_FAILURE(status)) {
+ return (status);
+ }
+
+ /* Save allocation type */
+
+ allocation = ACPI_MEM_MAPPED;
+ }
+
+
+ /* Return values */
+
+ table_info->pointer = table_ptr;
+ table_info->length = size;
+ table_info->allocation = allocation;
+ table_info->base_pointer = table_ptr;
+
return (status);
}