Пример #1
0
u32
acpi_ns_get_pathname_length (
	acpi_namespace_node     *node)
{
	u32                     size;
	acpi_namespace_node     *next_node;


	FUNCTION_ENTRY ();


	/*
	 * Compute length of pathname as 5 * number of name segments.
	 * Go back up the parent tree to the root
	 */
	for (size = 0, next_node = node;
		  acpi_ns_get_parent_object (next_node);
		  next_node = acpi_ns_get_parent_object (next_node)) {
		size += PATH_SEGMENT_LENGTH;
	}

	/* Special case for size still 0 - no parent for "special" nodes */

	if (!size) {
		size = PATH_SEGMENT_LENGTH;
	}

	return (size + 1);
}
Пример #2
0
static ACPI_STATUS
acpi_ns_search_parent_tree (
	u32                     target_name,
	ACPI_NAMESPACE_NODE     *node,
	OBJECT_TYPE_INTERNAL    type,
	ACPI_NAMESPACE_NODE     **return_node)
{
	ACPI_STATUS             status;
	ACPI_NAMESPACE_NODE     *parent_node;


	parent_node = acpi_ns_get_parent_object (node);

	/*
	 * If there is no parent (at the root) or type is "local", we won't be
	 * searching the parent tree.
	 */
	if ((acpi_ns_local (type))  ||
		(!parent_node))
	{


		return (AE_NOT_FOUND);
	}


	/* Search the parent tree */

	/*
	 * Search parents until found the target or we have backed up to
	 * the root
	 */

	while (parent_node) {
		/* Search parent scope */
		/* TBD: [Investigate] Why ACPI_TYPE_ANY? */

		status = acpi_ns_search_node (target_name, parent_node,
				   ACPI_TYPE_ANY, return_node);

		if (ACPI_SUCCESS (status)) {
			return (status);
		}

		/*
		 * Not found here, go up another level
		 * (until we reach the root)
		 */

		parent_node = acpi_ns_get_parent_object (parent_node);
	}


	/* Not found in parent tree */

	return (AE_NOT_FOUND);
}
Пример #3
0
ACPI_STATUS
acpi_get_parent (
	ACPI_HANDLE             handle,
	ACPI_HANDLE             *ret_handle)
{
	ACPI_NAMESPACE_NODE     *node;
	ACPI_STATUS             status = AE_OK;


	/* No trace macro, too verbose */


	if (!ret_handle) {
		return (AE_BAD_PARAMETER);
	}

	/* Special case for the predefined Root Node (no parent) */

	if (handle == ACPI_ROOT_OBJECT) {
		return (AE_NULL_ENTRY);
	}


	acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);

	/* Convert and validate the handle */

	node = acpi_ns_convert_handle_to_entry (handle);
	if (!node) {
		status = AE_BAD_PARAMETER;
		goto unlock_and_exit;
	}


	/* Get the parent entry */

	*ret_handle =
		acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_object (node));

	/* Return exeption if parent is null */

	if (!acpi_ns_get_parent_object (node)) {
		status = AE_NULL_ENTRY;
	}


unlock_and_exit:

	acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
	return (status);
}
Пример #4
0
acpi_name
acpi_ns_find_parent_name (
	acpi_namespace_node     *child_node)
{
	acpi_namespace_node     *parent_node;


	FUNCTION_TRACE ("Ns_find_parent_name");


	if (child_node) {
		/* Valid entry.  Get the parent Node */

		parent_node = acpi_ns_get_parent_object (child_node);
		if (parent_node) {
			ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Parent of %p [%4.4s] is %p [%4.4s]\n",
				child_node, (char*)&child_node->name, parent_node, (char*)&parent_node->name));

			if (parent_node->name) {
				return_VALUE (parent_node->name);
			}
		}

		ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "unable to find parent of %p (%4.4s)\n",
			child_node, (char*)&child_node->name));
	}

	return_VALUE (ACPI_UNKNOWN_NAME);
}
Пример #5
0
NATIVE_CHAR *
acpi_ns_get_table_pathname (
	acpi_namespace_node     *node)
{
	NATIVE_CHAR             *name_buffer;
	u32                     size;
	acpi_name               name;
	acpi_namespace_node     *child_node;
	acpi_namespace_node     *parent_node;


	FUNCTION_TRACE_PTR ("Ns_get_table_pathname", node);


	if (!acpi_gbl_root_node || !node) {
		/*
		 * If the name space has not been initialized,
		 * this function should not have been called.
		 */
		return_PTR (NULL);
	}

	child_node = node->child;


	/* Calculate required buffer size based on depth below root */

	size = 1;
	parent_node = child_node;
	while (parent_node) {
		parent_node = acpi_ns_get_parent_object (parent_node);
		if (parent_node) {
			size += ACPI_NAME_SIZE;
		}
	}


	/* Allocate a buffer to be returned to caller */

	name_buffer = ACPI_MEM_CALLOCATE (size + 1);
	if (!name_buffer) {
		REPORT_ERROR (("Ns_get_table_pathname: allocation failure\n"));
		return_PTR (NULL);
	}


	/* Store terminator byte, then build name backwards */

	name_buffer[size] = '\0';
	while ((size > ACPI_NAME_SIZE) &&
		acpi_ns_get_parent_object (child_node)) {
		size -= ACPI_NAME_SIZE;
		name = acpi_ns_find_parent_name (child_node);

		/* Put the name into the buffer */

		MOVE_UNALIGNED32_TO_32 ((name_buffer + size), &name);
		child_node = acpi_ns_get_parent_object (child_node);
	}

	name_buffer[--size] = AML_ROOT_PREFIX;

	if (size != 0) {
		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad pointer returned; size=%X\n", size));
	}

	return_PTR (name_buffer);
}
Пример #6
0
acpi_status
acpi_ns_handle_to_pathname (
	acpi_handle             target_handle,
	u32                     *buf_size,
	NATIVE_CHAR             *user_buffer)
{
	acpi_status             status = AE_OK;
	acpi_namespace_node     *node;
	u32                     path_length;
	u32                     user_buf_size;
	acpi_name               name;
	u32                     size;


	FUNCTION_TRACE_PTR ("Ns_handle_to_pathname", target_handle);


	if (!acpi_gbl_root_node) {
		/*
		 * If the name space has not been initialized,
		 * this function should not have been called.
		 */
		return_ACPI_STATUS (AE_NO_NAMESPACE);
	}

	node = acpi_ns_map_handle_to_node (target_handle);
	if (!node) {
		return_ACPI_STATUS (AE_BAD_PARAMETER);
	}


	/* Set return length to the required path length */

	path_length = acpi_ns_get_pathname_length (node);
	size = path_length - 1;

	user_buf_size = *buf_size;
	*buf_size = path_length;

	/* Check if the user buffer is sufficiently large */

	if (path_length > user_buf_size) {
		status = AE_BUFFER_OVERFLOW;
		goto exit;
	}

	/* Store null terminator */

	user_buffer[size] = 0;
	size -= ACPI_NAME_SIZE;

	/* Put the original ACPI name at the end of the path */

	MOVE_UNALIGNED32_TO_32 ((user_buffer + size),
			 &node->name);

	user_buffer[--size] = PATH_SEPARATOR;

	/* Build name backwards, putting "." between segments */

	while ((size > ACPI_NAME_SIZE) && node) {
		size -= ACPI_NAME_SIZE;
		name = acpi_ns_find_parent_name (node);
		MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &name);

		user_buffer[--size] = PATH_SEPARATOR;
		node = acpi_ns_get_parent_object (node);
	}

	/*
	 * Overlay the "." preceding the first segment with
	 * the root name "\"
	 */
	user_buffer[size] = '\\';

	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Len=%X, %s \n", path_length, user_buffer));

exit:
	return_ACPI_STATUS (status);
}
Пример #7
0
ACPI_STATUS
acpi_ns_lookup (
	ACPI_GENERIC_STATE      *scope_info,
	NATIVE_CHAR             *pathname,
	OBJECT_TYPE_INTERNAL    type,
	OPERATING_MODE          interpreter_mode,
	u32                     flags,
	ACPI_WALK_STATE         *walk_state,
	ACPI_NAMESPACE_NODE     **return_node)
{
	ACPI_STATUS             status;
	ACPI_NAMESPACE_NODE      *prefix_node;
	ACPI_NAMESPACE_NODE     *current_node = NULL;
	ACPI_NAMESPACE_NODE     *scope_to_push = NULL;
	ACPI_NAMESPACE_NODE     *this_node = NULL;
	u32                     num_segments;
	ACPI_NAME               simple_name;
	u8                      null_name_path = FALSE;
	OBJECT_TYPE_INTERNAL    type_to_check_for;
	OBJECT_TYPE_INTERNAL    this_search_type;

	DEBUG_ONLY_MEMBERS      (u32 i)


	if (!return_node) {
		return (AE_BAD_PARAMETER);
	}


	acpi_gbl_ns_lookup_count++;

	*return_node = ENTRY_NOT_FOUND;


	if (!acpi_gbl_root_node) {
		return (AE_NO_NAMESPACE);
	}

	/*
	 * Get the prefix scope.
	 * A null scope means use the root scope
	 */

	if ((!scope_info) ||
		(!scope_info->scope.node))
	{
		prefix_node = acpi_gbl_root_node;
	}
	else {
		prefix_node = scope_info->scope.node;
	}


	/*
	 * This check is explicitly split provide relax the Type_to_check_for
	 * conditions for Bank_field_defn. Originally, both Bank_field_defn and
	 * Def_field_defn caused Type_to_check_for to be set to ACPI_TYPE_REGION,
	 * but the Bank_field_defn may also check for a Field definition as well
	 * as an Operation_region.
	 */

	if (INTERNAL_TYPE_DEF_FIELD_DEFN == type) {
		/* Def_field_defn defines fields in a Region */

		type_to_check_for = ACPI_TYPE_REGION;
	}

	else if (INTERNAL_TYPE_BANK_FIELD_DEFN == type) {
		/* Bank_field_defn defines data fields in a Field Object */

		type_to_check_for = ACPI_TYPE_ANY;
	}

	else {
		type_to_check_for = type;
	}


	/* TBD: [Restructure] - Move the pathname stuff into a new procedure */

	/* Examine the name pointer */

	if (!pathname) {
		/*  8-12-98 ASL Grammar Update supports null Name_path  */

		null_name_path = TRUE;
		num_segments = 0;
		this_node = acpi_gbl_root_node;

	}

	else {
		/*
		 * Valid name pointer (Internal name format)
		 *
		 * Check for prefixes.  As represented in the AML stream, a
		 * Pathname consists of an optional scope prefix followed by
		 * a segment part.
		 *
		 * If present, the scope prefix is either a Root_prefix (in
		 * which case the name is fully qualified), or zero or more
		 * Parent_prefixes (in which case the name's scope is relative
		 * to the current scope).
		 *
		 * The segment part consists of either:
		 *  - A single 4-byte name segment, or
		 *  - A Dual_name_prefix followed by two 4-byte name segments, or
		 *  - A Multi_name_prefix_op, followed by a byte indicating the
		 *    number of segments and the segments themselves.
		 */

		if (*pathname == AML_ROOT_PREFIX) {
			/* Pathname is fully qualified, look in root name table */

			current_node = acpi_gbl_root_node;

			/* point to segment part */

			pathname++;

			/* Direct reference to root, "\" */

			if (!(*pathname)) {
				this_node = acpi_gbl_root_node;
				goto check_for_new_scope_and_exit;
			}
		}

		else {
			/* Pathname is relative to current scope, start there */

			current_node = prefix_node;

			/*
			 * Handle up-prefix (carat).  More than one prefix
			 * is supported
			 */

			while (*pathname == AML_PARENT_PREFIX) {
				/* Point to segment part or next Parent_prefix */

				pathname++;

				/*  Backup to the parent's scope  */

				this_node = acpi_ns_get_parent_object (current_node);
				if (!this_node) {
					/* Current scope has no parent scope */

					REPORT_ERROR (("Too many parent prefixes (^) - reached root\n"));
					return (AE_NOT_FOUND);
				}

				current_node = this_node;
			}
		}


		/*
		 * Examine the name prefix opcode, if any,
		 * to determine the number of segments
		 */

		if (*pathname == AML_DUAL_NAME_PREFIX) {
			num_segments = 2;

			/* point to first segment */

			pathname++;

		}

		else if (*pathname == AML_MULTI_NAME_PREFIX_OP) {
			num_segments = (u32)* (u8 *) ++pathname;

			/* point to first segment */

			pathname++;

		}

		else {
			/*
			 * No Dual or Multi prefix, hence there is only one
			 * segment and Pathname is already pointing to it.
			 */
			num_segments = 1;

		}

	}


	/*
	 * Search namespace for each segment of the name.
	 * Loop through and verify/add each name segment.
	 */


	while (num_segments-- && current_node) {
		/*
		 * Search for the current name segment under the current
		 * named object.  The Type is significant only at the last (topmost)
		 * level.  (We don't care about the types along the path, only
		 * the type of the final target object.)
		 */
		this_search_type = ACPI_TYPE_ANY;
		if (!num_segments) {
			this_search_type = type;
		}

		/* Pluck one ACPI name from the front of the pathname */

		MOVE_UNALIGNED32_TO_32 (&simple_name, pathname);

		/* Try to find the ACPI name */

		status = acpi_ns_search_and_enter (simple_name, walk_state,
				   current_node, interpreter_mode,
				   this_search_type, flags,
				   &this_node);

		if (ACPI_FAILURE (status)) {
			if (status == AE_NOT_FOUND) {
				/* Name not found in ACPI namespace  */

			}

			return (status);
		}


		/*
		 * If 1) This is the last segment (Num_segments == 0)
		 *    2) and looking for a specific type
		 *       (Not checking for TYPE_ANY)
		 *    3) Which is not an alias
		 *    4) which is not a local type (TYPE_DEF_ANY)
		 *    5) which is not a local type (TYPE_SCOPE)
		 *    6) which is not a local type (TYPE_INDEX_FIELD_DEFN)
		 *    7) and type of object is known (not TYPE_ANY)
		 *    8) and object does not match request
		 *
		 * Then we have a type mismatch.  Just warn and ignore it.
		 */
		if ((num_segments       == 0)                               &&
			(type_to_check_for  != ACPI_TYPE_ANY)                   &&
			(type_to_check_for  != INTERNAL_TYPE_ALIAS)             &&
			(type_to_check_for  != INTERNAL_TYPE_DEF_ANY)           &&
			(type_to_check_for  != INTERNAL_TYPE_SCOPE)             &&
			(type_to_check_for  != INTERNAL_TYPE_INDEX_FIELD_DEFN)  &&
			(this_node->type    != ACPI_TYPE_ANY)                   &&
			(this_node->type    != type_to_check_for))
		{
			/* Complain about a type mismatch */

			REPORT_WARNING (
				("Ns_lookup: %4.4s, type %X, checking for type %X\n",
				&simple_name, this_node->type, type_to_check_for));
		}

		/*
		 * If this is the last name segment and we are not looking for a
		 * specific type, but the type of found object is known, use that type
		 * to see if it opens a scope.
		 */

		if ((0 == num_segments) && (ACPI_TYPE_ANY == type)) {
			type = this_node->type;
		}

		if ((num_segments || acpi_ns_opens_scope (type)) &&
			(this_node->child == NULL))
		{
			/*
			 * More segments or the type implies enclosed scope,
			 * and the next scope has not been allocated.
			 */

		}

		current_node = this_node;

		/* point to next name segment */

		pathname += ACPI_NAME_SIZE;
	}


	/*
	 * Always check if we need to open a new scope
	 */

check_for_new_scope_and_exit:

	if (!(flags & NS_DONT_OPEN_SCOPE) && (walk_state)) {
		/*
		 * If entry is a type which opens a scope,
		 * push the new scope on the scope stack.
		 */

		if (acpi_ns_opens_scope (type_to_check_for)) {
			/*  8-12-98 ASL Grammar Update supports null Name_path  */

			if (null_name_path) {
				/* TBD: [Investigate] - is this the correct thing to do? */

				scope_to_push = NULL;
			}
			else {
				scope_to_push = this_node;
			}

			status = acpi_ds_scope_stack_push (scope_to_push, type,
					   walk_state);
			if (ACPI_FAILURE (status)) {
				return (status);
			}

		}
	}

	*return_node = this_node;
	return (AE_OK);
}
Пример #8
0
ACPI_STATUS
acpi_ev_initialize_region (
	ACPI_OPERAND_OBJECT     *region_obj,
	u8                      acpi_ns_locked)
{
	ACPI_OPERAND_OBJECT    *handler_obj;
	ACPI_OPERAND_OBJECT    *obj_desc;
	ACPI_ADDRESS_SPACE_TYPE space_id;
	ACPI_NAMESPACE_NODE    *node;
	ACPI_STATUS             status;
	ACPI_NAMESPACE_NODE    *method_node;
	ACPI_NAME              *reg_name_ptr = (ACPI_NAME *) METHOD_NAME__REG;


	if (!region_obj) {
		return (AE_BAD_PARAMETER);
	}

	ACPI_ASSERT(region_obj->region.node);

	node = acpi_ns_get_parent_object (region_obj->region.node);
	space_id = region_obj->region.space_id;

	region_obj->region.addr_handler = NULL;
	region_obj->region.extra->extra.method_REG = NULL;
	region_obj->region.flags &= ~(AOPOBJ_INITIALIZED);

	/*
	 *  Find any "_REG" associated with this region definition
	 */
	status = acpi_ns_search_node (*reg_name_ptr, node,
			  ACPI_TYPE_METHOD, &method_node);
	if (ACPI_SUCCESS (status)) {
		/*
		 *  The _REG method is optional and there can be only one per region
		 *  definition.  This will be executed when the handler is attached
		 *  or removed
		 */
		region_obj->region.extra->extra.method_REG = method_node;
	}

	/*
	 *  The following loop depends upon the root Node having no parent
	 *  ie: Acpi_gbl_Root_node->Parent_entry being set to NULL
	 */
	while (node) {
		/*
		 *  Check to see if a handler exists
		 */
		handler_obj = NULL;
		obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) node);
		if (obj_desc) {
			/*
			 *  can only be a handler if the object exists
			 */
			switch (node->type)
			{
			case ACPI_TYPE_DEVICE:

				handler_obj = obj_desc->device.addr_handler;
				break;

			case ACPI_TYPE_PROCESSOR:

				handler_obj = obj_desc->processor.addr_handler;
				break;

			case ACPI_TYPE_THERMAL:

				handler_obj = obj_desc->thermal_zone.addr_handler;
				break;
			}

			while (handler_obj) {
				/*
				 *  This guy has at least one address handler
				 *  see if it has the type we want
				 */
				if (handler_obj->addr_handler.space_id == space_id) {
					/*
					 *  Found it! Now update the region and the handler
					 */
					acpi_ev_associate_region_and_handler (handler_obj, region_obj, acpi_ns_locked);
					return (AE_OK);
				}

				handler_obj = handler_obj->addr_handler.next;

			} /* while handlerobj */
		}

		/*
		 *  This one does not have the handler we need
		 *  Pop up one level
		 */
		node = acpi_ns_get_parent_object (node);

	} /* while Node != ROOT */

	/*
	 *  If we get here, there is no handler for this region
	 */
	return (AE_NOT_EXIST);
}
Пример #9
0
ACPI_STATUS
acpi_ev_pci_config_region_setup (
	ACPI_HANDLE             handle,
	u32                     function,
	void                    *handler_context,
	void                    **region_context)
{
	ACPI_STATUS             status = AE_OK;
	ACPI_INTEGER            temp;
	PCI_HANDLER_CONTEXT     *pci_context = *region_context;
	ACPI_OPERAND_OBJECT     *handler_obj;
	ACPI_NAMESPACE_NODE     *node;
	ACPI_OPERAND_OBJECT     *region_obj = (ACPI_OPERAND_OBJECT *) handle;
	DEVICE_ID               object_hID;

	handler_obj = region_obj->region.addr_handler;

	if (!handler_obj) {
		/*
		 *  No installed handler. This shouldn't happen because the dispatch
		 *  routine checks before we get here, but we check again just in case.
		 */
		return(AE_NOT_EXIST);
	}

	if (function == ACPI_REGION_DEACTIVATE) {
		if (pci_context) {
			acpi_cm_free (pci_context);
			*region_context = NULL;
		}

		return (status);
	}


	/* Create a new context */

	pci_context = acpi_cm_callocate (sizeof(PCI_HANDLER_CONTEXT));
	if (!pci_context) {
		return (AE_NO_MEMORY);
	}

	/*
	 *  For PCI Config space access, we have to pass the segment, bus,
	 *  device and function numbers.  This routine must acquire those.
	 */

	/*
	 *  First get device and function numbers from the _ADR object
	 *  in the parent's scope.
	 */
	ACPI_ASSERT(region_obj->region.node);

	node = acpi_ns_get_parent_object (region_obj->region.node);


	/* Acpi_evaluate the _ADR object */

	status = acpi_cm_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp);
	/*
	 *  The default is zero, since the allocation above zeroed the data, just
	 *  do nothing on failures.
	 */
	if (ACPI_SUCCESS (status)) {
		/*
		 *  Got it..
		 */
		pci_context->dev_func = (u32) temp;
	}

	/*
	 *  Get the _SEG and _BBN values from the device upon which the handler
	 *  is installed.
	 *
	 *  We need to get the _SEG and _BBN objects relative to the PCI BUS device.
	 *  This is the device the handler has been registered to handle.
	 */

	/*
	 *  If the Addr_handler.Node is still pointing to the root, we need
	 *  to scan upward for a PCI Root bridge and re-associate the Op_region
	 *  handlers with that device.
	 */
	if (handler_obj->addr_handler.node == acpi_gbl_root_node) {
		/*
		 * Node is currently the parent object
		 */
		while (node != acpi_gbl_root_node) {
			status = acpi_cm_execute_HID(node, &object_hID);

			if (ACPI_SUCCESS (status)) {
				if (!(STRNCMP(object_hID.buffer, PCI_ROOT_HID_STRING,
						   sizeof (PCI_ROOT_HID_STRING))))
				{
					acpi_install_address_space_handler(node,
							   ADDRESS_SPACE_PCI_CONFIG,
							   ACPI_DEFAULT_HANDLER, NULL, NULL);

					break;
				}
			}

			node = acpi_ns_get_parent_object(node);
		}
	}
	else {
		node = handler_obj->addr_handler.node;
	}

	status = acpi_cm_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp);
	if (ACPI_SUCCESS (status)) {
		/*
		 *  Got it..
		 */
		pci_context->seg = (u32) temp;
	}

	status = acpi_cm_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp);
	if (ACPI_SUCCESS (status)) {
		/*
		 *  Got it..
		 */
		pci_context->bus = (u32) temp;
	}

	*region_context = pci_context;

	return (AE_OK);
}