ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_status;
ACPI_EXTERN struct acpi_generic_address acpi_gbl_xpm1b_enable;
+/* DSDT information. Used to check for DSDT corruption */
+
+ACPI_EXTERN struct acpi_table_desc *acpi_gbl_DSDT;
+ACPI_EXTERN struct acpi_table_header acpi_gbl_original_dsdt_header;
+
/*
* Handle both ACPI 1.0 and ACPI 2.0 Integer widths. The integer width is
* determined by the revision of the DSDT: If the DSDT revision is less than
acpi_status
acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length);
+void acpi_tb_check_dsdt_header(void);
+
void
acpi_tb_install_table(acpi_physical_address address,
char *signature, u32 table_index);
ACPI_FUNCTION_TRACE(ps_execute_method);
+ /* Quick validation of DSDT header */
+
+ acpi_tb_check_dsdt_header();
+
/* Validate the Info and method Node */
if (!info || !info->resolved_node) {
return sum;
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_tb_check_dsdt_header
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
+ * if the DSDT has been replaced from outside the OS and/or if
+ * the DSDT header has been corrupted.
+ *
+ ******************************************************************************/
+
+void acpi_tb_check_dsdt_header(void)
+{
+
+ /* Compare original length and checksum to current values */
+
+ if (acpi_gbl_original_dsdt_header.length !=
+ acpi_gbl_DSDT->pointer->length
+ || acpi_gbl_original_dsdt_header.checksum !=
+ acpi_gbl_DSDT->pointer->checksum) {
+ ACPI_ERROR((AE_INFO,
+ "The DSDT has been corrupted or replaced - old, new headers below"));
+ acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
+ acpi_tb_print_table_header(acpi_gbl_DSDT->address,
+ acpi_gbl_DSDT->pointer);
+
+ /* Disable further error messages */
+
+ acpi_gbl_original_dsdt_header.length =
+ acpi_gbl_DSDT->pointer->length;
+ acpi_gbl_original_dsdt_header.checksum =
+ acpi_gbl_DSDT->pointer->checksum;
+ }
+}
+
/*******************************************************************************
*
* FUNCTION: acpi_tb_install_table
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+ acpi_gbl_DSDT = &acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT];
+
/*
- * Load the namespace. The DSDT is required, but any SSDT and PSDT tables
- * are optional.
+ * Load the namespace. The DSDT is required, but any SSDT and
+ * PSDT tables are optional. Verify the DSDT.
*/
if (!acpi_gbl_root_table_list.count ||
- !ACPI_COMPARE_NAME(&
- (acpi_gbl_root_table_list.
- tables[ACPI_TABLE_INDEX_DSDT].signature),
- ACPI_SIG_DSDT)
- ||
- ACPI_FAILURE(acpi_tb_verify_table
- (&acpi_gbl_root_table_list.
- tables[ACPI_TABLE_INDEX_DSDT]))) {
+ !ACPI_COMPARE_NAME(&acpi_gbl_DSDT->signature, ACPI_SIG_DSDT) ||
+ ACPI_FAILURE(acpi_tb_verify_table(acpi_gbl_DSDT))) {
status = AE_NO_ACPI_TABLES;
goto unlock_and_exit;
}
- /* A valid DSDT is required */
-
- status =
- acpi_tb_verify_table(&acpi_gbl_root_table_list.
- tables[ACPI_TABLE_INDEX_DSDT]);
- if (ACPI_FAILURE(status)) {
-
- status = AE_NO_ACPI_TABLES;
- goto unlock_and_exit;
- }
+ /*
+ * Save the original DSDT header for detection of table corruption
+ * and/or replacement of the DSDT from outside the OS.
+ */
+ ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT->pointer,
+ sizeof(struct acpi_table_header));
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);