patch-2.4.0-test3 linux/drivers/acpi/namespace/nsnames.c

Next file: linux/drivers/acpi/namespace/nsobject.c
Previous file: linux/drivers/acpi/namespace/nsload.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/namespace/nsnames.c linux/drivers/acpi/namespace/nsnames.c
@@ -0,0 +1,503 @@
+
+/******************************************************************************
+ *
+ * Module Name: nsnames - Name manipulation and search
+ *
+ *****************************************************************************/
+
+/*
+ *  Copyright (C) 2000 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "acpi.h"
+#include "amlcode.h"
+#include "interp.h"
+#include "namesp.h"
+
+
+#define _COMPONENT          NAMESPACE
+	 MODULE_NAME         ("nsnames");
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ns_name_of_scope
+ *
+ * PARAMETERS:  Scope           - Scope whose name is needed
+ *
+ * RETURN:      Pointer to storage containing the fully qualified name of
+ *              the scope, in Label format (all segments strung together
+ *              with no separators)
+ *
+ * DESCRIPTION: Used via Acpi_ns_name_of_current_scope() and Acpi_ns_last_fQN()
+ *              for label generation in the interpreter, and for debug
+ *              printing in Acpi_ns_search_table().
+ *
+ ***************************************************************************/
+
+char *
+acpi_ns_name_of_scope (
+	ACPI_NAME_TABLE         *scope)
+{
+	char                    *name_buffer;
+	ACPI_SIZE               size;
+	ACPI_NAME               name;
+	ACPI_NAMED_OBJECT       *entry_to_search;
+	ACPI_NAMED_OBJECT       *parent_entry;
+
+
+	if (!acpi_gbl_root_object->child_table || !scope) {
+		/*
+		 * If the name space has not been initialized,
+		 * this function should not have been called.
+		 */
+		return (NULL);
+	}
+
+	entry_to_search = scope->entries;
+
+
+	/* Calculate required buffer size based on depth below root NT */
+
+	size = 1;
+	parent_entry = entry_to_search;
+	while (parent_entry) {
+		parent_entry = acpi_ns_get_parent_entry (parent_entry);
+		if (parent_entry) {
+			size += ACPI_NAME_SIZE;
+		}
+	}
+
+
+	/* Allocate the buffer */
+
+	name_buffer = acpi_cm_callocate (size + 1);
+	if (!name_buffer) {
+		REPORT_ERROR ("Ns_name_of_scope: allocation failure");
+		return (NULL);
+	}
+
+
+	/* Store terminator byte, then build name backwards */
+
+	name_buffer[size] = '\0';
+	while ((size > ACPI_NAME_SIZE) &&
+		acpi_ns_get_parent_entry (entry_to_search))
+	{
+		size -= ACPI_NAME_SIZE;
+		name = acpi_ns_find_parent_name (entry_to_search);
+
+		/* Put the name into the buffer */
+
+		MOVE_UNALIGNED32_TO_32 ((name_buffer + size), &name);
+		entry_to_search = acpi_ns_get_parent_entry (entry_to_search);
+	}
+
+	name_buffer[--size] = AML_ROOT_PREFIX;
+
+
+	return (name_buffer);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ns_name_of_current_scope
+ *
+ * PARAMETERS:  none
+ *
+ * RETURN:      pointer to storage containing the name of the current scope
+ *
+ ***************************************************************************/
+
+char *
+acpi_ns_name_of_current_scope (
+	ACPI_WALK_STATE         *walk_state)
+{
+	char                    *scope_name;
+
+
+	if (walk_state && walk_state->scope_info) {
+		scope_name =
+			acpi_ns_name_of_scope (walk_state->scope_info->scope.name_table);
+
+		return (scope_name);
+	}
+
+	REPORT_ERROR ("Current scope pointer is invalid");
+
+	return (NULL);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ns_handle_to_pathname
+ *
+ * PARAMETERS:  Target_handle           - Handle of nte whose name is to be found
+ *              Buf_size                - Size of the buffer provided
+ *              User_buffer             - Where the pathname is returned
+ *
+ * RETURN:      Status, Buffer is filled with pathname if status == AE_OK
+ *
+ * DESCRIPTION: Build and return a full namespace pathname
+ *
+ * MUTEX:       Locks Namespace
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_handle_to_pathname (
+	ACPI_HANDLE             target_handle,
+	u32                     *buf_size,
+	char                    *user_buffer)
+{
+	ACPI_STATUS             status = AE_OK;
+	ACPI_NAMED_OBJECT       *entry_to_search = NULL;
+	ACPI_NAMED_OBJECT       *temp = NULL;
+	ACPI_SIZE               path_length = 0;
+	ACPI_SIZE               size;
+	u32                     user_buf_size;
+	ACPI_NAME               name;
+	u8                      namespace_was_locked;
+
+
+	if (!acpi_gbl_root_object->child_table || !target_handle) {
+		/*
+		 * If the name space has not been initialized,
+		 * this function should not have been called.
+		 */
+
+		return (AE_NO_NAMESPACE);
+	}
+
+	namespace_was_locked = acpi_gbl_acpi_mutex_info[ACPI_MTX_NAMESPACE].locked;
+	if (!namespace_was_locked) {
+		acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
+	}
+
+	entry_to_search = acpi_ns_convert_handle_to_entry (target_handle);
+	if (!entry_to_search) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	/*
+	 * Compute length of pathname as 5 * number of name segments.
+	 * Go back up the parent tree to the root
+	 */
+	for (size = 0, temp = entry_to_search;
+		  acpi_ns_get_parent_entry (temp);
+		  temp = acpi_ns_get_parent_entry (temp))
+	{
+		size += PATH_SEGMENT_LENGTH;
+	}
+
+	/* Set return length to the required path length */
+
+	path_length = size + 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 unlock_and_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),
+			 &entry_to_search->name);
+
+	user_buffer[--size] = PATH_SEPARATOR;
+
+	/* Build name backwards, putting "." between segments */
+
+	while ((size > ACPI_NAME_SIZE) && entry_to_search) {
+		size -= ACPI_NAME_SIZE;
+		name = acpi_ns_find_parent_name (entry_to_search);
+		MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &name);
+
+		user_buffer[--size] = PATH_SEPARATOR;
+		entry_to_search = acpi_ns_get_parent_entry (entry_to_search);
+	}
+
+	/*
+	 * Overlay the "." preceding the first segment with
+	 * the root name "\"
+	 */
+
+	user_buffer[size] = '\\';
+
+
+unlock_and_exit:
+
+	if (!namespace_was_locked) {
+		acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+	}
+
+	return (status);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ns_pattern_match
+ *
+ * PARAMETERS:  Obj_entry       - A namespace entry
+ *              Search_for      - Wildcard pattern string
+ *
+ * DESCRIPTION: Matches a namespace name against a wildcard pattern.  Only
+ *              a very simple pattern - 4 chars, either a valid char or a "?"
+ *              to match any.
+ *
+ ***************************************************************************/
+
+u8
+acpi_ns_pattern_match (
+	ACPI_NAMED_OBJECT       *obj_entry,
+	char                    *search_for)
+{
+	s32                     i;
+
+
+	for (i = 0; i < ACPI_NAME_SIZE; i++) {
+		if (search_for[i] != '?' &&
+			search_for[i] != ((char *) &obj_entry->name)[i])
+		{
+			/* No match */
+
+			return FALSE;
+		}
+	}
+
+	/* name matches pattern */
+
+	return TRUE;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ns_name_compare
+ *
+ * PARAMETERS:  Obj_handle      - A namespace entry
+ *              Level           - Current nesting level
+ *              Context         - A FIND_CONTEXT structure
+ *
+ * DESCRIPTION: A User_function called by Acpi_ns_walk_namespace(). It performs
+ *              a pattern match for Acpi_ns_low_find_names(), and updates the list
+ *              and count as required.
+ *
+ ***************************************************************************/
+
+ACPI_STATUS
+acpi_ns_name_compare (
+	ACPI_HANDLE             obj_handle,
+	u32                     level,
+	void                    *context,
+	void                    **return_value)
+{
+	FIND_CONTEXT            *find = context;
+
+
+	/* Match, yes or no? */
+
+	if (acpi_ns_pattern_match ((ACPI_NAMED_OBJECT*) obj_handle,
+			 find->search_for))
+	{
+		/* Name matches pattern */
+
+		if (find->list) {
+			find->list[*(find->count)] = obj_handle;
+		}
+
+		++*(find->count);
+	}
+
+	 /* Don't terminate the walk */
+	return AE_OK;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ns_low_find_names
+ *
+ * PARAMETERS:  *This_entry         - Table to be searched
+ *              *Search_for         - Pattern to be found.
+ *                                    4 bytes, ? matches any character.
+ *              *Count              - Output count of matches found.
+ *                                    Outermost caller should preset to 0
+ *              List[]              - Output array of handles.  If
+ *                                    null, only the count is obtained.
+ *              Max_depth           - Maximum depth of search.  Use
+ *                                    INT_MAX for an effectively
+ *                                    unlimited depth.
+ *
+ * DESCRIPTION: Low-level find name.
+ *              Traverse the name space finding names which match a search
+ *              pattern, and return an array of handles in List[].
+ *
+ ***************************************************************************/
+
+void
+acpi_ns_low_find_names (
+	ACPI_NAMED_OBJECT       *this_entry,
+	char                    *search_for,
+	s32                     *count,
+	ACPI_HANDLE             list[],
+	s32                     max_depth)
+{
+	FIND_CONTEXT            find;
+
+
+	if (0 == max_depth || !this_entry || !search_for || !count) {
+		/*
+		 * Zero requested depth, nothing to search,
+		 * nothing to search for, or count pointer bad
+		 */
+
+		return;
+	}
+
+	/* Init the context structure used by compare routine */
+
+	find.list       = list;
+	find.count      = count;
+	find.search_for = search_for;
+
+	/* Walk the namespace and find all matches */
+
+	acpi_ns_walk_namespace (ACPI_TYPE_ANY, (ACPI_HANDLE) this_entry,
+			   max_depth, NS_WALK_NO_UNLOCK,
+			   acpi_ns_name_compare, &find, NULL);
+
+	if (list) {
+		/* null-terminate the output array */
+
+		list[*count] = (ACPI_HANDLE) 0;
+	}
+
+	return;
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION:    Acpi_ns_find_names
+
+ *
+ * PARAMETERS:  *Search_for         - pattern to be found.
+ *                                    4 bytes, ? matches any character.
+ *                                    If NULL, "????" will be used.
+ *              Start_handle        - Root of subtree to be searched, or
+ *                                    NS_ALL to search the entire namespace
+ *              Max_depth           - Maximum depth of search.  Use INT_MAX
+ *                                    for an effectively unlimited depth.
+ *
+ * DESCRIPTION: Traverse the name space finding names which match a search
+ *              pattern, and return an array of handles.  The end of the
+ *              array is marked by the value (ACPI_HANDLE)0.  A return value
+ *              of (ACPI_HANDLE *)0 indicates that no matching names were
+ *              found or that space for the list could not be allocated.
+ *              if Start_handle is NS_ALL (null) search from the root,
+ *              else it is a handle whose children are to be searched.
+ *
+ ***************************************************************************/
+
+ACPI_HANDLE *
+acpi_ns_find_names (
+	char                    *search_for,
+	ACPI_HANDLE             start_handle,
+	s32                     max_depth)
+{
+	ACPI_HANDLE             *list = NULL;
+	s32                     count;
+
+
+	if (!acpi_gbl_root_object->child_table) {
+		/*
+		 * If the name space has not been initialized,
+		 * there surely are no matching names.
+		 */
+		return (NULL);
+	}
+
+	if (NS_ALL == start_handle) {
+		/* base is root */
+
+		start_handle = acpi_gbl_root_object;
+	}
+
+	else if (((ACPI_NAMED_OBJECT *) start_handle)->child_table) {
+		/* base has children to search */
+
+		start_handle =
+			((ACPI_NAMED_OBJECT *) start_handle)->child_table->entries;
+	}
+
+	else {
+		/*
+		 * If base is not the root and has no children,
+		 * there is nothing to search.
+		 */
+		return (NULL);
+	}
+
+	if (!search_for) {
+		/* Search name not specified */
+
+		search_for = "????";
+	}
+
+
+	/* Pass 1.  Get required buffer size, don't try to build list */
+
+	count = 0;
+	acpi_ns_low_find_names (start_handle, search_for, &count,
+			   NULL, max_depth);
+
+	if (0 == count) {
+		return (NULL);
+	}
+
+	/* Allow for trailing null */
+	count++;
+
+	list = acpi_cm_callocate (count * sizeof(ACPI_HANDLE));
+	if (!list) {
+		REPORT_ERROR ("Ns_find_names: allocation failure");
+		return (NULL);
+	}
+
+	/* Pass 2.  Fill buffer */
+
+	count = 0;
+	acpi_ns_low_find_names (start_handle, search_for, &count, list, max_depth);
+
+	return (list);
+}
+
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)