nsxfeval.c revision 1.1.1.3 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 - 2013, Intel Corp.
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 #define __NSXFEVAL_C__
47 #define EXPORT_ACPI_INTERFACES
48
49 #include "acpi.h"
50 #include "accommon.h"
51 #include "acnamesp.h"
52 #include "acinterp.h"
53
54
55 #define _COMPONENT ACPI_NAMESPACE
56 ACPI_MODULE_NAME ("nsxfeval")
57
58 /* Local prototypes */
59
60 static void
61 AcpiNsResolveReferences (
62 ACPI_EVALUATE_INFO *Info);
63
64
65 /*******************************************************************************
66 *
67 * FUNCTION: AcpiEvaluateObjectTyped
68 *
69 * PARAMETERS: Handle - Object handle (optional)
70 * Pathname - Object pathname (optional)
71 * ExternalParams - List of parameters to pass to method,
72 * terminated by NULL. May be NULL
73 * if no parameters are being passed.
74 * ReturnBuffer - Where to put method's return value (if
75 * any). If NULL, no value is returned.
76 * ReturnType - Expected type of return object
77 *
78 * RETURN: Status
79 *
80 * DESCRIPTION: Find and evaluate the given object, passing the given
81 * parameters if necessary. One of "Handle" or "Pathname" must
82 * be valid (non-null)
83 *
84 ******************************************************************************/
85
86 ACPI_STATUS
87 AcpiEvaluateObjectTyped (
88 ACPI_HANDLE Handle,
89 ACPI_STRING Pathname,
90 ACPI_OBJECT_LIST *ExternalParams,
91 ACPI_BUFFER *ReturnBuffer,
92 ACPI_OBJECT_TYPE ReturnType)
93 {
94 ACPI_STATUS Status;
95 BOOLEAN FreeBufferOnError = FALSE;
96
97
98 ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
99
100
101 /* Return buffer must be valid */
102
103 if (!ReturnBuffer)
104 {
105 return_ACPI_STATUS (AE_BAD_PARAMETER);
106 }
107
108 if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
109 {
110 FreeBufferOnError = TRUE;
111 }
112
113 /* Evaluate the object */
114
115 Status = AcpiEvaluateObject (Handle, Pathname,
116 ExternalParams, ReturnBuffer);
117 if (ACPI_FAILURE (Status))
118 {
119 return_ACPI_STATUS (Status);
120 }
121
122 /* Type ANY means "don't care" */
123
124 if (ReturnType == ACPI_TYPE_ANY)
125 {
126 return_ACPI_STATUS (AE_OK);
127 }
128
129 if (ReturnBuffer->Length == 0)
130 {
131 /* Error because caller specifically asked for a return value */
132
133 ACPI_ERROR ((AE_INFO, "No return value"));
134 return_ACPI_STATUS (AE_NULL_OBJECT);
135 }
136
137 /* Examine the object type returned from EvaluateObject */
138
139 if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
140 {
141 return_ACPI_STATUS (AE_OK);
142 }
143
144 /* Return object type does not match requested type */
145
146 ACPI_ERROR ((AE_INFO,
147 "Incorrect return type [%s] requested [%s]",
148 AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
149 AcpiUtGetTypeName (ReturnType)));
150
151 if (FreeBufferOnError)
152 {
153 /*
154 * Free a buffer created via ACPI_ALLOCATE_BUFFER.
155 * Note: We use AcpiOsFree here because AcpiOsAllocate was used
156 * to allocate the buffer. This purposefully bypasses the
157 * (optionally enabled) allocation tracking mechanism since we
158 * only want to track internal allocations.
159 */
160 AcpiOsFree (ReturnBuffer->Pointer);
161 ReturnBuffer->Pointer = NULL;
162 }
163
164 ReturnBuffer->Length = 0;
165 return_ACPI_STATUS (AE_TYPE);
166 }
167
168 ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
169
170
171 /*******************************************************************************
172 *
173 * FUNCTION: AcpiEvaluateObject
174 *
175 * PARAMETERS: Handle - Object handle (optional)
176 * Pathname - Object pathname (optional)
177 * ExternalParams - List of parameters to pass to method,
178 * terminated by NULL. May be NULL
179 * if no parameters are being passed.
180 * ReturnBuffer - Where to put method's return value (if
181 * any). If NULL, no value is returned.
182 *
183 * RETURN: Status
184 *
185 * DESCRIPTION: Find and evaluate the given object, passing the given
186 * parameters if necessary. One of "Handle" or "Pathname" must
187 * be valid (non-null)
188 *
189 ******************************************************************************/
190
191 ACPI_STATUS
192 AcpiEvaluateObject (
193 ACPI_HANDLE Handle,
194 ACPI_STRING Pathname,
195 ACPI_OBJECT_LIST *ExternalParams,
196 ACPI_BUFFER *ReturnBuffer)
197 {
198 ACPI_STATUS Status;
199 ACPI_EVALUATE_INFO *Info;
200 ACPI_SIZE BufferSpaceNeeded;
201 UINT32 i;
202
203
204 ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
205
206
207 /* Allocate and initialize the evaluation information block */
208
209 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
210 if (!Info)
211 {
212 return_ACPI_STATUS (AE_NO_MEMORY);
213 }
214
215 /* Convert and validate the device handle */
216
217 Info->PrefixNode = AcpiNsValidateHandle (Handle);
218 if (!Info->PrefixNode)
219 {
220 Status = AE_BAD_PARAMETER;
221 goto Cleanup;
222 }
223
224 /*
225 * Get the actual namespace node for the target object.
226 * Handles these cases:
227 *
228 * 1) Null node, valid pathname from root (absolute path)
229 * 2) Node and valid pathname (path relative to Node)
230 * 3) Node, Null pathname
231 */
232 if ((Pathname) &&
233 (ACPI_IS_ROOT_PREFIX (Pathname[0])))
234 {
235 /* The path is fully qualified, just evaluate by name */
236
237 Info->PrefixNode = NULL;
238 }
239 else if (!Handle)
240 {
241 /*
242 * A handle is optional iff a fully qualified pathname is specified.
243 * Since we've already handled fully qualified names above, this is
244 * an error.
245 */
246 if (!Pathname)
247 {
248 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
249 "Both Handle and Pathname are NULL"));
250 }
251 else
252 {
253 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
254 "Null Handle with relative pathname [%s]", Pathname));
255 }
256
257 Status = AE_BAD_PARAMETER;
258 goto Cleanup;
259 }
260
261 Info->RelativePathname = Pathname;
262
263 /*
264 * Convert all external objects passed as arguments to the
265 * internal version(s).
266 */
267 if (ExternalParams && ExternalParams->Count)
268 {
269 Info->ParamCount = (UINT16) ExternalParams->Count;
270
271 /* Warn on impossible argument count */
272
273 if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
274 {
275 ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
276 "Excess arguments (%u) - using only %u",
277 Info->ParamCount, ACPI_METHOD_NUM_ARGS));
278
279 Info->ParamCount = ACPI_METHOD_NUM_ARGS;
280 }
281
282 /*
283 * Allocate a new parameter block for the internal objects
284 * Add 1 to count to allow for null terminated internal list
285 */
286 Info->Parameters = ACPI_ALLOCATE_ZEROED (
287 ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
288 if (!Info->Parameters)
289 {
290 Status = AE_NO_MEMORY;
291 goto Cleanup;
292 }
293
294 /* Convert each external object in the list to an internal object */
295
296 for (i = 0; i < Info->ParamCount; i++)
297 {
298 Status = AcpiUtCopyEobjectToIobject (
299 &ExternalParams->Pointer[i], &Info->Parameters[i]);
300 if (ACPI_FAILURE (Status))
301 {
302 goto Cleanup;
303 }
304 }
305
306 Info->Parameters[Info->ParamCount] = NULL;
307 }
308
309
310 #if 0
311
312 /*
313 * Begin incoming argument count analysis. Check for too few args
314 * and too many args.
315 */
316
317 switch (AcpiNsGetType (Info->Node))
318 {
319 case ACPI_TYPE_METHOD:
320
321 /* Check incoming argument count against the method definition */
322
323 if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
324 {
325 ACPI_ERROR ((AE_INFO,
326 "Insufficient arguments (%u) - %u are required",
327 Info->ParamCount,
328 Info->ObjDesc->Method.ParamCount));
329
330 Status = AE_MISSING_ARGUMENTS;
331 goto Cleanup;
332 }
333
334 else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
335 {
336 ACPI_WARNING ((AE_INFO,
337 "Excess arguments (%u) - only %u are required",
338 Info->ParamCount,
339 Info->ObjDesc->Method.ParamCount));
340
341 /* Just pass the required number of arguments */
342
343 Info->ParamCount = Info->ObjDesc->Method.ParamCount;
344 }
345
346 /*
347 * Any incoming external objects to be passed as arguments to the
348 * method must be converted to internal objects
349 */
350 if (Info->ParamCount)
351 {
352 /*
353 * Allocate a new parameter block for the internal objects
354 * Add 1 to count to allow for null terminated internal list
355 */
356 Info->Parameters = ACPI_ALLOCATE_ZEROED (
357 ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
358 if (!Info->Parameters)
359 {
360 Status = AE_NO_MEMORY;
361 goto Cleanup;
362 }
363
364 /* Convert each external object in the list to an internal object */
365
366 for (i = 0; i < Info->ParamCount; i++)
367 {
368 Status = AcpiUtCopyEobjectToIobject (
369 &ExternalParams->Pointer[i], &Info->Parameters[i]);
370 if (ACPI_FAILURE (Status))
371 {
372 goto Cleanup;
373 }
374 }
375
376 Info->Parameters[Info->ParamCount] = NULL;
377 }
378 break;
379
380 default:
381
382 /* Warn if arguments passed to an object that is not a method */
383
384 if (Info->ParamCount)
385 {
386 ACPI_WARNING ((AE_INFO,
387 "%u arguments were passed to a non-method ACPI object",
388 Info->ParamCount));
389 }
390 break;
391 }
392
393 #endif
394
395
396 /* Now we can evaluate the object */
397
398 Status = AcpiNsEvaluate (Info);
399
400 /*
401 * If we are expecting a return value, and all went well above,
402 * copy the return value to an external object.
403 */
404 if (ReturnBuffer)
405 {
406 if (!Info->ReturnObject)
407 {
408 ReturnBuffer->Length = 0;
409 }
410 else
411 {
412 if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
413 ACPI_DESC_TYPE_NAMED)
414 {
415 /*
416 * If we received a NS Node as a return object, this means that
417 * the object we are evaluating has nothing interesting to
418 * return (such as a mutex, etc.) We return an error because
419 * these types are essentially unsupported by this interface.
420 * We don't check up front because this makes it easier to add
421 * support for various types at a later date if necessary.
422 */
423 Status = AE_TYPE;
424 Info->ReturnObject = NULL; /* No need to delete a NS Node */
425 ReturnBuffer->Length = 0;
426 }
427
428 if (ACPI_SUCCESS (Status))
429 {
430 /* Dereference Index and RefOf references */
431
432 AcpiNsResolveReferences (Info);
433
434 /* Get the size of the returned object */
435
436 Status = AcpiUtGetObjectSize (Info->ReturnObject,
437 &BufferSpaceNeeded);
438 if (ACPI_SUCCESS (Status))
439 {
440 /* Validate/Allocate/Clear caller buffer */
441
442 Status = AcpiUtInitializeBuffer (ReturnBuffer,
443 BufferSpaceNeeded);
444 if (ACPI_FAILURE (Status))
445 {
446 /*
447 * Caller's buffer is too small or a new one can't
448 * be allocated
449 */
450 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
451 "Needed buffer size %X, %s\n",
452 (UINT32) BufferSpaceNeeded,
453 AcpiFormatException (Status)));
454 }
455 else
456 {
457 /* We have enough space for the object, build it */
458
459 Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
460 ReturnBuffer);
461 }
462 }
463 }
464 }
465 }
466
467 if (Info->ReturnObject)
468 {
469 /*
470 * Delete the internal return object. NOTE: Interpreter must be
471 * locked to avoid race condition.
472 */
473 AcpiExEnterInterpreter ();
474
475 /* Remove one reference on the return object (should delete it) */
476
477 AcpiUtRemoveReference (Info->ReturnObject);
478 AcpiExExitInterpreter ();
479 }
480
481
482 Cleanup:
483
484 /* Free the input parameter list (if we created one) */
485
486 if (Info->Parameters)
487 {
488 /* Free the allocated parameter block */
489
490 AcpiUtDeleteInternalObjectList (Info->Parameters);
491 }
492
493 ACPI_FREE (Info);
494 return_ACPI_STATUS (Status);
495 }
496
497 ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
498
499
500 /*******************************************************************************
501 *
502 * FUNCTION: AcpiNsResolveReferences
503 *
504 * PARAMETERS: Info - Evaluation info block
505 *
506 * RETURN: Info->ReturnObject is replaced with the dereferenced object
507 *
508 * DESCRIPTION: Dereference certain reference objects. Called before an
509 * internal return object is converted to an external ACPI_OBJECT.
510 *
511 * Performs an automatic dereference of Index and RefOf reference objects.
512 * These reference objects are not supported by the ACPI_OBJECT, so this is a
513 * last resort effort to return something useful. Also, provides compatibility
514 * with other ACPI implementations.
515 *
516 * NOTE: does not handle references within returned package objects or nested
517 * references, but this support could be added later if found to be necessary.
518 *
519 ******************************************************************************/
520
521 static void
522 AcpiNsResolveReferences (
523 ACPI_EVALUATE_INFO *Info)
524 {
525 ACPI_OPERAND_OBJECT *ObjDesc = NULL;
526 ACPI_NAMESPACE_NODE *Node;
527
528
529 /* We are interested in reference objects only */
530
531 if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
532 {
533 return;
534 }
535
536 /*
537 * Two types of references are supported - those created by Index and
538 * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
539 * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
540 * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
541 * an ACPI_OBJECT.
542 */
543 switch (Info->ReturnObject->Reference.Class)
544 {
545 case ACPI_REFCLASS_INDEX:
546
547 ObjDesc = *(Info->ReturnObject->Reference.Where);
548 break;
549
550 case ACPI_REFCLASS_REFOF:
551
552 Node = Info->ReturnObject->Reference.Object;
553 if (Node)
554 {
555 ObjDesc = Node->Object;
556 }
557 break;
558
559 default:
560
561 return;
562 }
563
564 /* Replace the existing reference object */
565
566 if (ObjDesc)
567 {
568 AcpiUtAddReference (ObjDesc);
569 AcpiUtRemoveReference (Info->ReturnObject);
570 Info->ReturnObject = ObjDesc;
571 }
572
573 return;
574 }
575
576
577 /*******************************************************************************
578 *
579 * FUNCTION: AcpiWalkNamespace
580 *
581 * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for
582 * StartObject - Handle in namespace where search begins
583 * MaxDepth - Depth to which search is to reach
584 * DescendingCallback - Called during tree descent
585 * when an object of "Type" is found
586 * AscendingCallback - Called during tree ascent
587 * when an object of "Type" is found
588 * Context - Passed to user function(s) above
589 * ReturnValue - Location where return value of
590 * UserFunction is put if terminated early
591 *
592 * RETURNS Return value from the UserFunction if terminated early.
593 * Otherwise, returns NULL.
594 *
595 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
596 * starting (and ending) at the object specified by StartHandle.
597 * The callback function is called whenever an object that matches
598 * the type parameter is found. If the callback function returns
599 * a non-zero value, the search is terminated immediately and this
600 * value is returned to the caller.
601 *
602 * The point of this procedure is to provide a generic namespace
603 * walk routine that can be called from multiple places to
604 * provide multiple services; the callback function(s) can be
605 * tailored to each task, whether it is a print function,
606 * a compare function, etc.
607 *
608 ******************************************************************************/
609
610 ACPI_STATUS
611 AcpiWalkNamespace (
612 ACPI_OBJECT_TYPE Type,
613 ACPI_HANDLE StartObject,
614 UINT32 MaxDepth,
615 ACPI_WALK_CALLBACK DescendingCallback,
616 ACPI_WALK_CALLBACK AscendingCallback,
617 void *Context,
618 void **ReturnValue)
619 {
620 ACPI_STATUS Status;
621
622
623 ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
624
625
626 /* Parameter validation */
627
628 if ((Type > ACPI_TYPE_LOCAL_MAX) ||
629 (!MaxDepth) ||
630 (!DescendingCallback && !AscendingCallback))
631 {
632 return_ACPI_STATUS (AE_BAD_PARAMETER);
633 }
634
635 /*
636 * Need to acquire the namespace reader lock to prevent interference
637 * with any concurrent table unloads (which causes the deletion of
638 * namespace objects). We cannot allow the deletion of a namespace node
639 * while the user function is using it. The exception to this are the
640 * nodes created and deleted during control method execution -- these
641 * nodes are marked as temporary nodes and are ignored by the namespace
642 * walk. Thus, control methods can be executed while holding the
643 * namespace deletion lock (and the user function can execute control
644 * methods.)
645 */
646 Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
647 if (ACPI_FAILURE (Status))
648 {
649 return_ACPI_STATUS (Status);
650 }
651
652 /*
653 * Lock the namespace around the walk. The namespace will be
654 * unlocked/locked around each call to the user function - since the user
655 * function must be allowed to make ACPICA calls itself (for example, it
656 * will typically execute control methods during device enumeration.)
657 */
658 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
659 if (ACPI_FAILURE (Status))
660 {
661 goto UnlockAndExit;
662 }
663
664 /* Now we can validate the starting node */
665
666 if (!AcpiNsValidateHandle (StartObject))
667 {
668 Status = AE_BAD_PARAMETER;
669 goto UnlockAndExit2;
670 }
671
672 Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
673 ACPI_NS_WALK_UNLOCK, DescendingCallback,
674 AscendingCallback, Context, ReturnValue);
675
676 UnlockAndExit2:
677 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
678
679 UnlockAndExit:
680 (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
681 return_ACPI_STATUS (Status);
682 }
683
684 ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
685
686
687 /*******************************************************************************
688 *
689 * FUNCTION: AcpiNsGetDeviceCallback
690 *
691 * PARAMETERS: Callback from AcpiGetDevice
692 *
693 * RETURN: Status
694 *
695 * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
696 * present devices, or if they specified a HID, it filters based
697 * on that.
698 *
699 ******************************************************************************/
700
701 static ACPI_STATUS
702 AcpiNsGetDeviceCallback (
703 ACPI_HANDLE ObjHandle,
704 UINT32 NestingLevel,
705 void *Context,
706 void **ReturnValue)
707 {
708 ACPI_GET_DEVICES_INFO *Info = Context;
709 ACPI_STATUS Status;
710 ACPI_NAMESPACE_NODE *Node;
711 UINT32 Flags;
712 ACPI_PNP_DEVICE_ID *Hid;
713 ACPI_PNP_DEVICE_ID_LIST *Cid;
714 UINT32 i;
715 BOOLEAN Found;
716 int NoMatch;
717
718
719 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
720 if (ACPI_FAILURE (Status))
721 {
722 return (Status);
723 }
724
725 Node = AcpiNsValidateHandle (ObjHandle);
726 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
727 if (ACPI_FAILURE (Status))
728 {
729 return (Status);
730 }
731
732 if (!Node)
733 {
734 return (AE_BAD_PARAMETER);
735 }
736
737 /*
738 * First, filter based on the device HID and CID.
739 *
740 * 01/2010: For this case where a specific HID is requested, we don't
741 * want to run _STA until we have an actual HID match. Thus, we will
742 * not unnecessarily execute _STA on devices for which the caller
743 * doesn't care about. Previously, _STA was executed unconditionally
744 * on all devices found here.
745 *
746 * A side-effect of this change is that now we will continue to search
747 * for a matching HID even under device trees where the parent device
748 * would have returned a _STA that indicates it is not present or
749 * not functioning (thus aborting the search on that branch).
750 */
751 if (Info->Hid != NULL)
752 {
753 Status = AcpiUtExecute_HID (Node, &Hid);
754 if (Status == AE_NOT_FOUND)
755 {
756 return (AE_OK);
757 }
758 else if (ACPI_FAILURE (Status))
759 {
760 return (AE_CTRL_DEPTH);
761 }
762
763 NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
764 ACPI_FREE (Hid);
765
766 if (NoMatch)
767 {
768 /*
769 * HID does not match, attempt match within the
770 * list of Compatible IDs (CIDs)
771 */
772 Status = AcpiUtExecute_CID (Node, &Cid);
773 if (Status == AE_NOT_FOUND)
774 {
775 return (AE_OK);
776 }
777 else if (ACPI_FAILURE (Status))
778 {
779 return (AE_CTRL_DEPTH);
780 }
781
782 /* Walk the CID list */
783
784 Found = FALSE;
785 for (i = 0; i < Cid->Count; i++)
786 {
787 if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
788 {
789 /* Found a matching CID */
790
791 Found = TRUE;
792 break;
793 }
794 }
795
796 ACPI_FREE (Cid);
797 if (!Found)
798 {
799 return (AE_OK);
800 }
801 }
802 }
803
804 /* Run _STA to determine if device is present */
805
806 Status = AcpiUtExecute_STA (Node, &Flags);
807 if (ACPI_FAILURE (Status))
808 {
809 return (AE_CTRL_DEPTH);
810 }
811
812 if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
813 !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
814 {
815 /*
816 * Don't examine the children of the device only when the
817 * device is neither present nor functional. See ACPI spec,
818 * description of _STA for more information.
819 */
820 return (AE_CTRL_DEPTH);
821 }
822
823 /* We have a valid device, invoke the user function */
824
825 Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
826 ReturnValue);
827 return (Status);
828 }
829
830
831 /*******************************************************************************
832 *
833 * FUNCTION: AcpiGetDevices
834 *
835 * PARAMETERS: HID - HID to search for. Can be NULL.
836 * UserFunction - Called when a matching object is found
837 * Context - Passed to user function
838 * ReturnValue - Location where return value of
839 * UserFunction is put if terminated early
840 *
841 * RETURNS Return value from the UserFunction if terminated early.
842 * Otherwise, returns NULL.
843 *
844 * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
845 * starting (and ending) at the object specified by StartHandle.
846 * The UserFunction is called whenever an object of type
847 * Device is found. If the user function returns
848 * a non-zero value, the search is terminated immediately and this
849 * value is returned to the caller.
850 *
851 * This is a wrapper for WalkNamespace, but the callback performs
852 * additional filtering. Please see AcpiNsGetDeviceCallback.
853 *
854 ******************************************************************************/
855
856 ACPI_STATUS
857 AcpiGetDevices (
858 char *HID,
859 ACPI_WALK_CALLBACK UserFunction,
860 void *Context,
861 void **ReturnValue)
862 {
863 ACPI_STATUS Status;
864 ACPI_GET_DEVICES_INFO Info;
865
866
867 ACPI_FUNCTION_TRACE (AcpiGetDevices);
868
869
870 /* Parameter validation */
871
872 if (!UserFunction)
873 {
874 return_ACPI_STATUS (AE_BAD_PARAMETER);
875 }
876
877 /*
878 * We're going to call their callback from OUR callback, so we need
879 * to know what it is, and their context parameter.
880 */
881 Info.Hid = HID;
882 Info.Context = Context;
883 Info.UserFunction = UserFunction;
884
885 /*
886 * Lock the namespace around the walk.
887 * The namespace will be unlocked/locked around each call
888 * to the user function - since this function
889 * must be allowed to make Acpi calls itself.
890 */
891 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
892 if (ACPI_FAILURE (Status))
893 {
894 return_ACPI_STATUS (Status);
895 }
896
897 Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
898 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
899 AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
900
901 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
902 return_ACPI_STATUS (Status);
903 }
904
905 ACPI_EXPORT_SYMBOL (AcpiGetDevices)
906
907
908 /*******************************************************************************
909 *
910 * FUNCTION: AcpiAttachData
911 *
912 * PARAMETERS: ObjHandle - Namespace node
913 * Handler - Handler for this attachment
914 * Data - Pointer to data to be attached
915 *
916 * RETURN: Status
917 *
918 * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
919 *
920 ******************************************************************************/
921
922 ACPI_STATUS
923 AcpiAttachData (
924 ACPI_HANDLE ObjHandle,
925 ACPI_OBJECT_HANDLER Handler,
926 void *Data)
927 {
928 ACPI_NAMESPACE_NODE *Node;
929 ACPI_STATUS Status;
930
931
932 /* Parameter validation */
933
934 if (!ObjHandle ||
935 !Handler ||
936 !Data)
937 {
938 return (AE_BAD_PARAMETER);
939 }
940
941 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
942 if (ACPI_FAILURE (Status))
943 {
944 return (Status);
945 }
946
947 /* Convert and validate the handle */
948
949 Node = AcpiNsValidateHandle (ObjHandle);
950 if (!Node)
951 {
952 Status = AE_BAD_PARAMETER;
953 goto UnlockAndExit;
954 }
955
956 Status = AcpiNsAttachData (Node, Handler, Data);
957
958 UnlockAndExit:
959 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
960 return (Status);
961 }
962
963 ACPI_EXPORT_SYMBOL (AcpiAttachData)
964
965
966 /*******************************************************************************
967 *
968 * FUNCTION: AcpiDetachData
969 *
970 * PARAMETERS: ObjHandle - Namespace node handle
971 * Handler - Handler used in call to AcpiAttachData
972 *
973 * RETURN: Status
974 *
975 * DESCRIPTION: Remove data that was previously attached to a node.
976 *
977 ******************************************************************************/
978
979 ACPI_STATUS
980 AcpiDetachData (
981 ACPI_HANDLE ObjHandle,
982 ACPI_OBJECT_HANDLER Handler)
983 {
984 ACPI_NAMESPACE_NODE *Node;
985 ACPI_STATUS Status;
986
987
988 /* Parameter validation */
989
990 if (!ObjHandle ||
991 !Handler)
992 {
993 return (AE_BAD_PARAMETER);
994 }
995
996 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
997 if (ACPI_FAILURE (Status))
998 {
999 return (Status);
1000 }
1001
1002 /* Convert and validate the handle */
1003
1004 Node = AcpiNsValidateHandle (ObjHandle);
1005 if (!Node)
1006 {
1007 Status = AE_BAD_PARAMETER;
1008 goto UnlockAndExit;
1009 }
1010
1011 Status = AcpiNsDetachData (Node, Handler);
1012
1013 UnlockAndExit:
1014 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1015 return (Status);
1016 }
1017
1018 ACPI_EXPORT_SYMBOL (AcpiDetachData)
1019
1020
1021 /*******************************************************************************
1022 *
1023 * FUNCTION: AcpiGetData
1024 *
1025 * PARAMETERS: ObjHandle - Namespace node
1026 * Handler - Handler used in call to AttachData
1027 * Data - Where the data is returned
1028 *
1029 * RETURN: Status
1030 *
1031 * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
1032 *
1033 ******************************************************************************/
1034
1035 ACPI_STATUS
1036 AcpiGetData (
1037 ACPI_HANDLE ObjHandle,
1038 ACPI_OBJECT_HANDLER Handler,
1039 void **Data)
1040 {
1041 ACPI_NAMESPACE_NODE *Node;
1042 ACPI_STATUS Status;
1043
1044
1045 /* Parameter validation */
1046
1047 if (!ObjHandle ||
1048 !Handler ||
1049 !Data)
1050 {
1051 return (AE_BAD_PARAMETER);
1052 }
1053
1054 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1055 if (ACPI_FAILURE (Status))
1056 {
1057 return (Status);
1058 }
1059
1060 /* Convert and validate the handle */
1061
1062 Node = AcpiNsValidateHandle (ObjHandle);
1063 if (!Node)
1064 {
1065 Status = AE_BAD_PARAMETER;
1066 goto UnlockAndExit;
1067 }
1068
1069 Status = AcpiNsGetAttachedData (Node, Handler, Data);
1070
1071 UnlockAndExit:
1072 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1073 return (Status);
1074 }
1075
1076 ACPI_EXPORT_SYMBOL (AcpiGetData)
1077