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

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

ACPICA: Add acpi_os_physical_table_override interface



This interface allows the host to override a table via a
physical address, instead of the logical address required by
acpi_os_table_override. This simplifies the host implementation.
Initial implementation by Thomas Renninger. ACPICA implementation
creates a single function for table overrides that attempts both
a logical and a physical override.

Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarThomas Renninger <trenn@suse.de>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent ea143604
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -67,6 +67,11 @@ acpi_status acpi_tb_resize_root_table_list(void);

acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc);

struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
						 *table_header,
						 struct acpi_table_desc
						 *table_desc);

acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index);

+97 −20
Original line number Diff line number Diff line
@@ -114,7 +114,6 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
	u32 i;
	acpi_status status = AE_OK;
	struct acpi_table_header *override_table = NULL;

	ACPI_FUNCTION_TRACE(tb_add_table);

@@ -224,25 +223,10 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
	/*
	 * ACPI Table Override:
	 * Allow the host to override dynamically loaded tables.
	 * NOTE: the table is fully mapped at this point, and the mapping will
	 * be deleted by tb_table_override if the table is actually overridden.
	 */
	status = acpi_os_table_override(table_desc->pointer, &override_table);
	if (ACPI_SUCCESS(status) && override_table) {
		ACPI_INFO((AE_INFO,
			   "%4.4s @ 0x%p Table override, replaced with:",
			   table_desc->pointer->signature,
			   ACPI_CAST_PTR(void, table_desc->address)));

		/* We can delete the table that was passed as a parameter */

		acpi_tb_delete_table(table_desc);

		/* Setup descriptor for the new table */

		table_desc->address = ACPI_PTR_TO_PHYSADDR(override_table);
		table_desc->pointer = override_table;
		table_desc->length = override_table->length;
		table_desc->flags = ACPI_TABLE_ORIGIN_OVERRIDE;
	}
	(void)acpi_tb_table_override(table_desc->pointer, table_desc);

	/* Add the table to the global root table list */

@@ -261,6 +245,95 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
	return_ACPI_STATUS(status);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_table_override
 *
 * PARAMETERS:  table_header        - Header for the original table
 *              table_desc          - Table descriptor initialized for the
 *                                    original table. May or may not be mapped.
 *
 * RETURN:      Pointer to the entire new table. NULL if table not overridden.
 *              If overridden, installs the new table within the input table
 *              descriptor.
 *
 * DESCRIPTION: Attempt table override by calling the OSL override functions.
 *              Note: If the table is overridden, then the entire new table
 *              is mapped and returned by this function.
 *
 ******************************************************************************/

struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header
						 *table_header,
						 struct acpi_table_desc
						 *table_desc)
{
	acpi_status status;
	struct acpi_table_header *new_table = NULL;
	acpi_physical_address new_address = 0;
	u32 new_table_length = 0;
	u8 new_flags;
	char *override_type;

	/* (1) Attempt logical override (returns a logical address) */

	status = acpi_os_table_override(table_header, &new_table);
	if (ACPI_SUCCESS(status) && new_table) {
		new_address = ACPI_PTR_TO_PHYSADDR(new_table);
		new_table_length = new_table->length;
		new_flags = ACPI_TABLE_ORIGIN_OVERRIDE;
		override_type = "Logical";
		goto finish_override;
	}

	/* (2) Attempt physical override (returns a physical address) */

	status = acpi_os_physical_table_override(table_header,
						 &new_address,
						 &new_table_length);
	if (ACPI_SUCCESS(status) && new_address && new_table_length) {

		/* Map the entire new table */

		new_table = acpi_os_map_memory(new_address, new_table_length);
		if (!new_table) {
			ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
					"%4.4s %p Attempted physical table override failed",
					table_header->signature,
					ACPI_CAST_PTR(void,
						      table_desc->address)));
			return (NULL);
		}

		override_type = "Physical";
		new_flags = ACPI_TABLE_ORIGIN_MAPPED;
		goto finish_override;
	}

	return (NULL);		/* There was no override */

      finish_override:

	ACPI_INFO((AE_INFO,
		   "%4.4s %p %s table override, new table: %p",
		   table_header->signature,
		   ACPI_CAST_PTR(void, table_desc->address),
		   override_type, new_table));

	/* We can now unmap/delete the original table (if fully mapped) */

	acpi_tb_delete_table(table_desc);

	/* Setup descriptor for the new table */

	table_desc->address = new_address;
	table_desc->pointer = new_table;
	table_desc->length = new_table_length;
	table_desc->flags = new_flags;

	return (new_table);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_resize_root_table_list
@@ -396,7 +469,11 @@ void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
	case ACPI_TABLE_ORIGIN_ALLOCATED:
		ACPI_FREE(table_desc->pointer);
		break;
	default:;

		/* Not mapped or allocated, there is nothing we can do */

	default:
		return;
	}

	table_desc->pointer = NULL;
+50 −43
Original line number Diff line number Diff line
@@ -446,7 +446,7 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
 * RETURN:      None
 *
 * DESCRIPTION: Install an ACPI table into the global data structure. The
 *              table override mechanism is implemented here to allow the host
 *              table override mechanism is called to allow the host
 *              OS to replace any table before it is installed in the root
 *              table array.
 *
@@ -456,11 +456,9 @@ void
acpi_tb_install_table(acpi_physical_address address,
		      char *signature, u32 table_index)
{
	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;
	struct acpi_table_header *table;
	struct acpi_table_header *final_table;
	struct acpi_table_desc *table_desc;

	if (!address) {
		ACPI_ERROR((AE_INFO,
@@ -471,69 +469,78 @@ acpi_tb_install_table(acpi_physical_address address,

	/* Map just the table header */

	mapped_table =
	    acpi_os_map_memory(address, sizeof(struct acpi_table_header));
	if (!mapped_table) {
	table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
	if (!table) {
		ACPI_ERROR((AE_INFO,
			    "Could not map memory for table [%s] at %p",
			    signature, ACPI_CAST_PTR(void, address)));
		return;
	}

	/* If a particular signature is expected (DSDT/FACS), it must match */

	if (signature && !ACPI_COMPARE_NAME(mapped_table->signature, signature)) {
	if (signature && !ACPI_COMPARE_NAME(table->signature, signature)) {
		ACPI_ERROR((AE_INFO,
			    "Invalid signature 0x%X for ACPI table, expected [%s]",
			    *ACPI_CAST_PTR(u32, mapped_table->signature),
			    signature));
			    *ACPI_CAST_PTR(u32, table->signature), signature));
		goto unmap_and_exit;
	}

	/*
	 * Initialize the table entry. Set the pointer to NULL, since the
	 * table is not fully mapped at this time.
	 */
	table_desc = &acpi_gbl_root_table_list.tables[table_index];

	table_desc->address = address;
	table_desc->pointer = NULL;
	table_desc->length = table->length;
	table_desc->flags = ACPI_TABLE_ORIGIN_MAPPED;
	ACPI_MOVE_32_TO_32(table_desc->signature.ascii, table->signature);

	/*
	 * 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.
	 *
	 * NOTE: If the table is overridden, then final_table will contain a
	 * mapped pointer to the full new table. If the table is not overridden,
	 * or if there has been a physical override, then the table will be
	 * fully mapped later (in verify table). In any case, we must
	 * unmap the header that was mapped above.
	 */
	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;
	final_table = acpi_tb_table_override(table, table_desc);
	if (!final_table) {
		final_table = table;	/* There was no override */
	}

	/* Initialize the table entry */

	acpi_gbl_root_table_list.tables[table_index].address = address;
	acpi_gbl_root_table_list.tables[table_index].length =
	    table_to_install->length;
	acpi_gbl_root_table_list.tables[table_index].flags = flags;
	acpi_tb_print_table_header(table_desc->address, final_table);

	ACPI_MOVE_32_TO_32(&
			   (acpi_gbl_root_table_list.tables[table_index].
			    signature), table_to_install->signature);

	acpi_tb_print_table_header(address, table_to_install);
	/* Set the global integer width (based upon revision of the DSDT) */

	if (table_index == ACPI_TABLE_INDEX_DSDT) {
		acpi_ut_set_integer_width(final_table->revision);
	}

		/* Global integer width is based upon revision of the DSDT */

		acpi_ut_set_integer_width(table_to_install->revision);
	/*
	 * If we have a physical override during this early loading of the ACPI
	 * tables, unmap the table for now. It will be mapped again later when
	 * it is actually used. This supports very early loading of ACPI tables,
	 * before virtual memory is fully initialized and running within the
	 * host OS. Note: A logical override has the ACPI_TABLE_ORIGIN_OVERRIDE
	 * flag set and will not be deleted below.
	 */
	if (final_table != table) {
		acpi_tb_delete_table(table_desc);
	}

      unmap_and_exit:
	acpi_os_unmap_memory(mapped_table, sizeof(struct acpi_table_header));

	/* Always unmap the table header that we mapped above */

	acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
}

/*******************************************************************************
+9 −0
Original line number Diff line number Diff line
@@ -554,6 +554,15 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
	return AE_OK;
}

acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
				acpi_physical_address * new_address,
				u32 *new_table_length)
{
	return AE_SUPPORT;
}


static irqreturn_t acpi_irq(int irq, void *dev_id)
{
	u32 handled;
+5 −0
Original line number Diff line number Diff line
@@ -95,6 +95,11 @@ acpi_status
acpi_os_table_override(struct acpi_table_header *existing_table,
		       struct acpi_table_header **new_table);

acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
				acpi_physical_address * new_address,
				u32 *new_table_length);

/*
 * Spinlock primitives
 */