Merge with 2.4.0-test3-pre4.
[linux-2.6/linux-mips.git] / drivers / acpi / namespace / nsnames.c
blob1c4ab7c0bc99789389364b07703a12b00472c89e
2 /******************************************************************************
4 * Module Name: nsnames - Name manipulation and search
6 *****************************************************************************/
8 /*
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
27 #include "acpi.h"
28 #include "amlcode.h"
29 #include "interp.h"
30 #include "namesp.h"
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
45 * with no separators)
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 ***************************************************************************/
53 char *
54 acpi_ns_name_of_scope (
55 ACPI_NAME_TABLE *scope)
57 char *name_buffer;
58 ACPI_SIZE size;
59 ACPI_NAME name;
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.
69 return (NULL);
72 entry_to_search = scope->entries;
75 /* Calculate required buffer size based on depth below root NT */
77 size = 1;
78 parent_entry = entry_to_search;
79 while (parent_entry) {
80 parent_entry = acpi_ns_get_parent_entry (parent_entry);
81 if (parent_entry) {
82 size += ACPI_NAME_SIZE;
87 /* Allocate the buffer */
89 name_buffer = acpi_cm_callocate (size + 1);
90 if (!name_buffer) {
91 REPORT_ERROR ("Ns_name_of_scope: allocation failure");
92 return (NULL);
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
122 * PARAMETERS: none
124 * RETURN: pointer to storage containing the name of the current scope
126 ***************************************************************************/
128 char *
129 acpi_ns_name_of_current_scope (
130 ACPI_WALK_STATE *walk_state)
132 char *scope_name;
135 if (walk_state && walk_state->scope_info) {
136 scope_name =
137 acpi_ns_name_of_scope (walk_state->scope_info->scope.name_table);
139 return (scope_name);
142 REPORT_ERROR ("Current scope pointer is invalid");
144 return (NULL);
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 ***************************************************************************/
164 ACPI_STATUS
165 acpi_ns_handle_to_pathname (
166 ACPI_HANDLE target_handle,
167 u32 *buf_size,
168 char *user_buffer)
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;
174 ACPI_SIZE size;
175 u32 user_buf_size;
176 ACPI_NAME name;
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
248 * the root name "\"
251 user_buffer[size] = '\\';
254 unlock_and_exit:
256 if (!namespace_was_locked) {
257 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
260 return (status);
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 "?"
273 * to match any.
275 ***************************************************************************/
278 acpi_ns_pattern_match (
279 ACPI_NAMED_OBJECT *obj_entry,
280 char *search_for)
282 s32 i;
285 for (i = 0; i < ACPI_NAME_SIZE; i++) {
286 if (search_for[i] != '?' &&
287 search_for[i] != ((char *) &obj_entry->name)[i])
289 /* No match */
291 return FALSE;
295 /* name matches pattern */
297 return TRUE;
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 ***************************************************************************/
315 ACPI_STATUS
316 acpi_ns_name_compare (
317 ACPI_HANDLE obj_handle,
318 u32 level,
319 void *context,
320 void **return_value)
322 FIND_CONTEXT *find = context;
325 /* Match, yes or no? */
327 if (acpi_ns_pattern_match ((ACPI_NAMED_OBJECT*) obj_handle,
328 find->search_for))
330 /* Name matches pattern */
332 if (find->list) {
333 find->list[*(find->count)] = obj_handle;
336 ++*(find->count);
339 /* Don't terminate the walk */
340 return AE_OK;
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
357 * unlimited depth.
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 ***************************************************************************/
365 void
366 acpi_ns_low_find_names (
367 ACPI_NAMED_OBJECT *this_entry,
368 char *search_for,
369 s32 *count,
370 ACPI_HANDLE list[],
371 s32 max_depth)
373 FIND_CONTEXT find;
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
382 return;
385 /* Init the context structure used by compare routine */
387 find.list = list;
388 find.count = count;
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);
397 if (list) {
398 /* null-terminate the output array */
400 list[*count] = (ACPI_HANDLE) 0;
403 return;
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 ***************************************************************************/
430 ACPI_HANDLE *
431 acpi_ns_find_names (
432 char *search_for,
433 ACPI_HANDLE start_handle,
434 s32 max_depth)
436 ACPI_HANDLE *list = NULL;
437 s32 count;
440 if (!acpi_gbl_root_object->child_table) {
442 * If the name space has not been initialized,
443 * there surely are no matching names.
445 return (NULL);
448 if (NS_ALL == start_handle) {
449 /* base is root */
451 start_handle = acpi_gbl_root_object;
454 else if (((ACPI_NAMED_OBJECT *) start_handle)->child_table) {
455 /* base has children to search */
457 start_handle =
458 ((ACPI_NAMED_OBJECT *) start_handle)->child_table->entries;
461 else {
463 * If base is not the root and has no children,
464 * there is nothing to search.
466 return (NULL);
469 if (!search_for) {
470 /* Search name not specified */
472 search_for = "????";
476 /* Pass 1. Get required buffer size, don't try to build list */
478 count = 0;
479 acpi_ns_low_find_names (start_handle, search_for, &count,
480 NULL, max_depth);
482 if (0 == count) {
483 return (NULL);
486 /* Allow for trailing null */
487 count++;
489 list = acpi_cm_callocate (count * sizeof(ACPI_HANDLE));
490 if (!list) {
491 REPORT_ERROR ("Ns_find_names: allocation failure");
492 return (NULL);
495 /* Pass 2. Fill buffer */
497 count = 0;
498 acpi_ns_low_find_names (start_handle, search_for, &count, list, max_depth);
500 return (list);