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