2 /******************************************************************************
4 * Module Name: nsnames - Name manipulation and search
6 *****************************************************************************/
9 * Copyright (C) 2000 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #define _COMPONENT NAMESPACE
34 MODULE_NAME ("nsnames");
37 /****************************************************************************
39 * FUNCTION: Acpi_ns_name_of_scope
41 * PARAMETERS: Scope - Scope whose name is needed
43 * RETURN: Pointer to storage containing the fully qualified name of
44 * the scope, in Label format (all segments strung together
47 * DESCRIPTION: Used via Acpi_ns_name_of_current_scope() and Acpi_ns_last_fQN()
48 * for label generation in the interpreter, and for debug
49 * printing in Acpi_ns_search_table().
51 ***************************************************************************/
54 acpi_ns_name_of_scope (
55 ACPI_NAME_TABLE
*scope
)
60 ACPI_NAMED_OBJECT
*entry_to_search
;
61 ACPI_NAMED_OBJECT
*parent_entry
;
64 if (!acpi_gbl_root_object
->child_table
|| !scope
) {
66 * If the name space has not been initialized,
67 * this function should not have been called.
72 entry_to_search
= scope
->entries
;
75 /* Calculate required buffer size based on depth below root NT */
78 parent_entry
= entry_to_search
;
79 while (parent_entry
) {
80 parent_entry
= acpi_ns_get_parent_entry (parent_entry
);
82 size
+= ACPI_NAME_SIZE
;
87 /* Allocate the buffer */
89 name_buffer
= acpi_cm_callocate (size
+ 1);
91 REPORT_ERROR ("Ns_name_of_scope: allocation failure");
96 /* Store terminator byte, then build name backwards */
98 name_buffer
[size
] = '\0';
99 while ((size
> ACPI_NAME_SIZE
) &&
100 acpi_ns_get_parent_entry (entry_to_search
))
102 size
-= ACPI_NAME_SIZE
;
103 name
= acpi_ns_find_parent_name (entry_to_search
);
105 /* Put the name into the buffer */
107 MOVE_UNALIGNED32_TO_32 ((name_buffer
+ size
), &name
);
108 entry_to_search
= acpi_ns_get_parent_entry (entry_to_search
);
111 name_buffer
[--size
] = AML_ROOT_PREFIX
;
114 return (name_buffer
);
118 /****************************************************************************
120 * FUNCTION: Acpi_ns_name_of_current_scope
124 * RETURN: pointer to storage containing the name of the current scope
126 ***************************************************************************/
129 acpi_ns_name_of_current_scope (
130 ACPI_WALK_STATE
*walk_state
)
135 if (walk_state
&& walk_state
->scope_info
) {
137 acpi_ns_name_of_scope (walk_state
->scope_info
->scope
.name_table
);
142 REPORT_ERROR ("Current scope pointer is invalid");
148 /****************************************************************************
150 * FUNCTION: Acpi_ns_handle_to_pathname
152 * PARAMETERS: Target_handle - Handle of nte whose name is to be found
153 * Buf_size - Size of the buffer provided
154 * User_buffer - Where the pathname is returned
156 * RETURN: Status, Buffer is filled with pathname if status == AE_OK
158 * DESCRIPTION: Build and return a full namespace pathname
160 * MUTEX: Locks Namespace
162 ***************************************************************************/
165 acpi_ns_handle_to_pathname (
166 ACPI_HANDLE target_handle
,
170 ACPI_STATUS status
= AE_OK
;
171 ACPI_NAMED_OBJECT
*entry_to_search
= NULL
;
172 ACPI_NAMED_OBJECT
*temp
= NULL
;
173 ACPI_SIZE path_length
= 0;
177 u8 namespace_was_locked
;
180 if (!acpi_gbl_root_object
->child_table
|| !target_handle
) {
182 * If the name space has not been initialized,
183 * this function should not have been called.
186 return (AE_NO_NAMESPACE
);
189 namespace_was_locked
= acpi_gbl_acpi_mutex_info
[ACPI_MTX_NAMESPACE
].locked
;
190 if (!namespace_was_locked
) {
191 acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE
);
194 entry_to_search
= acpi_ns_convert_handle_to_entry (target_handle
);
195 if (!entry_to_search
) {
196 return (AE_BAD_PARAMETER
);
200 * Compute length of pathname as 5 * number of name segments.
201 * Go back up the parent tree to the root
203 for (size
= 0, temp
= entry_to_search
;
204 acpi_ns_get_parent_entry (temp
);
205 temp
= acpi_ns_get_parent_entry (temp
))
207 size
+= PATH_SEGMENT_LENGTH
;
210 /* Set return length to the required path length */
212 path_length
= size
+ 1;
213 user_buf_size
= *buf_size
;
214 *buf_size
= path_length
;
216 /* Check if the user buffer is sufficiently large */
218 if (path_length
> user_buf_size
) {
219 status
= AE_BUFFER_OVERFLOW
;
220 goto unlock_and_exit
;
223 /* Store null terminator */
225 user_buffer
[size
] = 0;
226 size
-= ACPI_NAME_SIZE
;
228 /* Put the original ACPI name at the end of the path */
230 MOVE_UNALIGNED32_TO_32 ((user_buffer
+ size
),
231 &entry_to_search
->name
);
233 user_buffer
[--size
] = PATH_SEPARATOR
;
235 /* Build name backwards, putting "." between segments */
237 while ((size
> ACPI_NAME_SIZE
) && entry_to_search
) {
238 size
-= ACPI_NAME_SIZE
;
239 name
= acpi_ns_find_parent_name (entry_to_search
);
240 MOVE_UNALIGNED32_TO_32 ((user_buffer
+ size
), &name
);
242 user_buffer
[--size
] = PATH_SEPARATOR
;
243 entry_to_search
= acpi_ns_get_parent_entry (entry_to_search
);
247 * Overlay the "." preceding the first segment with
251 user_buffer
[size
] = '\\';
256 if (!namespace_was_locked
) {
257 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE
);
264 /****************************************************************************
266 * FUNCTION: Acpi_ns_pattern_match
268 * PARAMETERS: Obj_entry - A namespace entry
269 * Search_for - Wildcard pattern string
271 * DESCRIPTION: Matches a namespace name against a wildcard pattern. Only
272 * a very simple pattern - 4 chars, either a valid char or a "?"
275 ***************************************************************************/
278 acpi_ns_pattern_match (
279 ACPI_NAMED_OBJECT
*obj_entry
,
285 for (i
= 0; i
< ACPI_NAME_SIZE
; i
++) {
286 if (search_for
[i
] != '?' &&
287 search_for
[i
] != ((char *) &obj_entry
->name
)[i
])
295 /* name matches pattern */
301 /****************************************************************************
303 * FUNCTION: Acpi_ns_name_compare
305 * PARAMETERS: Obj_handle - A namespace entry
306 * Level - Current nesting level
307 * Context - A FIND_CONTEXT structure
309 * DESCRIPTION: A User_function called by Acpi_ns_walk_namespace(). It performs
310 * a pattern match for Acpi_ns_low_find_names(), and updates the list
311 * and count as required.
313 ***************************************************************************/
316 acpi_ns_name_compare (
317 ACPI_HANDLE obj_handle
,
322 FIND_CONTEXT
*find
= context
;
325 /* Match, yes or no? */
327 if (acpi_ns_pattern_match ((ACPI_NAMED_OBJECT
*) obj_handle
,
330 /* Name matches pattern */
333 find
->list
[*(find
->count
)] = obj_handle
;
339 /* Don't terminate the walk */
344 /****************************************************************************
346 * FUNCTION: Acpi_ns_low_find_names
348 * PARAMETERS: *This_entry - Table to be searched
349 * *Search_for - Pattern to be found.
350 * 4 bytes, ? matches any character.
351 * *Count - Output count of matches found.
352 * Outermost caller should preset to 0
353 * List[] - Output array of handles. If
354 * null, only the count is obtained.
355 * Max_depth - Maximum depth of search. Use
356 * INT_MAX for an effectively
359 * DESCRIPTION: Low-level find name.
360 * Traverse the name space finding names which match a search
361 * pattern, and return an array of handles in List[].
363 ***************************************************************************/
366 acpi_ns_low_find_names (
367 ACPI_NAMED_OBJECT
*this_entry
,
376 if (0 == max_depth
|| !this_entry
|| !search_for
|| !count
) {
378 * Zero requested depth, nothing to search,
379 * nothing to search for, or count pointer bad
385 /* Init the context structure used by compare routine */
389 find
.search_for
= search_for
;
391 /* Walk the namespace and find all matches */
393 acpi_ns_walk_namespace (ACPI_TYPE_ANY
, (ACPI_HANDLE
) this_entry
,
394 max_depth
, NS_WALK_NO_UNLOCK
,
395 acpi_ns_name_compare
, &find
, NULL
);
398 /* null-terminate the output array */
400 list
[*count
] = (ACPI_HANDLE
) 0;
407 /****************************************************************************
409 * FUNCTION: Acpi_ns_find_names
412 * PARAMETERS: *Search_for - pattern to be found.
413 * 4 bytes, ? matches any character.
414 * If NULL, "????" will be used.
415 * Start_handle - Root of subtree to be searched, or
416 * NS_ALL to search the entire namespace
417 * Max_depth - Maximum depth of search. Use INT_MAX
418 * for an effectively unlimited depth.
420 * DESCRIPTION: Traverse the name space finding names which match a search
421 * pattern, and return an array of handles. The end of the
422 * array is marked by the value (ACPI_HANDLE)0. A return value
423 * of (ACPI_HANDLE *)0 indicates that no matching names were
424 * found or that space for the list could not be allocated.
425 * if Start_handle is NS_ALL (null) search from the root,
426 * else it is a handle whose children are to be searched.
428 ***************************************************************************/
433 ACPI_HANDLE start_handle
,
436 ACPI_HANDLE
*list
= NULL
;
440 if (!acpi_gbl_root_object
->child_table
) {
442 * If the name space has not been initialized,
443 * there surely are no matching names.
448 if (NS_ALL
== start_handle
) {
451 start_handle
= acpi_gbl_root_object
;
454 else if (((ACPI_NAMED_OBJECT
*) start_handle
)->child_table
) {
455 /* base has children to search */
458 ((ACPI_NAMED_OBJECT
*) start_handle
)->child_table
->entries
;
463 * If base is not the root and has no children,
464 * there is nothing to search.
470 /* Search name not specified */
476 /* Pass 1. Get required buffer size, don't try to build list */
479 acpi_ns_low_find_names (start_handle
, search_for
, &count
,
486 /* Allow for trailing null */
489 list
= acpi_cm_callocate (count
* sizeof(ACPI_HANDLE
));
491 REPORT_ERROR ("Ns_find_names: allocation failure");
495 /* Pass 2. Fill buffer */
498 acpi_ns_low_find_names (start_handle
, search_for
, &count
, list
, max_depth
);