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