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 "acpi.h"
156#include "accommon.h"
157#include "acnamesp.h"
158#include "acinterp.h"
159
160
161#define _COMPONENT          ACPI_NAMESPACE
162        ACPI_MODULE_NAME    ("nsxfeval")
163
164/* Local prototypes */
165
166static void
167AcpiNsResolveReferences (
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
192ACPI_STATUS
193AcpiEvaluateObjectTyped (
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
296Exit:
297    ACPI_FREE (FullPathname);
298    return_ACPI_STATUS (Status);
299}
300
301ACPI_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
324ACPI_STATUS
325AcpiEvaluateObject (
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
602CleanupReturnObject:
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
619Cleanup:
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
634ACPI_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
658static void
659AcpiNsResolveReferences (
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
747ACPI_STATUS
748AcpiWalkNamespace (
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
813UnlockAndExit2:
814    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
815
816UnlockAndExit:
817    (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
818    return_ACPI_STATUS (Status);
819}
820
821ACPI_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
838static ACPI_STATUS
839AcpiNsGetDeviceCallback (
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
993ACPI_STATUS
994AcpiGetDevices (
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
1042ACPI_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
1059ACPI_STATUS
1060AcpiAttachData (
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
1095UnlockAndExit:
1096    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1097    return (Status);
1098}
1099
1100ACPI_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
1116ACPI_STATUS
1117AcpiDetachData (
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
1150UnlockAndExit:
1151    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1152    return (Status);
1153}
1154
1155ACPI_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
1172ACPI_STATUS
1173AcpiGetData (
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
1208UnlockAndExit:
1209    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1210    return (Status);
1211}
1212
1213ACPI_EXPORT_SYMBOL (AcpiGetData)
1214