Ejemplo n.º 1
0
acpi_status
acpi_ev_address_space_dispatch (
	union acpi_operand_object       *region_obj,
	u32                             function,
	acpi_physical_address           address,
	u32                             bit_width,
	void                            *value)
{
	acpi_status                     status;
	acpi_status                     status2;
	acpi_adr_space_handler          handler;
	acpi_adr_space_setup            region_setup;
	union acpi_operand_object       *handler_desc;
	union acpi_operand_object       *region_obj2;
	void                            *region_context = NULL;


	ACPI_FUNCTION_TRACE ("ev_address_space_dispatch");


	region_obj2 = acpi_ns_get_secondary_object (region_obj);
	if (!region_obj2) {
		return_ACPI_STATUS (AE_NOT_EXIST);
	}

	/* Ensure that there is a handler associated with this region */

	handler_desc = region_obj->region.address_space;
	if (!handler_desc) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n",
			region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));

		return_ACPI_STATUS (AE_NOT_EXIST);
	}

	/*
	 * It may be the case that the region has never been initialized
	 * Some types of regions require special init code
	 */
	if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
		/*
		 * This region has not been initialized yet, do it
		 */
		region_setup = handler_desc->address_space.setup;
		if (!region_setup) {
			/* No initialization routine, exit with error */

			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
				region_obj, acpi_ut_get_region_name (region_obj->region.space_id)));
			return_ACPI_STATUS (AE_NOT_EXIST);
		}

		/*
		 * We must exit the interpreter because the region setup will potentially
		 * execute control methods (e.g., _REG method for this region)
		 */
		acpi_ex_exit_interpreter ();

		status = region_setup (region_obj, ACPI_REGION_ACTIVATE,
				  handler_desc->address_space.context, &region_context);

		/* Re-enter the interpreter */

		status2 = acpi_ex_enter_interpreter ();
		if (ACPI_FAILURE (status2)) {
			return_ACPI_STATUS (status2);
		}

		/* Check for failure of the Region Setup */

		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
				acpi_format_exception (status),
				acpi_ut_get_region_name (region_obj->region.space_id)));
			return_ACPI_STATUS (status);
		}

		/*
		 * Region initialization may have been completed by region_setup
		 */
		if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
			region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;

			if (region_obj2->extra.region_context) {
				/* The handler for this region was already installed */

				ACPI_MEM_FREE (region_context);
			}
			else {
				/*
				 * Save the returned context for use in all accesses to
				 * this particular region
				 */
				region_obj2->extra.region_context = region_context;
			}
		}
	}

	/* We have everything we need, we can invoke the address space handler */

	handler = handler_desc->address_space.handler;

	ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
		"Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
		&region_obj->region.address_space->address_space, handler,
		ACPI_HIDWORD (address), ACPI_LODWORD (address),
		acpi_ut_get_region_name (region_obj->region.space_id)));

	if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 * For handlers other than the default (supplied) handlers, we must
		 * exit the interpreter because the handler *might* block -- we don't
		 * know what it will do, so we can't hold the lock on the intepreter.
		 */
		acpi_ex_exit_interpreter();
	}

	/* Call the handler */

	status = handler (function, address, bit_width, value,
			 handler_desc->address_space.context,
			 region_obj2->extra.region_context);

	if (ACPI_FAILURE (status)) {
		ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
			acpi_ut_get_region_name (region_obj->region.space_id),
			acpi_format_exception (status)));
	}

	if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 * We just returned from a non-default handler, we must re-enter the
		 * interpreter
		 */
		status2 = acpi_ex_enter_interpreter ();
		if (ACPI_FAILURE (status2)) {
			return_ACPI_STATUS (status2);
		}
	}

	return_ACPI_STATUS (status);
}
Ejemplo n.º 2
0
static acpi_status
acpi_ns_init_one_object(acpi_handle obj_handle,
			u32 level, void *context, void **return_value)
{
	acpi_object_type type;
	acpi_status status = AE_OK;
	struct acpi_init_walk_info *info =
	    (struct acpi_init_walk_info *)context;
	struct acpi_namespace_node *node =
	    (struct acpi_namespace_node *)obj_handle;
	union acpi_operand_object *obj_desc;

	ACPI_FUNCTION_NAME(ns_init_one_object);

	info->object_count++;

	/* And even then, we are only interested in a few object types */

	type = acpi_ns_get_type(obj_handle);
	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return (AE_OK);
	}

	/* Increment counters for object types we are looking for */

	switch (type) {
	case ACPI_TYPE_REGION:

		info->op_region_count++;
		break;

	case ACPI_TYPE_BUFFER_FIELD:

		info->field_count++;
		break;

	case ACPI_TYPE_LOCAL_BANK_FIELD:

		info->field_count++;
		break;

	case ACPI_TYPE_BUFFER:

		info->buffer_count++;
		break;

	case ACPI_TYPE_PACKAGE:

		info->package_count++;
		break;

	default:

		/* No init required, just exit now */

		return (AE_OK);
	}

	/* If the object is already initialized, nothing else to do */

	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
		return (AE_OK);
	}

	/* Must lock the interpreter before executing AML code */

	acpi_ex_enter_interpreter();

	/*
	 * Each of these types can contain executable AML code within the
	 * declaration.
	 */
	switch (type) {
	case ACPI_TYPE_REGION:

		info->op_region_init++;
		status = acpi_ds_get_region_arguments(obj_desc);
		break;

	case ACPI_TYPE_BUFFER_FIELD:

		info->field_init++;
		status = acpi_ds_get_buffer_field_arguments(obj_desc);
		break;

	case ACPI_TYPE_LOCAL_BANK_FIELD:

		info->field_init++;
		status = acpi_ds_get_bank_field_arguments(obj_desc);
		break;

	case ACPI_TYPE_BUFFER:

		info->buffer_init++;
		status = acpi_ds_get_buffer_arguments(obj_desc);
		break;

	case ACPI_TYPE_PACKAGE:

		/* Complete the initialization/resolution of the package object */

		info->package_init++;
		status =
		    acpi_ns_init_one_package(obj_handle, level, NULL, NULL);
		break;

	default:

		/* No other types can get here */

		break;
	}

	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status,
				"Could not execute arguments for [%4.4s] (%s)",
				acpi_ut_get_node_name(node),
				acpi_ut_get_type_name(type)));
	}

	/*
	 * We ignore errors from above, and always return OK, since we don't want
	 * to abort the walk on any single error.
	 */
	acpi_ex_exit_interpreter();
	return (AE_OK);
}
Ejemplo n.º 3
0
acpi_status
acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
			       union acpi_operand_object *field_obj,
			       u32 function,
			       u32 region_offset, u32 bit_width, u64 *value)
{
	acpi_status status;
	acpi_adr_space_handler handler;
	acpi_adr_space_setup region_setup;
	union acpi_operand_object *handler_desc;
	union acpi_operand_object *region_obj2;
	void *region_context = NULL;
	struct acpi_connection_info *context;
	acpi_physical_address address;

	ACPI_FUNCTION_TRACE(ev_address_space_dispatch);

	region_obj2 = acpi_ns_get_secondary_object(region_obj);
	if (!region_obj2) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/* Ensure that there is a handler associated with this region */

	handler_desc = region_obj->region.handler;
	if (!handler_desc) {
		ACPI_ERROR((AE_INFO,
			    "No handler for Region [%4.4s] (%p) [%s]",
			    acpi_ut_get_node_name(region_obj->region.node),
			    region_obj,
			    acpi_ut_get_region_name(region_obj->region.
						    space_id)));

		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	context = handler_desc->address_space.context;

	/*
	 * It may be the case that the region has never been initialized.
	 * Some types of regions require special init code
	 */
	if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {

		/* This region has not been initialized yet, do it */

		region_setup = handler_desc->address_space.setup;
		if (!region_setup) {

			/* No initialization routine, exit with error */

			ACPI_ERROR((AE_INFO,
				    "No init routine for region(%p) [%s]",
				    region_obj,
				    acpi_ut_get_region_name(region_obj->region.
							    space_id)));
			return_ACPI_STATUS(AE_NOT_EXIST);
		}

		/*
		 * We must exit the interpreter because the region setup will
		 * potentially execute control methods (for example, the _REG method
		 * for this region)
		 */
		acpi_ex_exit_interpreter();

		status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
				      context, &region_context);

		/* Re-enter the interpreter */

		acpi_ex_enter_interpreter();

		/* Check for failure of the Region Setup */

		if (ACPI_FAILURE(status)) {
			ACPI_EXCEPTION((AE_INFO, status,
					"During region initialization: [%s]",
					acpi_ut_get_region_name(region_obj->
								region.
								space_id)));
			return_ACPI_STATUS(status);
		}

		/* Region initialization may have been completed by region_setup */

		if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
			region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;

			/*
			 * Save the returned context for use in all accesses to
			 * the handler for this particular region
			 */
			if (!(region_obj2->extra.region_context)) {
				region_obj2->extra.region_context =
				    region_context;
			}
		}
	}

	/* We have everything we need, we can invoke the address space handler */

	handler = handler_desc->address_space.handler;
	address = (region_obj->region.address + region_offset);

	/*
	 * Special handling for generic_serial_bus and general_purpose_io:
	 * There are three extra parameters that must be passed to the
	 * handler via the context:
	 *   1) Connection buffer, a resource template from Connection() op
	 *   2) Length of the above buffer
	 *   3) Actual access length from the access_as() op
	 *
	 * In addition, for general_purpose_io, the Address and bit_width fields
	 * are defined as follows:
	 *   1) Address is the pin number index of the field (bit offset from
	 *      the previous Connection)
	 *   2) bit_width is the actual bit length of the field (number of pins)
	 */
	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
	    context && field_obj) {

		/* Get the Connection (resource_template) buffer */

		context->connection = field_obj->field.resource_buffer;
		context->length = field_obj->field.resource_length;
		context->access_length = field_obj->field.access_length;
	}
	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
	    context && field_obj) {

		/* Get the Connection (resource_template) buffer */

		context->connection = field_obj->field.resource_buffer;
		context->length = field_obj->field.resource_length;
		context->access_length = field_obj->field.access_length;
		address = field_obj->field.pin_number_index;
		bit_width = field_obj->field.bit_length;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
			  &region_obj->region.handler->address_space, handler,
			  ACPI_FORMAT_UINT64(address),
			  acpi_ut_get_region_name(region_obj->region.
						  space_id)));

	if (!(handler_desc->address_space.handler_flags &
	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 * For handlers other than the default (supplied) handlers, we must
		 * exit the interpreter because the handler *might* block -- we don't
		 * know what it will do, so we can't hold the lock on the intepreter.
		 */
		acpi_ex_exit_interpreter();
	}

	/* Call the handler */

	status = handler(function, address, bit_width, value, context,
			 region_obj2->extra.region_context);

	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
				acpi_ut_get_region_name(region_obj->region.
							space_id)));
	}

	if (!(handler_desc->address_space.handler_flags &
	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
		/*
		 * We just returned from a non-default handler, we must re-enter the
		 * interpreter
		 */
		acpi_ex_enter_interpreter();
	}

	return_ACPI_STATUS(status);
}
Ejemplo n.º 4
0
acpi_status
acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node)
{
	acpi_status status;

	ACPI_FUNCTION_TRACE(ns_load_table);

	acpi_ex_enter_interpreter();

	/*
	 * Parse the table and load the namespace with all named
	 * objects found within. Control methods are NOT parsed
	 * at this time. In fact, the control methods cannot be
	 * parsed until the entire namespace is loaded, because
	 * if a control method makes a forward reference (call)
	 * to another control method, we can't continue parsing
	 * because we don't know how many arguments to parse next!
	 */
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		goto unlock_interp;
	}

	/* If table already loaded into namespace, just return */

	if (acpi_tb_is_table_loaded(table_index)) {
		status = AE_ALREADY_EXISTS;
		goto unlock;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "**** Loading table into namespace ****\n"));

	status = acpi_tb_allocate_owner_id(table_index);
	if (ACPI_FAILURE(status)) {
		goto unlock;
	}

	status = acpi_ns_parse_table(table_index, node);
	if (ACPI_SUCCESS(status)) {
		acpi_tb_set_table_loaded_flag(table_index, TRUE);
	} else {
		/*
		 * On error, delete any namespace objects created by this table.
		 * We cannot initialize these objects, so delete them. There are
		 * a couple of expecially bad cases:
		 * AE_ALREADY_EXISTS - namespace collision.
		 * AE_NOT_FOUND - the target of a Scope operator does not
		 * exist. This target of Scope must already exist in the
		 * namespace, as per the ACPI specification.
		 */
		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
		acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list.
						  tables[table_index].owner_id);

		acpi_tb_release_owner_id(table_index);
		return_ACPI_STATUS(status);
	}

unlock:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
unlock_interp:
	(void)acpi_ex_exit_interpreter();

	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Now we can parse the control methods. We always parse
	 * them here for a sanity check, and if configured for
	 * just-in-time parsing, we delete the control method
	 * parse trees.
	 */
	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "**** Begin Table Object Initialization\n"));

	status = acpi_ds_initialize_objects(table_index, node);

	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
			  "**** Completed Table Object Initialization\n"));

	/*
	 * Execute any module-level code that was detected during the table load
	 * phase. Although illegal since ACPI 2.0, there are many machines that
	 * contain this type of code. Each block of detected executable AML code
	 * outside of any control method is wrapped with a temporary control
	 * method object and placed on a global list. The methods on this list
	 * are executed below.
	 *
	 * This case executes the module-level code for each table immediately
	 * after the table has been loaded. This provides compatibility with
	 * other ACPI implementations. Optionally, the execution can be deferred
	 * until later, see acpi_initialize_objects.
	 */
	if (!acpi_gbl_group_module_level_code) {
		acpi_ns_exec_module_code_list();
	}

	return_ACPI_STATUS(status);
}
Ejemplo n.º 5
0
static acpi_status
acpi_ns_init_one_object(acpi_handle obj_handle,
			u32 level, void *context, void **return_value)
{
	acpi_object_type type;
	acpi_status status;
	struct acpi_init_walk_info *info =
	    (struct acpi_init_walk_info *)context;
	struct acpi_namespace_node *node =
	    (struct acpi_namespace_node *)obj_handle;
	union acpi_operand_object *obj_desc;

	ACPI_FUNCTION_NAME("ns_init_one_object");

	info->object_count++;

	/* And even then, we are only interested in a few object types */

	type = acpi_ns_get_type(obj_handle);
	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return (AE_OK);
	}

	/* Increment counters for object types we are looking for */

	switch (type) {
	case ACPI_TYPE_REGION:
		info->op_region_count++;
		break;

	case ACPI_TYPE_BUFFER_FIELD:
		info->field_count++;
		break;

	case ACPI_TYPE_BUFFER:
		info->buffer_count++;
		break;

	case ACPI_TYPE_PACKAGE:
		info->package_count++;
		break;

	default:

		/* No init required, just exit now */
		return (AE_OK);
	}

	/*
	 * If the object is already initialized, nothing else to do
	 */
	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
		return (AE_OK);
	}

	/*
	 * Must lock the interpreter before executing AML code
	 */
	status = acpi_ex_enter_interpreter();
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/*
	 * Each of these types can contain executable AML code within the
	 * declaration.
	 */
	switch (type) {
	case ACPI_TYPE_REGION:

		info->op_region_init++;
		status = acpi_ds_get_region_arguments(obj_desc);
		break;

	case ACPI_TYPE_BUFFER_FIELD:

		info->field_init++;
		status = acpi_ds_get_buffer_field_arguments(obj_desc);
		break;

	case ACPI_TYPE_BUFFER:

		info->buffer_init++;
		status = acpi_ds_get_buffer_arguments(obj_desc);
		break;

	case ACPI_TYPE_PACKAGE:

		info->package_init++;
		status = acpi_ds_get_package_arguments(obj_desc);
		break;

	default:
		/* No other types can get here */
		break;
	}

	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR, "\n"));
		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
				  "Could not execute arguments for [%4.4s] (%s), %s\n",
				  acpi_ut_get_node_name(node),
				  acpi_ut_get_type_name(type),
				  acpi_format_exception(status)));
	}

	/*
	 * Print a dot for each object unless we are going to print the entire
	 * pathname
	 */
	if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
	}

	/*
	 * We ignore errors from above, and always return OK, since we don't want
	 * to abort the walk on any single error.
	 */
	acpi_ex_exit_interpreter();
	return (AE_OK);
}
Ejemplo n.º 6
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_evaluate_object
 *
 * PARAMETERS:  Handle              - Object handle (optional)
 *              Pathname            - Object pathname (optional)
 *              external_params     - List of parameters to pass to method,
 *                                    terminated by NULL.  May be NULL
 *                                    if no parameters are being passed.
 *              return_buffer       - Where to put method's return value (if
 *                                    any).  If NULL, no value is returned.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Find and evaluate the given object, passing the given
 *              parameters if necessary.  One of "Handle" or "Pathname" must
 *              be valid (non-null)
 *
 ******************************************************************************/
acpi_status
acpi_evaluate_object(acpi_handle handle,
		     acpi_string pathname,
		     struct acpi_object_list *external_params,
		     struct acpi_buffer *return_buffer)
{
	acpi_status status;
	struct acpi_evaluate_info *info;
	acpi_size buffer_space_needed;
	u32 i;

	ACPI_FUNCTION_TRACE(acpi_evaluate_object);

	/* Allocate and initialize the evaluation information block */

	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	info->pathname = pathname;

	/* Convert and validate the device handle */

	info->prefix_node = acpi_ns_validate_handle(handle);
	if (!info->prefix_node) {
		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	/*
	 * If there are parameters to be passed to a control method, the external
	 * objects must all be converted to internal objects
	 */
	if (external_params && external_params->count) {
		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */
		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
							 external_params->
							 count +
							 1) * sizeof(void *));
		if (!info->parameters) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Convert each external object in the list to an internal object */

		for (i = 0; i < external_params->count; i++) {
			status =
			    acpi_ut_copy_eobject_to_iobject(&external_params->
							    pointer[i],
							    &info->
							    parameters[i]);
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}
		}
		info->parameters[external_params->count] = NULL;
	}

	/*
	 * Three major cases:
	 * 1) Fully qualified pathname
	 * 2) No handle, not fully qualified pathname (error)
	 * 3) Valid handle
	 */
	if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) {

		/* The path is fully qualified, just evaluate by name */

		info->prefix_node = NULL;
		status = acpi_ns_evaluate(info);
	} else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname is specified.
		 * Since we've already handled fully qualified names above, this is
		 * an error
		 */
		if (!pathname) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Both Handle and Pathname are NULL"));
		} else {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Null Handle with relative pathname [%s]",
					  pathname));
		}

		status = AE_BAD_PARAMETER;
	} else {
		/* We have a namespace a node and a possible relative path */

		status = acpi_ns_evaluate(info);
	}

	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */
	if (return_buffer) {
		if (!info->return_object) {
			return_buffer->length = 0;
		} else {
			if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
			    ACPI_DESC_TYPE_NAMED) {
				/*
				 * If we received a NS Node as a return object, this means that
				 * the object we are evaluating has nothing interesting to
				 * return (such as a mutex, etc.)  We return an error because
				 * these types are essentially unsupported by this interface.
				 * We don't check up front because this makes it easier to add
				 * support for various types at a later date if necessary.
				 */
				status = AE_TYPE;
				info->return_object = NULL;	/* No need to delete a NS Node */
				return_buffer->length = 0;
			}

			if (ACPI_SUCCESS(status)) {

				/* Dereference Index and ref_of references */

				acpi_ns_resolve_references(info);

				/* Get the size of the returned object */

				status =
				    acpi_ut_get_object_size(info->return_object,
							    &buffer_space_needed);
				if (ACPI_SUCCESS(status)) {

					/* Validate/Allocate/Clear caller buffer */

					status =
					    acpi_ut_initialize_buffer
					    (return_buffer,
					     buffer_space_needed);
					if (ACPI_FAILURE(status)) {
						/*
						 * Caller's buffer is too small or a new one can't
						 * be allocated
						 */
						ACPI_DEBUG_PRINT((ACPI_DB_INFO,
								  "Needed buffer size %X, %s\n",
								  (u32)
								  buffer_space_needed,
								  acpi_format_exception
								  (status)));
					} else {
						/* We have enough space for the object, build it */

						status =
						    acpi_ut_copy_iobject_to_eobject
						    (info->return_object,
						     return_buffer);
					}
				}
			}
		}
	}

	if (info->return_object) {
		/*
		 * Delete the internal return object. NOTE: Interpreter must be
		 * locked to avoid race condition.
		 */
		acpi_ex_enter_interpreter();

		/* Remove one reference on the return object (should delete it) */

		acpi_ut_remove_reference(info->return_object);
		acpi_ex_exit_interpreter();
	}

      cleanup:

	/* Free the input parameter list (if we created one) */

	if (info->parameters) {

		/* Free the allocated parameter block */

		acpi_ut_delete_internal_object_list(info->parameters);
	}

	ACPI_FREE(info);
	return_ACPI_STATUS(status);
}
Ejemplo n.º 7
0
static acpi_status
acpi_ns_init_one_object(acpi_handle obj_handle,
			u32 level, void *context, void **return_value)
{
	acpi_object_type type;
	acpi_status status = AE_OK;
	struct acpi_init_walk_info *info =
	    (struct acpi_init_walk_info *)context;
	struct acpi_namespace_node *node =
	    (struct acpi_namespace_node *)obj_handle;
	union acpi_operand_object *obj_desc;

	ACPI_FUNCTION_NAME(ns_init_one_object);

	info->object_count++;

	

	type = acpi_ns_get_type(obj_handle);
	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return (AE_OK);
	}

	

	switch (type) {
	case ACPI_TYPE_REGION:
		info->op_region_count++;
		break;

	case ACPI_TYPE_BUFFER_FIELD:
		info->field_count++;
		break;

	case ACPI_TYPE_LOCAL_BANK_FIELD:
		info->field_count++;
		break;

	case ACPI_TYPE_BUFFER:
		info->buffer_count++;
		break;

	case ACPI_TYPE_PACKAGE:
		info->package_count++;
		break;

	default:

		
		return (AE_OK);
	}

	

	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
		return (AE_OK);
	}

	

	acpi_ex_enter_interpreter();

	switch (type) {
	case ACPI_TYPE_REGION:

		info->op_region_init++;
		status = acpi_ds_get_region_arguments(obj_desc);
		break;

	case ACPI_TYPE_BUFFER_FIELD:

		info->field_init++;
		status = acpi_ds_get_buffer_field_arguments(obj_desc);
		break;

	case ACPI_TYPE_LOCAL_BANK_FIELD:

		info->field_init++;
		status = acpi_ds_get_bank_field_arguments(obj_desc);
		break;

	case ACPI_TYPE_BUFFER:

		info->buffer_init++;
		status = acpi_ds_get_buffer_arguments(obj_desc);
		break;

	case ACPI_TYPE_PACKAGE:

		info->package_init++;
		status = acpi_ds_get_package_arguments(obj_desc);
		break;

	default:
		
		break;
	}

	if (ACPI_FAILURE(status)) {
		ACPI_EXCEPTION((AE_INFO, status,
				"Could not execute arguments for [%4.4s] (%s)",
				acpi_ut_get_node_name(node),
				acpi_ut_get_type_name(type)));
	}

	if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
	}

	acpi_ex_exit_interpreter();
	return (AE_OK);
}
Ejemplo n.º 8
0
acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info)
{
	acpi_status status;
	union acpi_parse_object *op = NULL;
	struct acpi_walk_state *walk_state = NULL;

	ACPI_FUNCTION_TRACE(ps_execute_table);

	/* Create and init a Root Node */

	op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
	if (!op) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	/* Create and initialize a new walk state */

	walk_state =
	    acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
				      NULL, NULL);
	if (!walk_state) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	status = acpi_ds_init_aml_walk(walk_state, op, info->node,
				       info->obj_desc->method.aml_start,
				       info->obj_desc->method.aml_length, info,
				       info->pass_number);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
		walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
	}

	/* Info->Node is the default location to load the table  */

	if (info->node && info->node != acpi_gbl_root_node) {
		status =
		    acpi_ds_scope_stack_push(info->node, ACPI_TYPE_METHOD,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}
	}

	/*
	 * Parse the AML, walk_state will be deleted by parse_aml
	 */
	acpi_ex_enter_interpreter();
	status = acpi_ps_parse_aml(walk_state);
	acpi_ex_exit_interpreter();
	walk_state = NULL;

cleanup:
	if (walk_state) {
		acpi_ds_delete_walk_state(walk_state);
	}
	if (op) {
		acpi_ps_delete_parse_tree(op);
	}
	return_ACPI_STATUS(status);
}
Ejemplo n.º 9
0
acpi_status
acpi_evaluate_object(acpi_handle handle,
		     acpi_string pathname,
		     struct acpi_object_list *external_params,
		     struct acpi_buffer *return_buffer)
{
	acpi_status status;
	acpi_status status2;
	struct acpi_parameter_info info;
	acpi_size buffer_space_needed;
	u32 i;

	ACPI_FUNCTION_TRACE("acpi_evaluate_object");

	info.node = handle;
	info.parameters = NULL;
	info.return_object = NULL;
	info.parameter_type = ACPI_PARAM_ARGS;

	/*
	 * If there are parameters to be passed to the object
	 * (which must be a control method), the external objects
	 * must be converted to internal objects
	 */
	if (external_params && external_params->count) {
		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */
		info.parameters = ACPI_MEM_CALLOCATE(((acpi_size)
						      external_params->count +
						      1) * sizeof(void *));
		if (!info.parameters) {
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		/*
		 * Convert each external object in the list to an
		 * internal object
		 */
		for (i = 0; i < external_params->count; i++) {
			status =
			    acpi_ut_copy_eobject_to_iobject(&external_params->
							    pointer[i],
							    &info.
							    parameters[i]);
			if (ACPI_FAILURE(status)) {
				acpi_ut_delete_internal_object_list(info.
								    parameters);
				return_ACPI_STATUS(status);
			}
		}
		info.parameters[external_params->count] = NULL;
	}

	/*
	 * Three major cases:
	 * 1) Fully qualified pathname
	 * 2) No handle, not fully qualified pathname (error)
	 * 3) Valid handle
	 */
	if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) {
		/*
		 *  The path is fully qualified, just evaluate by name
		 */
		status = acpi_ns_evaluate_by_name(pathname, &info);
	} else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname
		 * is specified.  Since we've already handled fully
		 * qualified names above, this is an error
		 */
		if (!pathname) {
			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
					  "Both Handle and Pathname are NULL\n"));
		} else {
			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
					  "Handle is NULL and Pathname is relative\n"));
		}

		status = AE_BAD_PARAMETER;
	} else {
		/*
		 * We get here if we have a handle -- and if we have a
		 * pathname it is relative.  The handle will be validated
		 * in the lower procedures
		 */
		if (!pathname) {
			/*
			 * The null pathname case means the handle is for
			 * the actual object to be evaluated
			 */
			status = acpi_ns_evaluate_by_handle(&info);
		} else {
			/*
			 * Both a Handle and a relative Pathname
			 */
			status = acpi_ns_evaluate_relative(pathname, &info);
		}
	}

	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */
	if (return_buffer) {
		if (!info.return_object) {
			return_buffer->length = 0;
		} else {
			if (ACPI_GET_DESCRIPTOR_TYPE(info.return_object) ==
			    ACPI_DESC_TYPE_NAMED) {
				/*
				 * If we received a NS Node as a return object, this means that
				 * the object we are evaluating has nothing interesting to
				 * return (such as a mutex, etc.)  We return an error because
				 * these types are essentially unsupported by this interface.
				 * We don't check up front because this makes it easier to add
				 * support for various types at a later date if necessary.
				 */
				status = AE_TYPE;
				info.return_object = NULL;	/* No need to delete a NS Node */
				return_buffer->length = 0;
			}

			if (ACPI_SUCCESS(status)) {
				/*
				 * Find out how large a buffer is needed
				 * to contain the returned object
				 */
				status =
				    acpi_ut_get_object_size(info.return_object,
							    &buffer_space_needed);
				if (ACPI_SUCCESS(status)) {
					/* Validate/Allocate/Clear caller buffer */

					status =
					    acpi_ut_initialize_buffer
					    (return_buffer,
					     buffer_space_needed);
					if (ACPI_FAILURE(status)) {
						/*
						 * Caller's buffer is too small or a new one can't be allocated
						 */
						ACPI_DEBUG_PRINT((ACPI_DB_INFO,
								  "Needed buffer size %X, %s\n",
								  (u32)
								  buffer_space_needed,
								  acpi_format_exception
								  (status)));
					} else {
						/*
						 *  We have enough space for the object, build it
						 */
						status =
						    acpi_ut_copy_iobject_to_eobject
						    (info.return_object,
						     return_buffer);
					}
				}
			}
		}
	}

	if (info.return_object) {
		/*
		 * Delete the internal return object.  NOTE: Interpreter
		 * must be locked to avoid race condition.
		 */
		status2 = acpi_ex_enter_interpreter();
		if (ACPI_SUCCESS(status2)) {
			/*
			 * Delete the internal return object. (Or at least
			 * decrement the reference count by one)
			 */
			acpi_ut_remove_reference(info.return_object);
			acpi_ex_exit_interpreter();
		}
	}

	/*
	 * Free the input parameter list (if we created one),
	 */
	if (info.parameters) {
		/* Free the allocated parameter block */

		acpi_ut_delete_internal_object_list(info.parameters);
	}

	return_ACPI_STATUS(status);
}
acpi_status
acpi_ns_one_complete_parse(u32 pass_number,
			   u32 table_index,
			   struct acpi_namespace_node *start_node)
{
	union acpi_parse_object *parse_root;
	acpi_status status;
	u32 aml_length;
	u8 *aml_start;
	struct acpi_walk_state *walk_state;
	struct acpi_table_header *table;
	acpi_owner_id owner_id;

	ACPI_FUNCTION_TRACE(ns_one_complete_parse);

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Table must consist of at least a complete header */

	if (table->length < sizeof(struct acpi_table_header)) {
		return_ACPI_STATUS(AE_BAD_HEADER);
	}

	aml_start = (u8 *)table + sizeof(struct acpi_table_header);
	aml_length = table->length - sizeof(struct acpi_table_header);

	status = acpi_tb_get_owner_id(table_index, &owner_id);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Create and init a Root Node */

	parse_root = acpi_ps_create_scope_op(aml_start);
	if (!parse_root) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Create and initialize a new walk state */

	walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
	if (!walk_state) {
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
				       aml_start, aml_length, NULL,
				       (u8)pass_number);
	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		goto cleanup;
	}

	/* Found OSDT table, enable the namespace override feature */

	if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_OSDT) &&
	    pass_number == ACPI_IMODE_LOAD_PASS1) {
		walk_state->namespace_override = TRUE;
	}

	/* start_node is the default location to load the table */

	if (start_node && start_node != acpi_gbl_root_node) {
		status =
		    acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			acpi_ds_delete_walk_state(walk_state);
			goto cleanup;
		}
	}

	/* Parse the AML */

	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
			  "*PARSE* pass %u parse\n", pass_number));
	acpi_ex_enter_interpreter();
	status = acpi_ps_parse_aml(walk_state);
	acpi_ex_exit_interpreter();

cleanup:
	acpi_ps_delete_parse_tree(parse_root);
	return_ACPI_STATUS(status);
}
Ejemplo n.º 11
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_evaluate_object
 *
 * PARAMETERS:  handle              - Object handle (optional)
 *              pathname            - Object pathname (optional)
 *              external_params     - List of parameters to pass to method,
 *                                    terminated by NULL. May be NULL
 *                                    if no parameters are being passed.
 *              return_buffer       - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Find and evaluate the given object, passing the given
 *              parameters if necessary. One of "Handle" or "Pathname" must
 *              be valid (non-null)
 *
 ******************************************************************************/
acpi_status
acpi_evaluate_object(acpi_handle handle,
		     acpi_string pathname,
		     struct acpi_object_list *external_params,
		     struct acpi_buffer *return_buffer)
{
	acpi_status status;
	struct acpi_evaluate_info *info;
	acpi_size buffer_space_needed;
	u32 i;

	ACPI_FUNCTION_TRACE(acpi_evaluate_object);

	/* Allocate and initialize the evaluation information block */

	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Convert and validate the device handle */

	info->prefix_node = acpi_ns_validate_handle(handle);
	if (!info->prefix_node) {
		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	/*
	 * Get the actual namespace node for the target object.
	 * Handles these cases:
	 *
	 * 1) Null node, valid pathname from root (absolute path)
	 * 2) Node and valid pathname (path relative to Node)
	 * 3) Node, Null pathname
	 */
	if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {

		/* The path is fully qualified, just evaluate by name */

		info->prefix_node = NULL;
	} else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname is specified.
		 * Since we've already handled fully qualified names above, this is
		 * an error.
		 */
		if (!pathname) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Both Handle and Pathname are NULL"));
		} else {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Null Handle with relative pathname [%s]",
					  pathname));
		}

		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	info->relative_pathname = pathname;

	/*
	 * Convert all external objects passed as arguments to the
	 * internal version(s).
	 */
	if (external_params && external_params->count) {
		info->param_count = (u16)external_params->count;

		/* Warn on impossible argument count */

		if (info->param_count > ACPI_METHOD_NUM_ARGS) {
			ACPI_WARN_PREDEFINED((AE_INFO, pathname,
					      ACPI_WARN_ALWAYS,
					      "Excess arguments (%u) - using only %u",
					      info->param_count,
					      ACPI_METHOD_NUM_ARGS));

			info->param_count = ACPI_METHOD_NUM_ARGS;
		}

		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */
		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info->
							 param_count +
							 1) * sizeof(void *));
		if (!info->parameters) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Convert each external object in the list to an internal object */

		for (i = 0; i < info->param_count; i++) {
			status =
			    acpi_ut_copy_eobject_to_iobject(&external_params->
							    pointer[i],
							    &info->
							    parameters[i]);
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}
		}

		info->parameters[info->param_count] = NULL;
	}

#if 0

	/*
	 * Begin incoming argument count analysis. Check for too few args
	 * and too many args.
	 */

	switch (acpi_ns_get_type(info->node)) {
	case ACPI_TYPE_METHOD:

		/* Check incoming argument count against the method definition */

		if (info->obj_desc->method.param_count > info->param_count) {
			ACPI_ERROR((AE_INFO,
				    "Insufficient arguments (%u) - %u are required",
				    info->param_count,
				    info->obj_desc->method.param_count));

			status = AE_MISSING_ARGUMENTS;
			goto cleanup;
		}

		else if (info->obj_desc->method.param_count < info->param_count) {
			ACPI_WARNING((AE_INFO,
				      "Excess arguments (%u) - only %u are required",
				      info->param_count,
				      info->obj_desc->method.param_count));

			/* Just pass the required number of arguments */

			info->param_count = info->obj_desc->method.param_count;
		}

		/*
		 * Any incoming external objects to be passed as arguments to the
		 * method must be converted to internal objects
		 */
		if (info->param_count) {
			/*
			 * Allocate a new parameter block for the internal objects
			 * Add 1 to count to allow for null terminated internal list
			 */
			info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
								 info->
								 param_count +
								 1) *
								sizeof(void *));
			if (!info->parameters) {
				status = AE_NO_MEMORY;
				goto cleanup;
			}

			/* Convert each external object in the list to an internal object */

			for (i = 0; i < info->param_count; i++) {
				status =
				    acpi_ut_copy_eobject_to_iobject
				    (&external_params->pointer[i],
				     &info->parameters[i]);
				if (ACPI_FAILURE(status)) {
					goto cleanup;
				}
			}

			info->parameters[info->param_count] = NULL;
		}
		break;

	default:

		/* Warn if arguments passed to an object that is not a method */

		if (info->param_count) {
			ACPI_WARNING((AE_INFO,
				      "%u arguments were passed to a non-method ACPI object",
				      info->param_count));
		}
		break;
	}

#endif

	/* Now we can evaluate the object */

	status = acpi_ns_evaluate(info);

	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */
	if (return_buffer) {
		if (!info->return_object) {
			return_buffer->length = 0;
		} else {
			if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
			    ACPI_DESC_TYPE_NAMED) {
				/*
				 * If we received a NS Node as a return object, this means that
				 * the object we are evaluating has nothing interesting to
				 * return (such as a mutex, etc.)  We return an error because
				 * these types are essentially unsupported by this interface.
				 * We don't check up front because this makes it easier to add
				 * support for various types at a later date if necessary.
				 */
				status = AE_TYPE;
				info->return_object = NULL;	/* No need to delete a NS Node */
				return_buffer->length = 0;
			}

			if (ACPI_SUCCESS(status)) {

				/* Dereference Index and ref_of references */

				acpi_ns_resolve_references(info);

				/* Get the size of the returned object */

				status =
				    acpi_ut_get_object_size(info->return_object,
							    &buffer_space_needed);
				if (ACPI_SUCCESS(status)) {

					/* Validate/Allocate/Clear caller buffer */

					status =
					    acpi_ut_initialize_buffer
					    (return_buffer,
					     buffer_space_needed);
					if (ACPI_FAILURE(status)) {
						/*
						 * Caller's buffer is too small or a new one can't
						 * be allocated
						 */
						ACPI_DEBUG_PRINT((ACPI_DB_INFO,
								  "Needed buffer size %X, %s\n",
								  (u32)
								  buffer_space_needed,
								  acpi_format_exception
								  (status)));
					} else {
						/* We have enough space for the object, build it */

						status =
						    acpi_ut_copy_iobject_to_eobject
						    (info->return_object,
						     return_buffer);
					}
				}
			}
		}
	}

	if (info->return_object) {
		/*
		 * Delete the internal return object. NOTE: Interpreter must be
		 * locked to avoid race condition.
		 */
		acpi_ex_enter_interpreter();

		/* Remove one reference on the return object (should delete it) */

		acpi_ut_remove_reference(info->return_object);
		acpi_ex_exit_interpreter();
	}

cleanup:

	/* Free the input parameter list (if we created one) */

	if (info->parameters) {

		/* Free the allocated parameter block */

		acpi_ut_delete_internal_object_list(info->parameters);
	}

	ACPI_FREE(info);
	return_ACPI_STATUS(status);
}
Ejemplo n.º 12
0
acpi_status
acpi_ns_init_one_object (
	acpi_handle             obj_handle,
	u32                     level,
	void                    *context,
	void                    **return_value)
{
	acpi_object_type8       type;
	acpi_status             status;
	acpi_init_walk_info     *info = (acpi_init_walk_info *) context;
	acpi_namespace_node     *node = (acpi_namespace_node *) obj_handle;
	acpi_operand_object     *obj_desc;


	PROC_NAME ("Ns_init_one_object");


	info->object_count++;


	/* And even then, we are only interested in a few object types */

	type = acpi_ns_get_type (obj_handle);
	obj_desc = node->object;
	if (!obj_desc) {
		return (AE_OK);
	}

	if ((type != ACPI_TYPE_REGION) &&
		(type != ACPI_TYPE_BUFFER_FIELD)) {
		return (AE_OK);
	}


	/*
	 * Must lock the interpreter before executing AML code
	 */
	status = acpi_ex_enter_interpreter ();
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	switch (type) {

	case ACPI_TYPE_REGION:

		info->op_region_count++;
		if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
			break;
		}

		info->op_region_init++;
		status = acpi_ds_get_region_arguments (obj_desc);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
					"%s while getting region arguments [%4.4s]\n",
					acpi_format_exception (status), (char*)&node->name));
		}

		if (!(acpi_dbg_level & ACPI_LV_INIT)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
		}

		break;


	case ACPI_TYPE_BUFFER_FIELD:

		info->field_count++;
		if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
			break;
		}

		info->field_init++;
		status = acpi_ds_get_buffer_field_arguments (obj_desc);
		if (ACPI_FAILURE (status)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
					"%s while getting buffer field arguments [%4.4s]\n",
					acpi_format_exception (status), (char*)&node->name));
		}
		if (!(acpi_dbg_level & ACPI_LV_INIT)) {
			ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
		}


		break;

	default:
		break;
	}


	/*
	 * We ignore errors from above, and always return OK, since
	 * we don't want to abort the walk on a single error.
	 */
	acpi_ex_exit_interpreter ();
	return (AE_OK);
}
Ejemplo n.º 13
0
acpi_status
acpi_ns_get_object_value (
	acpi_namespace_node     *node,
	acpi_operand_object     **return_obj_desc)
{
	acpi_status             status = AE_OK;
	acpi_operand_object     *obj_desc;
	acpi_operand_object     *source_desc;


	FUNCTION_TRACE ("Ns_get_object_value");


	/*
	 *  We take the value from certain objects directly
	 */
	if ((node->type == ACPI_TYPE_PROCESSOR) ||
		(node->type == ACPI_TYPE_POWER)) {
		/*
		 *  Create a Reference object to contain the object
		 */
		obj_desc = acpi_ut_create_internal_object (node->type);
		if (!obj_desc) {
		   status = AE_NO_MEMORY;
		   goto unlock_and_exit;
		}

		/*
		 *  Get the attached object
		 */
		source_desc = acpi_ns_get_attached_object (node);
		if (!source_desc) {
			status = AE_NULL_OBJECT;
			goto unlock_and_exit;
		}

		/*
		 * Just copy from the original to the return object
		 *
		 * TBD: [Future] - need a low-level object copy that handles
		 * the reference count automatically.  (Don't want to copy it)
		 */
		MEMCPY (obj_desc, source_desc, sizeof (acpi_operand_object));
		obj_desc->common.reference_count = 1;
		acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
	}


	/*
	 * Other objects require a reference object wrapper which we
	 * then attempt to resolve.
	 */
	else {
		/* Create an Reference object to contain the object */

		obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE);
		if (!obj_desc) {
		   status = AE_NO_MEMORY;
		   goto unlock_and_exit;
		}

		/* Construct a descriptor pointing to the name */

		obj_desc->reference.opcode = (u8) AML_NAME_OP;
		obj_desc->reference.object = (void *) node;

		/*
		 * Use Resolve_to_value() to get the associated value. This call
		 * always deletes Obj_desc (allocated above).
		 *
		 * NOTE: we can get away with passing in NULL for a walk state
		 * because Obj_desc is guaranteed to not be a reference to either
		 * a method local or a method argument
		 *
		 * Even though we do not directly invoke the interpreter
		 * for this, we must enter it because we could access an opregion.
		 * The opregion access code assumes that the interpreter
		 * is locked.
		 *
		 * We must release the namespace lock before entering the
		 * intepreter.
		 */
		acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
		status = acpi_ex_enter_interpreter ();
		if (ACPI_SUCCESS (status)) {
			status = acpi_ex_resolve_to_value (&obj_desc, NULL);

			acpi_ex_exit_interpreter ();
		}
	}

	/*
	 * If Acpi_ex_resolve_to_value() succeeded, the return value was
	 * placed in Obj_desc.
	 */
	if (ACPI_SUCCESS (status)) {
		status = AE_CTRL_RETURN_VALUE;

		*return_obj_desc = obj_desc;
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Returning obj %p\n", *return_obj_desc));
	}

	/* Namespace is unlocked */

	return_ACPI_STATUS (status);


unlock_and_exit:

	/* Unlock the namespace */

	acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS (status);
}