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 - 2014, 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