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