Пример #1
0
acpi_status
acpi_tb_get_table_body (
	struct acpi_pointer             *address,
	struct acpi_table_header        *header,
	struct acpi_table_desc          *table_info)
{
	acpi_status                     status;


	ACPI_FUNCTION_TRACE ("tb_get_table_body");


	if (!table_info || !address) {
		return_ACPI_STATUS (AE_BAD_PARAMETER);
	}

	/* Attempt table override. */

	status = acpi_tb_table_override (header, table_info);
	if (ACPI_SUCCESS (status)) {
		/* Table was overridden by the host OS */

		return_ACPI_STATUS (status);
	}

	/* No override, get the original table */

	status = acpi_tb_get_this_table (address, header, table_info);
	return_ACPI_STATUS (status);
}
Пример #2
0
acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
	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);
		}
	}

	/*
	 * 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 ((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_ERROR((AE_INFO,
			    "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
			    acpi_ut_valid_acpi_name(*(u32 *)table_desc->
						    pointer->
						    signature) ? table_desc->
			    pointer->signature : "????",
			    *(u32 *)table_desc->pointer->signature));

		return_ACPI_STATUS(AE_BAD_SIGNATURE);
	}

	(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;

		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;
		} 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;
	}

      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);
}
acpi_status
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
{
	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_desc->pointer->signature[0] != 0x00) &&
	    (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
	    && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) {
		ACPI_ERROR((AE_INFO,
			    "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
			    acpi_ut_valid_acpi_name(*(u32 *)table_desc->
						    pointer->
						    signature) ? table_desc->
			    pointer->signature : "????",
			    *(u32 *)table_desc->pointer->signature));

		return_ACPI_STATUS(AE_BAD_SIGNATURE);
	}

	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);

	

	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;
			}
		}

		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;
		}


		acpi_tb_delete_table(table_desc);
		*table_index = i;

		if (acpi_gbl_root_table_list.tables[i].
		    flags & ACPI_TABLE_IS_LOADED) {

			

			status = AE_ALREADY_EXISTS;
			goto release;
		} else {
			

			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;
		}
	}

	(void)acpi_tb_table_override(table_desc->pointer, table_desc);

	

	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;
	}

      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);
}