xref: /titanic_50/usr/src/uts/intel/io/acpica/namespace/nsxfeval.c (revision 3c112a2b34403220c06c3e2fcac403358cfba168)
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  *              PreOrderVisit       - Called during tree pre-order visit
548  *                                    when an object of "Type" is found
549  *              PostOrderVisit      - Called during tree post-order visit
550  *                                    when an object of "Type" is found
551  *              Context             - Passed to user function(s) above
552  *              ReturnValue         - Location where return value of
553  *                                    UserFunction is put if terminated early
554  *
555  * RETURNS      Return value from the UserFunction if terminated early.
556  *              Otherwise, returns NULL.
557  *
558  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
559  *              starting (and ending) at the object specified by StartHandle.
560  *              The callback function is called whenever an object that matches
561  *              the type parameter is found. If the callback function returns
562  *              a non-zero value, the search is terminated immediately and this
563  *              value is returned to the caller.
564  *
565  *              The point of this procedure is to provide a generic namespace
566  *              walk routine that can be called from multiple places to
567  *              provide multiple services; the callback function(s) can be
568  *              tailored to each task, whether it is a print function,
569  *              a compare function, etc.
570  *
571  ******************************************************************************/
572 
573 ACPI_STATUS
574 AcpiWalkNamespace (
575     ACPI_OBJECT_TYPE        Type,
576     ACPI_HANDLE             StartObject,
577     UINT32                  MaxDepth,
578     ACPI_WALK_CALLBACK      PreOrderVisit,
579     ACPI_WALK_CALLBACK      PostOrderVisit,
580     void                    *Context,
581     void                    **ReturnValue)
582 {
583     ACPI_STATUS             Status;
584 
585 
586     ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
587 
588 
589     /* Parameter validation */
590 
591     if ((Type > ACPI_TYPE_LOCAL_MAX) ||
592         (!MaxDepth)                  ||
593         (!PreOrderVisit && !PostOrderVisit))
594     {
595         return_ACPI_STATUS (AE_BAD_PARAMETER);
596     }
597 
598     /*
599      * Need to acquire the namespace reader lock to prevent interference
600      * with any concurrent table unloads (which causes the deletion of
601      * namespace objects). We cannot allow the deletion of a namespace node
602      * while the user function is using it. The exception to this are the
603      * nodes created and deleted during control method execution -- these
604      * nodes are marked as temporary nodes and are ignored by the namespace
605      * walk. Thus, control methods can be executed while holding the
606      * namespace deletion lock (and the user function can execute control
607      * methods.)
608      */
609     Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
610     if (ACPI_FAILURE (Status))
611     {
612         return (Status);
613     }
614 
615     /*
616      * Lock the namespace around the walk. The namespace will be
617      * unlocked/locked around each call to the user function - since the user
618      * function must be allowed to make ACPICA calls itself (for example, it
619      * will typically execute control methods during device enumeration.)
620      */
621     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
622     if (ACPI_FAILURE (Status))
623     {
624         goto UnlockAndExit;
625     }
626 
627     Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
628                 ACPI_NS_WALK_UNLOCK, PreOrderVisit,
629                 PostOrderVisit, Context, ReturnValue);
630 
631     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
632 
633 UnlockAndExit:
634     (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
635     return_ACPI_STATUS (Status);
636 }
637 
638 ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
639 
640 
641 /*******************************************************************************
642  *
643  * FUNCTION:    AcpiNsGetDeviceCallback
644  *
645  * PARAMETERS:  Callback from AcpiGetDevice
646  *
647  * RETURN:      Status
648  *
649  * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
650  *              present devices, or if they specified a HID, it filters based
651  *              on that.
652  *
653  ******************************************************************************/
654 
655 static ACPI_STATUS
656 AcpiNsGetDeviceCallback (
657     ACPI_HANDLE             ObjHandle,
658     UINT32                  NestingLevel,
659     void                    *Context,
660     void                    **ReturnValue)
661 {
662     ACPI_GET_DEVICES_INFO   *Info = Context;
663     ACPI_STATUS             Status;
664     ACPI_NAMESPACE_NODE     *Node;
665     UINT32                  Flags;
666     ACPI_DEVICE_ID          *Hid;
667     ACPI_DEVICE_ID_LIST     *Cid;
668     UINT32                  i;
669     BOOLEAN                 Found;
670     int                     NoMatch;
671 
672 
673     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
674     if (ACPI_FAILURE (Status))
675     {
676         return (Status);
677     }
678 
679     Node = AcpiNsMapHandleToNode (ObjHandle);
680     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
681     if (ACPI_FAILURE (Status))
682     {
683         return (Status);
684     }
685 
686     if (!Node)
687     {
688         return (AE_BAD_PARAMETER);
689     }
690 
691     /* Run _STA to determine if device is present */
692 
693     Status = AcpiUtExecute_STA (Node, &Flags);
694     if (ACPI_FAILURE (Status))
695     {
696         return (AE_CTRL_DEPTH);
697     }
698 
699     if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
700         !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
701     {
702         /*
703          * Don't examine the children of the device only when the
704          * device is neither present nor functional. See ACPI spec,
705          * description of _STA for more information.
706          */
707         return (AE_CTRL_DEPTH);
708     }
709 
710     /* Filter based on device HID & CID */
711 
712     if (Info->Hid != NULL)
713     {
714         Status = AcpiUtExecute_HID (Node, &Hid);
715         if (Status == AE_NOT_FOUND)
716         {
717             return (AE_OK);
718         }
719         else if (ACPI_FAILURE (Status))
720         {
721             return (AE_CTRL_DEPTH);
722         }
723 
724         NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
725         ACPI_FREE (Hid);
726 
727         if (NoMatch)
728         {
729             /*
730              * HID does not match, attempt match within the
731              * list of Compatible IDs (CIDs)
732              */
733             Status = AcpiUtExecute_CID (Node, &Cid);
734             if (Status == AE_NOT_FOUND)
735             {
736                 return (AE_OK);
737             }
738             else if (ACPI_FAILURE (Status))
739             {
740                 return (AE_CTRL_DEPTH);
741             }
742 
743             /* Walk the CID list */
744 
745             Found = FALSE;
746             for (i = 0; i < Cid->Count; i++)
747             {
748                 if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
749                 {
750                     /* Found a matching CID */
751 
752                     Found = TRUE;
753                     break;
754                 }
755             }
756 
757             ACPI_FREE (Cid);
758             if (!Found)
759             {
760                 return (AE_OK);
761             }
762         }
763     }
764 
765     /* We have a valid device, invoke the user function */
766 
767     Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
768                 ReturnValue);
769     return (Status);
770 }
771 
772 
773 /*******************************************************************************
774  *
775  * FUNCTION:    AcpiGetDevices
776  *
777  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
778  *              UserFunction        - Called when a matching object is found
779  *              Context             - Passed to user function
780  *              ReturnValue         - Location where return value of
781  *                                    UserFunction is put if terminated early
782  *
783  * RETURNS      Return value from the UserFunction if terminated early.
784  *              Otherwise, returns NULL.
785  *
786  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
787  *              starting (and ending) at the object specified by StartHandle.
788  *              The UserFunction is called whenever an object of type
789  *              Device is found.  If the user function returns
790  *              a non-zero value, the search is terminated immediately and this
791  *              value is returned to the caller.
792  *
793  *              This is a wrapper for WalkNamespace, but the callback performs
794  *              additional filtering. Please see AcpiNsGetDeviceCallback.
795  *
796  ******************************************************************************/
797 
798 ACPI_STATUS
799 AcpiGetDevices (
800     char                    *HID,
801     ACPI_WALK_CALLBACK      UserFunction,
802     void                    *Context,
803     void                    **ReturnValue)
804 {
805     ACPI_STATUS             Status;
806     ACPI_GET_DEVICES_INFO   Info;
807 
808 
809     ACPI_FUNCTION_TRACE (AcpiGetDevices);
810 
811 
812     /* Parameter validation */
813 
814     if (!UserFunction)
815     {
816         return_ACPI_STATUS (AE_BAD_PARAMETER);
817     }
818 
819     /*
820      * We're going to call their callback from OUR callback, so we need
821      * to know what it is, and their context parameter.
822      */
823     Info.Hid          = HID;
824     Info.Context      = Context;
825     Info.UserFunction = UserFunction;
826 
827     /*
828      * Lock the namespace around the walk.
829      * The namespace will be unlocked/locked around each call
830      * to the user function - since this function
831      * must be allowed to make Acpi calls itself.
832      */
833     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
834     if (ACPI_FAILURE (Status))
835     {
836         return_ACPI_STATUS (Status);
837     }
838 
839     Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
840                 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
841                 AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
842 
843     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
844     return_ACPI_STATUS (Status);
845 }
846 
847 ACPI_EXPORT_SYMBOL (AcpiGetDevices)
848 
849 
850 /*******************************************************************************
851  *
852  * FUNCTION:    AcpiAttachData
853  *
854  * PARAMETERS:  ObjHandle           - Namespace node
855  *              Handler             - Handler for this attachment
856  *              Data                - Pointer to data to be attached
857  *
858  * RETURN:      Status
859  *
860  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
861  *
862  ******************************************************************************/
863 
864 ACPI_STATUS
865 AcpiAttachData (
866     ACPI_HANDLE             ObjHandle,
867     ACPI_OBJECT_HANDLER     Handler,
868     void                    *Data)
869 {
870     ACPI_NAMESPACE_NODE     *Node;
871     ACPI_STATUS             Status;
872 
873 
874     /* Parameter validation */
875 
876     if (!ObjHandle  ||
877         !Handler    ||
878         !Data)
879     {
880         return (AE_BAD_PARAMETER);
881     }
882 
883     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
884     if (ACPI_FAILURE (Status))
885     {
886         return (Status);
887     }
888 
889     /* Convert and validate the handle */
890 
891     Node = AcpiNsMapHandleToNode (ObjHandle);
892     if (!Node)
893     {
894         Status = AE_BAD_PARAMETER;
895         goto UnlockAndExit;
896     }
897 
898     Status = AcpiNsAttachData (Node, Handler, Data);
899 
900 UnlockAndExit:
901     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
902     return (Status);
903 }
904 
905 ACPI_EXPORT_SYMBOL (AcpiAttachData)
906 
907 
908 /*******************************************************************************
909  *
910  * FUNCTION:    AcpiDetachData
911  *
912  * PARAMETERS:  ObjHandle           - Namespace node handle
913  *              Handler             - Handler used in call to AcpiAttachData
914  *
915  * RETURN:      Status
916  *
917  * DESCRIPTION: Remove data that was previously attached to a node.
918  *
919  ******************************************************************************/
920 
921 ACPI_STATUS
922 AcpiDetachData (
923     ACPI_HANDLE             ObjHandle,
924     ACPI_OBJECT_HANDLER     Handler)
925 {
926     ACPI_NAMESPACE_NODE     *Node;
927     ACPI_STATUS             Status;
928 
929 
930     /* Parameter validation */
931 
932     if (!ObjHandle  ||
933         !Handler)
934     {
935         return (AE_BAD_PARAMETER);
936     }
937 
938     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
939     if (ACPI_FAILURE (Status))
940     {
941         return (Status);
942     }
943 
944     /* Convert and validate the handle */
945 
946     Node = AcpiNsMapHandleToNode (ObjHandle);
947     if (!Node)
948     {
949         Status = AE_BAD_PARAMETER;
950         goto UnlockAndExit;
951     }
952 
953     Status = AcpiNsDetachData (Node, Handler);
954 
955 UnlockAndExit:
956     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
957     return (Status);
958 }
959 
960 ACPI_EXPORT_SYMBOL (AcpiDetachData)
961 
962 
963 /*******************************************************************************
964  *
965  * FUNCTION:    AcpiGetData
966  *
967  * PARAMETERS:  ObjHandle           - Namespace node
968  *              Handler             - Handler used in call to AttachData
969  *              Data                - Where the data is returned
970  *
971  * RETURN:      Status
972  *
973  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
974  *
975  ******************************************************************************/
976 
977 ACPI_STATUS
978 AcpiGetData (
979     ACPI_HANDLE             ObjHandle,
980     ACPI_OBJECT_HANDLER     Handler,
981     void                    **Data)
982 {
983     ACPI_NAMESPACE_NODE     *Node;
984     ACPI_STATUS             Status;
985 
986 
987     /* Parameter validation */
988 
989     if (!ObjHandle  ||
990         !Handler    ||
991         !Data)
992     {
993         return (AE_BAD_PARAMETER);
994     }
995 
996     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
997     if (ACPI_FAILURE (Status))
998     {
999         return (Status);
1000     }
1001 
1002     /* Convert and validate the handle */
1003 
1004     Node = AcpiNsMapHandleToNode (ObjHandle);
1005     if (!Node)
1006     {
1007         Status = AE_BAD_PARAMETER;
1008         goto UnlockAndExit;
1009     }
1010 
1011     Status = AcpiNsGetAttachedData (Node, Handler, Data);
1012 
1013 UnlockAndExit:
1014     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1015     return (Status);
1016 }
1017 
1018 ACPI_EXPORT_SYMBOL (AcpiGetData)
1019 
1020 
1021