Exemple #1
0
acpi_status acpi_load_table(struct acpi_table_header *table)
{
	acpi_status status;
	struct acpi_table_desc table_desc;
	u32 table_index;

	ACPI_FUNCTION_TRACE(acpi_load_table);

	/* Parameter validation */

	if (!table) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
	}

	/* Init local table descriptor */

	ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
	table_desc.address = ACPI_PTR_TO_PHYSADDR(table);
	table_desc.pointer = table;
	table_desc.length = table->length;
	table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN;

	/* Must acquire the interpreter lock during this operation */

	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Install the table and load it into the namespace */

	ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:"));
	status = acpi_tb_add_table(&table_desc, &table_index);
	if (ACPI_FAILURE(status)) {
		goto unlock_and_exit;
	}

	status = acpi_ns_load_table(table_index, acpi_gbl_root_node);

	/* Invoke table handler if present */

	if (acpi_gbl_table_handler) {
		(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
					     acpi_gbl_table_handler_context);
	}

      unlock_and_exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
	return_ACPI_STATUS(status);
}
/*******************************************************************************
 *
 * FUNCTION:    acpi_load_table
 *
 * PARAMETERS:  table_ptr       - pointer to a buffer containing the entire
 *                                table to be loaded
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This function is called to load a table from the caller's
 *              buffer. The buffer must contain an entire ACPI Table including
 *              a valid header. The header fields will be verified, and if it
 *              is determined that the table is invalid, the call will fail.
 *
 ******************************************************************************/
acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
{
	acpi_status status;
	u32 table_index;
	struct acpi_table_desc table_desc;

	if (!table_ptr)
		return AE_BAD_PARAMETER;

	ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
	table_desc.pointer = table_ptr;
	table_desc.length = table_ptr->length;
	table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN;

	/*
	 * Install the new table into the local data structures
	 */
	status = acpi_tb_add_table(&table_desc, &table_index);
	if (ACPI_FAILURE(status)) {
		return status;
	}
	status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
	return status;
}
acpi_status
acpi_ex_load_op(union acpi_operand_object *obj_desc,
		union acpi_operand_object *target,
		struct acpi_walk_state *walk_state)
{
	union acpi_operand_object *ddb_handle;
	struct acpi_table_desc table_desc;
	u32 table_index;
	acpi_status status;
	u32 length;

	ACPI_FUNCTION_TRACE(ex_load_op);

	ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));

	/* Source Object can be either an op_region or a Buffer/Field */

	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
	case ACPI_TYPE_REGION:

		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
				  obj_desc,
				  acpi_ut_get_object_type_name(obj_desc)));

		/* Region must be system_memory (from ACPI spec) */

		if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
		}

		/*
		 * If the Region Address and Length have not been previously evaluated,
		 * evaluate them now and save the results.
		 */
		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
			status = acpi_ds_get_region_arguments(obj_desc);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}

		/*
		 * We will simply map the memory region for the table. However, the
		 * memory region is technically not guaranteed to remain stable and
		 * we may eventually have to copy the table to a local buffer.
		 */
		table_desc.address = obj_desc->region.address;
		table_desc.length = obj_desc->region.length;
		table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED;
		break;

	case ACPI_TYPE_BUFFER:	/* Buffer or resolved region_field */

		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
				  "Load from Buffer or Field %p %s\n", obj_desc,
				  acpi_ut_get_object_type_name(obj_desc)));

		length = obj_desc->buffer.length;

		/* Must have at least an ACPI table header */

		if (length < sizeof(struct acpi_table_header)) {
			return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
		}

		/* Validate checksum here. It won't get validated in tb_add_table */

		status =
		    acpi_tb_verify_checksum(ACPI_CAST_PTR
					    (struct acpi_table_header,
					     obj_desc->buffer.pointer), length);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		/*
		 * We need to copy the buffer since the original buffer could be
		 * changed or deleted in the future
		 */
		table_desc.pointer = ACPI_ALLOCATE(length);
		if (!table_desc.pointer) {
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		ACPI_MEMCPY(table_desc.pointer, obj_desc->buffer.pointer,
			    length);
		table_desc.length = length;
		table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
		break;

	default:
		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
	}

	/*
	 * Install the new table into the local data structures
	 */
	status = acpi_tb_add_table(&table_desc, &table_index);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	/*
	 * Add the table to the namespace.
	 *
	 * Note: We load the table objects relative to the root of the namespace.
	 * This appears to go against the ACPI specification, but we do it for
	 * compatibility with other ACPI implementations.
	 */
	status =
	    acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
	if (ACPI_FAILURE(status)) {

		/* On error, table_ptr was deallocated above */

		return_ACPI_STATUS(status);
	}

	/* Store the ddb_handle into the Target operand */

	status = acpi_ex_store(ddb_handle, target, walk_state);
	if (ACPI_FAILURE(status)) {
		(void)acpi_ex_unload_table(ddb_handle);

		/* table_ptr was deallocated above */

		acpi_ut_remove_reference(ddb_handle);
		return_ACPI_STATUS(status);
	}

	/* Invoke table handler if present */

	if (acpi_gbl_table_handler) {
		(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD,
					     table_desc.pointer,
					     acpi_gbl_table_handler_context);
	}

      cleanup:
	if (ACPI_FAILURE(status)) {

		/* Delete allocated buffer or mapping */

		acpi_tb_delete_table(&table_desc);
	}
	return_ACPI_STATUS(status);
}
Exemple #4
0
acpi_status
acpi_ex_load_op(union acpi_operand_object *obj_desc,
		union acpi_operand_object *target,
		struct acpi_walk_state *walk_state)
{
	union acpi_operand_object *ddb_handle;
	struct acpi_table_desc table_desc;
	acpi_native_uint table_index;
	acpi_status status;
	u32 length;
	void *maddr;

	ACPI_FUNCTION_TRACE(ex_load_op);

	ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));

	/* Source Object can be either an op_region or a Buffer/Field */

	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
	case ACPI_TYPE_REGION:

		/* Region must be system_memory (from ACPI spec) */

		if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
		}

		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n",
				  obj_desc,
				  acpi_ut_get_object_type_name(obj_desc)));

		/*
		 * If the Region Address and Length have not been previously evaluated,
		 * evaluate them now and save the results.
		 */
		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
			status = acpi_ds_get_region_arguments(obj_desc);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}

 		length = obj_desc->region.length;
 		table_desc.pointer = ACPI_ALLOCATE(length);
 		if (!table_desc.pointer) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}

 		maddr = acpi_os_map_memory(obj_desc->region.address, length);
 		if (!maddr) {
 			ACPI_FREE(table_desc.pointer);
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
 		ACPI_MEMCPY(table_desc.pointer, maddr, length);
 		acpi_os_unmap_memory(maddr, length);

 		/* Keep the address for the pretty table info print */
		table_desc.address = obj_desc->region.address;
		table_desc.length = obj_desc->region.length;
		table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;
		break;

	case ACPI_TYPE_BUFFER:	/* Buffer or resolved region_field */

		/* Simply extract the buffer from the buffer object */

		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
				  "Load from Buffer or Field %p %s\n", obj_desc,
				  acpi_ut_get_object_type_name(obj_desc)));

		table_desc.pointer = ACPI_CAST_PTR(struct acpi_table_header,
						   obj_desc->buffer.pointer);
		table_desc.length = table_desc.pointer->length;
		table_desc.flags = ACPI_TABLE_ORIGIN_ALLOCATED;

		obj_desc->buffer.pointer = NULL;
		break;

	default:
		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
	}

	/*
	 * Install the new table into the local data structures
	 */
	status = acpi_tb_add_table(&table_desc, &table_index);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	status =
	    acpi_ex_add_table(table_index, acpi_gbl_root_node, &ddb_handle);
	if (ACPI_FAILURE(status)) {

		/* On error, table_ptr was deallocated above */

		return_ACPI_STATUS(status);
	}

	/* Store the ddb_handle into the Target operand */

	status = acpi_ex_store(ddb_handle, target, walk_state);
	if (ACPI_FAILURE(status)) {
		(void)acpi_ex_unload_table(ddb_handle);

		/* table_ptr was deallocated above */

		return_ACPI_STATUS(status);
	}

      cleanup:
	if (ACPI_FAILURE(status)) {
		acpi_tb_delete_table(&table_desc);
	}
	return_ACPI_STATUS(status);
}