diff options
Diffstat (limited to 'drivers/acpi/acpica/tbinstal.c')
| -rw-r--r-- | drivers/acpi/acpica/tbinstal.c | 846 | 
1 files changed, 318 insertions, 528 deletions
diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 42a13c0d701..755b90c40dd 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -5,7 +5,7 @@   *****************************************************************************/  /* - * Copyright (C) 2000 - 2013, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp.   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -43,693 +43,483 @@  #include <acpi/acpi.h>  #include "accommon.h" -#include "acnamesp.h"  #include "actables.h"  #define _COMPONENT          ACPI_TABLES  ACPI_MODULE_NAME("tbinstal") -/****************************************************************************** +/* Local prototypes */ +static u8 +acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index); + +/*******************************************************************************   * - * FUNCTION:    acpi_tb_verify_table + * FUNCTION:    acpi_tb_compare_tables   * - * PARAMETERS:  table_desc          - table + * PARAMETERS:  table_desc          - Table 1 descriptor to be compared + *              table_index         - Index of table 2 to be compared   * - * RETURN:      Status + * RETURN:      TRUE if both tables are identical.   * - * DESCRIPTION: this function is called to verify and map table + * DESCRIPTION: This function compares a table with another table that has + *              already been installed in the root table list.   * - *****************************************************************************/ -acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) + ******************************************************************************/ + +static u8 +acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)  {  	acpi_status status = AE_OK; - -	ACPI_FUNCTION_TRACE(tb_verify_table); - -	/* Map the table if necessary */ - -	if (!table_desc->pointer) { -		if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == -		    ACPI_TABLE_ORIGIN_MAPPED) { -			table_desc->pointer = -			    acpi_os_map_memory(table_desc->address, -					       table_desc->length); -		} -		if (!table_desc->pointer) { -			return_ACPI_STATUS(AE_NO_MEMORY); -		} +	u8 is_identical; +	struct acpi_table_header *table; +	u32 table_length; +	u8 table_flags; + +	status = +	    acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index], +				  &table, &table_length, &table_flags); +	if (ACPI_FAILURE(status)) { +		return (FALSE);  	} -	/* FACS is the odd table, has no standard ACPI header and no checksum */ - -	if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { +	/* +	 * Check for a table match on the entire table length, +	 * not just the header. +	 */ +	is_identical = (u8)((table_desc->length != table_length || +			     ACPI_MEMCMP(table_desc->pointer, table, +					 table_length)) ? FALSE : TRUE); -		/* Always calculate checksum, ignore bad checksum if requested */ +	/* Release the acquired table */ -		status = -		    acpi_tb_verify_checksum(table_desc->pointer, -					    table_desc->length); -	} - -	return_ACPI_STATUS(status); +	acpi_tb_release_table(table, table_length, table_flags); +	return (is_identical);  }  /*******************************************************************************   * - * FUNCTION:    acpi_tb_add_table + * FUNCTION:    acpi_tb_install_table_with_override   * - * PARAMETERS:  table_desc          - Table descriptor - *              table_index         - Where the table index is returned + * PARAMETERS:  table_index             - Index into root table array + *              new_table_desc          - New table descriptor to install + *              override                - Whether override should be performed   * - * RETURN:      Status + * RETURN:      None   * - * DESCRIPTION: This function is called to add an ACPI table. It is used to - *              dynamically load tables via the Load and load_table AML - *              operators. + * DESCRIPTION: Install an ACPI table into the global data structure. The + *              table override mechanism is called to allow the host + *              OS to replace any table before it is installed in the root + *              table array.   *   ******************************************************************************/ -acpi_status -acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) +void +acpi_tb_install_table_with_override(u32 table_index, +				    struct acpi_table_desc *new_table_desc, +				    u8 override)  { -	u32 i; -	acpi_status status = AE_OK; - -	ACPI_FUNCTION_TRACE(tb_add_table); -	if (!table_desc->pointer) { -		status = acpi_tb_verify_table(table_desc); -		if (ACPI_FAILURE(status) || !table_desc->pointer) { -			return_ACPI_STATUS(status); -		} +	if (table_index >= acpi_gbl_root_table_list.current_table_count) { +		return;  	}  	/* -	 * Validate the incoming table signature. +	 * ACPI Table Override:  	 * -	 * 1) Originally, we checked the table signature for "SSDT" or "PSDT". -	 * 2) We added support for OEMx tables, signature "OEM". -	 * 3) Valid tables were encountered with a null signature, so we just -	 *    gave up on validating the signature, (05/2008). -	 * 4) We encountered non-AML tables such as the MADT, which caused -	 *    interpreter errors and kernel faults. So now, we once again allow -	 *    only "SSDT", "OEMx", and now, also a null signature. (05/2011). +	 * 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.  	 */ -	if ((table_desc->pointer->signature[0] != 0x00) && -	    (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) -	    && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) { -		ACPI_BIOS_ERROR((AE_INFO, -				 "Table has invalid signature [%4.4s] (0x%8.8X), " -				 "must be SSDT or OEMx", -				 acpi_ut_valid_acpi_name(table_desc->pointer-> -							 signature) ? -				 table_desc->pointer->signature : "????", -				 *(u32 *)table_desc->pointer->signature)); - -		return_ACPI_STATUS(AE_BAD_SIGNATURE); +	if (override) { +		acpi_tb_override_table(new_table_desc);  	} -	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - -	/* Check if table is already registered */ - -	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { -		if (!acpi_gbl_root_table_list.tables[i].pointer) { -			status = -			    acpi_tb_verify_table(&acpi_gbl_root_table_list. -						 tables[i]); -			if (ACPI_FAILURE(status) -			    || !acpi_gbl_root_table_list.tables[i].pointer) { -				continue; -			} -		} - -		/* -		 * Check for a table match on the entire table length, -		 * not just the header. -		 */ -		if (table_desc->length != -		    acpi_gbl_root_table_list.tables[i].length) { -			continue; -		} - -		if (ACPI_MEMCMP(table_desc->pointer, -				acpi_gbl_root_table_list.tables[i].pointer, -				acpi_gbl_root_table_list.tables[i].length)) { -			continue; -		} - -		/* -		 * Note: the current mechanism does not unregister a table if it is -		 * dynamically unloaded. The related namespace entries are deleted, -		 * but the table remains in the root table list. -		 * -		 * The assumption here is that the number of different tables that -		 * will be loaded is actually small, and there is minimal overhead -		 * in just keeping the table in case it is needed again. -		 * -		 * If this assumption changes in the future (perhaps on large -		 * machines with many table load/unload operations), tables will -		 * need to be unregistered when they are unloaded, and slots in the -		 * root table list should be reused when empty. -		 */ - -		/* -		 * Table is already registered. -		 * We can delete the table that was passed as a parameter. -		 */ -		acpi_tb_delete_table(table_desc); -		*table_index = i; +	acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. +				      tables[table_index], +				      new_table_desc->address, +				      new_table_desc->flags, +				      new_table_desc->pointer); -		if (acpi_gbl_root_table_list.tables[i]. -		    flags & ACPI_TABLE_IS_LOADED) { +	acpi_tb_print_table_header(new_table_desc->address, +				   new_table_desc->pointer); -			/* Table is still loaded, this is an error */ +	/* Set the global integer width (based upon revision of the DSDT) */ -			status = AE_ALREADY_EXISTS; -			goto release; -		} else { -			/* Table was unloaded, allow it to be reloaded */ - -			table_desc->pointer = -			    acpi_gbl_root_table_list.tables[i].pointer; -			table_desc->address = -			    acpi_gbl_root_table_list.tables[i].address; -			status = AE_OK; -			goto print_header; -		} -	} - -	/* -	 * 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. -	 */ -	(void)acpi_tb_table_override(table_desc->pointer, table_desc); - -	/* Add the table to the global root table list */ - -	status = acpi_tb_store_table(table_desc->address, table_desc->pointer, -				     table_desc->length, table_desc->flags, -				     table_index); -	if (ACPI_FAILURE(status)) { -		goto release; +	if (table_index == ACPI_TABLE_INDEX_DSDT) { +		acpi_ut_set_integer_width(new_table_desc->pointer->revision);  	} - -      print_header: -	acpi_tb_print_table_header(table_desc->address, table_desc->pointer); - -      release: -	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -	return_ACPI_STATUS(status);  }  /*******************************************************************************   * - * FUNCTION:    acpi_tb_table_override + * FUNCTION:    acpi_tb_install_fixed_table   * - * PARAMETERS:  table_header        - Header for the original table - *              table_desc          - Table descriptor initialized for the - *                                    original table. May or may not be mapped. + * PARAMETERS:  address                 - Physical address of DSDT or FACS + *              signature               - Table signature, NULL if no need to + *                                        match + *              table_index             - Index into root table array   * - * RETURN:      Pointer to the entire new table. NULL if table not overridden. - *              If overridden, installs the new table within the input table - *              descriptor. + * RETURN:      Status   * - * 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. + * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data + *              structure.   *   ******************************************************************************/ -struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header -						 *table_header, -						 struct acpi_table_desc -						 *table_desc) +acpi_status +acpi_tb_install_fixed_table(acpi_physical_address address, +			    char *signature, u32 table_index)  { +	struct acpi_table_desc new_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) */ +	ACPI_FUNCTION_TRACE(tb_install_fixed_table); -	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; +	if (!address) { +		ACPI_ERROR((AE_INFO, +			    "Null physical address for ACPI table [%s]", +			    signature)); +		return (AE_NO_MEMORY);  	} -	/* (2) Attempt physical override (returns a physical address) */ +	/* Fill a table descriptor for validation */ -	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; +	status = acpi_tb_acquire_temp_table(&new_table_desc, address, +					    ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); +	if (ACPI_FAILURE(status)) { +		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", +			    ACPI_CAST_PTR(void, address))); +		return_ACPI_STATUS(status);  	} -	return (NULL);		/* There was no override */ - -      finish_override: +	/* Validate and verify a table before installation */ -	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) */ +	status = acpi_tb_verify_temp_table(&new_table_desc, signature); +	if (ACPI_FAILURE(status)) { +		goto release_and_exit; +	} -	acpi_tb_delete_table(table_desc); +	acpi_tb_install_table_with_override(table_index, &new_table_desc, TRUE); -	/* Setup descriptor for the new table */ +release_and_exit: -	table_desc->address = new_address; -	table_desc->pointer = new_table; -	table_desc->length = new_table_length; -	table_desc->flags = new_flags; +	/* Release the temporary table descriptor */ -	return (new_table); +	acpi_tb_release_temp_table(&new_table_desc); +	return_ACPI_STATUS(status);  }  /*******************************************************************************   * - * FUNCTION:    acpi_tb_resize_root_table_list + * FUNCTION:    acpi_tb_install_standard_table   * - * PARAMETERS:  None + * PARAMETERS:  address             - Address of the table (might be a virtual + *                                    address depending on the table_flags) + *              flags               - Flags for the table + *              reload              - Whether reload should be performed + *              override            - Whether override should be performed + *              table_index         - Where the table index is returned   *   * RETURN:      Status   * - * DESCRIPTION: Expand the size of global table array + * DESCRIPTION: This function is called to install an ACPI table that is + *              neither DSDT nor FACS (a "standard" table.) + *              When this function is called by "Load" or "LoadTable" opcodes, + *              or by acpi_load_table() API, the "Reload" parameter is set. + *              After sucessfully returning from this function, table is + *              "INSTALLED" but not "VALIDATED".   *   ******************************************************************************/ -acpi_status acpi_tb_resize_root_table_list(void) +acpi_status +acpi_tb_install_standard_table(acpi_physical_address address, +			       u8 flags, +			       u8 reload, u8 override, u32 *table_index)  { -	struct acpi_table_desc *tables; -	u32 table_count; - -	ACPI_FUNCTION_TRACE(tb_resize_root_table_list); - -	/* allow_resize flag is a parameter to acpi_initialize_tables */ +	u32 i; +	acpi_status status = AE_OK; +	struct acpi_table_desc new_table_desc; -	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { -		ACPI_ERROR((AE_INFO, -			    "Resize of Root Table Array is not allowed")); -		return_ACPI_STATUS(AE_SUPPORT); -	} +	ACPI_FUNCTION_TRACE(tb_install_standard_table); -	/* Increase the Table Array size */ +	/* Acquire a temporary table descriptor for validation */ -	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { -		table_count = acpi_gbl_root_table_list.max_table_count; -	} else { -		table_count = acpi_gbl_root_table_list.current_table_count; +	status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); +	if (ACPI_FAILURE(status)) { +		ACPI_ERROR((AE_INFO, "Could not acquire table length at %p", +			    ACPI_CAST_PTR(void, address))); +		return_ACPI_STATUS(status);  	} -	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) table_count + -				       ACPI_ROOT_TABLE_SIZE_INCREMENT) * -				      sizeof(struct acpi_table_desc)); -	if (!tables) { -		ACPI_ERROR((AE_INFO, -			    "Could not allocate new root table array")); -		return_ACPI_STATUS(AE_NO_MEMORY); +	/* +	 * Optionally do not load any SSDTs from the RSDT/XSDT. This can +	 * be useful for debugging ACPI problems on some machines. +	 */ +	if (!reload && +	    acpi_gbl_disable_ssdt_table_install && +	    ACPI_COMPARE_NAME(&new_table_desc.signature, ACPI_SIG_SSDT)) { +		ACPI_INFO((AE_INFO, "Ignoring installation of %4.4s at %p", +			   new_table_desc.signature.ascii, ACPI_CAST_PTR(void, +									 address))); +		goto release_and_exit;  	} -	/* Copy and free the previous table array */ - -	if (acpi_gbl_root_table_list.tables) { -		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, -			    (acpi_size) table_count * -			    sizeof(struct acpi_table_desc)); +	/* Validate and verify a table before installation */ -		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { -			ACPI_FREE(acpi_gbl_root_table_list.tables); -		} +	status = acpi_tb_verify_temp_table(&new_table_desc, NULL); +	if (ACPI_FAILURE(status)) { +		goto release_and_exit;  	} -	acpi_gbl_root_table_list.tables = tables; -	acpi_gbl_root_table_list.max_table_count = -	    table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; -	acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; - -	return_ACPI_STATUS(AE_OK); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_tb_store_table - * - * PARAMETERS:  address             - Table address - *              table               - Table header - *              length              - Table length - *              flags               - flags - * - * RETURN:      Status and table index. - * - * DESCRIPTION: Add an ACPI table to the global table list - * - ******************************************************************************/ +	if (reload) { +		/* +		 * Validate the incoming table signature. +		 * +		 * 1) Originally, we checked the table signature for "SSDT" or "PSDT". +		 * 2) We added support for OEMx tables, signature "OEM". +		 * 3) Valid tables were encountered with a null signature, so we just +		 *    gave up on validating the signature, (05/2008). +		 * 4) We encountered non-AML tables such as the MADT, which caused +		 *    interpreter errors and kernel faults. So now, we once again allow +		 *    only "SSDT", "OEMx", and now, also a null signature. (05/2011). +		 */ +		if ((new_table_desc.signature.ascii[0] != 0x00) && +		    (!ACPI_COMPARE_NAME +		     (&new_table_desc.signature, ACPI_SIG_SSDT)) +		    && (ACPI_STRNCMP(new_table_desc.signature.ascii, "OEM", 3))) +		{ +			ACPI_BIOS_ERROR((AE_INFO, +					 "Table has invalid signature [%4.4s] (0x%8.8X), " +					 "must be SSDT or OEMx", +					 acpi_ut_valid_acpi_name(new_table_desc. +								 signature. +								 ascii) ? +					 new_table_desc.signature. +					 ascii : "????", +					 new_table_desc.signature.integer)); + +			status = AE_BAD_SIGNATURE; +			goto release_and_exit; +		} -acpi_status -acpi_tb_store_table(acpi_physical_address address, -		    struct acpi_table_header *table, -		    u32 length, u8 flags, u32 *table_index) -{ -	acpi_status status; -	struct acpi_table_desc *new_table; +		/* Check if table is already registered */ -	/* Ensure that there is room for the table in the Root Table List */ +		for (i = 0; i < acpi_gbl_root_table_list.current_table_count; +		     ++i) { +			/* +			 * Check for a table match on the entire table length, +			 * not just the header. +			 */ +			if (!acpi_tb_compare_tables(&new_table_desc, i)) { +				continue; +			} -	if (acpi_gbl_root_table_list.current_table_count >= -	    acpi_gbl_root_table_list.max_table_count) { -		status = acpi_tb_resize_root_table_list(); -		if (ACPI_FAILURE(status)) { -			return (status); +			/* +			 * Note: the current mechanism does not unregister a table if it is +			 * dynamically unloaded. The related namespace entries are deleted, +			 * but the table remains in the root table list. +			 * +			 * The assumption here is that the number of different tables that +			 * will be loaded is actually small, and there is minimal overhead +			 * in just keeping the table in case it is needed again. +			 * +			 * If this assumption changes in the future (perhaps on large +			 * machines with many table load/unload operations), tables will +			 * need to be unregistered when they are unloaded, and slots in the +			 * root table list should be reused when empty. +			 */ +			if (acpi_gbl_root_table_list.tables[i]. +			    flags & ACPI_TABLE_IS_LOADED) { + +				/* Table is still loaded, this is an error */ + +				status = AE_ALREADY_EXISTS; +				goto release_and_exit; +			} else { +				/* +				 * Table was unloaded, allow it to be reloaded. +				 * As we are going to return AE_OK to the caller, we should +				 * take the responsibility of freeing the input descriptor. +				 * Refill the input descriptor to ensure +				 * acpi_tb_install_table_with_override() can be called again to +				 * indicate the re-installation. +				 */ +				acpi_tb_uninstall_table(&new_table_desc); +				*table_index = i; +				(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); +				return_ACPI_STATUS(AE_OK); +			}  		}  	} -	new_table = -	    &acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list. -					     current_table_count]; - -	/* Initialize added table */ - -	new_table->address = address; -	new_table->pointer = table; -	new_table->length = length; -	new_table->owner_id = 0; -	new_table->flags = flags; - -	ACPI_MOVE_32_TO_32(&new_table->signature, table->signature); - -	*table_index = acpi_gbl_root_table_list.current_table_count; -	acpi_gbl_root_table_list.current_table_count++; -	return (AE_OK); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_tb_delete_table - * - * PARAMETERS:  table_index         - Table index - * - * RETURN:      None - * - * DESCRIPTION: Delete one internal ACPI table - * - ******************************************************************************/ +	/* Add the table to the global root table list */ -void acpi_tb_delete_table(struct acpi_table_desc *table_desc) -{ -	/* Table must be mapped or allocated */ -	if (!table_desc->pointer) { -		return; +	status = acpi_tb_get_next_root_index(&i); +	if (ACPI_FAILURE(status)) { +		goto release_and_exit;  	} -	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { -	case ACPI_TABLE_ORIGIN_MAPPED: - -		acpi_os_unmap_memory(table_desc->pointer, table_desc->length); -		break; - -	case ACPI_TABLE_ORIGIN_ALLOCATED: -		ACPI_FREE(table_desc->pointer); -		break; +	*table_index = i; +	acpi_tb_install_table_with_override(i, &new_table_desc, override); -		/* Not mapped or allocated, there is nothing we can do */ +release_and_exit: -	default: +	/* Release the temporary table descriptor */ -		return; -	} - -	table_desc->pointer = NULL; +	acpi_tb_release_temp_table(&new_table_desc); +	return_ACPI_STATUS(status);  }  /*******************************************************************************   * - * FUNCTION:    acpi_tb_terminate + * FUNCTION:    acpi_tb_override_table   * - * PARAMETERS:  None + * PARAMETERS:  old_table_desc      - Validated table descriptor to be + *                                    overridden   *   * RETURN:      None   * - * DESCRIPTION: Delete all internal ACPI tables + * DESCRIPTION: Attempt table override by calling the OSL override functions. + *              Note: If the table is overridden, then the entire new table + *              is acquired and returned by this function. + *              Before/after invocation, the table descriptor is in a state + *              that is "VALIDATED".   *   ******************************************************************************/ -void acpi_tb_terminate(void) +void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)  { -	u32 i; - -	ACPI_FUNCTION_TRACE(tb_terminate); - -	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); - -	/* Delete the individual tables */ +	acpi_status status; +	char *override_type; +	struct acpi_table_desc new_table_desc; +	struct acpi_table_header *table; +	acpi_physical_address address; +	u32 length; -	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { -		acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); -	} +	/* (1) Attempt logical override (returns a logical address) */ -	/* -	 * Delete the root table array if allocated locally. Array cannot be -	 * mapped, so we don't need to check for that flag. -	 */ -	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { -		ACPI_FREE(acpi_gbl_root_table_list.tables); +	status = acpi_os_table_override(old_table_desc->pointer, &table); +	if (ACPI_SUCCESS(status) && table) { +		acpi_tb_acquire_temp_table(&new_table_desc, +					   ACPI_PTR_TO_PHYSADDR(table), +					   ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); +		override_type = "Logical"; +		goto finish_override;  	} -	acpi_gbl_root_table_list.tables = NULL; -	acpi_gbl_root_table_list.flags = 0; -	acpi_gbl_root_table_list.current_table_count = 0; +	/* (2) Attempt physical override (returns a physical address) */ -	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); -	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); +	status = acpi_os_physical_table_override(old_table_desc->pointer, +						 &address, &length); +	if (ACPI_SUCCESS(status) && address && length) { +		acpi_tb_acquire_temp_table(&new_table_desc, address, +					   ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); +		override_type = "Physical"; +		goto finish_override; +	} -	return_VOID; -} +	return;			/* There was no override */ -/******************************************************************************* - * - * FUNCTION:    acpi_tb_delete_namespace_by_owner - * - * PARAMETERS:  table_index         - Table index - * - * RETURN:      Status - * - * DESCRIPTION: Delete all namespace objects created when this table was loaded. - * - ******************************************************************************/ - -acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index) -{ -	acpi_owner_id owner_id; -	acpi_status status; +finish_override: -	ACPI_FUNCTION_TRACE(tb_delete_namespace_by_owner); +	/* Validate and verify a table before overriding */ -	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); +	status = acpi_tb_verify_temp_table(&new_table_desc, NULL);  	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); +		return;  	} -	if (table_index >= acpi_gbl_root_table_list.current_table_count) { - -		/* The table index does not exist */ - -		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -		return_ACPI_STATUS(AE_NOT_EXIST); -	} +	ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT +		   " %s table override, new table: " ACPI_PRINTF_UINT, +		   old_table_desc->signature.ascii, +		   ACPI_FORMAT_TO_UINT(old_table_desc->address), +		   override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address))); -	/* Get the owner ID for this table, used to delete namespace nodes */ +	/* We can now uninstall the original table */ -	owner_id = acpi_gbl_root_table_list.tables[table_index].owner_id; -	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); +	acpi_tb_uninstall_table(old_table_desc);  	/* -	 * Need to acquire the namespace writer lock to prevent interference -	 * with any concurrent namespace walks. The interpreter must be -	 * released during the deletion since the acquisition of the deletion -	 * lock may block, and also since the execution of a namespace walk -	 * must be allowed to use the interpreter. +	 * Replace the original table descriptor and keep its state as +	 * "VALIDATED".  	 */ -	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER); -	status = acpi_ut_acquire_write_lock(&acpi_gbl_namespace_rw_lock); - -	acpi_ns_delete_namespace_by_owner(owner_id); -	if (ACPI_FAILURE(status)) { -		return_ACPI_STATUS(status); -	} +	acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address, +				      new_table_desc.flags, +				      new_table_desc.pointer); +	acpi_tb_validate_temp_table(old_table_desc); -	acpi_ut_release_write_lock(&acpi_gbl_namespace_rw_lock); +	/* Release the temporary table descriptor */ -	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER); -	return_ACPI_STATUS(status); +	acpi_tb_release_temp_table(&new_table_desc);  }  /*******************************************************************************   * - * FUNCTION:    acpi_tb_allocate_owner_id + * FUNCTION:    acpi_tb_store_table   * - * PARAMETERS:  table_index         - Table index + * PARAMETERS:  address             - Table address + *              table               - Table header + *              length              - Table length + *              flags               - Install flags + *              table_index         - Where the table index is returned   * - * RETURN:      Status + * RETURN:      Status and table index.   * - * DESCRIPTION: Allocates owner_id in table_desc + * DESCRIPTION: Add an ACPI table to the global table list   *   ******************************************************************************/ -acpi_status acpi_tb_allocate_owner_id(u32 table_index) +acpi_status +acpi_tb_store_table(acpi_physical_address address, +		    struct acpi_table_header * table, +		    u32 length, u8 flags, u32 *table_index)  { -	acpi_status status = AE_BAD_PARAMETER; - -	ACPI_FUNCTION_TRACE(tb_allocate_owner_id); +	acpi_status status; +	struct acpi_table_desc *table_desc; -	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); -	if (table_index < acpi_gbl_root_table_list.current_table_count) { -		status = acpi_ut_allocate_owner_id -		    (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); +	status = acpi_tb_get_next_root_index(table_index); +	if (ACPI_FAILURE(status)) { +		return (status);  	} -	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_tb_release_owner_id - * - * PARAMETERS:  table_index         - Table index - * - * RETURN:      Status - * - * DESCRIPTION: Releases owner_id in table_desc - * - ******************************************************************************/ - -acpi_status acpi_tb_release_owner_id(u32 table_index) -{ -	acpi_status status = AE_BAD_PARAMETER; - -	ACPI_FUNCTION_TRACE(tb_release_owner_id); - -	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); -	if (table_index < acpi_gbl_root_table_list.current_table_count) { -		acpi_ut_release_owner_id(& -					 (acpi_gbl_root_table_list. -					  tables[table_index].owner_id)); -		status = AE_OK; -	} +	/* Initialize added table */ -	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -	return_ACPI_STATUS(status); +	table_desc = &acpi_gbl_root_table_list.tables[*table_index]; +	acpi_tb_init_table_descriptor(table_desc, address, flags, table); +	table_desc->pointer = table; +	return (AE_OK);  }  /*******************************************************************************   * - * FUNCTION:    acpi_tb_get_owner_id + * FUNCTION:    acpi_tb_uninstall_table   * - * PARAMETERS:  table_index         - Table index - *              owner_id            - Where the table owner_id is returned + * PARAMETERS:  table_desc          - Table descriptor   * - * RETURN:      Status + * RETURN:      None   * - * DESCRIPTION: returns owner_id for the ACPI table + * DESCRIPTION: Delete one internal ACPI table   *   ******************************************************************************/ -acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id) +void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)  { -	acpi_status status = AE_BAD_PARAMETER; - -	ACPI_FUNCTION_TRACE(tb_get_owner_id); - -	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); -	if (table_index < acpi_gbl_root_table_list.current_table_count) { -		*owner_id = -		    acpi_gbl_root_table_list.tables[table_index].owner_id; -		status = AE_OK; -	} -	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -	return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_tb_is_table_loaded - * - * PARAMETERS:  table_index         - Table index - * - * RETURN:      Table Loaded Flag - * - ******************************************************************************/ +	ACPI_FUNCTION_TRACE(tb_uninstall_table); -u8 acpi_tb_is_table_loaded(u32 table_index) -{ -	u8 is_loaded = FALSE; +	/* Table must be installed */ -	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); -	if (table_index < acpi_gbl_root_table_list.current_table_count) { -		is_loaded = (u8) -		    (acpi_gbl_root_table_list.tables[table_index].flags & -		     ACPI_TABLE_IS_LOADED); +	if (!table_desc->address) { +		return_VOID;  	} -	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); -	return (is_loaded); -} - -/******************************************************************************* - * - * FUNCTION:    acpi_tb_set_table_loaded_flag - * - * PARAMETERS:  table_index         - Table index - *              is_loaded           - TRUE if table is loaded, FALSE otherwise - * - * RETURN:      None - * - * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. - * - ******************************************************************************/ - -void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded) -{ +	acpi_tb_invalidate_table(table_desc); -	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); -	if (table_index < acpi_gbl_root_table_list.current_table_count) { -		if (is_loaded) { -			acpi_gbl_root_table_list.tables[table_index].flags |= -			    ACPI_TABLE_IS_LOADED; -		} else { -			acpi_gbl_root_table_list.tables[table_index].flags &= -			    ~ACPI_TABLE_IS_LOADED; -		} +	if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == +	    ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { +		ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address));  	} -	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); +	table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); +	return_VOID;  }  | 
