aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/namespace
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acpi/namespace
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/acpi/namespace')
-rw-r--r--drivers/acpi/namespace/Makefile12
-rw-r--r--drivers/acpi/namespace/nsaccess.c637
-rw-r--r--drivers/acpi/namespace/nsalloc.c685
-rw-r--r--drivers/acpi/namespace/nsdump.c673
-rw-r--r--drivers/acpi/namespace/nsdumpdv.c146
-rw-r--r--drivers/acpi/namespace/nseval.c487
-rw-r--r--drivers/acpi/namespace/nsinit.c441
-rw-r--r--drivers/acpi/namespace/nsload.c460
-rw-r--r--drivers/acpi/namespace/nsnames.c265
-rw-r--r--drivers/acpi/namespace/nsobject.c461
-rw-r--r--drivers/acpi/namespace/nsparse.c171
-rw-r--r--drivers/acpi/namespace/nssearch.c381
-rw-r--r--drivers/acpi/namespace/nsutils.c1069
-rw-r--r--drivers/acpi/namespace/nswalk.c289
-rw-r--r--drivers/acpi/namespace/nsxfeval.c764
-rw-r--r--drivers/acpi/namespace/nsxfname.c369
-rw-r--r--drivers/acpi/namespace/nsxfobj.c262
17 files changed, 7572 insertions, 0 deletions
diff --git a/drivers/acpi/namespace/Makefile b/drivers/acpi/namespace/Makefile
new file mode 100644
index 000000000000..3f63d3640696
--- /dev/null
+++ b/drivers/acpi/namespace/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for all Linux ACPI interpreter subdirectories
3#
4
5obj-y := nsaccess.o nsload.o nssearch.o nsxfeval.o \
6 nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
7 nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
8 nsparse.o
9
10obj-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
11
12EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
new file mode 100644
index 000000000000..1c0c12336c57
--- /dev/null
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -0,0 +1,637 @@
1/*******************************************************************************
2 *
3 * Module Name: nsaccess - Top-level functions for accessing ACPI namespace
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/amlcode.h>
47#include <acpi/acnamesp.h>
48#include <acpi/acdispat.h>
49
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsaccess")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_ns_root_initialize
58 *
59 * PARAMETERS: None
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: Allocate and initialize the default root named objects
64 *
65 * MUTEX: Locks namespace for entire execution
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_ns_root_initialize (void)
71{
72 acpi_status status;
73 const struct acpi_predefined_names *init_val = NULL;
74 struct acpi_namespace_node *new_node;
75 union acpi_operand_object *obj_desc;
76 acpi_string val = NULL;
77
78
79 ACPI_FUNCTION_TRACE ("ns_root_initialize");
80
81
82 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
83 if (ACPI_FAILURE (status)) {
84 return_ACPI_STATUS (status);
85 }
86
87 /*
88 * The global root ptr is initially NULL, so a non-NULL value indicates
89 * that acpi_ns_root_initialize() has already been called; just return.
90 */
91 if (acpi_gbl_root_node) {
92 status = AE_OK;
93 goto unlock_and_exit;
94 }
95
96 /*
97 * Tell the rest of the subsystem that the root is initialized
98 * (This is OK because the namespace is locked)
99 */
100 acpi_gbl_root_node = &acpi_gbl_root_node_struct;
101
102 /* Enter the pre-defined names in the name table */
103
104 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
105 "Entering predefined entries into namespace\n"));
106
107 for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
108 /* _OSI is optional for now, will be permanent later */
109
110 if (!ACPI_STRCMP (init_val->name, "_OSI") && !acpi_gbl_create_osi_method) {
111 continue;
112 }
113
114 status = acpi_ns_lookup (NULL, init_val->name, init_val->type,
115 ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
116 NULL, &new_node);
117
118 if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ {
119 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
120 "Could not create predefined name %s, %s\n",
121 init_val->name, acpi_format_exception (status)));
122 }
123
124 /*
125 * Name entered successfully.
126 * If entry in pre_defined_names[] specifies an
127 * initial value, create the initial value.
128 */
129 if (init_val->val) {
130 status = acpi_os_predefined_override (init_val, &val);
131 if (ACPI_FAILURE (status)) {
132 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
133 "Could not override predefined %s\n",
134 init_val->name));
135 }
136
137 if (!val) {
138 val = init_val->val;
139 }
140
141 /*
142 * Entry requests an initial value, allocate a
143 * descriptor for it.
144 */
145 obj_desc = acpi_ut_create_internal_object (init_val->type);
146 if (!obj_desc) {
147 status = AE_NO_MEMORY;
148 goto unlock_and_exit;
149 }
150
151 /*
152 * Convert value string from table entry to
153 * internal representation. Only types actually
154 * used for initial values are implemented here.
155 */
156 switch (init_val->type) {
157 case ACPI_TYPE_METHOD:
158 obj_desc->method.param_count = (u8) ACPI_TO_INTEGER (val);
159 obj_desc->common.flags |= AOPOBJ_DATA_VALID;
160
161#if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App)
162
163 /*
164 * i_aSL Compiler cheats by putting parameter count
165 * in the owner_iD
166 */
167 new_node->owner_id = obj_desc->method.param_count;
168#else
169 /* Mark this as a very SPECIAL method */
170
171 obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY;
172 obj_desc->method.implementation = acpi_ut_osi_implementation;
173#endif
174 break;
175
176 case ACPI_TYPE_INTEGER:
177
178 obj_desc->integer.value = ACPI_TO_INTEGER (val);
179 break;
180
181
182 case ACPI_TYPE_STRING:
183
184 /*
185 * Build an object around the static string
186 */
187 obj_desc->string.length = (u32) ACPI_STRLEN (val);
188 obj_desc->string.pointer = val;
189 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
190 break;
191
192
193 case ACPI_TYPE_MUTEX:
194
195 obj_desc->mutex.node = new_node;
196 obj_desc->mutex.sync_level = (u8) (ACPI_TO_INTEGER (val) - 1);
197
198 if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
199 /*
200 * Create a counting semaphore for the
201 * global lock
202 */
203 status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT,
204 1, &obj_desc->mutex.semaphore);
205 if (ACPI_FAILURE (status)) {
206 acpi_ut_remove_reference (obj_desc);
207 goto unlock_and_exit;
208 }
209
210 /*
211 * We just created the mutex for the
212 * global lock, save it
213 */
214 acpi_gbl_global_lock_semaphore = obj_desc->mutex.semaphore;
215 }
216 else {
217 /* Create a mutex */
218
219 status = acpi_os_create_semaphore (1, 1,
220 &obj_desc->mutex.semaphore);
221 if (ACPI_FAILURE (status)) {
222 acpi_ut_remove_reference (obj_desc);
223 goto unlock_and_exit;
224 }
225 }
226 break;
227
228
229 default:
230
231 ACPI_REPORT_ERROR (("Unsupported initial type value %X\n",
232 init_val->type));
233 acpi_ut_remove_reference (obj_desc);
234 obj_desc = NULL;
235 continue;
236 }
237
238 /* Store pointer to value descriptor in the Node */
239
240 status = acpi_ns_attach_object (new_node, obj_desc,
241 ACPI_GET_OBJECT_TYPE (obj_desc));
242
243 /* Remove local reference to the object */
244
245 acpi_ut_remove_reference (obj_desc);
246 }
247 }
248
249
250unlock_and_exit:
251 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
252
253 /* Save a handle to "_GPE", it is always present */
254
255 if (ACPI_SUCCESS (status)) {
256 status = acpi_ns_get_node_by_path ("\\_GPE", NULL, ACPI_NS_NO_UPSEARCH,
257 &acpi_gbl_fadt_gpe_device);
258 }
259
260 return_ACPI_STATUS (status);
261}
262
263
264/*******************************************************************************
265 *
266 * FUNCTION: acpi_ns_lookup
267 *
268 * PARAMETERS: prefix_node - Search scope if name is not fully qualified
269 * Pathname - Search pathname, in internal format
270 * (as represented in the AML stream)
271 * Type - Type associated with name
272 * interpreter_mode - IMODE_LOAD_PASS2 => add name if not found
273 * Flags - Flags describing the search restrictions
274 * walk_state - Current state of the walk
275 * return_node - Where the Node is placed (if found
276 * or created successfully)
277 *
278 * RETURN: Status
279 *
280 * DESCRIPTION: Find or enter the passed name in the name space.
281 * Log an error if name not found in Exec mode.
282 *
283 * MUTEX: Assumes namespace is locked.
284 *
285 ******************************************************************************/
286
287acpi_status
288acpi_ns_lookup (
289 union acpi_generic_state *scope_info,
290 char *pathname,
291 acpi_object_type type,
292 acpi_interpreter_mode interpreter_mode,
293 u32 flags,
294 struct acpi_walk_state *walk_state,
295 struct acpi_namespace_node **return_node)
296{
297 acpi_status status;
298 char *path = pathname;
299 struct acpi_namespace_node *prefix_node;
300 struct acpi_namespace_node *current_node = NULL;
301 struct acpi_namespace_node *this_node = NULL;
302 u32 num_segments;
303 u32 num_carats;
304 acpi_name simple_name;
305 acpi_object_type type_to_check_for;
306 acpi_object_type this_search_type;
307 u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
308 u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND |
309 ACPI_NS_SEARCH_PARENT);
310
311
312 ACPI_FUNCTION_TRACE ("ns_lookup");
313
314
315 if (!return_node) {
316 return_ACPI_STATUS (AE_BAD_PARAMETER);
317 }
318
319 acpi_gbl_ns_lookup_count++;
320 *return_node = ACPI_ENTRY_NOT_FOUND;
321
322 if (!acpi_gbl_root_node) {
323 return_ACPI_STATUS (AE_NO_NAMESPACE);
324 }
325
326 /*
327 * Get the prefix scope.
328 * A null scope means use the root scope
329 */
330 if ((!scope_info) ||
331 (!scope_info->scope.node)) {
332 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
333 "Null scope prefix, using root node (%p)\n",
334 acpi_gbl_root_node));
335
336 prefix_node = acpi_gbl_root_node;
337 }
338 else {
339 prefix_node = scope_info->scope.node;
340 if (ACPI_GET_DESCRIPTOR_TYPE (prefix_node) != ACPI_DESC_TYPE_NAMED) {
341 ACPI_REPORT_ERROR (("ns_lookup: %p is not a namespace node [%s]\n",
342 prefix_node, acpi_ut_get_descriptor_name (prefix_node)));
343 return_ACPI_STATUS (AE_AML_INTERNAL);
344 }
345
346 /*
347 * This node might not be a actual "scope" node (such as a
348 * Device/Method, etc.) It could be a Package or other object node.
349 * Backup up the tree to find the containing scope node.
350 */
351 while (!acpi_ns_opens_scope (prefix_node->type) &&
352 prefix_node->type != ACPI_TYPE_ANY) {
353 prefix_node = acpi_ns_get_parent_node (prefix_node);
354 }
355 }
356
357 /* Save type TBD: may be no longer necessary */
358
359 type_to_check_for = type;
360
361 /*
362 * Begin examination of the actual pathname
363 */
364 if (!pathname) {
365 /* A Null name_path is allowed and refers to the root */
366
367 num_segments = 0;
368 this_node = acpi_gbl_root_node;
369 path = "";
370
371 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
372 "Null Pathname (Zero segments), Flags=%X\n", flags));
373 }
374 else {
375 /*
376 * Name pointer is valid (and must be in internal name format)
377 *
378 * Check for scope prefixes:
379 *
380 * As represented in the AML stream, a namepath consists of an
381 * optional scope prefix followed by a name segment part.
382 *
383 * If present, the scope prefix is either a Root Prefix (in
384 * which case the name is fully qualified), or one or more
385 * Parent Prefixes (in which case the name's scope is relative
386 * to the current scope).
387 */
388 if (*path == (u8) AML_ROOT_PREFIX) {
389 /* Pathname is fully qualified, start from the root */
390
391 this_node = acpi_gbl_root_node;
392 search_parent_flag = ACPI_NS_NO_UPSEARCH;
393
394 /* Point to name segment part */
395
396 path++;
397
398 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
399 "Path is absolute from root [%p]\n", this_node));
400 }
401 else {
402 /* Pathname is relative to current scope, start there */
403
404 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
405 "Searching relative to prefix scope [%4.4s] (%p)\n",
406 acpi_ut_get_node_name (prefix_node), prefix_node));
407
408 /*
409 * Handle multiple Parent Prefixes (carat) by just getting
410 * the parent node for each prefix instance.
411 */
412 this_node = prefix_node;
413 num_carats = 0;
414 while (*path == (u8) AML_PARENT_PREFIX) {
415 /* Name is fully qualified, no search rules apply */
416
417 search_parent_flag = ACPI_NS_NO_UPSEARCH;
418 /*
419 * Point past this prefix to the name segment
420 * part or the next Parent Prefix
421 */
422 path++;
423
424 /* Backup to the parent node */
425
426 num_carats++;
427 this_node = acpi_ns_get_parent_node (this_node);
428 if (!this_node) {
429 /* Current scope has no parent scope */
430
431 ACPI_REPORT_ERROR (
432 ("ACPI path has too many parent prefixes (^) - reached beyond root node\n"));
433 return_ACPI_STATUS (AE_NOT_FOUND);
434 }
435 }
436
437 if (search_parent_flag == ACPI_NS_NO_UPSEARCH) {
438 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
439 "Search scope is [%4.4s], path has %d carat(s)\n",
440 acpi_ut_get_node_name (this_node), num_carats));
441 }
442 }
443
444 /*
445 * Determine the number of ACPI name segments in this pathname.
446 *
447 * The segment part consists of either:
448 * - A Null name segment (0)
449 * - A dual_name_prefix followed by two 4-byte name segments
450 * - A multi_name_prefix followed by a byte indicating the
451 * number of segments and the segments themselves.
452 * - A single 4-byte name segment
453 *
454 * Examine the name prefix opcode, if any, to determine the number of
455 * segments.
456 */
457 switch (*path) {
458 case 0:
459 /*
460 * Null name after a root or parent prefixes. We already
461 * have the correct target node and there are no name segments.
462 */
463 num_segments = 0;
464 type = this_node->type;
465
466 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
467 "Prefix-only Pathname (Zero name segments), Flags=%X\n",
468 flags));
469 break;
470
471 case AML_DUAL_NAME_PREFIX:
472
473 /* More than one name_seg, search rules do not apply */
474
475 search_parent_flag = ACPI_NS_NO_UPSEARCH;
476
477 /* Two segments, point to first name segment */
478
479 num_segments = 2;
480 path++;
481
482 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
483 "Dual Pathname (2 segments, Flags=%X)\n", flags));
484 break;
485
486 case AML_MULTI_NAME_PREFIX_OP:
487
488 /* More than one name_seg, search rules do not apply */
489
490 search_parent_flag = ACPI_NS_NO_UPSEARCH;
491
492 /* Extract segment count, point to first name segment */
493
494 path++;
495 num_segments = (u32) (u8) *path;
496 path++;
497
498 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
499 "Multi Pathname (%d Segments, Flags=%X) \n",
500 num_segments, flags));
501 break;
502
503 default:
504 /*
505 * Not a Null name, no Dual or Multi prefix, hence there is
506 * only one name segment and Pathname is already pointing to it.
507 */
508 num_segments = 1;
509
510 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
511 "Simple Pathname (1 segment, Flags=%X)\n", flags));
512 break;
513 }
514
515 ACPI_DEBUG_EXEC (acpi_ns_print_pathname (num_segments, path));
516 }
517
518
519 /*
520 * Search namespace for each segment of the name. Loop through and
521 * verify (or add to the namespace) each name segment.
522 *
523 * The object type is significant only at the last name
524 * segment. (We don't care about the types along the path, only
525 * the type of the final target object.)
526 */
527 this_search_type = ACPI_TYPE_ANY;
528 current_node = this_node;
529 while (num_segments && current_node) {
530 num_segments--;
531 if (!num_segments) {
532 /*
533 * This is the last segment, enable typechecking
534 */
535 this_search_type = type;
536
537 /*
538 * Only allow automatic parent search (search rules) if the caller
539 * requested it AND we have a single, non-fully-qualified name_seg
540 */
541 if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) &&
542 (flags & ACPI_NS_SEARCH_PARENT)) {
543 local_flags |= ACPI_NS_SEARCH_PARENT;
544 }
545
546 /* Set error flag according to caller */
547
548 if (flags & ACPI_NS_ERROR_IF_FOUND) {
549 local_flags |= ACPI_NS_ERROR_IF_FOUND;
550 }
551 }
552
553 /* Extract one ACPI name from the front of the pathname */
554
555 ACPI_MOVE_32_TO_32 (&simple_name, path);
556
557 /* Try to find the single (4 character) ACPI name */
558
559 status = acpi_ns_search_and_enter (simple_name, walk_state, current_node,
560 interpreter_mode, this_search_type, local_flags, &this_node);
561 if (ACPI_FAILURE (status)) {
562 if (status == AE_NOT_FOUND) {
563 /* Name not found in ACPI namespace */
564
565 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
566 "Name [%4.4s] not found in scope [%4.4s] %p\n",
567 (char *) &simple_name, (char *) &current_node->name,
568 current_node));
569 }
570
571 *return_node = this_node;
572 return_ACPI_STATUS (status);
573 }
574
575 /*
576 * Sanity typecheck of the target object:
577 *
578 * If 1) This is the last segment (num_segments == 0)
579 * 2) And we are looking for a specific type
580 * (Not checking for TYPE_ANY)
581 * 3) Which is not an alias
582 * 4) Which is not a local type (TYPE_SCOPE)
583 * 5) And the type of target object is known (not TYPE_ANY)
584 * 6) And target object does not match what we are looking for
585 *
586 * Then we have a type mismatch. Just warn and ignore it.
587 */
588 if ((num_segments == 0) &&
589 (type_to_check_for != ACPI_TYPE_ANY) &&
590 (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
591 (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
592 (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
593 (this_node->type != ACPI_TYPE_ANY) &&
594 (this_node->type != type_to_check_for)) {
595 /* Complain about a type mismatch */
596
597 ACPI_REPORT_WARNING (
598 ("ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)\n",
599 (char *) &simple_name, acpi_ut_get_type_name (this_node->type),
600 acpi_ut_get_type_name (type_to_check_for)));
601 }
602
603 /*
604 * If this is the last name segment and we are not looking for a
605 * specific type, but the type of found object is known, use that type
606 * to see if it opens a scope.
607 */
608 if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) {
609 type = this_node->type;
610 }
611
612 /* Point to next name segment and make this node current */
613
614 path += ACPI_NAME_SIZE;
615 current_node = this_node;
616 }
617
618 /*
619 * Always check if we need to open a new scope
620 */
621 if (!(flags & ACPI_NS_DONT_OPEN_SCOPE) && (walk_state)) {
622 /*
623 * If entry is a type which opens a scope, push the new scope on the
624 * scope stack.
625 */
626 if (acpi_ns_opens_scope (type)) {
627 status = acpi_ds_scope_stack_push (this_node, type, walk_state);
628 if (ACPI_FAILURE (status)) {
629 return_ACPI_STATUS (status);
630 }
631 }
632 }
633
634 *return_node = this_node;
635 return_ACPI_STATUS (AE_OK);
636}
637
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
new file mode 100644
index 000000000000..bfd922c5c7d1
--- /dev/null
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -0,0 +1,685 @@
1/*******************************************************************************
2 *
3 * Module Name: nsalloc - Namespace allocation and deletion utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME ("nsalloc")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ns_create_node
56 *
57 * PARAMETERS: acpi_name - Name of the new node
58 *
59 * RETURN: None
60 *
61 * DESCRIPTION: Create a namespace node
62 *
63 ******************************************************************************/
64
65struct acpi_namespace_node *
66acpi_ns_create_node (
67 u32 name)
68{
69 struct acpi_namespace_node *node;
70
71
72 ACPI_FUNCTION_TRACE ("ns_create_node");
73
74
75 node = ACPI_MEM_CALLOCATE (sizeof (struct acpi_namespace_node));
76 if (!node) {
77 return_PTR (NULL);
78 }
79
80 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_allocated++);
81
82 node->name.integer = name;
83 node->reference_count = 1;
84 ACPI_SET_DESCRIPTOR_TYPE (node, ACPI_DESC_TYPE_NAMED);
85
86 return_PTR (node);
87}
88
89
90/*******************************************************************************
91 *
92 * FUNCTION: acpi_ns_delete_node
93 *
94 * PARAMETERS: Node - Node to be deleted
95 *
96 * RETURN: None
97 *
98 * DESCRIPTION: Delete a namespace node
99 *
100 ******************************************************************************/
101
102void
103acpi_ns_delete_node (
104 struct acpi_namespace_node *node)
105{
106 struct acpi_namespace_node *parent_node;
107 struct acpi_namespace_node *prev_node;
108 struct acpi_namespace_node *next_node;
109
110
111 ACPI_FUNCTION_TRACE_PTR ("ns_delete_node", node);
112
113
114 parent_node = acpi_ns_get_parent_node (node);
115
116 prev_node = NULL;
117 next_node = parent_node->child;
118
119 /* Find the node that is the previous peer in the parent's child list */
120
121 while (next_node != node) {
122 prev_node = next_node;
123 next_node = prev_node->peer;
124 }
125
126 if (prev_node) {
127 /* Node is not first child, unlink it */
128
129 prev_node->peer = next_node->peer;
130 if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
131 prev_node->flags |= ANOBJ_END_OF_PEER_LIST;
132 }
133 }
134 else {
135 /* Node is first child (has no previous peer) */
136
137 if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
138 /* No peers at all */
139
140 parent_node->child = NULL;
141 }
142 else { /* Link peer list to parent */
143
144 parent_node->child = next_node->peer;
145 }
146 }
147
148
149 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
150
151 /*
152 * Detach an object if there is one then delete the node
153 */
154 acpi_ns_detach_object (node);
155 ACPI_MEM_FREE (node);
156 return_VOID;
157}
158
159
160#ifdef ACPI_ALPHABETIC_NAMESPACE
161/*******************************************************************************
162 *
163 * FUNCTION: acpi_ns_compare_names
164 *
165 * PARAMETERS: Name1 - First name to compare
166 * Name2 - Second name to compare
167 *
168 * RETURN: value from strncmp
169 *
170 * DESCRIPTION: Compare two ACPI names. Names that are prefixed with an
171 * underscore are forced to be alphabetically first.
172 *
173 ******************************************************************************/
174
175int
176acpi_ns_compare_names (
177 char *name1,
178 char *name2)
179{
180 char reversed_name1[ACPI_NAME_SIZE];
181 char reversed_name2[ACPI_NAME_SIZE];
182 u32 i;
183 u32 j;
184
185
186 /*
187 * Replace all instances of "underscore" with a value that is smaller so
188 * that all names that are prefixed with underscore(s) are alphabetically
189 * first.
190 *
191 * Reverse the name bytewise so we can just do a 32-bit compare instead
192 * of a strncmp.
193 */
194 for (i = 0, j= (ACPI_NAME_SIZE - 1); i < ACPI_NAME_SIZE; i++, j--) {
195 reversed_name1[j] = name1[i];
196 if (name1[i] == '_') {
197 reversed_name1[j] = '*';
198 }
199
200 reversed_name2[j] = name2[i];
201 if (name2[i] == '_') {
202 reversed_name2[j] = '*';
203 }
204 }
205
206 return (*(int *) reversed_name1 - *(int *) reversed_name2);
207}
208#endif
209
210
211/*******************************************************************************
212 *
213 * FUNCTION: acpi_ns_install_node
214 *
215 * PARAMETERS: walk_state - Current state of the walk
216 * parent_node - The parent of the new Node
217 * Node - The new Node to install
218 * Type - ACPI object type of the new Node
219 *
220 * RETURN: None
221 *
222 * DESCRIPTION: Initialize a new namespace node and install it amongst
223 * its peers.
224 *
225 * Note: Current namespace lookup is linear search. However, the
226 * nodes are linked in alphabetical order to 1) put all reserved
227 * names (start with underscore) first, and to 2) make a readable
228 * namespace dump.
229 *
230 ******************************************************************************/
231
232void
233acpi_ns_install_node (
234 struct acpi_walk_state *walk_state,
235 struct acpi_namespace_node *parent_node, /* Parent */
236 struct acpi_namespace_node *node, /* New Child*/
237 acpi_object_type type)
238{
239 u16 owner_id = 0;
240 struct acpi_namespace_node *child_node;
241#ifdef ACPI_ALPHABETIC_NAMESPACE
242
243 struct acpi_namespace_node *previous_child_node;
244#endif
245
246
247 ACPI_FUNCTION_TRACE ("ns_install_node");
248
249
250 /*
251 * Get the owner ID from the Walk state
252 * The owner ID is used to track table deletion and
253 * deletion of objects created by methods
254 */
255 if (walk_state) {
256 owner_id = walk_state->owner_id;
257 }
258
259 /* Link the new entry into the parent and existing children */
260
261 child_node = parent_node->child;
262 if (!child_node) {
263 parent_node->child = node;
264 node->flags |= ANOBJ_END_OF_PEER_LIST;
265 node->peer = parent_node;
266 }
267 else {
268#ifdef ACPI_ALPHABETIC_NAMESPACE
269 /*
270 * Walk the list whilst searching for the correct
271 * alphabetic placement.
272 */
273 previous_child_node = NULL;
274 while (acpi_ns_compare_names (acpi_ut_get_node_name (child_node), acpi_ut_get_node_name (node)) < 0) {
275 if (child_node->flags & ANOBJ_END_OF_PEER_LIST) {
276 /* Last peer; Clear end-of-list flag */
277
278 child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
279
280 /* This node is the new peer to the child node */
281
282 child_node->peer = node;
283
284 /* This node is the new end-of-list */
285
286 node->flags |= ANOBJ_END_OF_PEER_LIST;
287 node->peer = parent_node;
288 break;
289 }
290
291 /* Get next peer */
292
293 previous_child_node = child_node;
294 child_node = child_node->peer;
295 }
296
297 /* Did the node get inserted at the end-of-list? */
298
299 if (!(node->flags & ANOBJ_END_OF_PEER_LIST)) {
300 /*
301 * Loop above terminated without reaching the end-of-list.
302 * Insert the new node at the current location
303 */
304 if (previous_child_node) {
305 /* Insert node alphabetically */
306
307 node->peer = child_node;
308 previous_child_node->peer = node;
309 }
310 else {
311 /* Insert node alphabetically at start of list */
312
313 node->peer = child_node;
314 parent_node->child = node;
315 }
316 }
317#else
318 while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) {
319 child_node = child_node->peer;
320 }
321
322 child_node->peer = node;
323
324 /* Clear end-of-list flag */
325
326 child_node->flags &= ~ANOBJ_END_OF_PEER_LIST;
327 node->flags |= ANOBJ_END_OF_PEER_LIST;
328 node->peer = parent_node;
329#endif
330 }
331
332 /* Init the new entry */
333
334 node->owner_id = owner_id;
335 node->type = (u8) type;
336
337 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
338 "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
339 acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), node, owner_id,
340 acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type),
341 parent_node));
342
343 /*
344 * Increment the reference count(s) of all parents up to
345 * the root!
346 */
347 while ((node = acpi_ns_get_parent_node (node)) != NULL) {
348 node->reference_count++;
349 }
350
351 return_VOID;
352}
353
354
355/*******************************************************************************
356 *
357 * FUNCTION: acpi_ns_delete_children
358 *
359 * PARAMETERS: parent_node - Delete this objects children
360 *
361 * RETURN: None.
362 *
363 * DESCRIPTION: Delete all children of the parent object. In other words,
364 * deletes a "scope".
365 *
366 ******************************************************************************/
367
368void
369acpi_ns_delete_children (
370 struct acpi_namespace_node *parent_node)
371{
372 struct acpi_namespace_node *child_node;
373 struct acpi_namespace_node *next_node;
374 struct acpi_namespace_node *node;
375 u8 flags;
376
377
378 ACPI_FUNCTION_TRACE_PTR ("ns_delete_children", parent_node);
379
380
381 if (!parent_node) {
382 return_VOID;
383 }
384
385 /* If no children, all done! */
386
387 child_node = parent_node->child;
388 if (!child_node) {
389 return_VOID;
390 }
391
392 /*
393 * Deallocate all children at this level
394 */
395 do {
396 /* Get the things we need */
397
398 next_node = child_node->peer;
399 flags = child_node->flags;
400
401 /* Grandchildren should have all been deleted already */
402
403 if (child_node->child) {
404 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found a grandchild! P=%p C=%p\n",
405 parent_node, child_node));
406 }
407
408 /* Now we can free this child object */
409
410 ACPI_MEM_TRACKING (acpi_gbl_memory_lists[ACPI_MEM_LIST_NSNODE].total_freed++);
411
412 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n",
413 child_node, acpi_gbl_current_node_count));
414
415 /*
416 * Detach an object if there is one, then free the child node
417 */
418 acpi_ns_detach_object (child_node);
419
420 /*
421 * Decrement the reference count(s) of all parents up to
422 * the root! (counts were incremented when the node was created)
423 */
424 node = child_node;
425 while ((node = acpi_ns_get_parent_node (node)) != NULL) {
426 node->reference_count--;
427 }
428
429 /* There should be only one reference remaining on this node */
430
431 if (child_node->reference_count != 1) {
432 ACPI_REPORT_WARNING (("Existing references (%d) on node being deleted (%p)\n",
433 child_node->reference_count, child_node));
434 }
435
436 /* Now we can delete the node */
437
438 ACPI_MEM_FREE (child_node);
439
440 /* And move on to the next child in the list */
441
442 child_node = next_node;
443
444 } while (!(flags & ANOBJ_END_OF_PEER_LIST));
445
446
447 /* Clear the parent's child pointer */
448
449 parent_node->child = NULL;
450
451 return_VOID;
452}
453
454
455/*******************************************************************************
456 *
457 * FUNCTION: acpi_ns_delete_namespace_subtree
458 *
459 * PARAMETERS: parent_node - Root of the subtree to be deleted
460 *
461 * RETURN: None.
462 *
463 * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
464 * stored within the subtree.
465 *
466 ******************************************************************************/
467
468void
469acpi_ns_delete_namespace_subtree (
470 struct acpi_namespace_node *parent_node)
471{
472 struct acpi_namespace_node *child_node = NULL;
473 u32 level = 1;
474
475
476 ACPI_FUNCTION_TRACE ("ns_delete_namespace_subtree");
477
478
479 if (!parent_node) {
480 return_VOID;
481 }
482
483 /*
484 * Traverse the tree of objects until we bubble back up
485 * to where we started.
486 */
487 while (level > 0) {
488 /* Get the next node in this scope (NULL if none) */
489
490 child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node,
491 child_node);
492 if (child_node) {
493 /* Found a child node - detach any attached object */
494
495 acpi_ns_detach_object (child_node);
496
497 /* Check if this node has any children */
498
499 if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
500 /*
501 * There is at least one child of this node,
502 * visit the node
503 */
504 level++;
505 parent_node = child_node;
506 child_node = NULL;
507 }
508 }
509 else {
510 /*
511 * No more children of this parent node.
512 * Move up to the grandparent.
513 */
514 level--;
515
516 /*
517 * Now delete all of the children of this parent
518 * all at the same time.
519 */
520 acpi_ns_delete_children (parent_node);
521
522 /* New "last child" is this parent node */
523
524 child_node = parent_node;
525
526 /* Move up the tree to the grandparent */
527
528 parent_node = acpi_ns_get_parent_node (parent_node);
529 }
530 }
531
532 return_VOID;
533}
534
535
536/*******************************************************************************
537 *
538 * FUNCTION: acpi_ns_remove_reference
539 *
540 * PARAMETERS: Node - Named node whose reference count is to be
541 * decremented
542 *
543 * RETURN: None.
544 *
545 * DESCRIPTION: Remove a Node reference. Decrements the reference count
546 * of all parent Nodes up to the root. Any node along
547 * the way that reaches zero references is freed.
548 *
549 ******************************************************************************/
550
551void
552acpi_ns_remove_reference (
553 struct acpi_namespace_node *node)
554{
555 struct acpi_namespace_node *parent_node;
556 struct acpi_namespace_node *this_node;
557
558
559 ACPI_FUNCTION_ENTRY ();
560
561
562 /*
563 * Decrement the reference count(s) of this node and all
564 * nodes up to the root, Delete anything with zero remaining references.
565 */
566 this_node = node;
567 while (this_node) {
568 /* Prepare to move up to parent */
569
570 parent_node = acpi_ns_get_parent_node (this_node);
571
572 /* Decrement the reference count on this node */
573
574 this_node->reference_count--;
575
576 /* Delete the node if no more references */
577
578 if (!this_node->reference_count) {
579 /* Delete all children and delete the node */
580
581 acpi_ns_delete_children (this_node);
582 acpi_ns_delete_node (this_node);
583 }
584
585 this_node = parent_node;
586 }
587}
588
589
590/*******************************************************************************
591 *
592 * FUNCTION: acpi_ns_delete_namespace_by_owner
593 *
594 * PARAMETERS: owner_id - All nodes with this owner will be deleted
595 *
596 * RETURN: Status
597 *
598 * DESCRIPTION: Delete entries within the namespace that are owned by a
599 * specific ID. Used to delete entire ACPI tables. All
600 * reference counts are updated.
601 *
602 ******************************************************************************/
603
604void
605acpi_ns_delete_namespace_by_owner (
606 u16 owner_id)
607{
608 struct acpi_namespace_node *child_node;
609 struct acpi_namespace_node *deletion_node;
610 u32 level;
611 struct acpi_namespace_node *parent_node;
612
613
614 ACPI_FUNCTION_TRACE_U32 ("ns_delete_namespace_by_owner", owner_id);
615
616
617 parent_node = acpi_gbl_root_node;
618 child_node = NULL;
619 deletion_node = NULL;
620 level = 1;
621
622 /*
623 * Traverse the tree of nodes until we bubble back up
624 * to where we started.
625 */
626 while (level > 0) {
627 /*
628 * Get the next child of this parent node. When child_node is NULL,
629 * the first child of the parent is returned
630 */
631 child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node, child_node);
632
633 if (deletion_node) {
634 acpi_ns_remove_reference (deletion_node);
635 deletion_node = NULL;
636 }
637
638 if (child_node) {
639 if (child_node->owner_id == owner_id) {
640 /* Found a matching child node - detach any attached object */
641
642 acpi_ns_detach_object (child_node);
643 }
644
645 /* Check if this node has any children */
646
647 if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
648 /*
649 * There is at least one child of this node,
650 * visit the node
651 */
652 level++;
653 parent_node = child_node;
654 child_node = NULL;
655 }
656 else if (child_node->owner_id == owner_id) {
657 deletion_node = child_node;
658 }
659 }
660 else {
661 /*
662 * No more children of this parent node.
663 * Move up to the grandparent.
664 */
665 level--;
666 if (level != 0) {
667 if (parent_node->owner_id == owner_id) {
668 deletion_node = parent_node;
669 }
670 }
671
672 /* New "last child" is this parent node */
673
674 child_node = parent_node;
675
676 /* Move up the tree to the grandparent */
677
678 parent_node = acpi_ns_get_parent_node (parent_node);
679 }
680 }
681
682 return_VOID;
683}
684
685
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
new file mode 100644
index 000000000000..1f6af3eb6c91
--- /dev/null
+++ b/drivers/acpi/namespace/nsdump.c
@@ -0,0 +1,673 @@
1/******************************************************************************
2 *
3 * Module Name: nsdump - table dumping routines for debug
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acparser.h>
48
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsdump")
52
53
54#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ns_print_pathname
59 *
60 * PARAMETERS: num_segment - Number of ACPI name segments
61 * Pathname - The compressed (internal) path
62 *
63 * DESCRIPTION: Print an object's full namespace pathname
64 *
65 ******************************************************************************/
66
67void
68acpi_ns_print_pathname (
69 u32 num_segments,
70 char *pathname)
71{
72 ACPI_FUNCTION_NAME ("ns_print_pathname");
73
74
75 if (!(acpi_dbg_level & ACPI_LV_NAMES) || !(acpi_dbg_layer & ACPI_NAMESPACE)) {
76 return;
77 }
78
79 /* Print the entire name */
80
81 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "["));
82
83 while (num_segments) {
84 acpi_os_printf ("%4.4s", pathname);
85 pathname += ACPI_NAME_SIZE;
86
87 num_segments--;
88 if (num_segments) {
89 acpi_os_printf (".");
90 }
91 }
92
93 acpi_os_printf ("]\n");
94}
95
96
97/*******************************************************************************
98 *
99 * FUNCTION: acpi_ns_dump_pathname
100 *
101 * PARAMETERS: Handle - Object
102 * Msg - Prefix message
103 * Level - Desired debug level
104 * Component - Caller's component ID
105 *
106 * DESCRIPTION: Print an object's full namespace pathname
107 * Manages allocation/freeing of a pathname buffer
108 *
109 ******************************************************************************/
110
111void
112acpi_ns_dump_pathname (
113 acpi_handle handle,
114 char *msg,
115 u32 level,
116 u32 component)
117{
118
119 ACPI_FUNCTION_TRACE ("ns_dump_pathname");
120
121
122 /* Do this only if the requested debug level and component are enabled */
123
124 if (!(acpi_dbg_level & level) || !(acpi_dbg_layer & component)) {
125 return_VOID;
126 }
127
128 /* Convert handle to a full pathname and print it (with supplied message) */
129
130 acpi_ns_print_node_pathname (handle, msg);
131 acpi_os_printf ("\n");
132 return_VOID;
133}
134
135
136/*******************************************************************************
137 *
138 * FUNCTION: acpi_ns_dump_one_object
139 *
140 * PARAMETERS: Handle - Node to be dumped
141 * Level - Nesting level of the handle
142 * Context - Passed into walk_namespace
143 *
144 * DESCRIPTION: Dump a single Node
145 * This procedure is a user_function called by acpi_ns_walk_namespace.
146 *
147 ******************************************************************************/
148
149acpi_status
150acpi_ns_dump_one_object (
151 acpi_handle obj_handle,
152 u32 level,
153 void *context,
154 void **return_value)
155{
156 struct acpi_walk_info *info = (struct acpi_walk_info *) context;
157 struct acpi_namespace_node *this_node;
158 union acpi_operand_object *obj_desc = NULL;
159 acpi_object_type obj_type;
160 acpi_object_type type;
161 u32 bytes_to_dump;
162 u32 dbg_level;
163 u32 i;
164
165
166 ACPI_FUNCTION_NAME ("ns_dump_one_object");
167
168
169 /* Is output enabled? */
170
171 if (!(acpi_dbg_level & info->debug_level)) {
172 return (AE_OK);
173 }
174
175 if (!obj_handle) {
176 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n"));
177 return (AE_OK);
178 }
179
180 this_node = acpi_ns_map_handle_to_node (obj_handle);
181 type = this_node->type;
182
183 /* Check if the owner matches */
184
185 if ((info->owner_id != ACPI_UINT32_MAX) &&
186 (info->owner_id != this_node->owner_id)) {
187 return (AE_OK);
188 }
189
190 /* Indent the object according to the level */
191
192 acpi_os_printf ("%2d%*s", (u32) level - 1, (int) level * 2, " ");
193
194 /* Check the node type and name */
195
196 if (type > ACPI_TYPE_LOCAL_MAX) {
197 ACPI_REPORT_WARNING (("Invalid ACPI Type %08X\n", type));
198 }
199
200 if (!acpi_ut_valid_acpi_name (this_node->name.integer)) {
201 ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n",
202 this_node->name.integer));
203 }
204
205 /*
206 * Now we can print out the pertinent information
207 */
208 acpi_os_printf ("%4.4s %-12s %p ",
209 acpi_ut_get_node_name (this_node), acpi_ut_get_type_name (type), this_node);
210
211 dbg_level = acpi_dbg_level;
212 acpi_dbg_level = 0;
213 obj_desc = acpi_ns_get_attached_object (this_node);
214 acpi_dbg_level = dbg_level;
215
216 switch (info->display_type) {
217 case ACPI_DISPLAY_SUMMARY:
218
219 if (!obj_desc) {
220 /* No attached object, we are done */
221
222 acpi_os_printf ("\n");
223 return (AE_OK);
224 }
225
226 switch (type) {
227 case ACPI_TYPE_PROCESSOR:
228
229 acpi_os_printf ("ID %X Len %.4X Addr %p\n",
230 obj_desc->processor.proc_id, obj_desc->processor.length,
231 (char *) obj_desc->processor.address);
232 break;
233
234
235 case ACPI_TYPE_DEVICE:
236
237 acpi_os_printf ("Notify Object: %p\n", obj_desc);
238 break;
239
240
241 case ACPI_TYPE_METHOD:
242
243 acpi_os_printf ("Args %X Len %.4X Aml %p\n",
244 (u32) obj_desc->method.param_count,
245 obj_desc->method.aml_length, obj_desc->method.aml_start);
246 break;
247
248
249 case ACPI_TYPE_INTEGER:
250
251 acpi_os_printf ("= %8.8X%8.8X\n",
252 ACPI_FORMAT_UINT64 (obj_desc->integer.value));
253 break;
254
255
256 case ACPI_TYPE_PACKAGE:
257
258 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
259 acpi_os_printf ("Elements %.2X\n",
260 obj_desc->package.count);
261 }
262 else {
263 acpi_os_printf ("[Length not yet evaluated]\n");
264 }
265 break;
266
267
268 case ACPI_TYPE_BUFFER:
269
270 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
271 acpi_os_printf ("Len %.2X",
272 obj_desc->buffer.length);
273
274 /* Dump some of the buffer */
275
276 if (obj_desc->buffer.length > 0) {
277 acpi_os_printf (" =");
278 for (i = 0; (i < obj_desc->buffer.length && i < 12); i++) {
279 acpi_os_printf (" %.2hX", obj_desc->buffer.pointer[i]);
280 }
281 }
282 acpi_os_printf ("\n");
283 }
284 else {
285 acpi_os_printf ("[Length not yet evaluated]\n");
286 }
287 break;
288
289
290 case ACPI_TYPE_STRING:
291
292 acpi_os_printf ("Len %.2X ", obj_desc->string.length);
293 acpi_ut_print_string (obj_desc->string.pointer, 32);
294 acpi_os_printf ("\n");
295 break;
296
297
298 case ACPI_TYPE_REGION:
299
300 acpi_os_printf ("[%s]",
301 acpi_ut_get_region_name (obj_desc->region.space_id));
302 if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
303 acpi_os_printf (" Addr %8.8X%8.8X Len %.4X\n",
304 ACPI_FORMAT_UINT64 (obj_desc->region.address),
305 obj_desc->region.length);
306 }
307 else {
308 acpi_os_printf (" [Address/Length not yet evaluated]\n");
309 }
310 break;
311
312
313 case ACPI_TYPE_LOCAL_REFERENCE:
314
315 acpi_os_printf ("[%s]\n",
316 acpi_ps_get_opcode_name (obj_desc->reference.opcode));
317 break;
318
319
320 case ACPI_TYPE_BUFFER_FIELD:
321
322 if (obj_desc->buffer_field.buffer_obj &&
323 obj_desc->buffer_field.buffer_obj->buffer.node) {
324 acpi_os_printf ("Buf [%4.4s]",
325 acpi_ut_get_node_name (obj_desc->buffer_field.buffer_obj->buffer.node));
326 }
327 break;
328
329
330 case ACPI_TYPE_LOCAL_REGION_FIELD:
331
332 acpi_os_printf ("Rgn [%4.4s]",
333 acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node));
334 break;
335
336
337 case ACPI_TYPE_LOCAL_BANK_FIELD:
338
339 acpi_os_printf ("Rgn [%4.4s] Bnk [%4.4s]",
340 acpi_ut_get_node_name (obj_desc->common_field.region_obj->region.node),
341 acpi_ut_get_node_name (obj_desc->bank_field.bank_obj->common_field.node));
342 break;
343
344
345 case ACPI_TYPE_LOCAL_INDEX_FIELD:
346
347 acpi_os_printf ("Idx [%4.4s] Dat [%4.4s]",
348 acpi_ut_get_node_name (obj_desc->index_field.index_obj->common_field.node),
349 acpi_ut_get_node_name (obj_desc->index_field.data_obj->common_field.node));
350 break;
351
352
353 case ACPI_TYPE_LOCAL_ALIAS:
354 case ACPI_TYPE_LOCAL_METHOD_ALIAS:
355
356 acpi_os_printf ("Target %4.4s (%p)\n",
357 acpi_ut_get_node_name (obj_desc), obj_desc);
358 break;
359
360 default:
361
362 acpi_os_printf ("Object %p\n", obj_desc);
363 break;
364 }
365
366 /* Common field handling */
367
368 switch (type) {
369 case ACPI_TYPE_BUFFER_FIELD:
370 case ACPI_TYPE_LOCAL_REGION_FIELD:
371 case ACPI_TYPE_LOCAL_BANK_FIELD:
372 case ACPI_TYPE_LOCAL_INDEX_FIELD:
373
374 acpi_os_printf (" Off %.3X Len %.2X Acc %.2hd\n",
375 (obj_desc->common_field.base_byte_offset * 8)
376 + obj_desc->common_field.start_field_bit_offset,
377 obj_desc->common_field.bit_length,
378 obj_desc->common_field.access_byte_width);
379 break;
380
381 default:
382 break;
383 }
384 break;
385
386
387 case ACPI_DISPLAY_OBJECTS:
388
389 acpi_os_printf ("O:%p", obj_desc);
390 if (!obj_desc) {
391 /* No attached object, we are done */
392
393 acpi_os_printf ("\n");
394 return (AE_OK);
395 }
396
397 acpi_os_printf ("(R%d)",
398 obj_desc->common.reference_count);
399
400 switch (type) {
401 case ACPI_TYPE_METHOD:
402
403 /* Name is a Method and its AML offset/length are set */
404
405 acpi_os_printf (" M:%p-%X\n", obj_desc->method.aml_start,
406 obj_desc->method.aml_length);
407 break;
408
409 case ACPI_TYPE_INTEGER:
410
411 acpi_os_printf (" I:%8.8X8.8%X\n",
412 ACPI_FORMAT_UINT64 (obj_desc->integer.value));
413 break;
414
415 case ACPI_TYPE_STRING:
416
417 acpi_os_printf (" S:%p-%X\n", obj_desc->string.pointer,
418 obj_desc->string.length);
419 break;
420
421 case ACPI_TYPE_BUFFER:
422
423 acpi_os_printf (" B:%p-%X\n", obj_desc->buffer.pointer,
424 obj_desc->buffer.length);
425 break;
426
427 default:
428
429 acpi_os_printf ("\n");
430 break;
431 }
432 break;
433
434
435 default:
436 acpi_os_printf ("\n");
437 break;
438 }
439
440 /* If debug turned off, done */
441
442 if (!(acpi_dbg_level & ACPI_LV_VALUES)) {
443 return (AE_OK);
444 }
445
446
447 /* If there is an attached object, display it */
448
449 dbg_level = acpi_dbg_level;
450 acpi_dbg_level = 0;
451 obj_desc = acpi_ns_get_attached_object (this_node);
452 acpi_dbg_level = dbg_level;
453
454 /* Dump attached objects */
455
456 while (obj_desc) {
457 obj_type = ACPI_TYPE_INVALID;
458 acpi_os_printf (" Attached Object %p: ", obj_desc);
459
460 /* Decode the type of attached object and dump the contents */
461
462 switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
463 case ACPI_DESC_TYPE_NAMED:
464
465 acpi_os_printf ("(Ptr to Node)\n");
466 bytes_to_dump = sizeof (struct acpi_namespace_node);
467 break;
468
469
470 case ACPI_DESC_TYPE_OPERAND:
471
472 obj_type = ACPI_GET_OBJECT_TYPE (obj_desc);
473
474 if (obj_type > ACPI_TYPE_LOCAL_MAX) {
475 acpi_os_printf ("(Ptr to ACPI Object type %X [UNKNOWN])\n",
476 obj_type);
477 bytes_to_dump = 32;
478 }
479 else {
480 acpi_os_printf ("(Ptr to ACPI Object type %s, %X)\n",
481 acpi_ut_get_type_name (obj_type), obj_type);
482 bytes_to_dump = sizeof (union acpi_operand_object);
483 }
484 break;
485
486
487 default:
488
489 acpi_os_printf (
490 "(String or Buffer ptr - not an object descriptor) [%s]\n",
491 acpi_ut_get_descriptor_name (obj_desc));
492 bytes_to_dump = 16;
493 break;
494 }
495
496 ACPI_DUMP_BUFFER (obj_desc, bytes_to_dump);
497
498 /* If value is NOT an internal object, we are done */
499
500 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
501 goto cleanup;
502 }
503
504 /*
505 * Valid object, get the pointer to next level, if any
506 */
507 switch (obj_type) {
508 case ACPI_TYPE_STRING:
509 obj_desc = (void *) obj_desc->string.pointer;
510 break;
511
512 case ACPI_TYPE_BUFFER:
513 obj_desc = (void *) obj_desc->buffer.pointer;
514 break;
515
516 case ACPI_TYPE_BUFFER_FIELD:
517 obj_desc = (union acpi_operand_object *) obj_desc->buffer_field.buffer_obj;
518 break;
519
520 case ACPI_TYPE_PACKAGE:
521 obj_desc = (void *) obj_desc->package.elements;
522 break;
523
524 case ACPI_TYPE_METHOD:
525 obj_desc = (void *) obj_desc->method.aml_start;
526 break;
527
528 case ACPI_TYPE_LOCAL_REGION_FIELD:
529 obj_desc = (void *) obj_desc->field.region_obj;
530 break;
531
532 case ACPI_TYPE_LOCAL_BANK_FIELD:
533 obj_desc = (void *) obj_desc->bank_field.region_obj;
534 break;
535
536 case ACPI_TYPE_LOCAL_INDEX_FIELD:
537 obj_desc = (void *) obj_desc->index_field.index_obj;
538 break;
539
540 default:
541 goto cleanup;
542 }
543
544 obj_type = ACPI_TYPE_INVALID; /* Terminate loop after next pass */
545 }
546
547cleanup:
548 acpi_os_printf ("\n");
549 return (AE_OK);
550}
551
552
553#ifdef ACPI_FUTURE_USAGE
554
555/*******************************************************************************
556 *
557 * FUNCTION: acpi_ns_dump_objects
558 *
559 * PARAMETERS: Type - Object type to be dumped
560 * max_depth - Maximum depth of dump. Use ACPI_UINT32_MAX
561 * for an effectively unlimited depth.
562 * owner_id - Dump only objects owned by this ID. Use
563 * ACPI_UINT32_MAX to match all owners.
564 * start_handle - Where in namespace to start/end search
565 *
566 * DESCRIPTION: Dump typed objects within the loaded namespace.
567 * Uses acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object.
568 *
569 ******************************************************************************/
570
571void
572acpi_ns_dump_objects (
573 acpi_object_type type,
574 u8 display_type,
575 u32 max_depth,
576 u32 owner_id,
577 acpi_handle start_handle)
578{
579 struct acpi_walk_info info;
580
581
582 ACPI_FUNCTION_ENTRY ();
583
584
585 info.debug_level = ACPI_LV_TABLES;
586 info.owner_id = owner_id;
587 info.display_type = display_type;
588
589 (void) acpi_ns_walk_namespace (type, start_handle, max_depth,
590 ACPI_NS_WALK_NO_UNLOCK, acpi_ns_dump_one_object,
591 (void *) &info, NULL);
592}
593
594
595/*******************************************************************************
596 *
597 * FUNCTION: acpi_ns_dump_tables
598 *
599 * PARAMETERS: search_base - Root of subtree to be dumped, or
600 * NS_ALL to dump the entire namespace
601 * max_depth - Maximum depth of dump. Use INT_MAX
602 * for an effectively unlimited depth.
603 *
604 * DESCRIPTION: Dump the name space, or a portion of it.
605 *
606 ******************************************************************************/
607
608void
609acpi_ns_dump_tables (
610 acpi_handle search_base,
611 u32 max_depth)
612{
613 acpi_handle search_handle = search_base;
614
615
616 ACPI_FUNCTION_TRACE ("ns_dump_tables");
617
618
619 if (!acpi_gbl_root_node) {
620 /*
621 * If the name space has not been initialized,
622 * there is nothing to dump.
623 */
624 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "namespace not initialized!\n"));
625 return_VOID;
626 }
627
628 if (ACPI_NS_ALL == search_base) {
629 /* entire namespace */
630
631 search_handle = acpi_gbl_root_node;
632 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES, "\\\n"));
633 }
634
635 acpi_ns_dump_objects (ACPI_TYPE_ANY, ACPI_DISPLAY_OBJECTS, max_depth,
636 ACPI_UINT32_MAX, search_handle);
637 return_VOID;
638}
639
640#endif /* ACPI_FUTURE_USAGE */
641
642
643/*******************************************************************************
644 *
645 * FUNCTION: acpi_ns_dump_entry
646 *
647 * PARAMETERS: Handle - Node to be dumped
648 * debug_level - Output level
649 *
650 * DESCRIPTION: Dump a single Node
651 *
652 ******************************************************************************/
653
654void
655acpi_ns_dump_entry (
656 acpi_handle handle,
657 u32 debug_level)
658{
659 struct acpi_walk_info info;
660
661
662 ACPI_FUNCTION_ENTRY ();
663
664
665 info.debug_level = debug_level;
666 info.owner_id = ACPI_UINT32_MAX;
667 info.display_type = ACPI_DISPLAY_SUMMARY;
668
669 (void) acpi_ns_dump_one_object (handle, 1, &info, NULL);
670}
671
672#endif
673
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
new file mode 100644
index 000000000000..d30a59e6b07d
--- /dev/null
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -0,0 +1,146 @@
1/******************************************************************************
2 *
3 * Module Name: nsdump - table dumping routines for debug
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME ("nsdumpdv")
51
52
53#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_ns_dump_one_device
58 *
59 * PARAMETERS: Handle - Node to be dumped
60 * Level - Nesting level of the handle
61 * Context - Passed into walk_namespace
62 *
63 * DESCRIPTION: Dump a single Node that represents a device
64 * This procedure is a user_function called by acpi_ns_walk_namespace.
65 *
66 ******************************************************************************/
67
68acpi_status
69acpi_ns_dump_one_device (
70 acpi_handle obj_handle,
71 u32 level,
72 void *context,
73 void **return_value)
74{
75 struct acpi_buffer buffer;
76 struct acpi_device_info *info;
77 acpi_status status;
78 u32 i;
79
80
81 ACPI_FUNCTION_NAME ("ns_dump_one_device");
82
83
84 status = acpi_ns_dump_one_object (obj_handle, level, context, return_value);
85
86 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
87 status = acpi_get_object_info (obj_handle, &buffer);
88 if (ACPI_SUCCESS (status)) {
89 info = buffer.pointer;
90 for (i = 0; i < level; i++) {
91 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " "));
92 }
93
94 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES,
95 " HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
96 info->hardware_id.value, ACPI_FORMAT_UINT64 (info->address),
97 info->current_status));
98 ACPI_MEM_FREE (info);
99 }
100
101 return (status);
102}
103
104
105/*******************************************************************************
106 *
107 * FUNCTION: acpi_ns_dump_root_devices
108 *
109 * PARAMETERS: None
110 *
111 * DESCRIPTION: Dump all objects of type "device"
112 *
113 ******************************************************************************/
114
115void
116acpi_ns_dump_root_devices (void)
117{
118 acpi_handle sys_bus_handle;
119 acpi_status status;
120
121
122 ACPI_FUNCTION_NAME ("ns_dump_root_devices");
123
124
125 /* Only dump the table if tracing is enabled */
126
127 if (!(ACPI_LV_TABLES & acpi_dbg_level)) {
128 return;
129 }
130
131 status = acpi_get_handle(NULL, ACPI_NS_SYSTEM_BUS, &sys_bus_handle);
132 if (ACPI_FAILURE (status)) {
133 return;
134 }
135
136 ACPI_DEBUG_PRINT ((ACPI_DB_TABLES,
137 "Display of all devices in the namespace:\n"));
138
139 status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE, sys_bus_handle,
140 ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
141 acpi_ns_dump_one_device, NULL, NULL);
142}
143
144#endif
145
146
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
new file mode 100644
index 000000000000..0d008d53657e
--- /dev/null
+++ b/drivers/acpi/namespace/nseval.c
@@ -0,0 +1,487 @@
1/*******************************************************************************
2 *
3 * Module Name: nseval - Object evaluation interfaces -- includes control
4 * method lookup and execution.
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acparser.h>
48#include <acpi/acinterp.h>
49#include <acpi/acnamesp.h>
50
51
52#define _COMPONENT ACPI_NAMESPACE
53 ACPI_MODULE_NAME ("nseval")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ns_evaluate_relative
59 *
60 * PARAMETERS: Pathname - Name of method to execute, If NULL, the
61 * handle is the object to execute
62 * Info - Method info block
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: Find and execute the requested method using the handle as a
67 * scope
68 *
69 * MUTEX: Locks Namespace
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_ns_evaluate_relative (
75 char *pathname,
76 struct acpi_parameter_info *info)
77{
78 acpi_status status;
79 struct acpi_namespace_node *node = NULL;
80 union acpi_generic_state *scope_info;
81 char *internal_path = NULL;
82
83
84 ACPI_FUNCTION_TRACE ("ns_evaluate_relative");
85
86
87 /*
88 * Must have a valid object handle
89 */
90 if (!info || !info->node) {
91 return_ACPI_STATUS (AE_BAD_PARAMETER);
92 }
93
94 /* Build an internal name string for the method */
95
96 status = acpi_ns_internalize_name (pathname, &internal_path);
97 if (ACPI_FAILURE (status)) {
98 return_ACPI_STATUS (status);
99 }
100
101 scope_info = acpi_ut_create_generic_state ();
102 if (!scope_info) {
103 goto cleanup1;
104 }
105
106 /* Get the prefix handle and Node */
107
108 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
109 if (ACPI_FAILURE (status)) {
110 goto cleanup;
111 }
112
113 info->node = acpi_ns_map_handle_to_node (info->node);
114 if (!info->node) {
115 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
116 status = AE_BAD_PARAMETER;
117 goto cleanup;
118 }
119
120 /* Lookup the name in the namespace */
121
122 scope_info->scope.node = info->node;
123 status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
124 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
125 &node);
126
127 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
128
129 if (ACPI_FAILURE (status)) {
130 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
131 pathname, acpi_format_exception (status)));
132 goto cleanup;
133 }
134
135 /*
136 * Now that we have a handle to the object, we can attempt to evaluate it.
137 */
138 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
139 pathname, node, acpi_ns_get_attached_object (node)));
140
141 info->node = node;
142 status = acpi_ns_evaluate_by_handle (info);
143
144 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
145 pathname));
146
147cleanup:
148 acpi_ut_delete_generic_state (scope_info);
149
150cleanup1:
151 ACPI_MEM_FREE (internal_path);
152 return_ACPI_STATUS (status);
153}
154
155
156/*******************************************************************************
157 *
158 * FUNCTION: acpi_ns_evaluate_by_name
159 *
160 * PARAMETERS: Pathname - Fully qualified pathname to the object
161 * Info - Contains:
162 * return_object - Where to put method's return value (if
163 * any). If NULL, no value is returned.
164 * Params - List of parameters to pass to the method,
165 * terminated by NULL. Params itself may be
166 * NULL if no parameters are being passed.
167 *
168 * RETURN: Status
169 *
170 * DESCRIPTION: Find and execute the requested method passing the given
171 * parameters
172 *
173 * MUTEX: Locks Namespace
174 *
175 ******************************************************************************/
176
177acpi_status
178acpi_ns_evaluate_by_name (
179 char *pathname,
180 struct acpi_parameter_info *info)
181{
182 acpi_status status;
183 char *internal_path = NULL;
184
185
186 ACPI_FUNCTION_TRACE ("ns_evaluate_by_name");
187
188
189 /* Build an internal name string for the method */
190
191 status = acpi_ns_internalize_name (pathname, &internal_path);
192 if (ACPI_FAILURE (status)) {
193 return_ACPI_STATUS (status);
194 }
195
196 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
197 if (ACPI_FAILURE (status)) {
198 goto cleanup;
199 }
200
201 /* Lookup the name in the namespace */
202
203 status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
204 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
205 &info->node);
206
207 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
208
209 if (ACPI_FAILURE (status)) {
210 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
211 "Object at [%s] was not found, status=%.4X\n",
212 pathname, status));
213 goto cleanup;
214 }
215
216 /*
217 * Now that we have a handle to the object, we can attempt to evaluate it.
218 */
219 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
220 pathname, info->node, acpi_ns_get_attached_object (info->node)));
221
222 status = acpi_ns_evaluate_by_handle (info);
223
224 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
225 pathname));
226
227
228cleanup:
229
230 /* Cleanup */
231
232 if (internal_path) {
233 ACPI_MEM_FREE (internal_path);
234 }
235
236 return_ACPI_STATUS (status);
237}
238
239
240/*******************************************************************************
241 *
242 * FUNCTION: acpi_ns_evaluate_by_handle
243 *
244 * PARAMETERS: Handle - Method Node to execute
245 * Params - List of parameters to pass to the method,
246 * terminated by NULL. Params itself may be
247 * NULL if no parameters are being passed.
248 * param_type - Type of Parameter list
249 * return_object - Where to put method's return value (if
250 * any). If NULL, no value is returned.
251 *
252 * RETURN: Status
253 *
254 * DESCRIPTION: Execute the requested method passing the given parameters
255 *
256 * MUTEX: Locks Namespace
257 *
258 ******************************************************************************/
259
260acpi_status
261acpi_ns_evaluate_by_handle (
262 struct acpi_parameter_info *info)
263{
264 acpi_status status;
265
266
267 ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
268
269
270 /* Check if namespace has been initialized */
271
272 if (!acpi_gbl_root_node) {
273 return_ACPI_STATUS (AE_NO_NAMESPACE);
274 }
275
276 /* Parameter Validation */
277
278 if (!info) {
279 return_ACPI_STATUS (AE_BAD_PARAMETER);
280 }
281
282 /* Initialize the return value to an invalid object */
283
284 info->return_object = NULL;
285
286 /* Get the prefix handle and Node */
287
288 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
289 if (ACPI_FAILURE (status)) {
290 return_ACPI_STATUS (status);
291 }
292
293 info->node = acpi_ns_map_handle_to_node (info->node);
294 if (!info->node) {
295 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
296 return_ACPI_STATUS (AE_BAD_PARAMETER);
297 }
298
299 /*
300 * For a method alias, we must grab the actual method node so that proper
301 * scoping context will be established before execution.
302 */
303 if (acpi_ns_get_type (info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
304 info->node = ACPI_CAST_PTR (struct acpi_namespace_node, info->node->object);
305 }
306
307 /*
308 * Two major cases here:
309 * 1) The object is an actual control method -- execute it.
310 * 2) The object is not a method -- just return it's current value
311 *
312 * In both cases, the namespace is unlocked by the acpi_ns* procedure
313 */
314 if (acpi_ns_get_type (info->node) == ACPI_TYPE_METHOD) {
315 /*
316 * Case 1) We have an actual control method to execute
317 */
318 status = acpi_ns_execute_control_method (info);
319 }
320 else {
321 /*
322 * Case 2) Object is NOT a method, just return its current value
323 */
324 status = acpi_ns_get_object_value (info);
325 }
326
327 /*
328 * Check if there is a return value on the stack that must be dealt with
329 */
330 if (status == AE_CTRL_RETURN_VALUE) {
331 /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
332
333 status = AE_OK;
334 }
335
336 /*
337 * Namespace was unlocked by the handling acpi_ns* function, so we
338 * just return
339 */
340 return_ACPI_STATUS (status);
341}
342
343
344/*******************************************************************************
345 *
346 * FUNCTION: acpi_ns_execute_control_method
347 *
348 * PARAMETERS: Info - Method info block (w/params)
349 *
350 * RETURN: Status
351 *
352 * DESCRIPTION: Execute the requested method passing the given parameters
353 *
354 * MUTEX: Assumes namespace is locked
355 *
356 ******************************************************************************/
357
358acpi_status
359acpi_ns_execute_control_method (
360 struct acpi_parameter_info *info)
361{
362 acpi_status status;
363 union acpi_operand_object *obj_desc;
364
365
366 ACPI_FUNCTION_TRACE ("ns_execute_control_method");
367
368
369 /* Verify that there is a method associated with this object */
370
371 obj_desc = acpi_ns_get_attached_object (info->node);
372 if (!obj_desc) {
373 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
374
375 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
376 return_ACPI_STATUS (AE_NULL_OBJECT);
377 }
378
379 ACPI_DUMP_PATHNAME (info->node, "Execute Method:",
380 ACPI_LV_INFO, _COMPONENT);
381
382 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
383 obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1));
384
385 /*
386 * Unlock the namespace before execution. This allows namespace access
387 * via the external Acpi* interfaces while a method is being executed.
388 * However, any namespace deletion must acquire both the namespace and
389 * interpreter locks to ensure that no thread is using the portion of the
390 * namespace that is being deleted.
391 */
392 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
393 if (ACPI_FAILURE (status)) {
394 return_ACPI_STATUS (status);
395 }
396
397 /*
398 * Execute the method via the interpreter. The interpreter is locked
399 * here before calling into the AML parser
400 */
401 status = acpi_ex_enter_interpreter ();
402 if (ACPI_FAILURE (status)) {
403 return_ACPI_STATUS (status);
404 }
405
406 status = acpi_psx_execute (info);
407 acpi_ex_exit_interpreter ();
408
409 return_ACPI_STATUS (status);
410}
411
412
413/*******************************************************************************
414 *
415 * FUNCTION: acpi_ns_get_object_value
416 *
417 * PARAMETERS: Info - Method info block (w/params)
418 *
419 * RETURN: Status
420 *
421 * DESCRIPTION: Return the current value of the object
422 *
423 * MUTEX: Assumes namespace is locked, leaves namespace unlocked
424 *
425 ******************************************************************************/
426
427acpi_status
428acpi_ns_get_object_value (
429 struct acpi_parameter_info *info)
430{
431 acpi_status status = AE_OK;
432 struct acpi_namespace_node *resolved_node = info->node;
433
434
435 ACPI_FUNCTION_TRACE ("ns_get_object_value");
436
437
438 /*
439 * Objects require additional resolution steps (e.g., the Node may be a
440 * field that must be read, etc.) -- we can't just grab the object out of
441 * the node.
442 */
443
444 /*
445 * Use resolve_node_to_value() to get the associated value. This call always
446 * deletes obj_desc (allocated above).
447 *
448 * NOTE: we can get away with passing in NULL for a walk state because
449 * obj_desc is guaranteed to not be a reference to either a method local or
450 * a method argument (because this interface can only be called from the
451 * acpi_evaluate external interface, never called from a running method.)
452 *
453 * Even though we do not directly invoke the interpreter for this, we must
454 * enter it because we could access an opregion. The opregion access code
455 * assumes that the interpreter is locked.
456 *
457 * We must release the namespace lock before entering the intepreter.
458 */
459 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
460 if (ACPI_FAILURE (status)) {
461 return_ACPI_STATUS (status);
462 }
463
464 status = acpi_ex_enter_interpreter ();
465 if (ACPI_SUCCESS (status)) {
466 status = acpi_ex_resolve_node_to_value (&resolved_node, NULL);
467 /*
468 * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed
469 * in resolved_node.
470 */
471 acpi_ex_exit_interpreter ();
472
473 if (ACPI_SUCCESS (status)) {
474 status = AE_CTRL_RETURN_VALUE;
475 info->return_object = ACPI_CAST_PTR
476 (union acpi_operand_object, resolved_node);
477 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
478 info->return_object,
479 acpi_ut_get_object_type_name (info->return_object)));
480 }
481 }
482
483 /* Namespace is unlocked */
484
485 return_ACPI_STATUS (status);
486}
487
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
new file mode 100644
index 000000000000..4a46b380605b
--- /dev/null
+++ b/drivers/acpi/namespace/nsinit.c
@@ -0,0 +1,441 @@
1/******************************************************************************
2 *
3 * Module Name: nsinit - namespace initialization
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acdispat.h>
48#include <acpi/acinterp.h>
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsinit")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ns_initialize_objects
57 *
58 * PARAMETERS: None
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Walk the entire namespace and perform any necessary
63 * initialization on the objects found therein
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_ns_initialize_objects (
69 void)
70{
71 acpi_status status;
72 struct acpi_init_walk_info info;
73
74
75 ACPI_FUNCTION_TRACE ("ns_initialize_objects");
76
77
78 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
79 "**** Starting initialization of namespace objects ****\n"));
80 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
81 "Completing Region/Field/Buffer/Package initialization:"));
82
83 /* Set all init info to zero */
84
85 ACPI_MEMSET (&info, 0, sizeof (struct acpi_init_walk_info));
86
87 /* Walk entire namespace from the supplied root */
88
89 status = acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
90 ACPI_UINT32_MAX, acpi_ns_init_one_object,
91 &info, NULL);
92 if (ACPI_FAILURE (status)) {
93 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
94 acpi_format_exception (status)));
95 }
96
97 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
98 "\nInitialized %hd/%hd Regions %hd/%hd Fields %hd/%hd Buffers %hd/%hd Packages (%hd nodes)\n",
99 info.op_region_init, info.op_region_count,
100 info.field_init, info.field_count,
101 info.buffer_init, info.buffer_count,
102 info.package_init, info.package_count, info.object_count));
103
104 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
105 "%hd Control Methods found\n", info.method_count));
106 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
107 "%hd Op Regions found\n", info.op_region_count));
108
109 return_ACPI_STATUS (AE_OK);
110}
111
112
113/*******************************************************************************
114 *
115 * FUNCTION: acpi_ns_initialize_devices
116 *
117 * PARAMETERS: None
118 *
119 * RETURN: acpi_status
120 *
121 * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
122 * This means running _INI on all present devices.
123 *
124 * Note: We install PCI config space handler on region access,
125 * not here.
126 *
127 ******************************************************************************/
128
129acpi_status
130acpi_ns_initialize_devices (
131 void)
132{
133 acpi_status status;
134 struct acpi_device_walk_info info;
135
136
137 ACPI_FUNCTION_TRACE ("ns_initialize_devices");
138
139
140 /* Init counters */
141
142 info.device_count = 0;
143 info.num_STA = 0;
144 info.num_INI = 0;
145
146 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
147 "Executing all Device _STA and_INI methods:"));
148
149 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
150 if (ACPI_FAILURE (status)) {
151 return_ACPI_STATUS (status);
152 }
153
154 /* Walk namespace for all objects */
155
156 status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
157 ACPI_UINT32_MAX, TRUE, acpi_ns_init_one_device, &info, NULL);
158
159 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
160
161 if (ACPI_FAILURE (status)) {
162 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed! %s\n",
163 acpi_format_exception (status)));
164 }
165
166 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
167 "\n%hd Devices found containing: %hd _STA, %hd _INI methods\n",
168 info.device_count, info.num_STA, info.num_INI));
169
170 return_ACPI_STATUS (status);
171}
172
173
174/*******************************************************************************
175 *
176 * FUNCTION: acpi_ns_init_one_object
177 *
178 * PARAMETERS: obj_handle - Node
179 * Level - Current nesting level
180 * Context - Points to a init info struct
181 * return_value - Not used
182 *
183 * RETURN: Status
184 *
185 * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
186 * within the namespace.
187 *
188 * Currently, the only objects that require initialization are:
189 * 1) Methods
190 * 2) Op Regions
191 *
192 ******************************************************************************/
193
194acpi_status
195acpi_ns_init_one_object (
196 acpi_handle obj_handle,
197 u32 level,
198 void *context,
199 void **return_value)
200{
201 acpi_object_type type;
202 acpi_status status;
203 struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context;
204 struct acpi_namespace_node *node = (struct acpi_namespace_node *) obj_handle;
205 union acpi_operand_object *obj_desc;
206
207
208 ACPI_FUNCTION_NAME ("ns_init_one_object");
209
210
211 info->object_count++;
212
213 /* And even then, we are only interested in a few object types */
214
215 type = acpi_ns_get_type (obj_handle);
216 obj_desc = acpi_ns_get_attached_object (node);
217 if (!obj_desc) {
218 return (AE_OK);
219 }
220
221 /* Increment counters for object types we are looking for */
222
223 switch (type) {
224 case ACPI_TYPE_REGION:
225 info->op_region_count++;
226 break;
227
228 case ACPI_TYPE_BUFFER_FIELD:
229 info->field_count++;
230 break;
231
232 case ACPI_TYPE_BUFFER:
233 info->buffer_count++;
234 break;
235
236 case ACPI_TYPE_PACKAGE:
237 info->package_count++;
238 break;
239
240 default:
241
242 /* No init required, just exit now */
243 return (AE_OK);
244 }
245
246 /*
247 * If the object is already initialized, nothing else to do
248 */
249 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
250 return (AE_OK);
251 }
252
253 /*
254 * Must lock the interpreter before executing AML code
255 */
256 status = acpi_ex_enter_interpreter ();
257 if (ACPI_FAILURE (status)) {
258 return (status);
259 }
260
261 /*
262 * Each of these types can contain executable AML code within the
263 * declaration.
264 */
265 switch (type) {
266 case ACPI_TYPE_REGION:
267
268 info->op_region_init++;
269 status = acpi_ds_get_region_arguments (obj_desc);
270 break;
271
272 case ACPI_TYPE_BUFFER_FIELD:
273
274 info->field_init++;
275 status = acpi_ds_get_buffer_field_arguments (obj_desc);
276 break;
277
278 case ACPI_TYPE_BUFFER:
279
280 info->buffer_init++;
281 status = acpi_ds_get_buffer_arguments (obj_desc);
282 break;
283
284 case ACPI_TYPE_PACKAGE:
285
286 info->package_init++;
287 status = acpi_ds_get_package_arguments (obj_desc);
288 break;
289
290 default:
291 /* No other types can get here */
292 break;
293 }
294
295 if (ACPI_FAILURE (status)) {
296 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n"));
297 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
298 "Could not execute arguments for [%4.4s] (%s), %s\n",
299 acpi_ut_get_node_name (node), acpi_ut_get_type_name (type),
300 acpi_format_exception (status)));
301 }
302
303 /*
304 * Print a dot for each object unless we are going to print the entire
305 * pathname
306 */
307 if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
308 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
309 }
310
311 /*
312 * We ignore errors from above, and always return OK, since we don't want
313 * to abort the walk on any single error.
314 */
315 acpi_ex_exit_interpreter ();
316 return (AE_OK);
317}
318
319
320/*******************************************************************************
321 *
322 * FUNCTION: acpi_ns_init_one_device
323 *
324 * PARAMETERS: acpi_walk_callback
325 *
326 * RETURN: acpi_status
327 *
328 * DESCRIPTION: This is called once per device soon after ACPI is enabled
329 * to initialize each device. It determines if the device is
330 * present, and if so, calls _INI.
331 *
332 ******************************************************************************/
333
334acpi_status
335acpi_ns_init_one_device (
336 acpi_handle obj_handle,
337 u32 nesting_level,
338 void *context,
339 void **return_value)
340{
341 struct acpi_device_walk_info *info = (struct acpi_device_walk_info *) context;
342 struct acpi_parameter_info pinfo;
343 u32 flags;
344 acpi_status status;
345
346
347 ACPI_FUNCTION_TRACE ("ns_init_one_device");
348
349
350 pinfo.parameters = NULL;
351 pinfo.parameter_type = ACPI_PARAM_ARGS;
352
353 pinfo.node = acpi_ns_map_handle_to_node (obj_handle);
354 if (!pinfo.node) {
355 return_ACPI_STATUS (AE_BAD_PARAMETER);
356 }
357
358 /*
359 * We will run _STA/_INI on Devices, Processors and thermal_zones only
360 */
361 if ((pinfo.node->type != ACPI_TYPE_DEVICE) &&
362 (pinfo.node->type != ACPI_TYPE_PROCESSOR) &&
363 (pinfo.node->type != ACPI_TYPE_THERMAL)) {
364 return_ACPI_STATUS (AE_OK);
365 }
366
367 if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
368 (!(acpi_dbg_level & ACPI_LV_INFO))) {
369 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
370 }
371
372 info->device_count++;
373
374 /*
375 * Run _STA to determine if we can run _INI on the device.
376 */
377 ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_STA"));
378 status = acpi_ut_execute_STA (pinfo.node, &flags);
379
380 if (ACPI_FAILURE (status)) {
381 if (pinfo.node->type == ACPI_TYPE_DEVICE) {
382 /* Ignore error and move on to next device */
383
384 return_ACPI_STATUS (AE_OK);
385 }
386
387 /* _STA is not required for Processor or thermal_zone objects */
388 }
389 else {
390 info->num_STA++;
391
392 if (!(flags & 0x01)) {
393 /* Don't look at children of a not present device */
394
395 return_ACPI_STATUS(AE_CTRL_DEPTH);
396 }
397 }
398
399 /*
400 * The device is present. Run _INI.
401 */
402 ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, pinfo.node, "_INI"));
403 status = acpi_ns_evaluate_relative ("_INI", &pinfo);
404 if (ACPI_FAILURE (status)) {
405 /* No _INI (AE_NOT_FOUND) means device requires no initialization */
406
407 if (status != AE_NOT_FOUND) {
408 /* Ignore error and move on to next device */
409
410#ifdef ACPI_DEBUG_OUTPUT
411 char *scope_name = acpi_ns_get_external_pathname (pinfo.node);
412
413 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%s._INI failed: %s\n",
414 scope_name, acpi_format_exception (status)));
415
416 ACPI_MEM_FREE (scope_name);
417#endif
418 }
419
420 status = AE_OK;
421 }
422 else {
423 /* Delete any return object (especially if implicit_return is enabled) */
424
425 if (pinfo.return_object) {
426 acpi_ut_remove_reference (pinfo.return_object);
427 }
428
429 /* Count of successful INIs */
430
431 info->num_INI++;
432 }
433
434 if (acpi_gbl_init_handler) {
435 /* External initialization handler is present, call it */
436
437 status = acpi_gbl_init_handler (pinfo.node, ACPI_INIT_DEVICE_INI);
438 }
439
440 return_ACPI_STATUS (status);
441}
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
new file mode 100644
index 000000000000..1d7aedf68a77
--- /dev/null
+++ b/drivers/acpi/namespace/nsload.c
@@ -0,0 +1,460 @@
1/******************************************************************************
2 *
3 * Module Name: nsload - namespace loading/expanding/contracting procedures
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acdispat.h>
48
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsload")
52
53
54#ifndef ACPI_NO_METHOD_EXECUTION
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_ns_load_table
59 *
60 * PARAMETERS: table_desc - Descriptor for table to be loaded
61 * Node - Owning NS node
62 *
63 * RETURN: Status
64 *
65 * DESCRIPTION: Load one ACPI table into the namespace
66 *
67 ******************************************************************************/
68
69acpi_status
70acpi_ns_load_table (
71 struct acpi_table_desc *table_desc,
72 struct acpi_namespace_node *node)
73{
74 acpi_status status;
75
76
77 ACPI_FUNCTION_TRACE ("ns_load_table");
78
79
80 /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */
81
82 if (!(acpi_gbl_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) {
83 /* Just ignore this table */
84
85 return_ACPI_STATUS (AE_OK);
86 }
87
88 /* Check validity of the AML start and length */
89
90 if (!table_desc->aml_start) {
91 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null AML pointer\n"));
92 return_ACPI_STATUS (AE_BAD_PARAMETER);
93 }
94
95 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n",
96 table_desc->aml_start));
97
98 /* Ignore table if there is no AML contained within */
99
100 if (!table_desc->aml_length) {
101 ACPI_REPORT_WARNING (("Zero-length AML block in table [%4.4s]\n",
102 table_desc->pointer->signature));
103 return_ACPI_STATUS (AE_OK);
104 }
105
106 /*
107 * Parse the table and load the namespace with all named
108 * objects found within. Control methods are NOT parsed
109 * at this time. In fact, the control methods cannot be
110 * parsed until the entire namespace is loaded, because
111 * if a control method makes a forward reference (call)
112 * to another control method, we can't continue parsing
113 * because we don't know how many arguments to parse next!
114 */
115 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
116 "**** Loading table into namespace ****\n"));
117
118 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
119 if (ACPI_FAILURE (status)) {
120 return_ACPI_STATUS (status);
121 }
122
123 status = acpi_ns_parse_table (table_desc, node->child);
124 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
125
126 if (ACPI_FAILURE (status)) {
127 return_ACPI_STATUS (status);
128 }
129
130 /*
131 * Now we can parse the control methods. We always parse
132 * them here for a sanity check, and if configured for
133 * just-in-time parsing, we delete the control method
134 * parse trees.
135 */
136 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
137 "**** Begin Table Method Parsing and Object Initialization ****\n"));
138
139 status = acpi_ds_initialize_objects (table_desc, node);
140
141 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
142 "**** Completed Table Method Parsing and Object Initialization ****\n"));
143
144 return_ACPI_STATUS (status);
145}
146
147
148/*******************************************************************************
149 *
150 * FUNCTION: acpi_ns_load_table_by_type
151 *
152 * PARAMETERS: table_type - Id of the table type to load
153 *
154 * RETURN: Status
155 *
156 * DESCRIPTION: Load an ACPI table or tables into the namespace. All tables
157 * of the given type are loaded. The mechanism allows this
158 * routine to be called repeatedly.
159 *
160 ******************************************************************************/
161
162acpi_status
163acpi_ns_load_table_by_type (
164 acpi_table_type table_type)
165{
166 u32 i;
167 acpi_status status;
168 struct acpi_table_desc *table_desc;
169
170
171 ACPI_FUNCTION_TRACE ("ns_load_table_by_type");
172
173
174 status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
175 if (ACPI_FAILURE (status)) {
176 return_ACPI_STATUS (status);
177 }
178
179 /*
180 * Table types supported are:
181 * DSDT (one), SSDT/PSDT (multiple)
182 */
183 switch (table_type) {
184 case ACPI_TABLE_DSDT:
185
186 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n"));
187
188 table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next;
189
190 /* If table already loaded into namespace, just return */
191
192 if (table_desc->loaded_into_namespace) {
193 goto unlock_and_exit;
194 }
195
196 /* Now load the single DSDT */
197
198 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
199 if (ACPI_SUCCESS (status)) {
200 table_desc->loaded_into_namespace = TRUE;
201 }
202 break;
203
204
205 case ACPI_TABLE_SSDT:
206
207 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n",
208 acpi_gbl_table_lists[ACPI_TABLE_SSDT].count));
209
210 /*
211 * Traverse list of SSDT tables
212 */
213 table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next;
214 for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) {
215 /*
216 * Only attempt to load table if it is not
217 * already loaded!
218 */
219 if (!table_desc->loaded_into_namespace) {
220 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
221 if (ACPI_FAILURE (status)) {
222 break;
223 }
224
225 table_desc->loaded_into_namespace = TRUE;
226 }
227
228 table_desc = table_desc->next;
229 }
230 break;
231
232
233 case ACPI_TABLE_PSDT:
234
235 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n",
236 acpi_gbl_table_lists[ACPI_TABLE_PSDT].count));
237
238 /*
239 * Traverse list of PSDT tables
240 */
241 table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next;
242
243 for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) {
244 /* Only attempt to load table if it is not already loaded! */
245
246 if (!table_desc->loaded_into_namespace) {
247 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
248 if (ACPI_FAILURE (status)) {
249 break;
250 }
251
252 table_desc->loaded_into_namespace = TRUE;
253 }
254
255 table_desc = table_desc->next;
256 }
257 break;
258
259
260 default:
261 status = AE_SUPPORT;
262 break;
263 }
264
265
266unlock_and_exit:
267 (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
268 return_ACPI_STATUS (status);
269}
270
271
272/*******************************************************************************
273 *
274 * FUNCTION: acpi_load_namespace
275 *
276 * PARAMETERS: None
277 *
278 * RETURN: Status
279 *
280 * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
281 * (DSDT points to either the BIOS or a buffer.)
282 *
283 ******************************************************************************/
284
285acpi_status
286acpi_ns_load_namespace (
287 void)
288{
289 acpi_status status;
290
291
292 ACPI_FUNCTION_TRACE ("acpi_load_name_space");
293
294
295 /* There must be at least a DSDT installed */
296
297 if (acpi_gbl_DSDT == NULL) {
298 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
299 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
300 }
301
302 /*
303 * Load the namespace. The DSDT is required,
304 * but the SSDT and PSDT tables are optional.
305 */
306 status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
307 if (ACPI_FAILURE (status)) {
308 return_ACPI_STATUS (status);
309 }
310
311 /* Ignore exceptions from these */
312
313 (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
314 (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
315
316 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
317 "ACPI Namespace successfully loaded at root %p\n",
318 acpi_gbl_root_node));
319
320 return_ACPI_STATUS (status);
321}
322
323
324#ifdef ACPI_FUTURE_USAGE
325
326/*******************************************************************************
327 *
328 * FUNCTION: acpi_ns_delete_subtree
329 *
330 * PARAMETERS: start_handle - Handle in namespace where search begins
331 *
332 * RETURNS Status
333 *
334 * DESCRIPTION: Walks the namespace starting at the given handle and deletes
335 * all objects, entries, and scopes in the entire subtree.
336 *
337 * Namespace/Interpreter should be locked or the subsystem should
338 * be in shutdown before this routine is called.
339 *
340 ******************************************************************************/
341
342acpi_status
343acpi_ns_delete_subtree (
344 acpi_handle start_handle)
345{
346 acpi_status status;
347 acpi_handle child_handle;
348 acpi_handle parent_handle;
349 acpi_handle next_child_handle;
350 acpi_handle dummy;
351 u32 level;
352
353
354 ACPI_FUNCTION_TRACE ("ns_delete_subtree");
355
356
357 parent_handle = start_handle;
358 child_handle = NULL;
359 level = 1;
360
361 /*
362 * Traverse the tree of objects until we bubble back up
363 * to where we started.
364 */
365 while (level > 0) {
366 /* Attempt to get the next object in this scope */
367
368 status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
369 child_handle, &next_child_handle);
370
371 child_handle = next_child_handle;
372
373 /* Did we get a new object? */
374
375 if (ACPI_SUCCESS (status)) {
376 /* Check if this object has any children */
377
378 if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle,
379 NULL, &dummy))) {
380 /*
381 * There is at least one child of this object,
382 * visit the object
383 */
384 level++;
385 parent_handle = child_handle;
386 child_handle = NULL;
387 }
388 }
389 else {
390 /*
391 * No more children in this object, go back up to
392 * the object's parent
393 */
394 level--;
395
396 /* Delete all children now */
397
398 acpi_ns_delete_children (child_handle);
399
400 child_handle = parent_handle;
401 status = acpi_get_parent (parent_handle, &parent_handle);
402 if (ACPI_FAILURE (status)) {
403 return_ACPI_STATUS (status);
404 }
405 }
406 }
407
408 /* Now delete the starting object, and we are done */
409
410 acpi_ns_delete_node (child_handle);
411
412 return_ACPI_STATUS (AE_OK);
413}
414
415
416/*******************************************************************************
417 *
418 * FUNCTION: acpi_ns_unload_name_space
419 *
420 * PARAMETERS: Handle - Root of namespace subtree to be deleted
421 *
422 * RETURN: Status
423 *
424 * DESCRIPTION: Shrinks the namespace, typically in response to an undocking
425 * event. Deletes an entire subtree starting from (and
426 * including) the given handle.
427 *
428 ******************************************************************************/
429
430acpi_status
431acpi_ns_unload_namespace (
432 acpi_handle handle)
433{
434 acpi_status status;
435
436
437 ACPI_FUNCTION_TRACE ("ns_unload_name_space");
438
439
440 /* Parameter validation */
441
442 if (!acpi_gbl_root_node) {
443 return_ACPI_STATUS (AE_NO_NAMESPACE);
444 }
445
446 if (!handle) {
447 return_ACPI_STATUS (AE_BAD_PARAMETER);
448 }
449
450 /* This function does the real work */
451
452 status = acpi_ns_delete_subtree (handle);
453
454 return_ACPI_STATUS (status);
455}
456
457#endif /* ACPI_FUTURE_USAGE */
458
459#endif
460
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
new file mode 100644
index 000000000000..b6f8f910eff0
--- /dev/null
+++ b/drivers/acpi/namespace/nsnames.c
@@ -0,0 +1,265 @@
1/*******************************************************************************
2 *
3 * Module Name: nsnames - Name manipulation and search
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/amlcode.h>
47#include <acpi/acnamesp.h>
48
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsnames")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ns_build_external_path
57 *
58 * PARAMETERS: Node - NS node whose pathname is needed
59 * Size - Size of the pathname
60 * *name_buffer - Where to return the pathname
61 *
62 * RETURN: Places the pathname into the name_buffer, in external format
63 * (name segments separated by path separators)
64 *
65 * DESCRIPTION: Generate a full pathaname
66 *
67 ******************************************************************************/
68
69void
70acpi_ns_build_external_path (
71 struct acpi_namespace_node *node,
72 acpi_size size,
73 char *name_buffer)
74{
75 acpi_size index;
76 struct acpi_namespace_node *parent_node;
77
78
79 ACPI_FUNCTION_NAME ("ns_build_external_path");
80
81
82 /* Special case for root */
83
84 index = size - 1;
85 if (index < ACPI_NAME_SIZE) {
86 name_buffer[0] = AML_ROOT_PREFIX;
87 name_buffer[1] = 0;
88 return;
89 }
90
91 /* Store terminator byte, then build name backwards */
92
93 parent_node = node;
94 name_buffer[index] = 0;
95
96 while ((index > ACPI_NAME_SIZE) && (parent_node != acpi_gbl_root_node)) {
97 index -= ACPI_NAME_SIZE;
98
99 /* Put the name into the buffer */
100
101 ACPI_MOVE_32_TO_32 ((name_buffer + index), &parent_node->name);
102 parent_node = acpi_ns_get_parent_node (parent_node);
103
104 /* Prefix name with the path separator */
105
106 index--;
107 name_buffer[index] = ACPI_PATH_SEPARATOR;
108 }
109
110 /* Overwrite final separator with the root prefix character */
111
112 name_buffer[index] = AML_ROOT_PREFIX;
113
114 if (index != 0) {
115 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
116 "Could not construct pathname; index=%X, size=%X, Path=%s\n",
117 (u32) index, (u32) size, &name_buffer[size]));
118 }
119
120 return;
121}
122
123
124#ifdef ACPI_DEBUG_OUTPUT
125/*******************************************************************************
126 *
127 * FUNCTION: acpi_ns_get_external_pathname
128 *
129 * PARAMETERS: Node - NS node whose pathname is needed
130 *
131 * RETURN: Pointer to storage containing the fully qualified name of
132 * the node, In external format (name segments separated by path
133 * separators.)
134 *
135 * DESCRIPTION: Used for debug printing in acpi_ns_search_table().
136 *
137 ******************************************************************************/
138
139char *
140acpi_ns_get_external_pathname (
141 struct acpi_namespace_node *node)
142{
143 char *name_buffer;
144 acpi_size size;
145
146
147 ACPI_FUNCTION_TRACE_PTR ("ns_get_external_pathname", node);
148
149
150 /* Calculate required buffer size based on depth below root */
151
152 size = acpi_ns_get_pathname_length (node);
153
154 /* Allocate a buffer to be returned to caller */
155
156 name_buffer = ACPI_MEM_CALLOCATE (size);
157 if (!name_buffer) {
158 ACPI_REPORT_ERROR (("ns_get_table_pathname: allocation failure\n"));
159 return_PTR (NULL);
160 }
161
162 /* Build the path in the allocated buffer */
163
164 acpi_ns_build_external_path (node, size, name_buffer);
165 return_PTR (name_buffer);
166}
167#endif
168
169
170/*******************************************************************************
171 *
172 * FUNCTION: acpi_ns_get_pathname_length
173 *
174 * PARAMETERS: Node - Namespace node
175 *
176 * RETURN: Length of path, including prefix
177 *
178 * DESCRIPTION: Get the length of the pathname string for this node
179 *
180 ******************************************************************************/
181
182acpi_size
183acpi_ns_get_pathname_length (
184 struct acpi_namespace_node *node)
185{
186 acpi_size size;
187 struct acpi_namespace_node *next_node;
188
189
190 ACPI_FUNCTION_ENTRY ();
191
192
193 /*
194 * Compute length of pathname as 5 * number of name segments.
195 * Go back up the parent tree to the root
196 */
197 size = 0;
198 next_node = node;
199
200 while (next_node && (next_node != acpi_gbl_root_node)) {
201 size += ACPI_PATH_SEGMENT_LENGTH;
202 next_node = acpi_ns_get_parent_node (next_node);
203 }
204
205 if (!size) {
206 size = 1; /* Root node case */
207 }
208
209 return (size + 1); /* +1 for null string terminator */
210}
211
212
213/*******************************************************************************
214 *
215 * FUNCTION: acpi_ns_handle_to_pathname
216 *
217 * PARAMETERS: target_handle - Handle of named object whose name is
218 * to be found
219 * Buffer - Where the pathname is returned
220 *
221 * RETURN: Status, Buffer is filled with pathname if status is AE_OK
222 *
223 * DESCRIPTION: Build and return a full namespace pathname
224 *
225 ******************************************************************************/
226
227acpi_status
228acpi_ns_handle_to_pathname (
229 acpi_handle target_handle,
230 struct acpi_buffer *buffer)
231{
232 acpi_status status;
233 struct acpi_namespace_node *node;
234 acpi_size required_size;
235
236
237 ACPI_FUNCTION_TRACE_PTR ("ns_handle_to_pathname", target_handle);
238
239
240 node = acpi_ns_map_handle_to_node (target_handle);
241 if (!node) {
242 return_ACPI_STATUS (AE_BAD_PARAMETER);
243 }
244
245 /* Determine size required for the caller buffer */
246
247 required_size = acpi_ns_get_pathname_length (node);
248
249 /* Validate/Allocate/Clear caller buffer */
250
251 status = acpi_ut_initialize_buffer (buffer, required_size);
252 if (ACPI_FAILURE (status)) {
253 return_ACPI_STATUS (status);
254 }
255
256 /* Build the path in the caller buffer */
257
258 acpi_ns_build_external_path (node, required_size, buffer->pointer);
259
260 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X] \n",
261 (char *) buffer->pointer, (u32) required_size));
262 return_ACPI_STATUS (AE_OK);
263}
264
265
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
new file mode 100644
index 000000000000..4e41e66db61f
--- /dev/null
+++ b/drivers/acpi/namespace/nsobject.c
@@ -0,0 +1,461 @@
1/*******************************************************************************
2 *
3 * Module Name: nsobject - Utilities for objects attached to namespace
4 * table entries
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acnamesp.h>
48
49
50#define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsobject")
52
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_ns_attach_object
57 *
58 * PARAMETERS: Node - Parent Node
59 * Object - Object to be attached
60 * Type - Type of object, or ACPI_TYPE_ANY if not
61 * known
62 *
63 * DESCRIPTION: Record the given object as the value associated with the
64 * name whose acpi_handle is passed. If Object is NULL
65 * and Type is ACPI_TYPE_ANY, set the name as having no value.
66 * Note: Future may require that the Node->Flags field be passed
67 * as a parameter.
68 *
69 * MUTEX: Assumes namespace is locked
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_ns_attach_object (
75 struct acpi_namespace_node *node,
76 union acpi_operand_object *object,
77 acpi_object_type type)
78{
79 union acpi_operand_object *obj_desc;
80 union acpi_operand_object *last_obj_desc;
81 acpi_object_type object_type = ACPI_TYPE_ANY;
82
83
84 ACPI_FUNCTION_TRACE ("ns_attach_object");
85
86
87 /*
88 * Parameter validation
89 */
90 if (!node) {
91 /* Invalid handle */
92
93 ACPI_REPORT_ERROR (("ns_attach_object: Null named_obj handle\n"));
94 return_ACPI_STATUS (AE_BAD_PARAMETER);
95 }
96
97 if (!object && (ACPI_TYPE_ANY != type)) {
98 /* Null object */
99
100 ACPI_REPORT_ERROR (("ns_attach_object: Null object, but type not ACPI_TYPE_ANY\n"));
101 return_ACPI_STATUS (AE_BAD_PARAMETER);
102 }
103
104 if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
105 /* Not a name handle */
106
107 ACPI_REPORT_ERROR (("ns_attach_object: Invalid handle %p [%s]\n",
108 node, acpi_ut_get_descriptor_name (node)));
109 return_ACPI_STATUS (AE_BAD_PARAMETER);
110 }
111
112 /* Check if this object is already attached */
113
114 if (node->object == object) {
115 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj %p already installed in name_obj %p\n",
116 object, node));
117
118 return_ACPI_STATUS (AE_OK);
119 }
120
121 /* If null object, we will just install it */
122
123 if (!object) {
124 obj_desc = NULL;
125 object_type = ACPI_TYPE_ANY;
126 }
127
128 /*
129 * If the source object is a namespace Node with an attached object,
130 * we will use that (attached) object
131 */
132 else if ((ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) &&
133 ((struct acpi_namespace_node *) object)->object) {
134 /*
135 * Value passed is a name handle and that name has a
136 * non-null value. Use that name's value and type.
137 */
138 obj_desc = ((struct acpi_namespace_node *) object)->object;
139 object_type = ((struct acpi_namespace_node *) object)->type;
140 }
141
142 /*
143 * Otherwise, we will use the parameter object, but we must type
144 * it first
145 */
146 else {
147 obj_desc = (union acpi_operand_object *) object;
148
149 /* Use the given type */
150
151 object_type = type;
152 }
153
154 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
155 obj_desc, node, acpi_ut_get_node_name (node)));
156
157 /* Detach an existing attached object if present */
158
159 if (node->object) {
160 acpi_ns_detach_object (node);
161 }
162
163 if (obj_desc) {
164 /*
165 * Must increment the new value's reference count
166 * (if it is an internal object)
167 */
168 acpi_ut_add_reference (obj_desc);
169
170 /*
171 * Handle objects with multiple descriptors - walk
172 * to the end of the descriptor list
173 */
174 last_obj_desc = obj_desc;
175 while (last_obj_desc->common.next_object) {
176 last_obj_desc = last_obj_desc->common.next_object;
177 }
178
179 /* Install the object at the front of the object list */
180
181 last_obj_desc->common.next_object = node->object;
182 }
183
184 node->type = (u8) object_type;
185 node->object = obj_desc;
186
187 return_ACPI_STATUS (AE_OK);
188}
189
190
191/*******************************************************************************
192 *
193 * FUNCTION: acpi_ns_detach_object
194 *
195 * PARAMETERS: Node - An node whose object will be detached
196 *
197 * RETURN: None.
198 *
199 * DESCRIPTION: Detach/delete an object associated with a namespace node.
200 * if the object is an allocated object, it is freed.
201 * Otherwise, the field is simply cleared.
202 *
203 ******************************************************************************/
204
205void
206acpi_ns_detach_object (
207 struct acpi_namespace_node *node)
208{
209 union acpi_operand_object *obj_desc;
210
211
212 ACPI_FUNCTION_TRACE ("ns_detach_object");
213
214
215 obj_desc = node->object;
216
217 if (!obj_desc ||
218 (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA)) {
219 return_VOID;
220 }
221
222 /* Clear the entry in all cases */
223
224 node->object = NULL;
225 if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) {
226 node->object = obj_desc->common.next_object;
227 if (node->object &&
228 (ACPI_GET_OBJECT_TYPE (node->object) != ACPI_TYPE_LOCAL_DATA)) {
229 node->object = node->object->common.next_object;
230 }
231 }
232
233 /* Reset the node type to untyped */
234
235 node->type = ACPI_TYPE_ANY;
236
237 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n",
238 node, acpi_ut_get_node_name (node), obj_desc));
239
240 /* Remove one reference on the object (and all subobjects) */
241
242 acpi_ut_remove_reference (obj_desc);
243 return_VOID;
244}
245
246
247/*******************************************************************************
248 *
249 * FUNCTION: acpi_ns_get_attached_object
250 *
251 * PARAMETERS: Node - Parent Node to be examined
252 *
253 * RETURN: Current value of the object field from the Node whose
254 * handle is passed
255 *
256 * DESCRIPTION: Obtain the object attached to a namespace node.
257 *
258 ******************************************************************************/
259
260union acpi_operand_object *
261acpi_ns_get_attached_object (
262 struct acpi_namespace_node *node)
263{
264 ACPI_FUNCTION_TRACE_PTR ("ns_get_attached_object", node);
265
266
267 if (!node) {
268 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Null Node ptr\n"));
269 return_PTR (NULL);
270 }
271
272 if (!node->object ||
273 ((ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_OPERAND) &&
274 (ACPI_GET_DESCRIPTOR_TYPE (node->object) != ACPI_DESC_TYPE_NAMED)) ||
275 (ACPI_GET_OBJECT_TYPE (node->object) == ACPI_TYPE_LOCAL_DATA)) {
276 return_PTR (NULL);
277 }
278
279 return_PTR (node->object);
280}
281
282
283/*******************************************************************************
284 *
285 * FUNCTION: acpi_ns_get_secondary_object
286 *
287 * PARAMETERS: Node - Parent Node to be examined
288 *
289 * RETURN: Current value of the object field from the Node whose
290 * handle is passed.
291 *
292 * DESCRIPTION: Obtain a secondary object associated with a namespace node.
293 *
294 ******************************************************************************/
295
296union acpi_operand_object *
297acpi_ns_get_secondary_object (
298 union acpi_operand_object *obj_desc)
299{
300 ACPI_FUNCTION_TRACE_PTR ("ns_get_secondary_object", obj_desc);
301
302
303 if ((!obj_desc) ||
304 (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
305 (!obj_desc->common.next_object) ||
306 (ACPI_GET_OBJECT_TYPE (obj_desc->common.next_object) == ACPI_TYPE_LOCAL_DATA)) {
307 return_PTR (NULL);
308 }
309
310 return_PTR (obj_desc->common.next_object);
311}
312
313
314/*******************************************************************************
315 *
316 * FUNCTION: acpi_ns_attach_data
317 *
318 * PARAMETERS: Node - Namespace node
319 * Handler - Handler to be associated with the data
320 * Data - Data to be attached
321 *
322 * RETURN: Status
323 *
324 * DESCRIPTION: Low-level attach data. Create and attach a Data object.
325 *
326 ******************************************************************************/
327
328acpi_status
329acpi_ns_attach_data (
330 struct acpi_namespace_node *node,
331 acpi_object_handler handler,
332 void *data)
333{
334 union acpi_operand_object *prev_obj_desc;
335 union acpi_operand_object *obj_desc;
336 union acpi_operand_object *data_desc;
337
338
339 /* We only allow one attachment per handler */
340
341 prev_obj_desc = NULL;
342 obj_desc = node->object;
343 while (obj_desc) {
344 if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
345 (obj_desc->data.handler == handler)) {
346 return (AE_ALREADY_EXISTS);
347 }
348
349 prev_obj_desc = obj_desc;
350 obj_desc = obj_desc->common.next_object;
351 }
352
353 /* Create an internal object for the data */
354
355 data_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_DATA);
356 if (!data_desc) {
357 return (AE_NO_MEMORY);
358 }
359
360 data_desc->data.handler = handler;
361 data_desc->data.pointer = data;
362
363 /* Install the data object */
364
365 if (prev_obj_desc) {
366 prev_obj_desc->common.next_object = data_desc;
367 }
368 else {
369 node->object = data_desc;
370 }
371
372 return (AE_OK);
373}
374
375
376/*******************************************************************************
377 *
378 * FUNCTION: acpi_ns_detach_data
379 *
380 * PARAMETERS: Node - Namespace node
381 * Handler - Handler associated with the data
382 *
383 * RETURN: Status
384 *
385 * DESCRIPTION: Low-level detach data. Delete the data node, but the caller
386 * is responsible for the actual data.
387 *
388 ******************************************************************************/
389
390acpi_status
391acpi_ns_detach_data (
392 struct acpi_namespace_node *node,
393 acpi_object_handler handler)
394{
395 union acpi_operand_object *obj_desc;
396 union acpi_operand_object *prev_obj_desc;
397
398
399 prev_obj_desc = NULL;
400 obj_desc = node->object;
401 while (obj_desc) {
402 if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
403 (obj_desc->data.handler == handler)) {
404 if (prev_obj_desc) {
405 prev_obj_desc->common.next_object = obj_desc->common.next_object;
406 }
407 else {
408 node->object = obj_desc->common.next_object;
409 }
410
411 acpi_ut_remove_reference (obj_desc);
412 return (AE_OK);
413 }
414
415 prev_obj_desc = obj_desc;
416 obj_desc = obj_desc->common.next_object;
417 }
418
419 return (AE_NOT_FOUND);
420}
421
422
423/*******************************************************************************
424 *
425 * FUNCTION: acpi_ns_get_attached_data
426 *
427 * PARAMETERS: Node - Namespace node
428 * Handler - Handler associated with the data
429 * Data - Where the data is returned
430 *
431 * RETURN: Status
432 *
433 * DESCRIPTION: Low level interface to obtain data previously associated with
434 * a namespace node.
435 *
436 ******************************************************************************/
437
438acpi_status
439acpi_ns_get_attached_data (
440 struct acpi_namespace_node *node,
441 acpi_object_handler handler,
442 void **data)
443{
444 union acpi_operand_object *obj_desc;
445
446
447 obj_desc = node->object;
448 while (obj_desc) {
449 if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_DATA) &&
450 (obj_desc->data.handler == handler)) {
451 *data = obj_desc->data.pointer;
452 return (AE_OK);
453 }
454
455 obj_desc = obj_desc->common.next_object;
456 }
457
458 return (AE_NOT_FOUND);
459}
460
461
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
new file mode 100644
index 000000000000..a0e13e8d3764
--- /dev/null
+++ b/drivers/acpi/namespace/nsparse.c
@@ -0,0 +1,171 @@
1/******************************************************************************
2 *
3 * Module Name: nsparse - namespace interface to AML parser
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/acparser.h>
48#include <acpi/acdispat.h>
49
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsparse")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: ns_one_complete_parse
58 *
59 * PARAMETERS: pass_number - 1 or 2
60 * table_desc - The table to be parsed.
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
65 *
66 ******************************************************************************/
67
68acpi_status
69acpi_ns_one_complete_parse (
70 u32 pass_number,
71 struct acpi_table_desc *table_desc)
72{
73 union acpi_parse_object *parse_root;
74 acpi_status status;
75 struct acpi_walk_state *walk_state;
76
77
78 ACPI_FUNCTION_TRACE ("ns_one_complete_parse");
79
80
81 /* Create and init a Root Node */
82
83 parse_root = acpi_ps_create_scope_op ();
84 if (!parse_root) {
85 return_ACPI_STATUS (AE_NO_MEMORY);
86 }
87
88 /* Create and initialize a new walk state */
89
90 walk_state = acpi_ds_create_walk_state (table_desc->table_id,
91 NULL, NULL, NULL);
92 if (!walk_state) {
93 acpi_ps_free_op (parse_root);
94 return_ACPI_STATUS (AE_NO_MEMORY);
95 }
96
97 status = acpi_ds_init_aml_walk (walk_state, parse_root, NULL,
98 table_desc->aml_start, table_desc->aml_length,
99 NULL, pass_number);
100 if (ACPI_FAILURE (status)) {
101 acpi_ds_delete_walk_state (walk_state);
102 return_ACPI_STATUS (status);
103 }
104
105 /* Parse the AML */
106
107 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "*PARSE* pass %d parse\n", pass_number));
108 status = acpi_ps_parse_aml (walk_state);
109
110 acpi_ps_delete_parse_tree (parse_root);
111 return_ACPI_STATUS (status);
112}
113
114
115/*******************************************************************************
116 *
117 * FUNCTION: acpi_ns_parse_table
118 *
119 * PARAMETERS: table_desc - An ACPI table descriptor for table to parse
120 * start_node - Where to enter the table into the namespace
121 *
122 * RETURN: Status
123 *
124 * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
125 *
126 ******************************************************************************/
127
128acpi_status
129acpi_ns_parse_table (
130 struct acpi_table_desc *table_desc,
131 struct acpi_namespace_node *start_node)
132{
133 acpi_status status;
134
135
136 ACPI_FUNCTION_TRACE ("ns_parse_table");
137
138
139 /*
140 * AML Parse, pass 1
141 *
142 * In this pass, we load most of the namespace. Control methods
143 * are not parsed until later. A parse tree is not created. Instead,
144 * each Parser Op subtree is deleted when it is finished. This saves
145 * a great deal of memory, and allows a small cache of parse objects
146 * to service the entire parse. The second pass of the parse then
147 * performs another complete parse of the AML..
148 */
149 status = acpi_ns_one_complete_parse (1, table_desc);
150 if (ACPI_FAILURE (status)) {
151 return_ACPI_STATUS (status);
152 }
153
154 /*
155 * AML Parse, pass 2
156 *
157 * In this pass, we resolve forward references and other things
158 * that could not be completed during the first pass.
159 * Another complete parse of the AML is performed, but the
160 * overhead of this is compensated for by the fact that the
161 * parse objects are all cached.
162 */
163 status = acpi_ns_one_complete_parse (2, table_desc);
164 if (ACPI_FAILURE (status)) {
165 return_ACPI_STATUS (status);
166 }
167
168 return_ACPI_STATUS (status);
169}
170
171
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
new file mode 100644
index 000000000000..0e6dea23603b
--- /dev/null
+++ b/drivers/acpi/namespace/nssearch.c
@@ -0,0 +1,381 @@
1/*******************************************************************************
2 *
3 * Module Name: nssearch - Namespace search
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME ("nssearch")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ns_search_node
56 *
57 * PARAMETERS: *target_name - Ascii ACPI name to search for
58 * *Node - Starting node where search will begin
59 * Type - Object type to match
60 * **return_node - Where the matched Named obj is returned
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Search a single level of the namespace. Performs a
65 * simple search of the specified level, and does not add
66 * entries or search parents.
67 *
68 *
69 * Named object lists are built (and subsequently dumped) in the
70 * order in which the names are encountered during the namespace load;
71 *
72 * All namespace searching is linear in this implementation, but
73 * could be easily modified to support any improved search
74 * algorithm. However, the linear search was chosen for simplicity
75 * and because the trees are small and the other interpreter
76 * execution overhead is relatively high.
77 *
78 ******************************************************************************/
79
80acpi_status
81acpi_ns_search_node (
82 u32 target_name,
83 struct acpi_namespace_node *node,
84 acpi_object_type type,
85 struct acpi_namespace_node **return_node)
86{
87 struct acpi_namespace_node *next_node;
88
89
90 ACPI_FUNCTION_TRACE ("ns_search_node");
91
92
93#ifdef ACPI_DEBUG_OUTPUT
94 if (ACPI_LV_NAMES & acpi_dbg_level) {
95 char *scope_name;
96
97 scope_name = acpi_ns_get_external_pathname (node);
98 if (scope_name) {
99 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
100 "Searching %s (%p) For [%4.4s] (%s)\n",
101 scope_name, node, (char *) &target_name,
102 acpi_ut_get_type_name (type)));
103
104 ACPI_MEM_FREE (scope_name);
105 }
106 }
107#endif
108
109 /*
110 * Search for name at this namespace level, which is to say that we
111 * must search for the name among the children of this object
112 */
113 next_node = node->child;
114 while (next_node) {
115 /* Check for match against the name */
116
117 if (next_node->name.integer == target_name) {
118 /* Resolve a control method alias if any */
119
120 if (acpi_ns_get_type (next_node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
121 next_node = ACPI_CAST_PTR (struct acpi_namespace_node, next_node->object);
122 }
123
124 /*
125 * Found matching entry.
126 */
127 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
128 "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
129 (char *) &target_name, acpi_ut_get_type_name (next_node->type),
130 next_node, acpi_ut_get_node_name (node), node));
131
132 *return_node = next_node;
133 return_ACPI_STATUS (AE_OK);
134 }
135
136 /*
137 * The last entry in the list points back to the parent,
138 * so a flag is used to indicate the end-of-list
139 */
140 if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
141 /* Searched entire list, we are done */
142
143 break;
144 }
145
146 /* Didn't match name, move on to the next peer object */
147
148 next_node = next_node->peer;
149 }
150
151 /* Searched entire namespace level, not found */
152
153 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
154 "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
155 (char *) &target_name, acpi_ut_get_type_name (type),
156 acpi_ut_get_node_name (node), node, node->child));
157
158 return_ACPI_STATUS (AE_NOT_FOUND);
159}
160
161
162/*******************************************************************************
163 *
164 * FUNCTION: acpi_ns_search_parent_tree
165 *
166 * PARAMETERS: *target_name - Ascii ACPI name to search for
167 * *Node - Starting node where search will begin
168 * Type - Object type to match
169 * **return_node - Where the matched Node is returned
170 *
171 * RETURN: Status
172 *
173 * DESCRIPTION: Called when a name has not been found in the current namespace
174 * level. Before adding it or giving up, ACPI scope rules require
175 * searching enclosing scopes in cases identified by acpi_ns_local().
176 *
177 * "A name is located by finding the matching name in the current
178 * name space, and then in the parent name space. If the parent
179 * name space does not contain the name, the search continues
180 * recursively until either the name is found or the name space
181 * does not have a parent (the root of the name space). This
182 * indicates that the name is not found" (From ACPI Specification,
183 * section 5.3)
184 *
185 ******************************************************************************/
186
187static acpi_status
188acpi_ns_search_parent_tree (
189 u32 target_name,
190 struct acpi_namespace_node *node,
191 acpi_object_type type,
192 struct acpi_namespace_node **return_node)
193{
194 acpi_status status;
195 struct acpi_namespace_node *parent_node;
196
197
198 ACPI_FUNCTION_TRACE ("ns_search_parent_tree");
199
200
201 parent_node = acpi_ns_get_parent_node (node);
202
203 /*
204 * If there is no parent (i.e., we are at the root) or type is "local",
205 * we won't be searching the parent tree.
206 */
207 if (!parent_node) {
208 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[%4.4s] has no parent\n",
209 (char *) &target_name));
210 return_ACPI_STATUS (AE_NOT_FOUND);
211 }
212
213 if (acpi_ns_local (type)) {
214 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
215 "[%4.4s] type [%s] must be local to this scope (no parent search)\n",
216 (char *) &target_name, acpi_ut_get_type_name (type)));
217 return_ACPI_STATUS (AE_NOT_FOUND);
218 }
219
220 /* Search the parent tree */
221
222 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
223 "Searching parent [%4.4s] for [%4.4s]\n",
224 acpi_ut_get_node_name (parent_node), (char *) &target_name));
225
226 /*
227 * Search parents until target is found or we have backed up to the root
228 */
229 while (parent_node) {
230 /*
231 * Search parent scope. Use TYPE_ANY because we don't care about the
232 * object type at this point, we only care about the existence of
233 * the actual name we are searching for. Typechecking comes later.
234 */
235 status = acpi_ns_search_node (target_name, parent_node,
236 ACPI_TYPE_ANY, return_node);
237 if (ACPI_SUCCESS (status)) {
238 return_ACPI_STATUS (status);
239 }
240
241 /*
242 * Not found here, go up another level
243 * (until we reach the root)
244 */
245 parent_node = acpi_ns_get_parent_node (parent_node);
246 }
247
248 /* Not found in parent tree */
249
250 return_ACPI_STATUS (AE_NOT_FOUND);
251}
252
253
254/*******************************************************************************
255 *
256 * FUNCTION: acpi_ns_search_and_enter
257 *
258 * PARAMETERS: target_name - Ascii ACPI name to search for (4 chars)
259 * walk_state - Current state of the walk
260 * *Node - Starting node where search will begin
261 * interpreter_mode - Add names only in ACPI_MODE_LOAD_PASS_x.
262 * Otherwise,search only.
263 * Type - Object type to match
264 * Flags - Flags describing the search restrictions
265 * **return_node - Where the Node is returned
266 *
267 * RETURN: Status
268 *
269 * DESCRIPTION: Search for a name segment in a single namespace level,
270 * optionally adding it if it is not found. If the passed
271 * Type is not Any and the type previously stored in the
272 * entry was Any (i.e. unknown), update the stored type.
273 *
274 * In ACPI_IMODE_EXECUTE, search only.
275 * In other modes, search and add if not found.
276 *
277 ******************************************************************************/
278
279acpi_status
280acpi_ns_search_and_enter (
281 u32 target_name,
282 struct acpi_walk_state *walk_state,
283 struct acpi_namespace_node *node,
284 acpi_interpreter_mode interpreter_mode,
285 acpi_object_type type,
286 u32 flags,
287 struct acpi_namespace_node **return_node)
288{
289 acpi_status status;
290 struct acpi_namespace_node *new_node;
291
292
293 ACPI_FUNCTION_TRACE ("ns_search_and_enter");
294
295
296 /* Parameter validation */
297
298 if (!node || !target_name || !return_node) {
299 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
300 "Null param: Node %p Name %X return_node %p\n",
301 node, target_name, return_node));
302
303 ACPI_REPORT_ERROR (("ns_search_and_enter: Null parameter\n"));
304 return_ACPI_STATUS (AE_BAD_PARAMETER);
305 }
306
307 /* Name must consist of printable characters */
308
309 if (!acpi_ut_valid_acpi_name (target_name)) {
310 ACPI_REPORT_ERROR (("ns_search_and_enter: Bad character in ACPI Name: %X\n",
311 target_name));
312 return_ACPI_STATUS (AE_BAD_CHARACTER);
313 }
314
315 /* Try to find the name in the namespace level specified by the caller */
316
317 *return_node = ACPI_ENTRY_NOT_FOUND;
318 status = acpi_ns_search_node (target_name, node, type, return_node);
319 if (status != AE_NOT_FOUND) {
320 /*
321 * If we found it AND the request specifies that a find is an error,
322 * return the error
323 */
324 if ((status == AE_OK) &&
325 (flags & ACPI_NS_ERROR_IF_FOUND)) {
326 status = AE_ALREADY_EXISTS;
327 }
328
329 /*
330 * Either found it or there was an error
331 * -- finished either way
332 */
333 return_ACPI_STATUS (status);
334 }
335
336 /*
337 * The name was not found. If we are NOT performing the first pass
338 * (name entry) of loading the namespace, search the parent tree (all the
339 * way to the root if necessary.) We don't want to perform the parent
340 * search when the namespace is actually being loaded. We want to perform
341 * the search when namespace references are being resolved (load pass 2)
342 * and during the execution phase.
343 */
344 if ((interpreter_mode != ACPI_IMODE_LOAD_PASS1) &&
345 (flags & ACPI_NS_SEARCH_PARENT)) {
346 /*
347 * Not found at this level - search parent tree according to the
348 * ACPI specification
349 */
350 status = acpi_ns_search_parent_tree (target_name, node, type, return_node);
351 if (ACPI_SUCCESS (status)) {
352 return_ACPI_STATUS (status);
353 }
354 }
355
356 /*
357 * In execute mode, just search, never add names. Exit now.
358 */
359 if (interpreter_mode == ACPI_IMODE_EXECUTE) {
360 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
361 "%4.4s Not found in %p [Not adding]\n",
362 (char *) &target_name, node));
363
364 return_ACPI_STATUS (AE_NOT_FOUND);
365 }
366
367 /* Create the new named object */
368
369 new_node = acpi_ns_create_node (target_name);
370 if (!new_node) {
371 return_ACPI_STATUS (AE_NO_MEMORY);
372 }
373
374 /* Install the new object into the parent's list of children */
375
376 acpi_ns_install_node (walk_state, node, new_node, type);
377 *return_node = new_node;
378
379 return_ACPI_STATUS (AE_OK);
380}
381
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
new file mode 100644
index 000000000000..75da76cc0b19
--- /dev/null
+++ b/drivers/acpi/namespace/nsutils.c
@@ -0,0 +1,1069 @@
1/******************************************************************************
2 *
3 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
4 * parents and siblings and Scope manipulation
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45
46#include <acpi/acpi.h>
47#include <acpi/acnamesp.h>
48#include <acpi/amlcode.h>
49#include <acpi/actables.h>
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsutils")
53
54
55/*******************************************************************************
56 *
57 * FUNCTION: acpi_ns_report_error
58 *
59 * PARAMETERS: module_name - Caller's module name (for error output)
60 * line_number - Caller's line number (for error output)
61 * component_id - Caller's component ID (for error output)
62 * Message - Error message to use on failure
63 *
64 * RETURN: None
65 *
66 * DESCRIPTION: Print warning message with full pathname
67 *
68 ******************************************************************************/
69
70void
71acpi_ns_report_error (
72 char *module_name,
73 u32 line_number,
74 u32 component_id,
75 char *internal_name,
76 acpi_status lookup_status)
77{
78 acpi_status status;
79 char *name = NULL;
80
81
82 acpi_os_printf ("%8s-%04d: *** Error: Looking up ",
83 module_name, line_number);
84
85 if (lookup_status == AE_BAD_CHARACTER) {
86 /* There is a non-ascii character in the name */
87
88 acpi_os_printf ("[0x%4.4X] (NON-ASCII)\n",
89 *(ACPI_CAST_PTR (u32, internal_name)));
90 }
91 else {
92 /* Convert path to external format */
93
94 status = acpi_ns_externalize_name (ACPI_UINT32_MAX,
95 internal_name, NULL, &name);
96
97 /* Print target name */
98
99 if (ACPI_SUCCESS (status)) {
100 acpi_os_printf ("[%s]", name);
101 }
102 else {
103 acpi_os_printf ("[COULD NOT EXTERNALIZE NAME]");
104 }
105
106 if (name) {
107 ACPI_MEM_FREE (name);
108 }
109 }
110
111 acpi_os_printf (" in namespace, %s\n",
112 acpi_format_exception (lookup_status));
113}
114
115
116/*******************************************************************************
117 *
118 * FUNCTION: acpi_ns_report_method_error
119 *
120 * PARAMETERS: module_name - Caller's module name (for error output)
121 * line_number - Caller's line number (for error output)
122 * component_id - Caller's component ID (for error output)
123 * Message - Error message to use on failure
124 *
125 * RETURN: None
126 *
127 * DESCRIPTION: Print warning message with full pathname
128 *
129 ******************************************************************************/
130
131void
132acpi_ns_report_method_error (
133 char *module_name,
134 u32 line_number,
135 u32 component_id,
136 char *message,
137 struct acpi_namespace_node *prefix_node,
138 char *path,
139 acpi_status method_status)
140{
141 acpi_status status;
142 struct acpi_namespace_node *node = prefix_node;
143
144
145 if (path) {
146 status = acpi_ns_get_node_by_path (path, prefix_node,
147 ACPI_NS_NO_UPSEARCH, &node);
148 if (ACPI_FAILURE (status)) {
149 acpi_os_printf ("report_method_error: Could not get node\n");
150 return;
151 }
152 }
153
154 acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
155 acpi_ns_print_node_pathname (node, message);
156 acpi_os_printf (", %s\n", acpi_format_exception (method_status));
157}
158
159
160/*******************************************************************************
161 *
162 * FUNCTION: acpi_ns_print_node_pathname
163 *
164 * PARAMETERS: Node - Object
165 * Msg - Prefix message
166 *
167 * DESCRIPTION: Print an object's full namespace pathname
168 * Manages allocation/freeing of a pathname buffer
169 *
170 ******************************************************************************/
171
172void
173acpi_ns_print_node_pathname (
174 struct acpi_namespace_node *node,
175 char *msg)
176{
177 struct acpi_buffer buffer;
178 acpi_status status;
179
180
181 if (!node) {
182 acpi_os_printf ("[NULL NAME]");
183 return;
184 }
185
186 /* Convert handle to full pathname and print it (with supplied message) */
187
188 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
189
190 status = acpi_ns_handle_to_pathname (node, &buffer);
191 if (ACPI_SUCCESS (status)) {
192 if (msg) {
193 acpi_os_printf ("%s ", msg);
194 }
195
196 acpi_os_printf ("[%s] (Node %p)", (char *) buffer.pointer, node);
197 ACPI_MEM_FREE (buffer.pointer);
198 }
199}
200
201
202/*******************************************************************************
203 *
204 * FUNCTION: acpi_ns_valid_root_prefix
205 *
206 * PARAMETERS: Prefix - Character to be checked
207 *
208 * RETURN: TRUE if a valid prefix
209 *
210 * DESCRIPTION: Check if a character is a valid ACPI Root prefix
211 *
212 ******************************************************************************/
213
214u8
215acpi_ns_valid_root_prefix (
216 char prefix)
217{
218
219 return ((u8) (prefix == '\\'));
220}
221
222
223/*******************************************************************************
224 *
225 * FUNCTION: acpi_ns_valid_path_separator
226 *
227 * PARAMETERS: Sep - Character to be checked
228 *
229 * RETURN: TRUE if a valid path separator
230 *
231 * DESCRIPTION: Check if a character is a valid ACPI path separator
232 *
233 ******************************************************************************/
234
235u8
236acpi_ns_valid_path_separator (
237 char sep)
238{
239
240 return ((u8) (sep == '.'));
241}
242
243
244/*******************************************************************************
245 *
246 * FUNCTION: acpi_ns_get_type
247 *
248 * PARAMETERS: Handle - Parent Node to be examined
249 *
250 * RETURN: Type field from Node whose handle is passed
251 *
252 ******************************************************************************/
253
254acpi_object_type
255acpi_ns_get_type (
256 struct acpi_namespace_node *node)
257{
258 ACPI_FUNCTION_TRACE ("ns_get_type");
259
260
261 if (!node) {
262 ACPI_REPORT_WARNING (("ns_get_type: Null Node input pointer\n"));
263 return_VALUE (ACPI_TYPE_ANY);
264 }
265
266 return_VALUE ((acpi_object_type) node->type);
267}
268
269
270/*******************************************************************************
271 *
272 * FUNCTION: acpi_ns_local
273 *
274 * PARAMETERS: Type - A namespace object type
275 *
276 * RETURN: LOCAL if names must be found locally in objects of the
277 * passed type, 0 if enclosing scopes should be searched
278 *
279 ******************************************************************************/
280
281u32
282acpi_ns_local (
283 acpi_object_type type)
284{
285 ACPI_FUNCTION_TRACE ("ns_local");
286
287
288 if (!acpi_ut_valid_object_type (type)) {
289 /* Type code out of range */
290
291 ACPI_REPORT_WARNING (("ns_local: Invalid Object Type\n"));
292 return_VALUE (ACPI_NS_NORMAL);
293 }
294
295 return_VALUE ((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
296}
297
298
299/*******************************************************************************
300 *
301 * FUNCTION: acpi_ns_get_internal_name_length
302 *
303 * PARAMETERS: Info - Info struct initialized with the
304 * external name pointer.
305 *
306 * RETURN: Status
307 *
308 * DESCRIPTION: Calculate the length of the internal (AML) namestring
309 * corresponding to the external (ASL) namestring.
310 *
311 ******************************************************************************/
312
313void
314acpi_ns_get_internal_name_length (
315 struct acpi_namestring_info *info)
316{
317 char *next_external_char;
318 u32 i;
319
320
321 ACPI_FUNCTION_ENTRY ();
322
323
324 next_external_char = info->external_name;
325 info->num_carats = 0;
326 info->num_segments = 0;
327 info->fully_qualified = FALSE;
328
329 /*
330 * For the internal name, the required length is 4 bytes per segment, plus
331 * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null
332 * (which is not really needed, but no there's harm in putting it there)
333 *
334 * strlen() + 1 covers the first name_seg, which has no path separator
335 */
336 if (acpi_ns_valid_root_prefix (next_external_char[0])) {
337 info->fully_qualified = TRUE;
338 next_external_char++;
339 }
340 else {
341 /*
342 * Handle Carat prefixes
343 */
344 while (*next_external_char == '^') {
345 info->num_carats++;
346 next_external_char++;
347 }
348 }
349
350 /*
351 * Determine the number of ACPI name "segments" by counting the number of
352 * path separators within the string. Start with one segment since the
353 * segment count is [(# separators) + 1], and zero separators is ok.
354 */
355 if (*next_external_char) {
356 info->num_segments = 1;
357 for (i = 0; next_external_char[i]; i++) {
358 if (acpi_ns_valid_path_separator (next_external_char[i])) {
359 info->num_segments++;
360 }
361 }
362 }
363
364 info->length = (ACPI_NAME_SIZE * info->num_segments) +
365 4 + info->num_carats;
366
367 info->next_external_char = next_external_char;
368}
369
370
371/*******************************************************************************
372 *
373 * FUNCTION: acpi_ns_build_internal_name
374 *
375 * PARAMETERS: Info - Info struct fully initialized
376 *
377 * RETURN: Status
378 *
379 * DESCRIPTION: Construct the internal (AML) namestring
380 * corresponding to the external (ASL) namestring.
381 *
382 ******************************************************************************/
383
384acpi_status
385acpi_ns_build_internal_name (
386 struct acpi_namestring_info *info)
387{
388 u32 num_segments = info->num_segments;
389 char *internal_name = info->internal_name;
390 char *external_name = info->next_external_char;
391 char *result = NULL;
392 acpi_native_uint i;
393
394
395 ACPI_FUNCTION_TRACE ("ns_build_internal_name");
396
397
398 /* Setup the correct prefixes, counts, and pointers */
399
400 if (info->fully_qualified) {
401 internal_name[0] = '\\';
402
403 if (num_segments <= 1) {
404 result = &internal_name[1];
405 }
406 else if (num_segments == 2) {
407 internal_name[1] = AML_DUAL_NAME_PREFIX;
408 result = &internal_name[2];
409 }
410 else {
411 internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
412 internal_name[2] = (char) num_segments;
413 result = &internal_name[3];
414 }
415 }
416 else {
417 /*
418 * Not fully qualified.
419 * Handle Carats first, then append the name segments
420 */
421 i = 0;
422 if (info->num_carats) {
423 for (i = 0; i < info->num_carats; i++) {
424 internal_name[i] = '^';
425 }
426 }
427
428 if (num_segments <= 1) {
429 result = &internal_name[i];
430 }
431 else if (num_segments == 2) {
432 internal_name[i] = AML_DUAL_NAME_PREFIX;
433 result = &internal_name[(acpi_native_uint) (i+1)];
434 }
435 else {
436 internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
437 internal_name[(acpi_native_uint) (i+1)] = (char) num_segments;
438 result = &internal_name[(acpi_native_uint) (i+2)];
439 }
440 }
441
442 /* Build the name (minus path separators) */
443
444 for (; num_segments; num_segments--) {
445 for (i = 0; i < ACPI_NAME_SIZE; i++) {
446 if (acpi_ns_valid_path_separator (*external_name) ||
447 (*external_name == 0)) {
448 /* Pad the segment with underscore(s) if segment is short */
449
450 result[i] = '_';
451 }
452 else {
453 /* Convert the character to uppercase and save it */
454
455 result[i] = (char) ACPI_TOUPPER ((int) *external_name);
456 external_name++;
457 }
458 }
459
460 /* Now we must have a path separator, or the pathname is bad */
461
462 if (!acpi_ns_valid_path_separator (*external_name) &&
463 (*external_name != 0)) {
464 return_ACPI_STATUS (AE_BAD_PARAMETER);
465 }
466
467 /* Move on the next segment */
468
469 external_name++;
470 result += ACPI_NAME_SIZE;
471 }
472
473 /* Terminate the string */
474
475 *result = 0;
476
477 if (info->fully_qualified) {
478 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (abs) \"\\%s\"\n",
479 internal_name, internal_name));
480 }
481 else {
482 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
483 internal_name, internal_name));
484 }
485
486 return_ACPI_STATUS (AE_OK);
487}
488
489
490/*******************************************************************************
491 *
492 * FUNCTION: acpi_ns_internalize_name
493 *
494 * PARAMETERS: *external_name - External representation of name
495 * **Converted Name - Where to return the resulting
496 * internal represention of the name
497 *
498 * RETURN: Status
499 *
500 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
501 * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
502 *
503 *******************************************************************************/
504
505acpi_status
506acpi_ns_internalize_name (
507 char *external_name,
508 char **converted_name)
509{
510 char *internal_name;
511 struct acpi_namestring_info info;
512 acpi_status status;
513
514
515 ACPI_FUNCTION_TRACE ("ns_internalize_name");
516
517
518 if ((!external_name) ||
519 (*external_name == 0) ||
520 (!converted_name)) {
521 return_ACPI_STATUS (AE_BAD_PARAMETER);
522 }
523
524 /* Get the length of the new internal name */
525
526 info.external_name = external_name;
527 acpi_ns_get_internal_name_length (&info);
528
529 /* We need a segment to store the internal name */
530
531 internal_name = ACPI_MEM_CALLOCATE (info.length);
532 if (!internal_name) {
533 return_ACPI_STATUS (AE_NO_MEMORY);
534 }
535
536 /* Build the name */
537
538 info.internal_name = internal_name;
539 status = acpi_ns_build_internal_name (&info);
540 if (ACPI_FAILURE (status)) {
541 ACPI_MEM_FREE (internal_name);
542 return_ACPI_STATUS (status);
543 }
544
545 *converted_name = internal_name;
546 return_ACPI_STATUS (AE_OK);
547}
548
549
550/*******************************************************************************
551 *
552 * FUNCTION: acpi_ns_externalize_name
553 *
554 * PARAMETERS: *internal_name - Internal representation of name
555 * **converted_name - Where to return the resulting
556 * external representation of name
557 *
558 * RETURN: Status
559 *
560 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
561 * to its external form (e.g. "\_PR_.CPU0")
562 *
563 ******************************************************************************/
564
565acpi_status
566acpi_ns_externalize_name (
567 u32 internal_name_length,
568 char *internal_name,
569 u32 *converted_name_length,
570 char **converted_name)
571{
572 acpi_native_uint names_index = 0;
573 acpi_native_uint num_segments = 0;
574 acpi_native_uint required_length;
575 acpi_native_uint prefix_length = 0;
576 acpi_native_uint i = 0;
577 acpi_native_uint j = 0;
578
579
580 ACPI_FUNCTION_TRACE ("ns_externalize_name");
581
582
583 if (!internal_name_length ||
584 !internal_name ||
585 !converted_name) {
586 return_ACPI_STATUS (AE_BAD_PARAMETER);
587 }
588
589 /*
590 * Check for a prefix (one '\' | one or more '^').
591 */
592 switch (internal_name[0]) {
593 case '\\':
594 prefix_length = 1;
595 break;
596
597 case '^':
598 for (i = 0; i < internal_name_length; i++) {
599 if (internal_name[i] == '^') {
600 prefix_length = i + 1;
601 }
602 else {
603 break;
604 }
605 }
606
607 if (i == internal_name_length) {
608 prefix_length = i;
609 }
610
611 break;
612
613 default:
614 break;
615 }
616
617 /*
618 * Check for object names. Note that there could be 0-255 of these
619 * 4-byte elements.
620 */
621 if (prefix_length < internal_name_length) {
622 switch (internal_name[prefix_length]) {
623 case AML_MULTI_NAME_PREFIX_OP:
624
625 /* <count> 4-byte names */
626
627 names_index = prefix_length + 2;
628 num_segments = (acpi_native_uint) (u8)
629 internal_name[(acpi_native_uint) (prefix_length + 1)];
630 break;
631
632 case AML_DUAL_NAME_PREFIX:
633
634 /* Two 4-byte names */
635
636 names_index = prefix_length + 1;
637 num_segments = 2;
638 break;
639
640 case 0:
641
642 /* null_name */
643
644 names_index = 0;
645 num_segments = 0;
646 break;
647
648 default:
649
650 /* one 4-byte name */
651
652 names_index = prefix_length;
653 num_segments = 1;
654 break;
655 }
656 }
657
658 /*
659 * Calculate the length of converted_name, which equals the length
660 * of the prefix, length of all object names, length of any required
661 * punctuation ('.') between object names, plus the NULL terminator.
662 */
663 required_length = prefix_length + (4 * num_segments) +
664 ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
665
666 /*
667 * Check to see if we're still in bounds. If not, there's a problem
668 * with internal_name (invalid format).
669 */
670 if (required_length > internal_name_length) {
671 ACPI_REPORT_ERROR (("ns_externalize_name: Invalid internal name\n"));
672 return_ACPI_STATUS (AE_BAD_PATHNAME);
673 }
674
675 /*
676 * Build converted_name
677 */
678 *converted_name = ACPI_MEM_CALLOCATE (required_length);
679 if (!(*converted_name)) {
680 return_ACPI_STATUS (AE_NO_MEMORY);
681 }
682
683 j = 0;
684
685 for (i = 0; i < prefix_length; i++) {
686 (*converted_name)[j++] = internal_name[i];
687 }
688
689 if (num_segments > 0) {
690 for (i = 0; i < num_segments; i++) {
691 if (i > 0) {
692 (*converted_name)[j++] = '.';
693 }
694
695 (*converted_name)[j++] = internal_name[names_index++];
696 (*converted_name)[j++] = internal_name[names_index++];
697 (*converted_name)[j++] = internal_name[names_index++];
698 (*converted_name)[j++] = internal_name[names_index++];
699 }
700 }
701
702 if (converted_name_length) {
703 *converted_name_length = (u32) required_length;
704 }
705
706 return_ACPI_STATUS (AE_OK);
707}
708
709
710/*******************************************************************************
711 *
712 * FUNCTION: acpi_ns_map_handle_to_node
713 *
714 * PARAMETERS: Handle - Handle to be converted to an Node
715 *
716 * RETURN: A Name table entry pointer
717 *
718 * DESCRIPTION: Convert a namespace handle to a real Node
719 *
720 * Note: Real integer handles allow for more verification
721 * and keep all pointers within this subsystem.
722 *
723 ******************************************************************************/
724
725struct acpi_namespace_node *
726acpi_ns_map_handle_to_node (
727 acpi_handle handle)
728{
729
730 ACPI_FUNCTION_ENTRY ();
731
732
733 /*
734 * Simple implementation.
735 */
736 if (!handle) {
737 return (NULL);
738 }
739
740 if (handle == ACPI_ROOT_OBJECT) {
741 return (acpi_gbl_root_node);
742 }
743
744 /* We can at least attempt to verify the handle */
745
746 if (ACPI_GET_DESCRIPTOR_TYPE (handle) != ACPI_DESC_TYPE_NAMED) {
747 return (NULL);
748 }
749
750 return ((struct acpi_namespace_node *) handle);
751}
752
753
754/*******************************************************************************
755 *
756 * FUNCTION: acpi_ns_convert_entry_to_handle
757 *
758 * PARAMETERS: Node - Node to be converted to a Handle
759 *
760 * RETURN: A user handle
761 *
762 * DESCRIPTION: Convert a real Node to a namespace handle
763 *
764 ******************************************************************************/
765
766acpi_handle
767acpi_ns_convert_entry_to_handle (
768 struct acpi_namespace_node *node)
769{
770
771
772 /*
773 * Simple implementation for now;
774 */
775 return ((acpi_handle) node);
776
777
778/* ---------------------------------------------------
779
780 if (!Node)
781 {
782 return (NULL);
783 }
784
785 if (Node == acpi_gbl_root_node)
786 {
787 return (ACPI_ROOT_OBJECT);
788 }
789
790
791 return ((acpi_handle) Node);
792------------------------------------------------------*/
793}
794
795
796/*******************************************************************************
797 *
798 * FUNCTION: acpi_ns_terminate
799 *
800 * PARAMETERS: none
801 *
802 * RETURN: none
803 *
804 * DESCRIPTION: free memory allocated for table storage.
805 *
806 ******************************************************************************/
807
808void
809acpi_ns_terminate (void)
810{
811 union acpi_operand_object *obj_desc;
812
813
814 ACPI_FUNCTION_TRACE ("ns_terminate");
815
816
817 /*
818 * 1) Free the entire namespace -- all nodes and objects
819 *
820 * Delete all object descriptors attached to namepsace nodes
821 */
822 acpi_ns_delete_namespace_subtree (acpi_gbl_root_node);
823
824 /* Detach any objects attached to the root */
825
826 obj_desc = acpi_ns_get_attached_object (acpi_gbl_root_node);
827 if (obj_desc) {
828 acpi_ns_detach_object (acpi_gbl_root_node);
829 }
830
831 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n"));
832
833 /*
834 * 2) Now we can delete the ACPI tables
835 */
836 acpi_tb_delete_all_tables ();
837 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
838
839 return_VOID;
840}
841
842
843/*******************************************************************************
844 *
845 * FUNCTION: acpi_ns_opens_scope
846 *
847 * PARAMETERS: Type - A valid namespace type
848 *
849 * RETURN: NEWSCOPE if the passed type "opens a name scope" according
850 * to the ACPI specification, else 0
851 *
852 ******************************************************************************/
853
854u32
855acpi_ns_opens_scope (
856 acpi_object_type type)
857{
858 ACPI_FUNCTION_TRACE_STR ("ns_opens_scope", acpi_ut_get_type_name (type));
859
860
861 if (!acpi_ut_valid_object_type (type)) {
862 /* type code out of range */
863
864 ACPI_REPORT_WARNING (("ns_opens_scope: Invalid Object Type %X\n", type));
865 return_VALUE (ACPI_NS_NORMAL);
866 }
867
868 return_VALUE (((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
869}
870
871
872/*******************************************************************************
873 *
874 * FUNCTION: acpi_ns_get_node_by_path
875 *
876 * PARAMETERS: *Pathname - Name to be found, in external (ASL) format. The
877 * \ (backslash) and ^ (carat) prefixes, and the
878 * . (period) to separate segments are supported.
879 * start_node - Root of subtree to be searched, or NS_ALL for the
880 * root of the name space. If Name is fully
881 * qualified (first s8 is '\'), the passed value
882 * of Scope will not be accessed.
883 * Flags - Used to indicate whether to perform upsearch or
884 * not.
885 * return_node - Where the Node is returned
886 *
887 * DESCRIPTION: Look up a name relative to a given scope and return the
888 * corresponding Node. NOTE: Scope can be null.
889 *
890 * MUTEX: Locks namespace
891 *
892 ******************************************************************************/
893
894acpi_status
895acpi_ns_get_node_by_path (
896 char *pathname,
897 struct acpi_namespace_node *start_node,
898 u32 flags,
899 struct acpi_namespace_node **return_node)
900{
901 union acpi_generic_state scope_info;
902 acpi_status status;
903 char *internal_path = NULL;
904
905
906 ACPI_FUNCTION_TRACE_PTR ("ns_get_node_by_path", pathname);
907
908
909 if (pathname) {
910 /* Convert path to internal representation */
911
912 status = acpi_ns_internalize_name (pathname, &internal_path);
913 if (ACPI_FAILURE (status)) {
914 return_ACPI_STATUS (status);
915 }
916 }
917
918 /* Must lock namespace during lookup */
919
920 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
921 if (ACPI_FAILURE (status)) {
922 goto cleanup;
923 }
924
925 /* Setup lookup scope (search starting point) */
926
927 scope_info.scope.node = start_node;
928
929 /* Lookup the name in the namespace */
930
931 status = acpi_ns_lookup (&scope_info, internal_path,
932 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
933 (flags | ACPI_NS_DONT_OPEN_SCOPE),
934 NULL, return_node);
935 if (ACPI_FAILURE (status)) {
936 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s, %s\n",
937 internal_path, acpi_format_exception (status)));
938 }
939
940 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
941
942cleanup:
943 /* Cleanup */
944 if (internal_path) {
945 ACPI_MEM_FREE (internal_path);
946 }
947 return_ACPI_STATUS (status);
948}
949
950
951/*******************************************************************************
952 *
953 * FUNCTION: acpi_ns_find_parent_name
954 *
955 * PARAMETERS: *child_node - Named Obj whose name is to be found
956 *
957 * RETURN: The ACPI name
958 *
959 * DESCRIPTION: Search for the given obj in its parent scope and return the
960 * name segment, or "????" if the parent name can't be found
961 * (which "should not happen").
962 *
963 ******************************************************************************/
964#ifdef ACPI_FUTURE_USAGE
965acpi_name
966acpi_ns_find_parent_name (
967 struct acpi_namespace_node *child_node)
968{
969 struct acpi_namespace_node *parent_node;
970
971
972 ACPI_FUNCTION_TRACE ("ns_find_parent_name");
973
974
975 if (child_node) {
976 /* Valid entry. Get the parent Node */
977
978 parent_node = acpi_ns_get_parent_node (child_node);
979 if (parent_node) {
980 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
981 "Parent of %p [%4.4s] is %p [%4.4s]\n",
982 child_node, acpi_ut_get_node_name (child_node),
983 parent_node, acpi_ut_get_node_name (parent_node)));
984
985 if (parent_node->name.integer) {
986 return_VALUE ((acpi_name) parent_node->name.integer);
987 }
988 }
989
990 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
991 "Unable to find parent of %p (%4.4s)\n",
992 child_node, acpi_ut_get_node_name (child_node)));
993 }
994
995 return_VALUE (ACPI_UNKNOWN_NAME);
996}
997#endif
998
999
1000/*******************************************************************************
1001 *
1002 * FUNCTION: acpi_ns_get_parent_node
1003 *
1004 * PARAMETERS: Node - Current table entry
1005 *
1006 * RETURN: Parent entry of the given entry
1007 *
1008 * DESCRIPTION: Obtain the parent entry for a given entry in the namespace.
1009 *
1010 ******************************************************************************/
1011
1012
1013struct acpi_namespace_node *
1014acpi_ns_get_parent_node (
1015 struct acpi_namespace_node *node)
1016{
1017 ACPI_FUNCTION_ENTRY ();
1018
1019
1020 if (!node) {
1021 return (NULL);
1022 }
1023
1024 /*
1025 * Walk to the end of this peer list. The last entry is marked with a flag
1026 * and the peer pointer is really a pointer back to the parent. This saves
1027 * putting a parent back pointer in each and every named object!
1028 */
1029 while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) {
1030 node = node->peer;
1031 }
1032
1033
1034 return (node->peer);
1035}
1036
1037
1038/*******************************************************************************
1039 *
1040 * FUNCTION: acpi_ns_get_next_valid_node
1041 *
1042 * PARAMETERS: Node - Current table entry
1043 *
1044 * RETURN: Next valid Node in the linked node list. NULL if no more valid
1045 * nodes.
1046 *
1047 * DESCRIPTION: Find the next valid node within a name table.
1048 * Useful for implementing NULL-end-of-list loops.
1049 *
1050 ******************************************************************************/
1051
1052
1053struct acpi_namespace_node *
1054acpi_ns_get_next_valid_node (
1055 struct acpi_namespace_node *node)
1056{
1057
1058 /* If we are at the end of this peer list, return NULL */
1059
1060 if (node->flags & ANOBJ_END_OF_PEER_LIST) {
1061 return NULL;
1062 }
1063
1064 /* Otherwise just return the next peer */
1065
1066 return (node->peer);
1067}
1068
1069
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
new file mode 100644
index 000000000000..4de2444df300
--- /dev/null
+++ b/drivers/acpi/namespace/nswalk.c
@@ -0,0 +1,289 @@
1/******************************************************************************
2 *
3 * Module Name: nswalk - Functions for walking the ACPI namespace
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47
48
49#define _COMPONENT ACPI_NAMESPACE
50 ACPI_MODULE_NAME ("nswalk")
51
52
53/*******************************************************************************
54 *
55 * FUNCTION: acpi_ns_get_next_node
56 *
57 * PARAMETERS: Type - Type of node to be searched for
58 * parent_node - Parent node whose children we are
59 * getting
60 * child_node - Previous child that was found.
61 * The NEXT child will be returned
62 *
63 * RETURN: struct acpi_namespace_node - Pointer to the NEXT child or NULL if
64 * none is found.
65 *
66 * DESCRIPTION: Return the next peer node within the namespace. If Handle
67 * is valid, Scope is ignored. Otherwise, the first node
68 * within Scope is returned.
69 *
70 ******************************************************************************/
71
72struct acpi_namespace_node *
73acpi_ns_get_next_node (
74 acpi_object_type type,
75 struct acpi_namespace_node *parent_node,
76 struct acpi_namespace_node *child_node)
77{
78 struct acpi_namespace_node *next_node = NULL;
79
80
81 ACPI_FUNCTION_ENTRY ();
82
83
84 if (!child_node) {
85 /* It's really the parent's _scope_ that we want */
86
87 if (parent_node->child) {
88 next_node = parent_node->child;
89 }
90 }
91
92 else {
93 /* Start search at the NEXT node */
94
95 next_node = acpi_ns_get_next_valid_node (child_node);
96 }
97
98 /* If any type is OK, we are done */
99
100 if (type == ACPI_TYPE_ANY) {
101 /* next_node is NULL if we are at the end-of-list */
102
103 return (next_node);
104 }
105
106 /* Must search for the node -- but within this scope only */
107
108 while (next_node) {
109 /* If type matches, we are done */
110
111 if (next_node->type == type) {
112 return (next_node);
113 }
114
115 /* Otherwise, move on to the next node */
116
117 next_node = acpi_ns_get_next_valid_node (next_node);
118 }
119
120 /* Not found */
121
122 return (NULL);
123}
124
125
126/*******************************************************************************
127 *
128 * FUNCTION: acpi_ns_walk_namespace
129 *
130 * PARAMETERS: Type - acpi_object_type to search for
131 * start_node - Handle in namespace where search begins
132 * max_depth - Depth to which search is to reach
133 * unlock_before_callback- Whether to unlock the NS before invoking
134 * the callback routine
135 * user_function - Called when an object of "Type" is found
136 * Context - Passed to user function
137 * return_value - from the user_function if terminated early.
138 * Otherwise, returns NULL.
139 * RETURNS: Status
140 *
141 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
142 * starting (and ending) at the node specified by start_handle.
143 * The user_function is called whenever a node that matches
144 * the type parameter is found. If the user function returns
145 * a non-zero value, the search is terminated immediately and this
146 * value is returned to the caller.
147 *
148 * The point of this procedure is to provide a generic namespace
149 * walk routine that can be called from multiple places to
150 * provide multiple services; the User Function can be tailored
151 * to each task, whether it is a print function, a compare
152 * function, etc.
153 *
154 ******************************************************************************/
155
156acpi_status
157acpi_ns_walk_namespace (
158 acpi_object_type type,
159 acpi_handle start_node,
160 u32 max_depth,
161 u8 unlock_before_callback,
162 acpi_walk_callback user_function,
163 void *context,
164 void **return_value)
165{
166 acpi_status status;
167 acpi_status mutex_status;
168 struct acpi_namespace_node *child_node;
169 struct acpi_namespace_node *parent_node;
170 acpi_object_type child_type;
171 u32 level;
172
173
174 ACPI_FUNCTION_TRACE ("ns_walk_namespace");
175
176
177 /* Special case for the namespace Root Node */
178
179 if (start_node == ACPI_ROOT_OBJECT) {
180 start_node = acpi_gbl_root_node;
181 }
182
183 /* Null child means "get first node" */
184
185 parent_node = start_node;
186 child_node = NULL;
187 child_type = ACPI_TYPE_ANY;
188 level = 1;
189
190 /*
191 * Traverse the tree of nodes until we bubble back up to where we
192 * started. When Level is zero, the loop is done because we have
193 * bubbled up to (and passed) the original parent handle (start_entry)
194 */
195 while (level > 0) {
196 /* Get the next node in this scope. Null if not found */
197
198 status = AE_OK;
199 child_node = acpi_ns_get_next_node (ACPI_TYPE_ANY, parent_node, child_node);
200 if (child_node) {
201 /*
202 * Found node, Get the type if we are not
203 * searching for ANY
204 */
205 if (type != ACPI_TYPE_ANY) {
206 child_type = child_node->type;
207 }
208
209 if (child_type == type) {
210 /*
211 * Found a matching node, invoke the user
212 * callback function
213 */
214 if (unlock_before_callback) {
215 mutex_status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
216 if (ACPI_FAILURE (mutex_status)) {
217 return_ACPI_STATUS (mutex_status);
218 }
219 }
220
221 status = user_function (child_node, level,
222 context, return_value);
223
224 if (unlock_before_callback) {
225 mutex_status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
226 if (ACPI_FAILURE (mutex_status)) {
227 return_ACPI_STATUS (mutex_status);
228 }
229 }
230
231 switch (status) {
232 case AE_OK:
233 case AE_CTRL_DEPTH:
234
235 /* Just keep going */
236 break;
237
238 case AE_CTRL_TERMINATE:
239
240 /* Exit now, with OK status */
241
242 return_ACPI_STATUS (AE_OK);
243
244 default:
245
246 /* All others are valid exceptions */
247
248 return_ACPI_STATUS (status);
249 }
250 }
251
252 /*
253 * Depth first search:
254 * Attempt to go down another level in the namespace
255 * if we are allowed to. Don't go any further if we
256 * have reached the caller specified maximum depth
257 * or if the user function has specified that the
258 * maximum depth has been reached.
259 */
260 if ((level < max_depth) && (status != AE_CTRL_DEPTH)) {
261 if (acpi_ns_get_next_node (ACPI_TYPE_ANY, child_node, NULL)) {
262 /*
263 * There is at least one child of this
264 * node, visit the onde
265 */
266 level++;
267 parent_node = child_node;
268 child_node = NULL;
269 }
270 }
271 }
272 else {
273 /*
274 * No more children of this node (acpi_ns_get_next_node
275 * failed), go back upwards in the namespace tree to
276 * the node's parent.
277 */
278 level--;
279 child_node = parent_node;
280 parent_node = acpi_ns_get_parent_node (parent_node);
281 }
282 }
283
284 /* Complete walk, not terminated by user function */
285
286 return_ACPI_STATUS (AE_OK);
287}
288
289
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
new file mode 100644
index 000000000000..1dc995586cbe
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -0,0 +1,764 @@
1/*******************************************************************************
2 *
3 * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4 * ACPI Object evaluation interfaces
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48#include <acpi/acnamesp.h>
49#include <acpi/acinterp.h>
50
51
52#define _COMPONENT ACPI_NAMESPACE
53 ACPI_MODULE_NAME ("nsxfeval")
54
55
56/*******************************************************************************
57 *
58 * FUNCTION: acpi_evaluate_object_typed
59 *
60 * PARAMETERS: Handle - Object handle (optional)
61 * *Pathname - Object pathname (optional)
62 * **external_params - List of parameters to pass to method,
63 * terminated by NULL. May be NULL
64 * if no parameters are being passed.
65 * *return_buffer - Where to put method's return value (if
66 * any). If NULL, no value is returned.
67 * return_type - Expected type of return object
68 *
69 * RETURN: Status
70 *
71 * DESCRIPTION: Find and evaluate the given object, passing the given
72 * parameters if necessary. One of "Handle" or "Pathname" must
73 * be valid (non-null)
74 *
75 ******************************************************************************/
76#ifdef ACPI_FUTURE_USAGE
77acpi_status
78acpi_evaluate_object_typed (
79 acpi_handle handle,
80 acpi_string pathname,
81 struct acpi_object_list *external_params,
82 struct acpi_buffer *return_buffer,
83 acpi_object_type return_type)
84{
85 acpi_status status;
86 u8 must_free = FALSE;
87
88
89 ACPI_FUNCTION_TRACE ("acpi_evaluate_object_typed");
90
91
92 /* Return buffer must be valid */
93
94 if (!return_buffer) {
95 return_ACPI_STATUS (AE_BAD_PARAMETER);
96 }
97
98 if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
99 must_free = TRUE;
100 }
101
102 /* Evaluate the object */
103
104 status = acpi_evaluate_object (handle, pathname, external_params, return_buffer);
105 if (ACPI_FAILURE (status)) {
106 return_ACPI_STATUS (status);
107 }
108
109 /* Type ANY means "don't care" */
110
111 if (return_type == ACPI_TYPE_ANY) {
112 return_ACPI_STATUS (AE_OK);
113 }
114
115 if (return_buffer->length == 0) {
116 /* Error because caller specifically asked for a return value */
117
118 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
119 "No return value\n"));
120
121 return_ACPI_STATUS (AE_NULL_OBJECT);
122 }
123
124 /* Examine the object type returned from evaluate_object */
125
126 if (((union acpi_object *) return_buffer->pointer)->type == return_type) {
127 return_ACPI_STATUS (AE_OK);
128 }
129
130 /* Return object type does not match requested type */
131
132 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
133 "Incorrect return type [%s] requested [%s]\n",
134 acpi_ut_get_type_name (((union acpi_object *) return_buffer->pointer)->type),
135 acpi_ut_get_type_name (return_type)));
136
137 if (must_free) {
138 /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
139
140 acpi_os_free (return_buffer->pointer);
141 return_buffer->pointer = NULL;
142 }
143
144 return_buffer->length = 0;
145 return_ACPI_STATUS (AE_TYPE);
146}
147#endif /* ACPI_FUTURE_USAGE */
148
149
150/*******************************************************************************
151 *
152 * FUNCTION: acpi_evaluate_object
153 *
154 * PARAMETERS: Handle - Object handle (optional)
155 * Pathname - Object pathname (optional)
156 * external_params - List of parameters to pass to method,
157 * terminated by NULL. May be NULL
158 * if no parameters are being passed.
159 * return_buffer - Where to put method's return value (if
160 * any). If NULL, no value is returned.
161 *
162 * RETURN: Status
163 *
164 * DESCRIPTION: Find and evaluate the given object, passing the given
165 * parameters if necessary. One of "Handle" or "Pathname" must
166 * be valid (non-null)
167 *
168 ******************************************************************************/
169
170acpi_status
171acpi_evaluate_object (
172 acpi_handle handle,
173 acpi_string pathname,
174 struct acpi_object_list *external_params,
175 struct acpi_buffer *return_buffer)
176{
177 acpi_status status;
178 acpi_status status2;
179 struct acpi_parameter_info info;
180 acpi_size buffer_space_needed;
181 u32 i;
182
183
184 ACPI_FUNCTION_TRACE ("acpi_evaluate_object");
185
186
187 info.node = handle;
188 info.parameters = NULL;
189 info.return_object = NULL;
190 info.parameter_type = ACPI_PARAM_ARGS;
191
192 /*
193 * If there are parameters to be passed to the object
194 * (which must be a control method), the external objects
195 * must be converted to internal objects
196 */
197 if (external_params && external_params->count) {
198 /*
199 * Allocate a new parameter block for the internal objects
200 * Add 1 to count to allow for null terminated internal list
201 */
202 info.parameters = ACPI_MEM_CALLOCATE (
203 ((acpi_size) external_params->count + 1) *
204 sizeof (void *));
205 if (!info.parameters) {
206 return_ACPI_STATUS (AE_NO_MEMORY);
207 }
208
209 /*
210 * Convert each external object in the list to an
211 * internal object
212 */
213 for (i = 0; i < external_params->count; i++) {
214 status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i],
215 &info.parameters[i]);
216 if (ACPI_FAILURE (status)) {
217 acpi_ut_delete_internal_object_list (info.parameters);
218 return_ACPI_STATUS (status);
219 }
220 }
221 info.parameters[external_params->count] = NULL;
222 }
223
224
225 /*
226 * Three major cases:
227 * 1) Fully qualified pathname
228 * 2) No handle, not fully qualified pathname (error)
229 * 3) Valid handle
230 */
231 if ((pathname) &&
232 (acpi_ns_valid_root_prefix (pathname[0]))) {
233 /*
234 * The path is fully qualified, just evaluate by name
235 */
236 status = acpi_ns_evaluate_by_name (pathname, &info);
237 }
238 else if (!handle) {
239 /*
240 * A handle is optional iff a fully qualified pathname
241 * is specified. Since we've already handled fully
242 * qualified names above, this is an error
243 */
244 if (!pathname) {
245 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
246 "Both Handle and Pathname are NULL\n"));
247 }
248 else {
249 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
250 "Handle is NULL and Pathname is relative\n"));
251 }
252
253 status = AE_BAD_PARAMETER;
254 }
255 else {
256 /*
257 * We get here if we have a handle -- and if we have a
258 * pathname it is relative. The handle will be validated
259 * in the lower procedures
260 */
261 if (!pathname) {
262 /*
263 * The null pathname case means the handle is for
264 * the actual object to be evaluated
265 */
266 status = acpi_ns_evaluate_by_handle (&info);
267 }
268 else {
269 /*
270 * Both a Handle and a relative Pathname
271 */
272 status = acpi_ns_evaluate_relative (pathname, &info);
273 }
274 }
275
276
277 /*
278 * If we are expecting a return value, and all went well above,
279 * copy the return value to an external object.
280 */
281 if (return_buffer) {
282 if (!info.return_object) {
283 return_buffer->length = 0;
284 }
285 else {
286 if (ACPI_GET_DESCRIPTOR_TYPE (info.return_object) == ACPI_DESC_TYPE_NAMED) {
287 /*
288 * If we received a NS Node as a return object, this means that
289 * the object we are evaluating has nothing interesting to
290 * return (such as a mutex, etc.) We return an error because
291 * these types are essentially unsupported by this interface.
292 * We don't check up front because this makes it easier to add
293 * support for various types at a later date if necessary.
294 */
295 status = AE_TYPE;
296 info.return_object = NULL; /* No need to delete a NS Node */
297 return_buffer->length = 0;
298 }
299
300 if (ACPI_SUCCESS (status)) {
301 /*
302 * Find out how large a buffer is needed
303 * to contain the returned object
304 */
305 status = acpi_ut_get_object_size (info.return_object,
306 &buffer_space_needed);
307 if (ACPI_SUCCESS (status)) {
308 /* Validate/Allocate/Clear caller buffer */
309
310 status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed);
311 if (ACPI_FAILURE (status)) {
312 /*
313 * Caller's buffer is too small or a new one can't be allocated
314 */
315 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
316 "Needed buffer size %X, %s\n",
317 (u32) buffer_space_needed,
318 acpi_format_exception (status)));
319 }
320 else {
321 /*
322 * We have enough space for the object, build it
323 */
324 status = acpi_ut_copy_iobject_to_eobject (info.return_object,
325 return_buffer);
326 }
327 }
328 }
329 }
330 }
331
332 if (info.return_object) {
333 /*
334 * Delete the internal return object. NOTE: Interpreter
335 * must be locked to avoid race condition.
336 */
337 status2 = acpi_ex_enter_interpreter ();
338 if (ACPI_SUCCESS (status2)) {
339 /*
340 * Delete the internal return object. (Or at least
341 * decrement the reference count by one)
342 */
343 acpi_ut_remove_reference (info.return_object);
344 acpi_ex_exit_interpreter ();
345 }
346 }
347
348 /*
349 * Free the input parameter list (if we created one),
350 */
351 if (info.parameters) {
352 /* Free the allocated parameter block */
353
354 acpi_ut_delete_internal_object_list (info.parameters);
355 }
356
357 return_ACPI_STATUS (status);
358}
359EXPORT_SYMBOL(acpi_evaluate_object);
360
361
362/*******************************************************************************
363 *
364 * FUNCTION: acpi_walk_namespace
365 *
366 * PARAMETERS: Type - acpi_object_type to search for
367 * start_object - Handle in namespace where search begins
368 * max_depth - Depth to which search is to reach
369 * user_function - Called when an object of "Type" is found
370 * Context - Passed to user function
371 * return_value - Location where return value of
372 * user_function is put if terminated early
373 *
374 * RETURNS Return value from the user_function if terminated early.
375 * Otherwise, returns NULL.
376 *
377 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
378 * starting (and ending) at the object specified by start_handle.
379 * The user_function is called whenever an object that matches
380 * the type parameter is found. If the user function returns
381 * a non-zero value, the search is terminated immediately and this
382 * value is returned to the caller.
383 *
384 * The point of this procedure is to provide a generic namespace
385 * walk routine that can be called from multiple places to
386 * provide multiple services; the User Function can be tailored
387 * to each task, whether it is a print function, a compare
388 * function, etc.
389 *
390 ******************************************************************************/
391
392acpi_status
393acpi_walk_namespace (
394 acpi_object_type type,
395 acpi_handle start_object,
396 u32 max_depth,
397 acpi_walk_callback user_function,
398 void *context,
399 void **return_value)
400{
401 acpi_status status;
402
403
404 ACPI_FUNCTION_TRACE ("acpi_walk_namespace");
405
406
407 /* Parameter validation */
408
409 if ((type > ACPI_TYPE_EXTERNAL_MAX) ||
410 (!max_depth) ||
411 (!user_function)) {
412 return_ACPI_STATUS (AE_BAD_PARAMETER);
413 }
414
415 /*
416 * Lock the namespace around the walk.
417 * The namespace will be unlocked/locked around each call
418 * to the user function - since this function
419 * must be allowed to make Acpi calls itself.
420 */
421 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
422 if (ACPI_FAILURE (status)) {
423 return_ACPI_STATUS (status);
424 }
425
426 status = acpi_ns_walk_namespace (type, start_object, max_depth, ACPI_NS_WALK_UNLOCK,
427 user_function, context, return_value);
428
429 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
430 return_ACPI_STATUS (status);
431}
432EXPORT_SYMBOL(acpi_walk_namespace);
433
434
435/*******************************************************************************
436 *
437 * FUNCTION: acpi_ns_get_device_callback
438 *
439 * PARAMETERS: Callback from acpi_get_device
440 *
441 * RETURN: Status
442 *
443 * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
444 * present devices, or if they specified a HID, it filters based
445 * on that.
446 *
447 ******************************************************************************/
448
449static acpi_status
450acpi_ns_get_device_callback (
451 acpi_handle obj_handle,
452 u32 nesting_level,
453 void *context,
454 void **return_value)
455{
456 struct acpi_get_devices_info *info = context;
457 acpi_status status;
458 struct acpi_namespace_node *node;
459 u32 flags;
460 struct acpi_device_id hid;
461 struct acpi_compatible_id_list *cid;
462 acpi_native_uint i;
463
464
465 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
466 if (ACPI_FAILURE (status)) {
467 return (status);
468 }
469
470 node = acpi_ns_map_handle_to_node (obj_handle);
471 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
472 if (ACPI_FAILURE (status)) {
473 return (status);
474 }
475
476 if (!node) {
477 return (AE_BAD_PARAMETER);
478 }
479
480 /* Run _STA to determine if device is present */
481
482 status = acpi_ut_execute_STA (node, &flags);
483 if (ACPI_FAILURE (status)) {
484 return (AE_CTRL_DEPTH);
485 }
486
487 if (!(flags & 0x01)) {
488 /* Don't return at the device or children of the device if not there */
489
490 return (AE_CTRL_DEPTH);
491 }
492
493 /* Filter based on device HID & CID */
494
495 if (info->hid != NULL) {
496 status = acpi_ut_execute_HID (node, &hid);
497 if (status == AE_NOT_FOUND) {
498 return (AE_OK);
499 }
500 else if (ACPI_FAILURE (status)) {
501 return (AE_CTRL_DEPTH);
502 }
503
504 if (ACPI_STRNCMP (hid.value, info->hid, sizeof (hid.value)) != 0) {
505 /* Get the list of Compatible IDs */
506
507 status = acpi_ut_execute_CID (node, &cid);
508 if (status == AE_NOT_FOUND) {
509 return (AE_OK);
510 }
511 else if (ACPI_FAILURE (status)) {
512 return (AE_CTRL_DEPTH);
513 }
514
515 /* Walk the CID list */
516
517 for (i = 0; i < cid->count; i++) {
518 if (ACPI_STRNCMP (cid->id[i].value, info->hid,
519 sizeof (struct acpi_compatible_id)) != 0) {
520 ACPI_MEM_FREE (cid);
521 return (AE_OK);
522 }
523 }
524 ACPI_MEM_FREE (cid);
525 }
526 }
527
528 status = info->user_function (obj_handle, nesting_level, info->context, return_value);
529 return (status);
530}
531
532
533/*******************************************************************************
534 *
535 * FUNCTION: acpi_get_devices
536 *
537 * PARAMETERS: HID - HID to search for. Can be NULL.
538 * user_function - Called when a matching object is found
539 * Context - Passed to user function
540 * return_value - Location where return value of
541 * user_function is put if terminated early
542 *
543 * RETURNS Return value from the user_function if terminated early.
544 * Otherwise, returns NULL.
545 *
546 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
547 * starting (and ending) at the object specified by start_handle.
548 * The user_function is called whenever an object of type
549 * Device is found. If the user function returns
550 * a non-zero value, the search is terminated immediately and this
551 * value is returned to the caller.
552 *
553 * This is a wrapper for walk_namespace, but the callback performs
554 * additional filtering. Please see acpi_get_device_callback.
555 *
556 ******************************************************************************/
557
558acpi_status
559acpi_get_devices (
560 char *HID,
561 acpi_walk_callback user_function,
562 void *context,
563 void **return_value)
564{
565 acpi_status status;
566 struct acpi_get_devices_info info;
567
568
569 ACPI_FUNCTION_TRACE ("acpi_get_devices");
570
571
572 /* Parameter validation */
573
574 if (!user_function) {
575 return_ACPI_STATUS (AE_BAD_PARAMETER);
576 }
577
578 /*
579 * We're going to call their callback from OUR callback, so we need
580 * to know what it is, and their context parameter.
581 */
582 info.context = context;
583 info.user_function = user_function;
584 info.hid = HID;
585
586 /*
587 * Lock the namespace around the walk.
588 * The namespace will be unlocked/locked around each call
589 * to the user function - since this function
590 * must be allowed to make Acpi calls itself.
591 */
592 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
593 if (ACPI_FAILURE (status)) {
594 return_ACPI_STATUS (status);
595 }
596
597 status = acpi_ns_walk_namespace (ACPI_TYPE_DEVICE,
598 ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
599 ACPI_NS_WALK_UNLOCK,
600 acpi_ns_get_device_callback, &info,
601 return_value);
602
603 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
604 return_ACPI_STATUS (status);
605}
606EXPORT_SYMBOL(acpi_get_devices);
607
608
609/*******************************************************************************
610 *
611 * FUNCTION: acpi_attach_data
612 *
613 * PARAMETERS: obj_handle - Namespace node
614 * Handler - Handler for this attachment
615 * Data - Pointer to data to be attached
616 *
617 * RETURN: Status
618 *
619 * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
620 *
621 ******************************************************************************/
622
623acpi_status
624acpi_attach_data (
625 acpi_handle obj_handle,
626 acpi_object_handler handler,
627 void *data)
628{
629 struct acpi_namespace_node *node;
630 acpi_status status;
631
632
633 /* Parameter validation */
634
635 if (!obj_handle ||
636 !handler ||
637 !data) {
638 return (AE_BAD_PARAMETER);
639 }
640
641 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
642 if (ACPI_FAILURE (status)) {
643 return (status);
644 }
645
646 /* Convert and validate the handle */
647
648 node = acpi_ns_map_handle_to_node (obj_handle);
649 if (!node) {
650 status = AE_BAD_PARAMETER;
651 goto unlock_and_exit;
652 }
653
654 status = acpi_ns_attach_data (node, handler, data);
655
656unlock_and_exit:
657 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
658 return (status);
659}
660
661
662/*******************************************************************************
663 *
664 * FUNCTION: acpi_detach_data
665 *
666 * PARAMETERS: obj_handle - Namespace node handle
667 * Handler - Handler used in call to acpi_attach_data
668 *
669 * RETURN: Status
670 *
671 * DESCRIPTION: Remove data that was previously attached to a node.
672 *
673 ******************************************************************************/
674
675acpi_status
676acpi_detach_data (
677 acpi_handle obj_handle,
678 acpi_object_handler handler)
679{
680 struct acpi_namespace_node *node;
681 acpi_status status;
682
683
684 /* Parameter validation */
685
686 if (!obj_handle ||
687 !handler) {
688 return (AE_BAD_PARAMETER);
689 }
690
691 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
692 if (ACPI_FAILURE (status)) {
693 return (status);
694 }
695
696 /* Convert and validate the handle */
697
698 node = acpi_ns_map_handle_to_node (obj_handle);
699 if (!node) {
700 status = AE_BAD_PARAMETER;
701 goto unlock_and_exit;
702 }
703
704 status = acpi_ns_detach_data (node, handler);
705
706unlock_and_exit:
707 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
708 return (status);
709}
710
711
712/*******************************************************************************
713 *
714 * FUNCTION: acpi_get_data
715 *
716 * PARAMETERS: obj_handle - Namespace node
717 * Handler - Handler used in call to attach_data
718 * Data - Where the data is returned
719 *
720 * RETURN: Status
721 *
722 * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
723 *
724 ******************************************************************************/
725
726acpi_status
727acpi_get_data (
728 acpi_handle obj_handle,
729 acpi_object_handler handler,
730 void **data)
731{
732 struct acpi_namespace_node *node;
733 acpi_status status;
734
735
736 /* Parameter validation */
737
738 if (!obj_handle ||
739 !handler ||
740 !data) {
741 return (AE_BAD_PARAMETER);
742 }
743
744 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
745 if (ACPI_FAILURE (status)) {
746 return (status);
747 }
748
749 /* Convert and validate the handle */
750
751 node = acpi_ns_map_handle_to_node (obj_handle);
752 if (!node) {
753 status = AE_BAD_PARAMETER;
754 goto unlock_and_exit;
755 }
756
757 status = acpi_ns_get_attached_data (node, handler, data);
758
759unlock_and_exit:
760 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
761 return (status);
762}
763
764
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
new file mode 100644
index 000000000000..f2405efd1b9a
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -0,0 +1,369 @@
1/******************************************************************************
2 *
3 * Module Name: nsxfname - Public interfaces to the ACPI subsystem
4 * ACPI Namespace oriented interfaces
5 *
6 *****************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48#include <acpi/acnamesp.h>
49
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsxfname")
53
54
55/******************************************************************************
56 *
57 * FUNCTION: acpi_get_handle
58 *
59 * PARAMETERS: Parent - Object to search under (search scope).
60 * path_name - Pointer to an asciiz string containing the
61 * name
62 * ret_handle - Where the return handle is placed
63 *
64 * RETURN: Status
65 *
66 * DESCRIPTION: This routine will search for a caller specified name in the
67 * name space. The caller can restrict the search region by
68 * specifying a non NULL parent. The parent value is itself a
69 * namespace handle.
70 *
71 ******************************************************************************/
72
73acpi_status
74acpi_get_handle (
75 acpi_handle parent,
76 acpi_string pathname,
77 acpi_handle *ret_handle)
78{
79 acpi_status status;
80 struct acpi_namespace_node *node = NULL;
81 struct acpi_namespace_node *prefix_node = NULL;
82
83
84 ACPI_FUNCTION_ENTRY ();
85
86
87 /* Parameter Validation */
88
89 if (!ret_handle || !pathname) {
90 return (AE_BAD_PARAMETER);
91 }
92
93 /* Convert a parent handle to a prefix node */
94
95 if (parent) {
96 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
97 if (ACPI_FAILURE (status)) {
98 return (status);
99 }
100
101 prefix_node = acpi_ns_map_handle_to_node (parent);
102 if (!prefix_node) {
103 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
104 return (AE_BAD_PARAMETER);
105 }
106
107 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
108 if (ACPI_FAILURE (status)) {
109 return (status);
110 }
111 }
112
113 /* Special case for root, since we can't search for it */
114
115 if (ACPI_STRCMP (pathname, ACPI_NS_ROOT_PATH) == 0) {
116 *ret_handle = acpi_ns_convert_entry_to_handle (acpi_gbl_root_node);
117 return (AE_OK);
118 }
119
120 /*
121 * Find the Node and convert to a handle
122 */
123 status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH,
124 &node);
125
126 *ret_handle = NULL;
127 if (ACPI_SUCCESS (status)) {
128 *ret_handle = acpi_ns_convert_entry_to_handle (node);
129 }
130
131 return (status);
132}
133EXPORT_SYMBOL(acpi_get_handle);
134
135
136/******************************************************************************
137 *
138 * FUNCTION: acpi_get_name
139 *
140 * PARAMETERS: Handle - Handle to be converted to a pathname
141 * name_type - Full pathname or single segment
142 * Buffer - Buffer for returned path
143 *
144 * RETURN: Pointer to a string containing the fully qualified Name.
145 *
146 * DESCRIPTION: This routine returns the fully qualified name associated with
147 * the Handle parameter. This and the acpi_pathname_to_handle are
148 * complementary functions.
149 *
150 ******************************************************************************/
151
152acpi_status
153acpi_get_name (
154 acpi_handle handle,
155 u32 name_type,
156 struct acpi_buffer *buffer)
157{
158 acpi_status status;
159 struct acpi_namespace_node *node;
160
161
162 /* Parameter validation */
163
164 if (name_type > ACPI_NAME_TYPE_MAX) {
165 return (AE_BAD_PARAMETER);
166 }
167
168 status = acpi_ut_validate_buffer (buffer);
169 if (ACPI_FAILURE (status)) {
170 return (status);
171 }
172
173 if (name_type == ACPI_FULL_PATHNAME) {
174 /* Get the full pathname (From the namespace root) */
175
176 status = acpi_ns_handle_to_pathname (handle, buffer);
177 return (status);
178 }
179
180 /*
181 * Wants the single segment ACPI name.
182 * Validate handle and convert to a namespace Node
183 */
184 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
185 if (ACPI_FAILURE (status)) {
186 return (status);
187 }
188
189 node = acpi_ns_map_handle_to_node (handle);
190 if (!node) {
191 status = AE_BAD_PARAMETER;
192 goto unlock_and_exit;
193 }
194
195 /* Validate/Allocate/Clear caller buffer */
196
197 status = acpi_ut_initialize_buffer (buffer, ACPI_PATH_SEGMENT_LENGTH);
198 if (ACPI_FAILURE (status)) {
199 goto unlock_and_exit;
200 }
201
202 /* Just copy the ACPI name from the Node and zero terminate it */
203
204 ACPI_STRNCPY (buffer->pointer, acpi_ut_get_node_name (node),
205 ACPI_NAME_SIZE);
206 ((char *) buffer->pointer) [ACPI_NAME_SIZE] = 0;
207 status = AE_OK;
208
209
210unlock_and_exit:
211
212 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
213 return (status);
214}
215EXPORT_SYMBOL(acpi_get_name);
216
217
218/******************************************************************************
219 *
220 * FUNCTION: acpi_get_object_info
221 *
222 * PARAMETERS: Handle - Object Handle
223 * Info - Where the info is returned
224 *
225 * RETURN: Status
226 *
227 * DESCRIPTION: Returns information about an object as gleaned from the
228 * namespace node and possibly by running several standard
229 * control methods (Such as in the case of a device.)
230 *
231 ******************************************************************************/
232
233acpi_status
234acpi_get_object_info (
235 acpi_handle handle,
236 struct acpi_buffer *buffer)
237{
238 acpi_status status;
239 struct acpi_namespace_node *node;
240 struct acpi_device_info *info;
241 struct acpi_device_info *return_info;
242 struct acpi_compatible_id_list *cid_list = NULL;
243 acpi_size size;
244
245
246 /* Parameter validation */
247
248 if (!handle || !buffer) {
249 return (AE_BAD_PARAMETER);
250 }
251
252 status = acpi_ut_validate_buffer (buffer);
253 if (ACPI_FAILURE (status)) {
254 return (status);
255 }
256
257 info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_device_info));
258 if (!info) {
259 return (AE_NO_MEMORY);
260 }
261
262 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
263 if (ACPI_FAILURE (status)) {
264 goto cleanup;
265 }
266
267 node = acpi_ns_map_handle_to_node (handle);
268 if (!node) {
269 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
270 goto cleanup;
271 }
272
273 /* Init return structure */
274
275 size = sizeof (struct acpi_device_info);
276
277 info->type = node->type;
278 info->name = node->name.integer;
279 info->valid = 0;
280
281 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
282 if (ACPI_FAILURE (status)) {
283 goto cleanup;
284 }
285
286 /* If not a device, we are all done */
287
288 if (info->type == ACPI_TYPE_DEVICE) {
289 /*
290 * Get extra info for ACPI Devices objects only:
291 * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
292 *
293 * Note: none of these methods are required, so they may or may
294 * not be present for this device. The Info->Valid bitfield is used
295 * to indicate which methods were found and ran successfully.
296 */
297
298 /* Execute the Device._HID method */
299
300 status = acpi_ut_execute_HID (node, &info->hardware_id);
301 if (ACPI_SUCCESS (status)) {
302 info->valid |= ACPI_VALID_HID;
303 }
304
305 /* Execute the Device._UID method */
306
307 status = acpi_ut_execute_UID (node, &info->unique_id);
308 if (ACPI_SUCCESS (status)) {
309 info->valid |= ACPI_VALID_UID;
310 }
311
312 /* Execute the Device._CID method */
313
314 status = acpi_ut_execute_CID (node, &cid_list);
315 if (ACPI_SUCCESS (status)) {
316 size += ((acpi_size) cid_list->count - 1) *
317 sizeof (struct acpi_compatible_id);
318 info->valid |= ACPI_VALID_CID;
319 }
320
321 /* Execute the Device._STA method */
322
323 status = acpi_ut_execute_STA (node, &info->current_status);
324 if (ACPI_SUCCESS (status)) {
325 info->valid |= ACPI_VALID_STA;
326 }
327
328 /* Execute the Device._ADR method */
329
330 status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node,
331 &info->address);
332 if (ACPI_SUCCESS (status)) {
333 info->valid |= ACPI_VALID_ADR;
334 }
335
336 /* Execute the Device._sx_d methods */
337
338 status = acpi_ut_execute_sxds (node, info->highest_dstates);
339 if (ACPI_SUCCESS (status)) {
340 info->valid |= ACPI_VALID_SXDS;
341 }
342 }
343
344 /* Validate/Allocate/Clear caller buffer */
345
346 status = acpi_ut_initialize_buffer (buffer, size);
347 if (ACPI_FAILURE (status)) {
348 goto cleanup;
349 }
350
351 /* Populate the return buffer */
352
353 return_info = buffer->pointer;
354 ACPI_MEMCPY (return_info, info, sizeof (struct acpi_device_info));
355
356 if (cid_list) {
357 ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size);
358 }
359
360
361cleanup:
362 ACPI_MEM_FREE (info);
363 if (cid_list) {
364 ACPI_MEM_FREE (cid_list);
365 }
366 return (status);
367}
368EXPORT_SYMBOL(acpi_get_object_info);
369
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
new file mode 100644
index 000000000000..19acf32674b9
--- /dev/null
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -0,0 +1,262 @@
1/*******************************************************************************
2 *
3 * Module Name: nsxfobj - Public interfaces to the ACPI subsystem
4 * ACPI Object oriented interfaces
5 *
6 ******************************************************************************/
7
8/*
9 * Copyright (C) 2000 - 2005, R. Byron Moore
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer,
17 * without modification.
18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 * substantially similar to the "NO WARRANTY" disclaimer below
20 * ("Disclaimer") and any redistribution must be conditioned upon
21 * including a substantially similar Disclaimer requirement for further
22 * binary redistribution.
23 * 3. Neither the names of the above-listed copyright holders nor the names
24 * of any contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * Alternatively, this software may be distributed under the terms of the
28 * GNU General Public License ("GPL") version 2 as published by the Free
29 * Software Foundation.
30 *
31 * NO WARRANTY
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 * POSSIBILITY OF SUCH DAMAGES.
43 */
44
45#include <linux/module.h>
46
47#include <acpi/acpi.h>
48#include <acpi/acnamesp.h>
49
50
51#define _COMPONENT ACPI_NAMESPACE
52 ACPI_MODULE_NAME ("nsxfobj")
53
54/*******************************************************************************
55 *
56 * FUNCTION: acpi_get_type
57 *
58 * PARAMETERS: Handle - Handle of object whose type is desired
59 * *ret_type - Where the type will be placed
60 *
61 * RETURN: Status
62 *
63 * DESCRIPTION: This routine returns the type associatd with a particular handle
64 *
65 ******************************************************************************/
66
67acpi_status
68acpi_get_type (
69 acpi_handle handle,
70 acpi_object_type *ret_type)
71{
72 struct acpi_namespace_node *node;
73 acpi_status status;
74
75
76 /* Parameter Validation */
77
78 if (!ret_type) {
79 return (AE_BAD_PARAMETER);
80 }
81
82 /*
83 * Special case for the predefined Root Node
84 * (return type ANY)
85 */
86 if (handle == ACPI_ROOT_OBJECT) {
87 *ret_type = ACPI_TYPE_ANY;
88 return (AE_OK);
89 }
90
91 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
92 if (ACPI_FAILURE (status)) {
93 return (status);
94 }
95
96 /* Convert and validate the handle */
97
98 node = acpi_ns_map_handle_to_node (handle);
99 if (!node) {
100 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
101 return (AE_BAD_PARAMETER);
102 }
103
104 *ret_type = node->type;
105
106
107 status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
108 return (status);
109}
110EXPORT_SYMBOL(acpi_get_type);
111
112
113/*******************************************************************************
114 *
115 * FUNCTION: acpi_get_parent
116 *
117 * PARAMETERS: Handle - Handle of object whose parent is desired
118 * ret_handle - Where the parent handle will be placed
119 *
120 * RETURN: Status
121 *
122 * DESCRIPTION: Returns a handle to the parent of the object represented by
123 * Handle.
124 *
125 ******************************************************************************/
126
127acpi_status
128acpi_get_parent (
129 acpi_handle handle,
130 acpi_handle *ret_handle)
131{
132 struct acpi_namespace_node *node;
133 acpi_status status;
134
135
136 if (!ret_handle) {
137 return (AE_BAD_PARAMETER);
138 }
139
140 /* Special case for the predefined Root Node (no parent) */
141
142 if (handle == ACPI_ROOT_OBJECT) {
143 return (AE_NULL_ENTRY);
144 }
145
146 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
147 if (ACPI_FAILURE (status)) {
148 return (status);
149 }
150
151 /* Convert and validate the handle */
152
153 node = acpi_ns_map_handle_to_node (handle);
154 if (!node) {
155 status = AE_BAD_PARAMETER;
156 goto unlock_and_exit;
157 }
158
159 /* Get the parent entry */
160
161 *ret_handle =
162 acpi_ns_convert_entry_to_handle (acpi_ns_get_parent_node (node));
163
164 /* Return exception if parent is null */
165
166 if (!acpi_ns_get_parent_node (node)) {
167 status = AE_NULL_ENTRY;
168 }
169
170
171unlock_and_exit:
172
173 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
174 return (status);
175}
176EXPORT_SYMBOL(acpi_get_parent);
177
178
179/*******************************************************************************
180 *
181 * FUNCTION: acpi_get_next_object
182 *
183 * PARAMETERS: Type - Type of object to be searched for
184 * Parent - Parent object whose children we are getting
185 * last_child - Previous child that was found.
186 * The NEXT child will be returned
187 * ret_handle - Where handle to the next object is placed
188 *
189 * RETURN: Status
190 *
191 * DESCRIPTION: Return the next peer object within the namespace. If Handle is
192 * valid, Scope is ignored. Otherwise, the first object within
193 * Scope is returned.
194 *
195 ******************************************************************************/
196
197acpi_status
198acpi_get_next_object (
199 acpi_object_type type,
200 acpi_handle parent,
201 acpi_handle child,
202 acpi_handle *ret_handle)
203{
204 acpi_status status;
205 struct acpi_namespace_node *node;
206 struct acpi_namespace_node *parent_node = NULL;
207 struct acpi_namespace_node *child_node = NULL;
208
209
210 /* Parameter validation */
211
212 if (type > ACPI_TYPE_EXTERNAL_MAX) {
213 return (AE_BAD_PARAMETER);
214 }
215
216 status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
217 if (ACPI_FAILURE (status)) {
218 return (status);
219 }
220
221 /* If null handle, use the parent */
222
223 if (!child) {
224 /* Start search at the beginning of the specified scope */
225
226 parent_node = acpi_ns_map_handle_to_node (parent);
227 if (!parent_node) {
228 status = AE_BAD_PARAMETER;
229 goto unlock_and_exit;
230 }
231 }
232 else {
233 /* Non-null handle, ignore the parent */
234 /* Convert and validate the handle */
235
236 child_node = acpi_ns_map_handle_to_node (child);
237 if (!child_node) {
238 status = AE_BAD_PARAMETER;
239 goto unlock_and_exit;
240 }
241 }
242
243 /* Internal function does the real work */
244
245 node = acpi_ns_get_next_node (type, parent_node, child_node);
246 if (!node) {
247 status = AE_NOT_FOUND;
248 goto unlock_and_exit;
249 }
250
251 if (ret_handle) {
252 *ret_handle = acpi_ns_convert_entry_to_handle (node);
253 }
254
255
256unlock_and_exit:
257
258 (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
259 return (status);
260}
261EXPORT_SYMBOL(acpi_get_next_object);
262