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