dsutils.c revision 246849
1/*******************************************************************************
2 *
3 * Module Name: dsutils - Dispatcher utilities
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2013, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#define __DSUTILS_C__
45
46#include <contrib/dev/acpica/include/acpi.h>
47#include <contrib/dev/acpica/include/accommon.h>
48#include <contrib/dev/acpica/include/acparser.h>
49#include <contrib/dev/acpica/include/amlcode.h>
50#include <contrib/dev/acpica/include/acdispat.h>
51#include <contrib/dev/acpica/include/acinterp.h>
52#include <contrib/dev/acpica/include/acnamesp.h>
53#include <contrib/dev/acpica/include/acdebug.h>
54
55#define _COMPONENT          ACPI_DISPATCHER
56        ACPI_MODULE_NAME    ("dsutils")
57
58
59/*******************************************************************************
60 *
61 * FUNCTION:    AcpiDsClearImplicitReturn
62 *
63 * PARAMETERS:  WalkState           - Current State
64 *
65 * RETURN:      None.
66 *
67 * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
68 *              to delete "stale" return values (if enabled, the return value
69 *              from every operator is saved at least momentarily, in case the
70 *              parent method exits.)
71 *
72 ******************************************************************************/
73
74void
75AcpiDsClearImplicitReturn (
76    ACPI_WALK_STATE         *WalkState)
77{
78    ACPI_FUNCTION_NAME (DsClearImplicitReturn);
79
80
81    /*
82     * Slack must be enabled for this feature
83     */
84    if (!AcpiGbl_EnableInterpreterSlack)
85    {
86        return;
87    }
88
89    if (WalkState->ImplicitReturnObj)
90    {
91        /*
92         * Delete any "stale" implicit return. However, in
93         * complex statements, the implicit return value can be
94         * bubbled up several levels.
95         */
96        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
97            "Removing reference on stale implicit return obj %p\n",
98            WalkState->ImplicitReturnObj));
99
100        AcpiUtRemoveReference (WalkState->ImplicitReturnObj);
101        WalkState->ImplicitReturnObj = NULL;
102    }
103}
104
105
106#ifndef ACPI_NO_METHOD_EXECUTION
107/*******************************************************************************
108 *
109 * FUNCTION:    AcpiDsDoImplicitReturn
110 *
111 * PARAMETERS:  ReturnDesc          - The return value
112 *              WalkState           - Current State
113 *              AddReference        - True if a reference should be added to the
114 *                                    return object
115 *
116 * RETURN:      TRUE if implicit return enabled, FALSE otherwise
117 *
118 * DESCRIPTION: Implements the optional "implicit return".  We save the result
119 *              of every ASL operator and control method invocation in case the
120 *              parent method exit. Before storing a new return value, we
121 *              delete the previous return value.
122 *
123 ******************************************************************************/
124
125BOOLEAN
126AcpiDsDoImplicitReturn (
127    ACPI_OPERAND_OBJECT     *ReturnDesc,
128    ACPI_WALK_STATE         *WalkState,
129    BOOLEAN                 AddReference)
130{
131    ACPI_FUNCTION_NAME (DsDoImplicitReturn);
132
133
134    /*
135     * Slack must be enabled for this feature, and we must
136     * have a valid return object
137     */
138    if ((!AcpiGbl_EnableInterpreterSlack) ||
139        (!ReturnDesc))
140    {
141        return (FALSE);
142    }
143
144    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
145            "Result %p will be implicitly returned; Prev=%p\n",
146            ReturnDesc,
147            WalkState->ImplicitReturnObj));
148
149    /*
150     * Delete any "stale" implicit return value first. However, in
151     * complex statements, the implicit return value can be
152     * bubbled up several levels, so we don't clear the value if it
153     * is the same as the ReturnDesc.
154     */
155    if (WalkState->ImplicitReturnObj)
156    {
157        if (WalkState->ImplicitReturnObj == ReturnDesc)
158        {
159            return (TRUE);
160        }
161        AcpiDsClearImplicitReturn (WalkState);
162    }
163
164    /* Save the implicit return value, add a reference if requested */
165
166    WalkState->ImplicitReturnObj = ReturnDesc;
167    if (AddReference)
168    {
169        AcpiUtAddReference (ReturnDesc);
170    }
171
172    return (TRUE);
173}
174
175
176/*******************************************************************************
177 *
178 * FUNCTION:    AcpiDsIsResultUsed
179 *
180 * PARAMETERS:  Op                  - Current Op
181 *              WalkState           - Current State
182 *
183 * RETURN:      TRUE if result is used, FALSE otherwise
184 *
185 * DESCRIPTION: Check if a result object will be used by the parent
186 *
187 ******************************************************************************/
188
189BOOLEAN
190AcpiDsIsResultUsed (
191    ACPI_PARSE_OBJECT       *Op,
192    ACPI_WALK_STATE         *WalkState)
193{
194    const ACPI_OPCODE_INFO  *ParentInfo;
195
196    ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);
197
198
199    /* Must have both an Op and a Result Object */
200
201    if (!Op)
202    {
203        ACPI_ERROR ((AE_INFO, "Null Op"));
204        return_UINT8 (TRUE);
205    }
206
207    /*
208     * We know that this operator is not a
209     * Return() operator (would not come here.) The following code is the
210     * optional support for a so-called "implicit return". Some AML code
211     * assumes that the last value of the method is "implicitly" returned
212     * to the caller. Just save the last result as the return value.
213     * NOTE: this is optional because the ASL language does not actually
214     * support this behavior.
215     */
216    (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);
217
218    /*
219     * Now determine if the parent will use the result
220     *
221     * If there is no parent, or the parent is a ScopeOp, we are executing
222     * at the method level. An executing method typically has no parent,
223     * since each method is parsed separately. A method invoked externally
224     * via ExecuteControlMethod has a ScopeOp as the parent.
225     */
226    if ((!Op->Common.Parent) ||
227        (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
228    {
229        /* No parent, the return value cannot possibly be used */
230
231        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
232            "At Method level, result of [%s] not used\n",
233            AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
234        return_UINT8 (FALSE);
235    }
236
237    /* Get info on the parent. The RootOp is AML_SCOPE */
238
239    ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
240    if (ParentInfo->Class == AML_CLASS_UNKNOWN)
241    {
242        ACPI_ERROR ((AE_INFO,
243            "Unknown parent opcode Op=%p", Op));
244        return_UINT8 (FALSE);
245    }
246
247    /*
248     * Decide what to do with the result based on the parent. If
249     * the parent opcode will not use the result, delete the object.
250     * Otherwise leave it as is, it will be deleted when it is used
251     * as an operand later.
252     */
253    switch (ParentInfo->Class)
254    {
255    case AML_CLASS_CONTROL:
256
257        switch (Op->Common.Parent->Common.AmlOpcode)
258        {
259        case AML_RETURN_OP:
260
261            /* Never delete the return value associated with a return opcode */
262
263            goto ResultUsed;
264
265        case AML_IF_OP:
266        case AML_WHILE_OP:
267
268            /*
269             * If we are executing the predicate AND this is the predicate op,
270             * we will use the return value
271             */
272            if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) &&
273                (WalkState->ControlState->Control.PredicateOp == Op))
274            {
275                goto ResultUsed;
276            }
277            break;
278
279        default:
280            /* Ignore other control opcodes */
281            break;
282        }
283
284        /* The general control opcode returns no result */
285
286        goto ResultNotUsed;
287
288
289    case AML_CLASS_CREATE:
290
291        /*
292         * These opcodes allow TermArg(s) as operands and therefore
293         * the operands can be method calls. The result is used.
294         */
295        goto ResultUsed;
296
297
298    case AML_CLASS_NAMED_OBJECT:
299
300        if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
301            (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
302            (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
303            (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)  ||
304            (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
305            (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
306            (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
307        {
308            /*
309             * These opcodes allow TermArg(s) as operands and therefore
310             * the operands can be method calls. The result is used.
311             */
312            goto ResultUsed;
313        }
314
315        goto ResultNotUsed;
316
317
318    default:
319
320        /*
321         * In all other cases. the parent will actually use the return
322         * object, so keep it.
323         */
324        goto ResultUsed;
325    }
326
327
328ResultUsed:
329    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
330        "Result of [%s] used by Parent [%s] Op=%p\n",
331        AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
332        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
333
334    return_UINT8 (TRUE);
335
336
337ResultNotUsed:
338    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
339        "Result of [%s] not used by Parent [%s] Op=%p\n",
340        AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
341        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
342
343    return_UINT8 (FALSE);
344}
345
346
347/*******************************************************************************
348 *
349 * FUNCTION:    AcpiDsDeleteResultIfNotUsed
350 *
351 * PARAMETERS:  Op              - Current parse Op
352 *              ResultObj       - Result of the operation
353 *              WalkState       - Current state
354 *
355 * RETURN:      Status
356 *
357 * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
358 *              result descriptor, check if the parent opcode will actually use
359 *              this result. If not, delete the result now so that it will
360 *              not become orphaned.
361 *
362 ******************************************************************************/
363
364void
365AcpiDsDeleteResultIfNotUsed (
366    ACPI_PARSE_OBJECT       *Op,
367    ACPI_OPERAND_OBJECT     *ResultObj,
368    ACPI_WALK_STATE         *WalkState)
369{
370    ACPI_OPERAND_OBJECT     *ObjDesc;
371    ACPI_STATUS             Status;
372
373
374    ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
375
376
377    if (!Op)
378    {
379        ACPI_ERROR ((AE_INFO, "Null Op"));
380        return_VOID;
381    }
382
383    if (!ResultObj)
384    {
385        return_VOID;
386    }
387
388    if (!AcpiDsIsResultUsed (Op, WalkState))
389    {
390        /* Must pop the result stack (ObjDesc should be equal to ResultObj) */
391
392        Status = AcpiDsResultPop (&ObjDesc, WalkState);
393        if (ACPI_SUCCESS (Status))
394        {
395            AcpiUtRemoveReference (ResultObj);
396        }
397    }
398
399    return_VOID;
400}
401
402
403/*******************************************************************************
404 *
405 * FUNCTION:    AcpiDsResolveOperands
406 *
407 * PARAMETERS:  WalkState           - Current walk state with operands on stack
408 *
409 * RETURN:      Status
410 *
411 * DESCRIPTION: Resolve all operands to their values. Used to prepare
412 *              arguments to a control method invocation (a call from one
413 *              method to another.)
414 *
415 ******************************************************************************/
416
417ACPI_STATUS
418AcpiDsResolveOperands (
419    ACPI_WALK_STATE         *WalkState)
420{
421    UINT32                  i;
422    ACPI_STATUS             Status = AE_OK;
423
424
425    ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
426
427
428    /*
429     * Attempt to resolve each of the valid operands
430     * Method arguments are passed by reference, not by value. This means
431     * that the actual objects are passed, not copies of the objects.
432     */
433    for (i = 0; i < WalkState->NumOperands; i++)
434    {
435        Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
436        if (ACPI_FAILURE (Status))
437        {
438            break;
439        }
440    }
441
442    return_ACPI_STATUS (Status);
443}
444
445
446/*******************************************************************************
447 *
448 * FUNCTION:    AcpiDsClearOperands
449 *
450 * PARAMETERS:  WalkState           - Current walk state with operands on stack
451 *
452 * RETURN:      None
453 *
454 * DESCRIPTION: Clear all operands on the current walk state operand stack.
455 *
456 ******************************************************************************/
457
458void
459AcpiDsClearOperands (
460    ACPI_WALK_STATE         *WalkState)
461{
462    UINT32                  i;
463
464
465    ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
466
467
468    /* Remove a reference on each operand on the stack */
469
470    for (i = 0; i < WalkState->NumOperands; i++)
471    {
472        /*
473         * Remove a reference to all operands, including both
474         * "Arguments" and "Targets".
475         */
476        AcpiUtRemoveReference (WalkState->Operands[i]);
477        WalkState->Operands[i] = NULL;
478    }
479
480    WalkState->NumOperands = 0;
481    return_VOID;
482}
483#endif
484
485
486/*******************************************************************************
487 *
488 * FUNCTION:    AcpiDsCreateOperand
489 *
490 * PARAMETERS:  WalkState       - Current walk state
491 *              Arg             - Parse object for the argument
492 *              ArgIndex        - Which argument (zero based)
493 *
494 * RETURN:      Status
495 *
496 * DESCRIPTION: Translate a parse tree object that is an argument to an AML
497 *              opcode to the equivalent interpreter object. This may include
498 *              looking up a name or entering a new name into the internal
499 *              namespace.
500 *
501 ******************************************************************************/
502
503ACPI_STATUS
504AcpiDsCreateOperand (
505    ACPI_WALK_STATE         *WalkState,
506    ACPI_PARSE_OBJECT       *Arg,
507    UINT32                  ArgIndex)
508{
509    ACPI_STATUS             Status = AE_OK;
510    char                    *NameString;
511    UINT32                  NameLength;
512    ACPI_OPERAND_OBJECT     *ObjDesc;
513    ACPI_PARSE_OBJECT       *ParentOp;
514    UINT16                  Opcode;
515    ACPI_INTERPRETER_MODE   InterpreterMode;
516    const ACPI_OPCODE_INFO  *OpInfo;
517
518
519    ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
520
521
522    /* A valid name must be looked up in the namespace */
523
524    if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
525        (Arg->Common.Value.String) &&
526        !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
527    {
528        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
529
530        /* Get the entire name string from the AML stream */
531
532        Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer,
533                        &NameString, &NameLength);
534
535        if (ACPI_FAILURE (Status))
536        {
537            return_ACPI_STATUS (Status);
538        }
539
540        /* All prefixes have been handled, and the name is in NameString */
541
542        /*
543         * Special handling for BufferField declarations. This is a deferred
544         * opcode that unfortunately defines the field name as the last
545         * parameter instead of the first. We get here when we are performing
546         * the deferred execution, so the actual name of the field is already
547         * in the namespace. We don't want to attempt to look it up again
548         * because we may be executing in a different scope than where the
549         * actual opcode exists.
550         */
551        if ((WalkState->DeferredNode) &&
552            (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
553            (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
554        {
555            ObjDesc = ACPI_CAST_PTR (
556                        ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
557            Status = AE_OK;
558        }
559        else    /* All other opcodes */
560        {
561            /*
562             * Differentiate between a namespace "create" operation
563             * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
564             * IMODE_EXECUTE) in order to support the creation of
565             * namespace objects during the execution of control methods.
566             */
567            ParentOp = Arg->Common.Parent;
568            OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
569            if ((OpInfo->Flags & AML_NSNODE) &&
570                (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
571                (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
572                (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
573            {
574                /* Enter name into namespace if not found */
575
576                InterpreterMode = ACPI_IMODE_LOAD_PASS2;
577            }
578            else
579            {
580                /* Return a failure if name not found */
581
582                InterpreterMode = ACPI_IMODE_EXECUTE;
583            }
584
585            Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
586                        ACPI_TYPE_ANY, InterpreterMode,
587                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
588                        WalkState,
589                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
590            /*
591             * The only case where we pass through (ignore) a NOT_FOUND
592             * error is for the CondRefOf opcode.
593             */
594            if (Status == AE_NOT_FOUND)
595            {
596                if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP)
597                {
598                    /*
599                     * For the Conditional Reference op, it's OK if
600                     * the name is not found;  We just need a way to
601                     * indicate this to the interpreter, set the
602                     * object to the root
603                     */
604                    ObjDesc = ACPI_CAST_PTR (
605                                ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
606                    Status = AE_OK;
607                }
608                else
609                {
610                    /*
611                     * We just plain didn't find it -- which is a
612                     * very serious error at this point
613                     */
614                    Status = AE_AML_NAME_NOT_FOUND;
615                }
616            }
617
618            if (ACPI_FAILURE (Status))
619            {
620                ACPI_ERROR_NAMESPACE (NameString, Status);
621            }
622        }
623
624        /* Free the namestring created above */
625
626        ACPI_FREE (NameString);
627
628        /* Check status from the lookup */
629
630        if (ACPI_FAILURE (Status))
631        {
632            return_ACPI_STATUS (Status);
633        }
634
635        /* Put the resulting object onto the current object stack */
636
637        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
638        if (ACPI_FAILURE (Status))
639        {
640            return_ACPI_STATUS (Status);
641        }
642        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
643    }
644    else
645    {
646        /* Check for null name case */
647
648        if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
649            !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
650        {
651            /*
652             * If the name is null, this means that this is an
653             * optional result parameter that was not specified
654             * in the original ASL. Create a Zero Constant for a
655             * placeholder. (Store to a constant is a Noop.)
656             */
657            Opcode = AML_ZERO_OP;       /* Has no arguments! */
658
659            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
660                "Null namepath: Arg=%p\n", Arg));
661        }
662        else
663        {
664            Opcode = Arg->Common.AmlOpcode;
665        }
666
667        /* Get the object type of the argument */
668
669        OpInfo = AcpiPsGetOpcodeInfo (Opcode);
670        if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
671        {
672            return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
673        }
674
675        if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
676        {
677            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
678                "Argument previously created, already stacked\n"));
679
680            ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (
681                WalkState->Operands [WalkState->NumOperands - 1], WalkState));
682
683            /*
684             * Use value that was already previously returned
685             * by the evaluation of this argument
686             */
687            Status = AcpiDsResultPop (&ObjDesc, WalkState);
688            if (ACPI_FAILURE (Status))
689            {
690                /*
691                 * Only error is underflow, and this indicates
692                 * a missing or null operand!
693                 */
694                ACPI_EXCEPTION ((AE_INFO, Status,
695                    "Missing or null operand"));
696                return_ACPI_STATUS (Status);
697            }
698        }
699        else
700        {
701            /* Create an ACPI_INTERNAL_OBJECT for the argument */
702
703            ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
704            if (!ObjDesc)
705            {
706                return_ACPI_STATUS (AE_NO_MEMORY);
707            }
708
709            /* Initialize the new object */
710
711            Status = AcpiDsInitObjectFromOp (
712                        WalkState, Arg, Opcode, &ObjDesc);
713            if (ACPI_FAILURE (Status))
714            {
715                AcpiUtDeleteObjectDesc (ObjDesc);
716                return_ACPI_STATUS (Status);
717            }
718        }
719
720        /* Put the operand object on the object stack */
721
722        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
723        if (ACPI_FAILURE (Status))
724        {
725            return_ACPI_STATUS (Status);
726        }
727
728        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
729    }
730
731    return_ACPI_STATUS (AE_OK);
732}
733
734
735/*******************************************************************************
736 *
737 * FUNCTION:    AcpiDsCreateOperands
738 *
739 * PARAMETERS:  WalkState           - Current state
740 *              FirstArg            - First argument of a parser argument tree
741 *
742 * RETURN:      Status
743 *
744 * DESCRIPTION: Convert an operator's arguments from a parse tree format to
745 *              namespace objects and place those argument object on the object
746 *              stack in preparation for evaluation by the interpreter.
747 *
748 ******************************************************************************/
749
750ACPI_STATUS
751AcpiDsCreateOperands (
752    ACPI_WALK_STATE         *WalkState,
753    ACPI_PARSE_OBJECT       *FirstArg)
754{
755    ACPI_STATUS             Status = AE_OK;
756    ACPI_PARSE_OBJECT       *Arg;
757    ACPI_PARSE_OBJECT       *Arguments[ACPI_OBJ_NUM_OPERANDS];
758    UINT32                  ArgCount = 0;
759    UINT32                  Index = WalkState->NumOperands;
760    UINT32                  i;
761
762
763    ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
764
765
766    /* Get all arguments in the list */
767
768    Arg = FirstArg;
769    while (Arg)
770    {
771        if (Index >= ACPI_OBJ_NUM_OPERANDS)
772        {
773            return_ACPI_STATUS (AE_BAD_DATA);
774        }
775
776        Arguments[Index] = Arg;
777        WalkState->Operands [Index] = NULL;
778
779        /* Move on to next argument, if any */
780
781        Arg = Arg->Common.Next;
782        ArgCount++;
783        Index++;
784    }
785
786    Index--;
787
788    /* It is the appropriate order to get objects from the Result stack */
789
790    for (i = 0; i < ArgCount; i++)
791    {
792        Arg = Arguments[Index];
793
794        /* Force the filling of the operand stack in inverse order */
795
796        WalkState->OperandIndex = (UINT8) Index;
797
798        Status = AcpiDsCreateOperand (WalkState, Arg, Index);
799        if (ACPI_FAILURE (Status))
800        {
801            goto Cleanup;
802        }
803
804        Index--;
805
806        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%u (%p) done, Arg1=%p\n",
807            Index, Arg, FirstArg));
808    }
809
810    return_ACPI_STATUS (Status);
811
812
813Cleanup:
814    /*
815     * We must undo everything done above; meaning that we must
816     * pop everything off of the operand stack and delete those
817     * objects
818     */
819    AcpiDsObjStackPopAndDelete (ArgCount, WalkState);
820
821    ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
822    return_ACPI_STATUS (Status);
823}
824
825
826/*****************************************************************************
827 *
828 * FUNCTION:    AcpiDsEvaluateNamePath
829 *
830 * PARAMETERS:  WalkState       - Current state of the parse tree walk,
831 *                                the opcode of current operation should be
832 *                                AML_INT_NAMEPATH_OP
833 *
834 * RETURN:      Status
835 *
836 * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
837 *              interpreter object, convert it to value, if needed, duplicate
838 *              it, if needed, and push it onto the current result stack.
839 *
840 ****************************************************************************/
841
842ACPI_STATUS
843AcpiDsEvaluateNamePath (
844    ACPI_WALK_STATE         *WalkState)
845{
846    ACPI_STATUS             Status = AE_OK;
847    ACPI_PARSE_OBJECT       *Op = WalkState->Op;
848    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
849    ACPI_OPERAND_OBJECT     *NewObjDesc;
850    UINT8                   Type;
851
852
853    ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
854
855
856    if (!Op->Common.Parent)
857    {
858        /* This happens after certain exception processing */
859
860        goto Exit;
861    }
862
863    if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
864        (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) ||
865        (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
866    {
867        /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
868
869        goto Exit;
870    }
871
872    Status = AcpiDsCreateOperand (WalkState, Op, 0);
873    if (ACPI_FAILURE (Status))
874    {
875        goto Exit;
876    }
877
878    if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
879    {
880        NewObjDesc = *Operand;
881        goto PushResult;
882    }
883
884    Type = (*Operand)->Common.Type;
885
886    Status = AcpiExResolveToValue (Operand, WalkState);
887    if (ACPI_FAILURE (Status))
888    {
889        goto Exit;
890    }
891
892    if (Type == ACPI_TYPE_INTEGER)
893    {
894        /* It was incremented by AcpiExResolveToValue */
895
896        AcpiUtRemoveReference (*Operand);
897
898        Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState);
899        if (ACPI_FAILURE (Status))
900        {
901            goto Exit;
902        }
903    }
904    else
905    {
906        /*
907         * The object either was anew created or is
908         * a Namespace node - don't decrement it.
909         */
910        NewObjDesc = *Operand;
911    }
912
913    /* Cleanup for name-path operand */
914
915    Status = AcpiDsObjStackPop (1, WalkState);
916    if (ACPI_FAILURE (Status))
917    {
918        WalkState->ResultObj = NewObjDesc;
919        goto Exit;
920    }
921
922PushResult:
923
924    WalkState->ResultObj = NewObjDesc;
925
926    Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
927    if (ACPI_SUCCESS (Status))
928    {
929        /* Force to take it from stack */
930
931        Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
932    }
933
934Exit:
935
936    return_ACPI_STATUS (Status);
937}
938