xref: /titanic_51/usr/src/uts/intel/io/acpica/namespace/nsxfeval.c (revision de3d2ce46fc25c7b67ccbae4afe5f15e5357568f)
1 /*******************************************************************************
2  *
3  * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4  *                         ACPI Object evaluation interfaces
5  *
6  ******************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116 
117 
118 #define __NSXFEVAL_C__
119 
120 #include "acpi.h"
121 #include "accommon.h"
122 #include "acnamesp.h"
123 #include "acinterp.h"
124 
125 
126 #define _COMPONENT          ACPI_NAMESPACE
127         ACPI_MODULE_NAME    ("nsxfeval")
128 
129 /* Local prototypes */
130 
131 static void
132 AcpiNsResolveReferences (
133     ACPI_EVALUATE_INFO      *Info);
134 
135 
136 /*******************************************************************************
137  *
138  * FUNCTION:    AcpiEvaluateObjectTyped
139  *
140  * PARAMETERS:  Handle              - Object handle (optional)
141  *              Pathname            - Object pathname (optional)
142  *              ExternalParams      - List of parameters to pass to method,
143  *                                    terminated by NULL.  May be NULL
144  *                                    if no parameters are being passed.
145  *              ReturnBuffer        - Where to put method's return value (if
146  *                                    any).  If NULL, no value is returned.
147  *              ReturnType          - Expected type of return object
148  *
149  * RETURN:      Status
150  *
151  * DESCRIPTION: Find and evaluate the given object, passing the given
152  *              parameters if necessary.  One of "Handle" or "Pathname" must
153  *              be valid (non-null)
154  *
155  ******************************************************************************/
156 
157 ACPI_STATUS
158 AcpiEvaluateObjectTyped (
159     ACPI_HANDLE             Handle,
160     ACPI_STRING             Pathname,
161     ACPI_OBJECT_LIST        *ExternalParams,
162     ACPI_BUFFER             *ReturnBuffer,
163     ACPI_OBJECT_TYPE        ReturnType)
164 {
165     ACPI_STATUS             Status;
166     BOOLEAN                 MustFree = FALSE;
167 
168 
169     ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
170 
171 
172     /* Return buffer must be valid */
173 
174     if (!ReturnBuffer)
175     {
176         return_ACPI_STATUS (AE_BAD_PARAMETER);
177     }
178 
179     if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
180     {
181         MustFree = TRUE;
182     }
183 
184     /* Evaluate the object */
185 
186     Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer);
187     if (ACPI_FAILURE (Status))
188     {
189         return_ACPI_STATUS (Status);
190     }
191 
192     /* Type ANY means "don't care" */
193 
194     if (ReturnType == ACPI_TYPE_ANY)
195     {
196         return_ACPI_STATUS (AE_OK);
197     }
198 
199     if (ReturnBuffer->Length == 0)
200     {
201         /* Error because caller specifically asked for a return value */
202 
203         ACPI_ERROR ((AE_INFO, "No return value"));
204         return_ACPI_STATUS (AE_NULL_OBJECT);
205     }
206 
207     /* Examine the object type returned from EvaluateObject */
208 
209     if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
210     {
211         return_ACPI_STATUS (AE_OK);
212     }
213 
214     /* Return object type does not match requested type */
215 
216     ACPI_ERROR ((AE_INFO,
217         "Incorrect return type [%s] requested [%s]",
218         AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
219         AcpiUtGetTypeName (ReturnType)));
220 
221     if (MustFree)
222     {
223         /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
224 
225         AcpiOsFree (ReturnBuffer->Pointer);
226         ReturnBuffer->Pointer = NULL;
227     }
228 
229     ReturnBuffer->Length = 0;
230     return_ACPI_STATUS (AE_TYPE);
231 }
232 
233 ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
234 
235 
236 /*******************************************************************************
237  *
238  * FUNCTION:    AcpiEvaluateObject
239  *
240  * PARAMETERS:  Handle              - Object handle (optional)
241  *              Pathname            - Object pathname (optional)
242  *              ExternalParams      - List of parameters to pass to method,
243  *                                    terminated by NULL.  May be NULL
244  *                                    if no parameters are being passed.
245  *              ReturnBuffer        - Where to put method's return value (if
246  *                                    any).  If NULL, no value is returned.
247  *
248  * RETURN:      Status
249  *
250  * DESCRIPTION: Find and evaluate the given object, passing the given
251  *              parameters if necessary.  One of "Handle" or "Pathname" must
252  *              be valid (non-null)
253  *
254  ******************************************************************************/
255 
256 ACPI_STATUS
257 AcpiEvaluateObject (
258     ACPI_HANDLE             Handle,
259     ACPI_STRING             Pathname,
260     ACPI_OBJECT_LIST        *ExternalParams,
261     ACPI_BUFFER             *ReturnBuffer)
262 {
263     ACPI_STATUS             Status;
264     ACPI_EVALUATE_INFO      *Info;
265     ACPI_SIZE               BufferSpaceNeeded;
266     UINT32                  i;
267 
268 
269     ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
270 
271 
272     /* Allocate and initialize the evaluation information block */
273 
274     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
275     if (!Info)
276     {
277         return_ACPI_STATUS (AE_NO_MEMORY);
278     }
279 
280     Info->Pathname = Pathname;
281 
282     /* Convert and validate the device handle */
283 
284     Info->PrefixNode = AcpiNsMapHandleToNode (Handle);
285     if (!Info->PrefixNode)
286     {
287         Status = AE_BAD_PARAMETER;
288         goto Cleanup;
289     }
290 
291     /*
292      * If there are parameters to be passed to a control method, the external
293      * objects must all be converted to internal objects
294      */
295     if (ExternalParams && ExternalParams->Count)
296     {
297         /*
298          * Allocate a new parameter block for the internal objects
299          * Add 1 to count to allow for null terminated internal list
300          */
301         Info->Parameters = ACPI_ALLOCATE_ZEROED (
302             ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *));
303         if (!Info->Parameters)
304         {
305             Status = AE_NO_MEMORY;
306             goto Cleanup;
307         }
308 
309         /* Convert each external object in the list to an internal object */
310 
311         for (i = 0; i < ExternalParams->Count; i++)
312         {
313             Status = AcpiUtCopyEobjectToIobject (
314                         &ExternalParams->Pointer[i], &Info->Parameters[i]);
315             if (ACPI_FAILURE (Status))
316             {
317                 goto Cleanup;
318             }
319         }
320         Info->Parameters[ExternalParams->Count] = NULL;
321     }
322 
323     /*
324      * Three major cases:
325      * 1) Fully qualified pathname
326      * 2) No handle, not fully qualified pathname (error)
327      * 3) Valid handle
328      */
329     if ((Pathname) &&
330         (AcpiNsValidRootPrefix (Pathname[0])))
331     {
332         /* The path is fully qualified, just evaluate by name */
333 
334         Info->PrefixNode = NULL;
335         Status = AcpiNsEvaluate (Info);
336     }
337     else if (!Handle)
338     {
339         /*
340          * A handle is optional iff a fully qualified pathname is specified.
341          * Since we've already handled fully qualified names above, this is
342          * an error
343          */
344         if (!Pathname)
345         {
346             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
347                 "Both Handle and Pathname are NULL"));
348         }
349         else
350         {
351             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
352                 "Null Handle with relative pathname [%s]", Pathname));
353         }
354 
355         Status = AE_BAD_PARAMETER;
356     }
357     else
358     {
359         /* We have a namespace a node and a possible relative path */
360 
361         Status = AcpiNsEvaluate (Info);
362     }
363 
364     /*
365      * If we are expecting a return value, and all went well above,
366      * copy the return value to an external object.
367      */
368     if (ReturnBuffer)
369     {
370         if (!Info->ReturnObject)
371         {
372             ReturnBuffer->Length = 0;
373         }
374         else
375         {
376             if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
377                 ACPI_DESC_TYPE_NAMED)
378             {
379                 /*
380                  * If we received a NS Node as a return object, this means that
381                  * the object we are evaluating has nothing interesting to
382                  * return (such as a mutex, etc.)  We return an error because
383                  * these types are essentially unsupported by this interface.
384                  * We don't check up front because this makes it easier to add
385                  * support for various types at a later date if necessary.
386                  */
387                 Status = AE_TYPE;
388                 Info->ReturnObject = NULL;   /* No need to delete a NS Node */
389                 ReturnBuffer->Length = 0;
390             }
391 
392             if (ACPI_SUCCESS (Status))
393             {
394                 /* Dereference Index and RefOf references */
395 
396                 AcpiNsResolveReferences (Info);
397 
398                 /* Get the size of the returned object */
399 
400                 Status = AcpiUtGetObjectSize (Info->ReturnObject,
401                             &BufferSpaceNeeded);
402                 if (ACPI_SUCCESS (Status))
403                 {
404                     /* Validate/Allocate/Clear caller buffer */
405 
406                     Status = AcpiUtInitializeBuffer (ReturnBuffer,
407                                 BufferSpaceNeeded);
408                     if (ACPI_FAILURE (Status))
409                     {
410                         /*
411                          * Caller's buffer is too small or a new one can't
412                          * be allocated
413                          */
414                         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
415                             "Needed buffer size %X, %s\n",
416                             (UINT32) BufferSpaceNeeded,
417                             AcpiFormatException (Status)));
418                     }
419                     else
420                     {
421                         /* We have enough space for the object, build it */
422 
423                         Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
424                                     ReturnBuffer);
425                     }
426                 }
427             }
428         }
429     }
430 
431     if (Info->ReturnObject)
432     {
433         /*
434          * Delete the internal return object. NOTE: Interpreter must be
435          * locked to avoid race condition.
436          */
437         AcpiExEnterInterpreter ();
438 
439         /* Remove one reference on the return object (should delete it) */
440 
441         AcpiUtRemoveReference (Info->ReturnObject);
442         AcpiExExitInterpreter ();
443     }
444 
445 
446 Cleanup:
447 
448     /* Free the input parameter list (if we created one) */
449 
450     if (Info->Parameters)
451     {
452         /* Free the allocated parameter block */
453 
454         AcpiUtDeleteInternalObjectList (Info->Parameters);
455     }
456 
457     ACPI_FREE (Info);
458     return_ACPI_STATUS (Status);
459 }
460 
461 ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
462 
463 
464 /*******************************************************************************
465  *
466  * FUNCTION:    AcpiNsResolveReferences
467  *
468  * PARAMETERS:  Info                    - Evaluation info block
469  *
470  * RETURN:      Info->ReturnObject is replaced with the dereferenced object
471  *
472  * DESCRIPTION: Dereference certain reference objects. Called before an
473  *              internal return object is converted to an external ACPI_OBJECT.
474  *
475  * Performs an automatic dereference of Index and RefOf reference objects.
476  * These reference objects are not supported by the ACPI_OBJECT, so this is a
477  * last resort effort to return something useful. Also, provides compatibility
478  * with other ACPI implementations.
479  *
480  * NOTE: does not handle references within returned package objects or nested
481  * references, but this support could be added later if found to be necessary.
482  *
483  ******************************************************************************/
484 
485 static void
486 AcpiNsResolveReferences (
487     ACPI_EVALUATE_INFO      *Info)
488 {
489     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
490     ACPI_NAMESPACE_NODE     *Node;
491 
492 
493     /* We are interested in reference objects only */
494 
495     if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
496     {
497         return;
498     }
499 
500     /*
501      * Two types of references are supported - those created by Index and
502      * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
503      * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
504      * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
505      * an ACPI_OBJECT.
506      */
507     switch (Info->ReturnObject->Reference.Class)
508     {
509     case ACPI_REFCLASS_INDEX:
510 
511         ObjDesc = *(Info->ReturnObject->Reference.Where);
512         break;
513 
514     case ACPI_REFCLASS_REFOF:
515 
516         Node = Info->ReturnObject->Reference.Object;
517         if (Node)
518         {
519             ObjDesc = Node->Object;
520         }
521         break;
522 
523     default:
524         return;
525     }
526 
527     /* Replace the existing reference object */
528 
529     if (ObjDesc)
530     {
531         AcpiUtAddReference (ObjDesc);
532         AcpiUtRemoveReference (Info->ReturnObject);
533         Info->ReturnObject = ObjDesc;
534     }
535 
536     return;
537 }
538 
539 
540 /*******************************************************************************
541  *
542  * FUNCTION:    AcpiWalkNamespace
543  *
544  * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
545  *              StartObject         - Handle in namespace where search begins
546  *              MaxDepth            - Depth to which search is to reach
547  *              UserFunction        - Called when an object of "Type" is found
548  *              Context             - Passed to user function
549  *              ReturnValue         - Location where return value of
550  *                                    UserFunction is put if terminated early
551  *
552  * RETURNS      Return value from the UserFunction if terminated early.
553  *              Otherwise, returns NULL.
554  *
555  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
556  *              starting (and ending) at the object specified by StartHandle.
557  *              The UserFunction is called whenever an object that matches
558  *              the type parameter is found.  If the user function returns
559  *              a non-zero value, the search is terminated immediately and this
560  *              value is returned to the caller.
561  *
562  *              The point of this procedure is to provide a generic namespace
563  *              walk routine that can be called from multiple places to
564  *              provide multiple services;  the User Function can be tailored
565  *              to each task, whether it is a print function, a compare
566  *              function, etc.
567  *
568  ******************************************************************************/
569 
570 ACPI_STATUS
571 AcpiWalkNamespace (
572     ACPI_OBJECT_TYPE        Type,
573     ACPI_HANDLE             StartObject,
574     UINT32                  MaxDepth,
575     ACPI_WALK_CALLBACK      UserFunction,
576     void                    *Context,
577     void                    **ReturnValue)
578 {
579     ACPI_STATUS             Status;
580 
581 
582     ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
583 
584 
585     /* Parameter validation */
586 
587     if ((Type > ACPI_TYPE_LOCAL_MAX) ||
588         (!MaxDepth)                  ||
589         (!UserFunction))
590     {
591         return_ACPI_STATUS (AE_BAD_PARAMETER);
592     }
593 
594     /*
595      * Need to acquire the namespace reader lock to prevent interference
596      * with any concurrent table unloads (which causes the deletion of
597      * namespace objects). We cannot allow the deletion of a namespace node
598      * while the user function is using it. The exception to this are the
599      * nodes created and deleted during control method execution -- these
600      * nodes are marked as temporary nodes and are ignored by the namespace
601      * walk. Thus, control methods can be executed while holding the
602      * namespace deletion lock (and the user function can execute control
603      * methods.)
604      */
605     Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
606     if (ACPI_FAILURE (Status))
607     {
608         return (Status);
609     }
610 
611     /*
612      * Lock the namespace around the walk. The namespace will be
613      * unlocked/locked around each call to the user function - since the user
614      * function must be allowed to make ACPICA calls itself (for example, it
615      * will typically execute control methods during device enumeration.)
616      */
617     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
618     if (ACPI_FAILURE (Status))
619     {
620         goto UnlockAndExit;
621     }
622 
623     Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
624                 ACPI_NS_WALK_UNLOCK, UserFunction, Context, ReturnValue);
625 
626     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
627 
628 UnlockAndExit:
629     (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
630     return_ACPI_STATUS (Status);
631 }
632 
633 ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
634 
635 
636 /*******************************************************************************
637  *
638  * FUNCTION:    AcpiNsGetDeviceCallback
639  *
640  * PARAMETERS:  Callback from AcpiGetDevice
641  *
642  * RETURN:      Status
643  *
644  * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
645  *              present devices, or if they specified a HID, it filters based
646  *              on that.
647  *
648  ******************************************************************************/
649 
650 static ACPI_STATUS
651 AcpiNsGetDeviceCallback (
652     ACPI_HANDLE             ObjHandle,
653     UINT32                  NestingLevel,
654     void                    *Context,
655     void                    **ReturnValue)
656 {
657     ACPI_GET_DEVICES_INFO   *Info = Context;
658     ACPI_STATUS             Status;
659     ACPI_NAMESPACE_NODE     *Node;
660     UINT32                  Flags;
661     ACPI_DEVICE_ID          Hid;
662     ACPI_COMPATIBLE_ID_LIST *Cid;
663     UINT32                  i;
664     BOOLEAN                 Found;
665 
666 
667     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
668     if (ACPI_FAILURE (Status))
669     {
670         return (Status);
671     }
672 
673     Node = AcpiNsMapHandleToNode (ObjHandle);
674     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
675     if (ACPI_FAILURE (Status))
676     {
677         return (Status);
678     }
679 
680     if (!Node)
681     {
682         return (AE_BAD_PARAMETER);
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     /* Filter based on device HID & CID */
705 
706     if (Info->Hid != NULL)
707     {
708         Status = AcpiUtExecute_HID (Node, &Hid);
709         if (Status == AE_NOT_FOUND)
710         {
711             return (AE_OK);
712         }
713         else if (ACPI_FAILURE (Status))
714         {
715             return (AE_CTRL_DEPTH);
716         }
717 
718         if (ACPI_STRNCMP (Hid.Value, Info->Hid, sizeof (Hid.Value)) != 0)
719         {
720             /*
721              * HID does not match, attempt match within the
722              * list of Compatible IDs (CIDs)
723              */
724             Status = AcpiUtExecute_CID (Node, &Cid);
725             if (Status == AE_NOT_FOUND)
726             {
727                 return (AE_OK);
728             }
729             else if (ACPI_FAILURE (Status))
730             {
731                 return (AE_CTRL_DEPTH);
732             }
733 
734             /* Walk the CID list */
735 
736             Found = FALSE;
737             for (i = 0; i < Cid->Count; i++)
738             {
739                 if (ACPI_STRNCMP (Cid->Id[i].Value, Info->Hid,
740                         sizeof (ACPI_COMPATIBLE_ID)) == 0)
741                 {
742                     /* Found a matching CID */
743 
744                     Found = TRUE;
745                     break;
746                 }
747             }
748 
749             ACPI_FREE (Cid);
750             if (!Found)
751             {
752                 return (AE_OK);
753             }
754         }
755     }
756 
757     /* We have a valid device, invoke the user function */
758 
759     Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
760                 ReturnValue);
761     return (Status);
762 }
763 
764 
765 /*******************************************************************************
766  *
767  * FUNCTION:    AcpiGetDevices
768  *
769  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
770  *              UserFunction        - Called when a matching object is found
771  *              Context             - Passed to user function
772  *              ReturnValue         - Location where return value of
773  *                                    UserFunction is put if terminated early
774  *
775  * RETURNS      Return value from the UserFunction if terminated early.
776  *              Otherwise, returns NULL.
777  *
778  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
779  *              starting (and ending) at the object specified by StartHandle.
780  *              The UserFunction is called whenever an object of type
781  *              Device is found.  If the user function returns
782  *              a non-zero value, the search is terminated immediately and this
783  *              value is returned to the caller.
784  *
785  *              This is a wrapper for WalkNamespace, but the callback performs
786  *              additional filtering. Please see AcpiNsGetDeviceCallback.
787  *
788  ******************************************************************************/
789 
790 ACPI_STATUS
791 AcpiGetDevices (
792     char                    *HID,
793     ACPI_WALK_CALLBACK      UserFunction,
794     void                    *Context,
795     void                    **ReturnValue)
796 {
797     ACPI_STATUS             Status;
798     ACPI_GET_DEVICES_INFO   Info;
799 
800 
801     ACPI_FUNCTION_TRACE (AcpiGetDevices);
802 
803 
804     /* Parameter validation */
805 
806     if (!UserFunction)
807     {
808         return_ACPI_STATUS (AE_BAD_PARAMETER);
809     }
810 
811     /*
812      * We're going to call their callback from OUR callback, so we need
813      * to know what it is, and their context parameter.
814      */
815     Info.Hid          = HID;
816     Info.Context      = Context;
817     Info.UserFunction = UserFunction;
818 
819     /*
820      * Lock the namespace around the walk.
821      * The namespace will be unlocked/locked around each call
822      * to the user function - since this function
823      * must be allowed to make Acpi calls itself.
824      */
825     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
826     if (ACPI_FAILURE (Status))
827     {
828         return_ACPI_STATUS (Status);
829     }
830 
831     Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
832                 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
833                 AcpiNsGetDeviceCallback, &Info, ReturnValue);
834 
835     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
836     return_ACPI_STATUS (Status);
837 }
838 
839 ACPI_EXPORT_SYMBOL (AcpiGetDevices)
840 
841 
842 /*******************************************************************************
843  *
844  * FUNCTION:    AcpiAttachData
845  *
846  * PARAMETERS:  ObjHandle           - Namespace node
847  *              Handler             - Handler for this attachment
848  *              Data                - Pointer to data to be attached
849  *
850  * RETURN:      Status
851  *
852  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
853  *
854  ******************************************************************************/
855 
856 ACPI_STATUS
857 AcpiAttachData (
858     ACPI_HANDLE             ObjHandle,
859     ACPI_OBJECT_HANDLER     Handler,
860     void                    *Data)
861 {
862     ACPI_NAMESPACE_NODE     *Node;
863     ACPI_STATUS             Status;
864 
865 
866     /* Parameter validation */
867 
868     if (!ObjHandle  ||
869         !Handler    ||
870         !Data)
871     {
872         return (AE_BAD_PARAMETER);
873     }
874 
875     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
876     if (ACPI_FAILURE (Status))
877     {
878         return (Status);
879     }
880 
881     /* Convert and validate the handle */
882 
883     Node = AcpiNsMapHandleToNode (ObjHandle);
884     if (!Node)
885     {
886         Status = AE_BAD_PARAMETER;
887         goto UnlockAndExit;
888     }
889 
890     Status = AcpiNsAttachData (Node, Handler, Data);
891 
892 UnlockAndExit:
893     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
894     return (Status);
895 }
896 
897 ACPI_EXPORT_SYMBOL (AcpiAttachData)
898 
899 
900 /*******************************************************************************
901  *
902  * FUNCTION:    AcpiDetachData
903  *
904  * PARAMETERS:  ObjHandle           - Namespace node handle
905  *              Handler             - Handler used in call to AcpiAttachData
906  *
907  * RETURN:      Status
908  *
909  * DESCRIPTION: Remove data that was previously attached to a node.
910  *
911  ******************************************************************************/
912 
913 ACPI_STATUS
914 AcpiDetachData (
915     ACPI_HANDLE             ObjHandle,
916     ACPI_OBJECT_HANDLER     Handler)
917 {
918     ACPI_NAMESPACE_NODE     *Node;
919     ACPI_STATUS             Status;
920 
921 
922     /* Parameter validation */
923 
924     if (!ObjHandle  ||
925         !Handler)
926     {
927         return (AE_BAD_PARAMETER);
928     }
929 
930     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
931     if (ACPI_FAILURE (Status))
932     {
933         return (Status);
934     }
935 
936     /* Convert and validate the handle */
937 
938     Node = AcpiNsMapHandleToNode (ObjHandle);
939     if (!Node)
940     {
941         Status = AE_BAD_PARAMETER;
942         goto UnlockAndExit;
943     }
944 
945     Status = AcpiNsDetachData (Node, Handler);
946 
947 UnlockAndExit:
948     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
949     return (Status);
950 }
951 
952 ACPI_EXPORT_SYMBOL (AcpiDetachData)
953 
954 
955 /*******************************************************************************
956  *
957  * FUNCTION:    AcpiGetData
958  *
959  * PARAMETERS:  ObjHandle           - Namespace node
960  *              Handler             - Handler used in call to AttachData
961  *              Data                - Where the data is returned
962  *
963  * RETURN:      Status
964  *
965  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
966  *
967  ******************************************************************************/
968 
969 ACPI_STATUS
970 AcpiGetData (
971     ACPI_HANDLE             ObjHandle,
972     ACPI_OBJECT_HANDLER     Handler,
973     void                    **Data)
974 {
975     ACPI_NAMESPACE_NODE     *Node;
976     ACPI_STATUS             Status;
977 
978 
979     /* Parameter validation */
980 
981     if (!ObjHandle  ||
982         !Handler    ||
983         !Data)
984     {
985         return (AE_BAD_PARAMETER);
986     }
987 
988     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
989     if (ACPI_FAILURE (Status))
990     {
991         return (Status);
992     }
993 
994     /* Convert and validate the handle */
995 
996     Node = AcpiNsMapHandleToNode (ObjHandle);
997     if (!Node)
998     {
999         Status = AE_BAD_PARAMETER;
1000         goto UnlockAndExit;
1001     }
1002 
1003     Status = AcpiNsGetAttachedData (Node, Handler, Data);
1004 
1005 UnlockAndExit:
1006     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1007     return (Status);
1008 }
1009 
1010 ACPI_EXPORT_SYMBOL (AcpiGetData)
1011 
1012 
1013