Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac5f98db authored by Bob Moore's avatar Bob Moore Committed by Len Brown
Browse files

ACPICA: Allow OS override of all ACPI tables



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: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 4bbfb85d
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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;

/*
+46 −13
Original line number Diff line number Diff line
@@ -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));
}

/*******************************************************************************
+1 −30
Original line number Diff line number Diff line
@@ -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;
	}
+3 −2
Original line number Diff line number Diff line
@@ -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