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