Esempio n. 1
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_resolve_node_to_value
 *
 * PARAMETERS:  object_ptr      - Pointer to a location that contains
 *                                a pointer to a NS node, and will receive a
 *                                pointer to the resolved object.
 *              walk_state      - Current state. Valid only if executing AML
 *                                code. NULL if simply resolving an object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Resolve a Namespace node to a valued object
 *
 * Note: for some of the data types, the pointer attached to the Node
 * can be either a pointer to an actual internal object or a pointer into the
 * AML stream itself. These types are currently:
 *
 *      ACPI_TYPE_INTEGER
 *      ACPI_TYPE_STRING
 *      ACPI_TYPE_BUFFER
 *      ACPI_TYPE_MUTEX
 *      ACPI_TYPE_PACKAGE
 *
 ******************************************************************************/
acpi_status
acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr,
			      struct acpi_walk_state *walk_state)
{
	acpi_status status = AE_OK;
	union acpi_operand_object *source_desc;
	union acpi_operand_object *obj_desc = NULL;
	struct acpi_namespace_node *node;
	acpi_object_type entry_type;

	ACPI_FUNCTION_TRACE(ex_resolve_node_to_value);

	/*
	 * The stack pointer points to a struct acpi_namespace_node (Node). Get the
	 * object that is attached to the Node.
	 */
	node = *object_ptr;
	source_desc = acpi_ns_get_attached_object(node);
	entry_type = acpi_ns_get_type((acpi_handle)node);

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n",
			  node, source_desc,
			  acpi_ut_get_type_name(entry_type)));

	if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
	    (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {

		/* There is always exactly one level of indirection */

		node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object);
		source_desc = acpi_ns_get_attached_object(node);
		entry_type = acpi_ns_get_type((acpi_handle)node);
		*object_ptr = node;
	}
Esempio n. 2
0
static u8
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
			    acpi_adr_space_type space_id)
{
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj;

	/* Must have an existing internal object */

	obj_desc = acpi_ns_get_attached_object(node);
	if (obj_desc) {
		handler_obj = obj_desc->device.handler;

		/* Walk the linked list of handlers for this object */

		while (handler_obj) {
			if (handler_obj->address_space.space_id == space_id) {
				if (handler_obj->address_space.handler_flags &
				    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
					return (TRUE);
				}
			}

			handler_obj = handler_obj->address_space.next;
		}
	}

	return (FALSE);
}
Esempio n. 3
0
void
acpi_ns_terminate (void)
{
	union acpi_operand_object       *obj_desc;


	ACPI_FUNCTION_TRACE ("ns_terminate");


	/*
	 * 1) Free the entire namespace -- all nodes and objects
	 *
	 * Delete all object descriptors attached to namepsace nodes
	 */
	acpi_ns_delete_namespace_subtree (acpi_gbl_root_node);

	/* Detach any objects attached to the root */

	obj_desc = acpi_ns_get_attached_object (acpi_gbl_root_node);
	if (obj_desc) {
		acpi_ns_detach_object (acpi_gbl_root_node);
	}

	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));

	/*
	 * 2) Now we can delete the ACPI tables
	 */
	acpi_tb_delete_all_tables ();
	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));

	return_VOID;
}
Esempio n. 4
0
acpi_object_type
acpi_ds_method_data_get_type(u16 opcode,
			     u32 index, struct acpi_walk_state *walk_state)
{
	acpi_status status;
	struct acpi_namespace_node *node;
	union acpi_operand_object *object;

	ACPI_FUNCTION_TRACE(ds_method_data_get_type);

	/* Get the namespace node for the arg/local */

	status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
	if (ACPI_FAILURE(status)) {
		return_VALUE((ACPI_TYPE_NOT_FOUND));
	}

	/* Get the object */

	object = acpi_ns_get_attached_object(node);
	if (!object) {

		/* Uninitialized local/arg, return TYPE_ANY */

		return_VALUE(ACPI_TYPE_ANY);
	}

	/* Get the object type */

	return_VALUE(ACPI_GET_OBJECT_TYPE(object));
}
Esempio n. 5
0
void
acpi_ex_dump_node (
	struct acpi_namespace_node      *node,
	u32                             flags)
{

	ACPI_FUNCTION_ENTRY ();


	if (!flags) {
		if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
			return;
		}
	}

	acpi_os_printf ("%20s : %4.4s\n",     "Name", acpi_ut_get_node_name (node));
	acpi_ex_out_string ("Type",           acpi_ut_get_type_name (node->type));
	acpi_ex_out_integer ("Flags",         node->flags);
	acpi_ex_out_integer ("Owner Id",      node->owner_id);
	acpi_ex_out_integer ("Reference Count", node->reference_count);
	acpi_ex_out_pointer ("Attached Object", acpi_ns_get_attached_object (node));
	acpi_ex_out_pointer ("child_list",    node->child);
	acpi_ex_out_pointer ("next_peer",     node->peer);
	acpi_ex_out_pointer ("Parent",        acpi_ns_get_parent_node (node));
}
Esempio n. 6
0
acpi_status
acpi_ns_init_one_package(acpi_handle obj_handle,
			 u32 level, void *context, void **return_value)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node =
	    (struct acpi_namespace_node *)obj_handle;

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

	/* Exit if package is already initialized */

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

	status = acpi_ds_get_package_arguments(obj_desc);
	if (ACPI_FAILURE(status)) {
		return (AE_OK);
	}

	status =
	    acpi_ut_walk_package_tree(obj_desc, NULL,
				      acpi_ds_init_package_element, NULL);
	if (ACPI_FAILURE(status)) {
		return (AE_OK);
	}

	obj_desc->package.flags |= AOPOBJ_DATA_VALID;
	return (AE_OK);
}
Esempio n. 7
0
static acpi_status
acpi_db_walk_for_references(acpi_handle obj_handle,
			    u32 nesting_level,
			    void *context, void **return_value)
{
	union acpi_operand_object *obj_desc =
	    (union acpi_operand_object *)context;
	struct acpi_namespace_node *node =
	    (struct acpi_namespace_node *)obj_handle;

	/* Check for match against the namespace node itself */

	if (node == (void *)obj_desc) {
		acpi_os_printf("Object is a Node [%4.4s]\n",
			       acpi_ut_get_node_name(node));
	}

	/* Check for match against the object attached to the node */

	if (acpi_ns_get_attached_object(node) == obj_desc) {
		acpi_os_printf("Reference at Node->Object %p [%4.4s]\n",
			       node, acpi_ut_get_node_name(node));
	}

	return (AE_OK);
}
Esempio n. 8
0
static void acpi_db_decode_node(struct acpi_namespace_node *node)
{

	acpi_os_printf("<Node>          Name %4.4s",
		       acpi_ut_get_node_name(node));

	if (node->flags & ANOBJ_METHOD_ARG) {
		acpi_os_printf(" [Method Arg]");
	}
	if (node->flags & ANOBJ_METHOD_LOCAL) {
		acpi_os_printf(" [Method Local]");
	}

	switch (node->type) {

		/* These types have no attached object */

	case ACPI_TYPE_DEVICE:

		acpi_os_printf(" Device");
		break;

	case ACPI_TYPE_THERMAL:

		acpi_os_printf(" Thermal Zone");
		break;

	default:

		acpi_db_decode_internal_object(acpi_ns_get_attached_object
					       (node));
		break;
	}
}
Esempio n. 9
0
ACPI_STATUS
acpi_ns_execute_control_method (
	ACPI_NAMESPACE_NODE     *method_node,
	ACPI_OPERAND_OBJECT     **params,
	ACPI_OPERAND_OBJECT     **return_obj_desc)
{
	ACPI_STATUS             status;
	ACPI_OPERAND_OBJECT     *obj_desc;


	/* Verify that there is a method associated with this object */

	obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_node);
	if (!obj_desc) {
		return (AE_ERROR);
	}


	/*
	 * Unlock the namespace before execution.  This allows namespace access
	 * via the external Acpi* interfaces while a method is being executed.
	 * However, any namespace deletion must acquire both the namespace and
	 * interpreter locks to ensure that no thread is using the portion of the
	 * namespace that is being deleted.
	 */

	acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);

	/*
	 * Excecute the method via the interpreter
	 */
	status = acpi_aml_execute_method (method_node, params, return_obj_desc);

	return (status);
}
Esempio n. 10
0
acpi_status
acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info)
{
	acpi_status status;
	char *internal_path = NULL;

	ACPI_FUNCTION_TRACE("ns_evaluate_by_name");

	/* Build an internal name string for the method */

	status = acpi_ns_internalize_name(pathname, &internal_path);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	/* Lookup the name in the namespace */

	status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
				ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
				&info->node);

	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);

	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
				  "Object at [%s] was not found, status=%.4X\n",
				  pathname, status));
		goto cleanup;
	}

	/*
	 * Now that we have a handle to the object, we can attempt to evaluate it.
	 */
	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
			  pathname, info->node,
			  acpi_ns_get_attached_object(info->node)));

	status = acpi_ns_evaluate_by_handle(info);

	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
			  "*** Completed eval of object %s ***\n", pathname));

      cleanup:

	/* Cleanup */

	if (internal_path) {
		ACPI_MEM_FREE(internal_path);
	}

	return_ACPI_STATUS(status);
}
Esempio n. 11
0
static acpi_status
acpi_db_integrity_walk(acpi_handle obj_handle,
		       u32 nesting_level, void *context, void **return_value)
{
	struct acpi_integrity_info *info =
	    (struct acpi_integrity_info *)context;
	struct acpi_namespace_node *node =
	    (struct acpi_namespace_node *)obj_handle;
	union acpi_operand_object *object;
	u8 alias = TRUE;

	info->nodes++;

	/* Verify the NS node, and dereference aliases */

	while (alias) {
		if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
			acpi_os_printf
			    ("Invalid Descriptor Type for Node %p [%s] - "
			     "is %2.2X should be %2.2X\n", node,
			     acpi_ut_get_descriptor_name(node),
			     ACPI_GET_DESCRIPTOR_TYPE(node),
			     ACPI_DESC_TYPE_NAMED);
			return (AE_OK);
		}

		if ((node->type == ACPI_TYPE_LOCAL_ALIAS) ||
		    (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
			node = (struct acpi_namespace_node *)node->object;
		} else {
			alias = FALSE;
		}
	}

	if (node->type > ACPI_TYPE_LOCAL_MAX) {
		acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n",
			       node, node->type);
		return (AE_OK);
	}

	if (!acpi_ut_valid_nameseg(node->name.ascii)) {
		acpi_os_printf("Invalid AcpiName for Node %p\n", node);
		return (AE_OK);
	}

	object = acpi_ns_get_attached_object(node);
	if (object) {
		info->objects++;
		if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
			acpi_os_printf
			    ("Invalid Descriptor Type for Object %p [%s]\n",
			     object, acpi_ut_get_descriptor_name(object));
		}
	}

	return (AE_OK);
}
Esempio n. 12
0
acpi_status
acpi_ns_execute_control_method (
	acpi_namespace_node     *method_node,
	acpi_operand_object     **params,
	acpi_operand_object     **return_obj_desc)
{
	acpi_status             status;
	acpi_operand_object     *obj_desc;


	FUNCTION_TRACE ("Ns_execute_control_method");


	/* Verify that there is a method associated with this object */

	obj_desc = acpi_ns_get_attached_object (method_node);
	if (!obj_desc) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));

		acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
		return_ACPI_STATUS (AE_NULL_OBJECT);
	}


	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Control method at Offset %p Length %x]\n",
		obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1));

	DUMP_PATHNAME (method_node, "Ns_execute_control_method: Executing",
		ACPI_LV_NAMES, _COMPONENT);

	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "At offset %p\n",
			obj_desc->method.aml_start + 1));


	/*
	 * Unlock the namespace before execution.  This allows namespace access
	 * via the external Acpi* interfaces while a method is being executed.
	 * However, any namespace deletion must acquire both the namespace and
	 * interpreter locks to ensure that no thread is using the portion of the
	 * namespace that is being deleted.
	 */
	acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);

	/*
	 * Execute the method via the interpreter.  The interpreter is locked
	 * here before calling into the AML parser
	 */
	status = acpi_ex_enter_interpreter ();
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

	status = acpi_psx_execute (method_node, params, return_obj_desc);
	acpi_ex_exit_interpreter ();

	return_ACPI_STATUS (status);
}
Esempio n. 13
0
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
						       u32 gpe_number)
{
	union acpi_operand_object *obj_desc;
	struct acpi_gpe_block_info *gpe_block;
	acpi_native_uint i;

	ACPI_FUNCTION_ENTRY();

	/* A NULL gpe_block means use the FADT-defined GPE block(s) */

	if (!gpe_device) {

		/* Examine GPE Block 0 and 1 (These blocks are permanent) */

		for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
			gpe_block = acpi_gbl_gpe_fadt_blocks[i];
			if (gpe_block) {
				if ((gpe_number >= gpe_block->block_base_number)
				    && (gpe_number <
					gpe_block->block_base_number +
					(gpe_block->register_count * 8))) {
					return (&gpe_block->
						event_info[gpe_number -
							   gpe_block->
							   block_base_number]);
				}
			}
		}

		/* The gpe_number was not in the range of either FADT GPE block */

		return (NULL);
	}

	/* A Non-NULL gpe_device means this is a GPE Block Device */

	obj_desc =
	    acpi_ns_get_attached_object((struct acpi_namespace_node *)
					gpe_device);
	if (!obj_desc || !obj_desc->device.gpe_block) {
		return (NULL);
	}

	gpe_block = obj_desc->device.gpe_block;

	if ((gpe_number >= gpe_block->block_base_number) &&
	    (gpe_number <
	     gpe_block->block_base_number + (gpe_block->register_count * 8))) {
		return (&gpe_block->
			event_info[gpe_number - gpe_block->block_base_number]);
	}

	return (NULL);
}
Esempio n. 14
0
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
						       u32 gpe_number)
{
	union acpi_operand_object *obj_desc;
	struct acpi_gpe_block_info *gpe_block;
	u32 i;

	ACPI_FUNCTION_ENTRY();

	

	if (!gpe_device) {

		

		for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
			gpe_block = acpi_gbl_gpe_fadt_blocks[i];
			if (gpe_block) {
				if ((gpe_number >= gpe_block->block_base_number)
				    && (gpe_number <
					gpe_block->block_base_number +
					(gpe_block->register_count * 8))) {
					return (&gpe_block->
						event_info[gpe_number -
							   gpe_block->
							   block_base_number]);
				}
			}
		}

		

		return (NULL);
	}

	

	obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)
					       gpe_device);
	if (!obj_desc || !obj_desc->device.gpe_block) {
		return (NULL);
	}

	gpe_block = obj_desc->device.gpe_block;

	if ((gpe_number >= gpe_block->block_base_number) &&
	    (gpe_number <
	     gpe_block->block_base_number + (gpe_block->register_count * 8))) {
		return (&gpe_block->
			event_info[gpe_number - gpe_block->block_base_number]);
	}

	return (NULL);
}
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
{
	union acpi_operand_object *obj_desc;
	acpi_status status;

	obj_desc = acpi_ns_get_attached_object(obj_handle);

	/* Namespace is NOT locked */

	status = acpi_ev_initialize_region(obj_desc, FALSE);
	return (status);
}
Esempio n. 16
0
static acpi_status
acpi_db_classify_one_object(acpi_handle obj_handle,
			    u32 nesting_level,
			    void *context, void **return_value)
{
	struct acpi_namespace_node *node;
	union acpi_operand_object *obj_desc;
	u32 type;

	acpi_gbl_num_nodes++;

	node = (struct acpi_namespace_node *)obj_handle;
	obj_desc = acpi_ns_get_attached_object(node);

	acpi_db_enumerate_object(obj_desc);

	type = node->type;
	if (type > ACPI_TYPE_NS_NODE_MAX) {
		acpi_gbl_node_type_count_misc++;
	} else {
		acpi_gbl_node_type_count[type]++;
	}

	return (AE_OK);

#ifdef ACPI_FUTURE_IMPLEMENTATION

	/* TBD: These need to be counted during the initial parsing phase */

	if (acpi_ps_is_named_op(op->opcode)) {
		num_nodes++;
	}

	if (is_method) {
		num_method_elements++;
	}

	num_grammar_elements++;
	op = acpi_ps_get_depth_next(root, op);

	size_of_parse_tree = (num_grammar_elements - num_method_elements) *
	    (u32)sizeof(union acpi_parse_object);
	size_of_method_trees =
	    num_method_elements * (u32)sizeof(union acpi_parse_object);
	size_of_node_entries =
	    num_nodes * (u32)sizeof(struct acpi_namespace_node);
	size_of_acpi_objects =
	    num_nodes * (u32)sizeof(union acpi_operand_object);
#endif
}
Esempio n. 17
0
static acpi_status
acpi_ev_reg_run(acpi_handle obj_handle,
		u32 level, void *context, void **return_value)
{
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node;
	acpi_status status;
	struct acpi_reg_walk_info *info;

	info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context);

	/* Convert and validate the device handle */

	node = acpi_ns_validate_handle(obj_handle);
	if (!node) {
		return (AE_BAD_PARAMETER);
	}

	/*
	 * We only care about regions.and objects that are allowed to have address
	 * space handlers
	 */
	if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {
		return (AE_OK);
	}

	/* Check for an existing internal object */

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {

		/* No object, just exit */

		return (AE_OK);
	}

	/* Object is a Region */

	if (obj_desc->region.space_id != info->space_id) {

		/* This region is for a different address space, just ignore it */

		return (AE_OK);
	}

	info->reg_run_count++;
	status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);
	return (status);
}
Esempio n. 18
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_remove_gpe_block
 *
 * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Remove a previously installed block of GPE registers
 *
 ******************************************************************************/
acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
{
	union acpi_operand_object *obj_desc;
	acpi_status status;
	struct acpi_namespace_node *node;

	ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);

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

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

	node = acpi_ns_validate_handle(gpe_device);
	if (!node) {
		status = AE_BAD_PARAMETER;
		goto unlock_and_exit;
	}

	/* Validate the parent device */

	if (node->type != ACPI_TYPE_DEVICE) {
		status = AE_TYPE;
		goto unlock_and_exit;
	}

	/* Get the device_object attached to the node */

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc || !obj_desc->device.gpe_block) {
		return_ACPI_STATUS(AE_NULL_OBJECT);
	}

	/* Delete the GPE block (but not the device_object) */

	status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
	if (ACPI_SUCCESS(status)) {
		obj_desc->device.gpe_block = NULL;
	}

unlock_and_exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS(status);
}
Esempio n. 19
0
void
acpi_ds_method_data_delete_value (
	u16                             opcode,
	u32                             index,
	struct acpi_walk_state          *walk_state)
{
	acpi_status                     status;
	struct acpi_namespace_node      *node;
	union acpi_operand_object       *object;


	ACPI_FUNCTION_TRACE ("ds_method_data_delete_value");


	/* Get the namespace node for the arg/local */

	status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
	if (ACPI_FAILURE (status)) {
		return_VOID;
	}

	/* Get the associated object */

	object = acpi_ns_get_attached_object (node);

	/*
	 * Undefine the Arg or Local by setting its descriptor
	 * pointer to NULL. Locals/Args can contain both
	 * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
	 */
	node->object = NULL;

	if ((object) &&
		(ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_OPERAND)) {
		/*
		 * There is a valid object.
		 * Decrement the reference count by one to balance the
		 * increment when the object was stored.
		 */
		acpi_ut_remove_reference (object);
	}

	return_VOID;
}
Esempio n. 20
0
static acpi_status
acpi_db_display_non_root_handlers(acpi_handle obj_handle,
				  u32 nesting_level,
				  void *context, void **return_value)
{
	struct acpi_namespace_node *node =
	    ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *handler_obj;
	char *pathname;

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

	pathname = acpi_ns_get_normalized_pathname(node, TRUE);
	if (!pathname) {
		return (AE_OK);
	}

	/* Display all handlers associated with this device */

	handler_obj = obj_desc->common_notify.handler;
	while (handler_obj) {
		acpi_os_printf(ACPI_PREDEFINED_PREFIX,
			       acpi_ut_get_region_name((u8)handler_obj->
						       address_space.space_id),
			       handler_obj->address_space.space_id);

		acpi_os_printf(ACPI_HANDLER_PRESENT_STRING2,
			       (handler_obj->address_space.handler_flags &
				ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ? "Default"
			       : "User", handler_obj->address_space.handler);

		acpi_os_printf(" Device Name: %s (%p)\n", pathname, node);

		handler_obj = handler_obj->address_space.next;
	}

	ACPI_FREE(pathname);
	return (AE_OK);
}
Esempio n. 21
0
static acpi_status
acpi_ut_get_mutex_object(acpi_handle handle,
			 acpi_string pathname,
			 union acpi_operand_object **ret_obj)
{
	struct acpi_namespace_node *mutex_node;
	union acpi_operand_object *mutex_obj;
	acpi_status status;

	/* Parameter validation */

	if (!ret_obj || (!handle && !pathname)) {
		return (AE_BAD_PARAMETER);
	}

	/* Get a the namespace node for the mutex */

	mutex_node = handle;
	if (pathname != NULL) {
		status =
		    acpi_get_handle(handle, pathname,
				    ACPI_CAST_PTR(acpi_handle, &mutex_node));
		if (ACPI_FAILURE(status)) {
			return (status);
		}
	}

	/* Ensure that we actually have a Mutex object */

	if (!mutex_node || (mutex_node->type != ACPI_TYPE_MUTEX)) {
		return (AE_TYPE);
	}

	/* Get the low-level mutex object */

	mutex_obj = acpi_ns_get_attached_object(mutex_node);
	if (!mutex_obj) {
		return (AE_NULL_OBJECT);
	}

	*ret_obj = mutex_obj;
	return (AE_OK);
}
Esempio n. 22
0
ACPI_STATUS
acpi_ds_begin_method_execution (
	ACPI_NAMESPACE_NODE     *method_node,
	ACPI_OPERAND_OBJECT     *obj_desc)
{
	ACPI_STATUS             status = AE_OK;


	if (!method_node) {
		return (AE_NULL_ENTRY);
	}

	obj_desc = acpi_ns_get_attached_object (method_node);
	if (!obj_desc) {
		return (AE_NULL_OBJECT);
	}


	/*
	 * If there is a concurrency limit on this method, we need to
	 * obtain a unit from the method semaphore.  This releases the
	 * interpreter if we block
	 */

	if (obj_desc->method.semaphore) {
		status = acpi_aml_system_wait_semaphore (obj_desc->method.semaphore,
				 WAIT_FOREVER);
	}


	/*
	 * Increment the method parse tree thread count since there
	 * is one additional thread executing in it.  If configured
	 * for deletion-on-exit, the parse tree will be deleted when
	 * the last thread completes execution of the method
	 */

	obj_desc->method.thread_count++;


	return (status);
}
Esempio n. 23
0
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device,
						       u32 gpe_number)
{
	union acpi_operand_object *obj_desc;
	struct acpi_gpe_event_info *gpe_info;
	u32 i;

	ACPI_FUNCTION_ENTRY();

	/* A NULL gpe_device means use the FADT-defined GPE block(s) */

	if (!gpe_device) {

		/* Examine GPE Block 0 and 1 (These blocks are permanent) */

		for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
			gpe_info = acpi_ev_low_get_gpe_info(gpe_number,
							    acpi_gbl_gpe_fadt_blocks
							    [i]);
			if (gpe_info) {
				return (gpe_info);
			}
		}

		/* The gpe_number was not in the range of either FADT GPE block */

		return (NULL);
	}

	/* A Non-NULL gpe_device means this is a GPE Block Device */

	obj_desc =
	    acpi_ns_get_attached_object((struct acpi_namespace_node *)
					       gpe_device);
	if (!obj_desc || !obj_desc->device.gpe_block) {
		return (NULL);
	}

	return (acpi_ev_low_get_gpe_info
		(gpe_number, obj_desc->device.gpe_block));
}
Esempio n. 24
0
void
acpi_ns_terminate (void)
{
	acpi_operand_object     *obj_desc;
	acpi_namespace_node     *this_node;


	FUNCTION_TRACE ("Ns_terminate");


	this_node = acpi_gbl_root_node;

	/*
	 * 1) Free the entire namespace -- all objects, tables, and stacks
	 *
	 * Delete all objects linked to the root
	 * (additional table descriptors)
	 */
	acpi_ns_delete_namespace_subtree (this_node);

	/* Detach any object(s) attached to the root */

	obj_desc = acpi_ns_get_attached_object (this_node);
	if (obj_desc) {
		acpi_ns_detach_object (this_node);
		acpi_ut_remove_reference (obj_desc);
	}

	acpi_ns_delete_children (this_node);
	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));


	/*
	 * 2) Now we can delete the ACPI tables
	 */
	acpi_tb_delete_acpi_tables ();
	ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));

	return_VOID;
}
Esempio n. 25
0
void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags)
{

	ACPI_FUNCTION_ENTRY();

	if (!flags) {
		if (!
		    ((ACPI_LV_OBJECTS & acpi_dbg_level)
		     && (_COMPONENT & acpi_dbg_layer))) {
			return;
		}
	}

	acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node));
	acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type));
	acpi_ex_out_pointer("Attached Object",
			    acpi_ns_get_attached_object(node));
	acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node));

	acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node),
			    acpi_ex_dump_node);
}
Esempio n. 26
0
acpi_status
acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
		      union acpi_parse_object *op,
		      struct acpi_namespace_node *method_node,
		      u8 * aml_start,
		      u32 aml_length,
		      struct acpi_evaluate_info *info, u8 pass_number)
{
	acpi_status status;
	struct acpi_parse_state *parser_state = &walk_state->parser_state;
	union acpi_parse_object *extra_op;

	ACPI_FUNCTION_TRACE(ds_init_aml_walk);

	walk_state->parser_state.aml =
	    walk_state->parser_state.aml_start = aml_start;
	walk_state->parser_state.aml_end =
	    walk_state->parser_state.pkg_end = aml_start + aml_length;

	/* The next_op of the next_walk will be the beginning of the method */

	walk_state->next_op = NULL;
	walk_state->pass_number = pass_number;

	if (info) {
		walk_state->params = info->parameters;
		walk_state->caller_return_desc = &info->return_object;
	}

	status = acpi_ps_init_scope(&walk_state->parser_state, op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (method_node) {
		walk_state->parser_state.start_node = method_node;
		walk_state->walk_type = ACPI_WALK_METHOD;
		walk_state->method_node = method_node;
		walk_state->method_desc =
		    acpi_ns_get_attached_object(method_node);

		/* Push start scope on scope stack and make it current  */

		status =
		    acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		/* Init the method arguments */

		status = acpi_ds_method_data_init_args(walk_state->params,
						       ACPI_METHOD_NUM_ARGS,
						       walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	} else {
		/*
		 * Setup the current scope.
		 * Find a Named Op that has a namespace node associated with it.
		 * search upwards from this Op.  Current scope is the first
		 * Op with a namespace node.
		 */
		extra_op = parser_state->start_op;
		while (extra_op && !extra_op->common.node) {
			extra_op = extra_op->common.parent;
		}

		if (!extra_op) {
			parser_state->start_node = NULL;
		} else {
			parser_state->start_node = extra_op->common.node;
		}

		if (parser_state->start_node) {

			/* Push start scope on scope stack and make it current  */

			status =
			    acpi_ds_scope_stack_push(parser_state->start_node,
						     parser_state->start_node->
						     type, walk_state);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}
	}

	status = acpi_ds_init_callbacks(walk_state, pass_number);
	return_ACPI_STATUS(status);
}
Esempio n. 27
0
acpi_status
acpi_ds_call_control_method(struct acpi_thread_state *thread,
			    struct acpi_walk_state *this_walk_state,
			    union acpi_parse_object *op)
{
	acpi_status status;
	struct acpi_namespace_node *method_node;
	struct acpi_walk_state *next_walk_state = NULL;
	union acpi_operand_object *obj_desc;
	struct acpi_evaluate_info *info;
	u32 i;

	ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state);

	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
			  "Calling method %p, currentstate=%p\n",
			  this_walk_state->prev_op, this_walk_state));

	/*
	 * Get the namespace entry for the control method we are about to call
	 */
	method_node = this_walk_state->method_call_node;
	if (!method_node) {
		return_ACPI_STATUS(AE_NULL_ENTRY);
	}

	obj_desc = acpi_ns_get_attached_object(method_node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NULL_OBJECT);
	}

	/* Init for new method, possibly wait on method mutex */

	status = acpi_ds_begin_method_execution(method_node, obj_desc,
						this_walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Begin method parse/execution. Create a new walk state */

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

	/*
	 * The resolved arguments were put on the previous walk state's operand
	 * stack. Operands on the previous walk state stack always
	 * start at index 0. Also, null terminate the list of arguments
	 */
	this_walk_state->operands[this_walk_state->num_operands] = NULL;

	/*
	 * Allocate and initialize the evaluation information block
	 * TBD: this is somewhat inefficient, should change interface to
	 * ds_init_aml_walk. For now, keeps this struct off the CPU stack
	 */
	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	info->parameters = &this_walk_state->operands[0];
	info->parameter_type = ACPI_PARAM_ARGS;

	status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
				       obj_desc->method.aml_start,
				       obj_desc->method.aml_length, info,
				       ACPI_IMODE_EXECUTE);

	ACPI_FREE(info);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	/*
	 * Delete the operands on the previous walkstate operand stack
	 * (they were copied to new objects)
	 */
	for (i = 0; i < obj_desc->method.param_count; i++) {
		acpi_ut_remove_reference(this_walk_state->operands[i]);
		this_walk_state->operands[i] = NULL;
	}

	/* Clear the operand stack */

	this_walk_state->num_operands = 0;

	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
			  "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
			  method_node->name.ascii, next_walk_state));

	/* Invoke an internal method if necessary */

	if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
		status = obj_desc->method.implementation(next_walk_state);
	}

	return_ACPI_STATUS(status);

      cleanup:

	/* On error, we must terminate the method properly */

	acpi_ds_terminate_control_method(obj_desc, next_walk_state);
	if (next_walk_state) {
		acpi_ds_delete_walk_state(next_walk_state);
	}

	return_ACPI_STATUS(status);
}
Esempio n. 28
0
	}

	/*
	 * For a method alias, we must grab the actual method node so that proper
	 * scoping context will be established before execution.
	 */
	if (acpi_ns_get_type(info->resolved_node) ==
	    ACPI_TYPE_LOCAL_METHOD_ALIAS) {
		info->resolved_node =
		    ACPI_CAST_PTR(struct acpi_namespace_node,
				  info->resolved_node->object);
	}

	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname,
			  info->resolved_node,
			  acpi_ns_get_attached_object(info->resolved_node)));

	node = info->resolved_node;

	/*
	 * Two major cases here:
	 *
	 * 1) The object is a control method -- execute it
	 * 2) The object is not a method -- just return it's current value
	 */
	if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) {
		/*
		 * 1) Object is a control method - execute it
		 */

		/* Verify that there is a method object associated with this node */
Esempio n. 29
0
acpi_status
acpi_ds_store_object_to_local(u16 opcode,
			      u32 index,
			      union acpi_operand_object *obj_desc,
			      struct acpi_walk_state *walk_state)
{
	acpi_status status;
	struct acpi_namespace_node *node;
	union acpi_operand_object *current_obj_desc;
	union acpi_operand_object *new_obj_desc;

	ACPI_FUNCTION_TRACE(ds_store_object_to_local);
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
			  opcode, index, obj_desc));

	/* Parameter validation */

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

	/* Get the namespace node for the arg/local */

	status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	current_obj_desc = acpi_ns_get_attached_object(node);
	if (current_obj_desc == obj_desc) {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
				  obj_desc));
		return_ACPI_STATUS(status);
	}

	/*
	 * If the reference count on the object is more than one, we must
	 * take a copy of the object before we store.  A reference count
	 * of exactly 1 means that the object was just created during the
	 * evaluation of an expression, and we can safely use it since it
	 * is not used anywhere else.
	 */
	new_obj_desc = obj_desc;
	if (obj_desc->common.reference_count > 1) {
		status =
		    acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
						    walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	}

	/*
	 * If there is an object already in this slot, we either
	 * have to delete it, or if this is an argument and there
	 * is an object reference stored there, we have to do
	 * an indirect store!
	 */
	if (current_obj_desc) {
		/*
		 * Check for an indirect store if an argument
		 * contains an object reference (stored as an Node).
		 * We don't allow this automatic dereferencing for
		 * locals, since a store to a local should overwrite
		 * anything there, including an object reference.
		 *
		 * If both Arg0 and Local0 contain ref_of (Local4):
		 *
		 * Store (1, Arg0)             - Causes indirect store to local4
		 * Store (1, Local0)           - Stores 1 in local0, overwriting
		 *                                  the reference to local4
		 * Store (1, de_refof (Local0)) - Causes indirect store to local4
		 *
		 * Weird, but true.
		 */
		if (opcode == AML_ARG_OP) {
			/*
			 * If we have a valid reference object that came from ref_of(),
			 * do the indirect store
			 */
			if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
			     ACPI_DESC_TYPE_OPERAND)
			    && (current_obj_desc->common.type ==
				ACPI_TYPE_LOCAL_REFERENCE)
			    && (current_obj_desc->reference.opcode ==
				AML_REF_OF_OP)) {
				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
						  "Arg (%p) is an ObjRef(Node), storing in node %p\n",
						  new_obj_desc,
						  current_obj_desc));

				/*
				 * Store this object to the Node (perform the indirect store)
				 * NOTE: No implicit conversion is performed, as per the ACPI
				 * specification rules on storing to Locals/Args.
				 */
				status =
				    acpi_ex_store_object_to_node(new_obj_desc,
								 current_obj_desc->
								 reference.
								 object,
								 walk_state,
								 ACPI_NO_IMPLICIT_CONVERSION);

				/* Remove local reference if we copied the object above */

				if (new_obj_desc != obj_desc) {
					acpi_ut_remove_reference(new_obj_desc);
				}
				return_ACPI_STATUS(status);
			}
		}

		/*
		 * Delete the existing object
		 * before storing the new one
		 */
		acpi_ds_method_data_delete_value(opcode, index, walk_state);
	}

	/*
	 * Install the Obj descriptor (*new_obj_desc) into
	 * the descriptor for the Arg or Local.
	 * (increments the object reference count by one)
	 */
	status =
	    acpi_ds_method_data_set_value(opcode, index, new_obj_desc,
					  walk_state);

	/* Remove local reference if we copied the object above */

	if (new_obj_desc != obj_desc) {
		acpi_ut_remove_reference(new_obj_desc);
	}

	return_ACPI_STATUS(status);
}
Esempio n. 30
0
acpi_status
acpi_ev_queue_notify_request (
	struct acpi_namespace_node      *node,
	u32                             notify_value)
{
	union acpi_operand_object       *obj_desc;
	union acpi_operand_object       *handler_obj = NULL;
	union acpi_generic_state        *notify_info;
	acpi_status                     status = AE_OK;


	ACPI_FUNCTION_NAME ("ev_queue_notify_request");


	/*
	 * For value 3 (Ejection Request), some device method may need to be run.
	 * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run.
	 * For value 0x80 (Status Change) on the power button or sleep button,
	 * initiate soft-off or sleep operation?
	 */
	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
		"Dispatching Notify(%X) on node %p\n", notify_value, node));

	if (notify_value <= 7) {
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n",
				acpi_notify_value_names[notify_value]));
	}
	else {
		ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "notify value: 0x2.2_x **Device Specific**\n",
				notify_value));
	}

	/*
	 * Get the notify object attached to the NS Node
	 */
	obj_desc = acpi_ns_get_attached_object (node);
	if (obj_desc) {
		/* We have the notify object, Get the right handler */

		switch (node->type) {
		case ACPI_TYPE_DEVICE:
		case ACPI_TYPE_THERMAL:
		case ACPI_TYPE_PROCESSOR:
		case ACPI_TYPE_POWER:

			if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
				handler_obj = obj_desc->common_notify.system_notify;
			}
			else {
				handler_obj = obj_desc->common_notify.device_notify;
			}
			break;

		default:
			/* All other types are not supported */
			return (AE_TYPE);
		}
	}

	/* If there is any handler to run, schedule the dispatcher */

	if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) ||
		(acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) ||
		handler_obj) {
		notify_info = acpi_ut_create_generic_state ();
		if (!notify_info) {
			return (AE_NO_MEMORY);
		}

		notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY;
		notify_info->notify.node      = node;
		notify_info->notify.value     = (u16) notify_value;
		notify_info->notify.handler_obj = handler_obj;

		status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH,
				  acpi_ev_notify_dispatch, notify_info);
		if (ACPI_FAILURE (status)) {
			acpi_ut_delete_generic_state (notify_info);
		}
	}

	if (!handler_obj) {
		/* There is no per-device notify handler for this device */

		ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
			"No notify handler for [%4.4s] node %p\n",
			acpi_ut_get_node_name (node), node));
	}

	return (status);
}