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