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