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