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             * If we are executing the predicate AND this is the predicate op,
269             * we will use the return value
270             */
271            if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) &&
272                (WalkState->ControlState->Control.PredicateOp == Op))
273            {
274                goto ResultUsed;
275            }
276            break;
277
278        default:
279
280            /* Ignore other control opcodes */
281
282            break;
283        }
284
285        /* The general control opcode returns no result */
286
287        goto ResultNotUsed;
288
289    case AML_CLASS_CREATE:
290        /*
291         * These opcodes allow TermArg(s) as operands and therefore
292         * the operands can be method calls. The result is used.
293         */
294        goto ResultUsed;
295
296    case AML_CLASS_NAMED_OBJECT:
297
298        if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
299            (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
300            (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
301            (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)  ||
302            (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
303            (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
304            (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
305        {
306            /*
307             * These opcodes allow TermArg(s) as operands and therefore
308             * the operands can be method calls. The result is used.
309             */
310            goto ResultUsed;
311        }
312
313        goto ResultNotUsed;
314
315    default:
316        /*
317         * In all other cases. the parent will actually use the return
318         * object, so keep it.
319         */
320        goto ResultUsed;
321    }
322
323
324ResultUsed:
325    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
326        "Result of [%s] used by Parent [%s] Op=%p\n",
327        AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
328        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
329
330    return_UINT8 (TRUE);
331
332
333ResultNotUsed:
334    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
335        "Result of [%s] not used by Parent [%s] Op=%p\n",
336        AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
337        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
338
339    return_UINT8 (FALSE);
340}
341
342
343/*******************************************************************************
344 *
345 * FUNCTION:    AcpiDsDeleteResultIfNotUsed
346 *
347 * PARAMETERS:  Op              - Current parse Op
348 *              ResultObj       - Result of the operation
349 *              WalkState       - Current state
350 *
351 * RETURN:      Status
352 *
353 * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
354 *              result descriptor, check if the parent opcode will actually use
355 *              this result. If not, delete the result now so that it will
356 *              not become orphaned.
357 *
358 ******************************************************************************/
359
360void
361AcpiDsDeleteResultIfNotUsed (
362    ACPI_PARSE_OBJECT       *Op,
363    ACPI_OPERAND_OBJECT     *ResultObj,
364    ACPI_WALK_STATE         *WalkState)
365{
366    ACPI_OPERAND_OBJECT     *ObjDesc;
367    ACPI_STATUS             Status;
368
369
370    ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
371
372
373    if (!Op)
374    {
375        ACPI_ERROR ((AE_INFO, "Null Op"));
376        return_VOID;
377    }
378
379    if (!ResultObj)
380    {
381        return_VOID;
382    }
383
384    if (!AcpiDsIsResultUsed (Op, WalkState))
385    {
386        /* Must pop the result stack (ObjDesc should be equal to ResultObj) */
387
388        Status = AcpiDsResultPop (&ObjDesc, WalkState);
389        if (ACPI_SUCCESS (Status))
390        {
391            AcpiUtRemoveReference (ResultObj);
392        }
393    }
394
395    return_VOID;
396}
397
398
399/*******************************************************************************
400 *
401 * FUNCTION:    AcpiDsResolveOperands
402 *
403 * PARAMETERS:  WalkState           - Current walk state with operands on stack
404 *
405 * RETURN:      Status
406 *
407 * DESCRIPTION: Resolve all operands to their values. Used to prepare
408 *              arguments to a control method invocation (a call from one
409 *              method to another.)
410 *
411 ******************************************************************************/
412
413ACPI_STATUS
414AcpiDsResolveOperands (
415    ACPI_WALK_STATE         *WalkState)
416{
417    UINT32                  i;
418    ACPI_STATUS             Status = AE_OK;
419
420
421    ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
422
423
424    /*
425     * Attempt to resolve each of the valid operands
426     * Method arguments are passed by reference, not by value. This means
427     * that the actual objects are passed, not copies of the objects.
428     */
429    for (i = 0; i < WalkState->NumOperands; i++)
430    {
431        Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
432        if (ACPI_FAILURE (Status))
433        {
434            break;
435        }
436    }
437
438    return_ACPI_STATUS (Status);
439}
440
441
442/*******************************************************************************
443 *
444 * FUNCTION:    AcpiDsClearOperands
445 *
446 * PARAMETERS:  WalkState           - Current walk state with operands on stack
447 *
448 * RETURN:      None
449 *
450 * DESCRIPTION: Clear all operands on the current walk state operand stack.
451 *
452 ******************************************************************************/
453
454void
455AcpiDsClearOperands (
456    ACPI_WALK_STATE         *WalkState)
457{
458    UINT32                  i;
459
460
461    ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
462
463
464    /* Remove a reference on each operand on the stack */
465
466    for (i = 0; i < WalkState->NumOperands; i++)
467    {
468        /*
469         * Remove a reference to all operands, including both
470         * "Arguments" and "Targets".
471         */
472        AcpiUtRemoveReference (WalkState->Operands[i]);
473        WalkState->Operands[i] = NULL;
474    }
475
476    WalkState->NumOperands = 0;
477    return_VOID;
478}
479#endif
480
481
482/*******************************************************************************
483 *
484 * FUNCTION:    AcpiDsCreateOperand
485 *
486 * PARAMETERS:  WalkState       - Current walk state
487 *              Arg             - Parse object for the argument
488 *              ArgIndex        - Which argument (zero based)
489 *
490 * RETURN:      Status
491 *
492 * DESCRIPTION: Translate a parse tree object that is an argument to an AML
493 *              opcode to the equivalent interpreter object. This may include
494 *              looking up a name or entering a new name into the internal
495 *              namespace.
496 *
497 ******************************************************************************/
498
499ACPI_STATUS
500AcpiDsCreateOperand (
501    ACPI_WALK_STATE         *WalkState,
502    ACPI_PARSE_OBJECT       *Arg,
503    UINT32                  ArgIndex)
504{
505    ACPI_STATUS             Status = AE_OK;
506    char                    *NameString;
507    UINT32                  NameLength;
508    ACPI_OPERAND_OBJECT     *ObjDesc;
509    ACPI_PARSE_OBJECT       *ParentOp;
510    UINT16                  Opcode;
511    ACPI_INTERPRETER_MODE   InterpreterMode;
512    const ACPI_OPCODE_INFO  *OpInfo;
513
514
515    ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
516
517
518    /* A valid name must be looked up in the namespace */
519
520    if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
521        (Arg->Common.Value.String) &&
522        !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
523    {
524        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
525
526        /* Get the entire name string from the AML stream */
527
528        Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer,
529                        &NameString, &NameLength);
530
531        if (ACPI_FAILURE (Status))
532        {
533            return_ACPI_STATUS (Status);
534        }
535
536        /* All prefixes have been handled, and the name is in NameString */
537
538        /*
539         * Special handling for BufferField declarations. This is a deferred
540         * opcode that unfortunately defines the field name as the last
541         * parameter instead of the first. We get here when we are performing
542         * the deferred execution, so the actual name of the field is already
543         * in the namespace. We don't want to attempt to look it up again
544         * because we may be executing in a different scope than where the
545         * actual opcode exists.
546         */
547        if ((WalkState->DeferredNode) &&
548            (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
549            (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
550        {
551            ObjDesc = ACPI_CAST_PTR (
552                        ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
553            Status = AE_OK;
554        }
555        else    /* All other opcodes */
556        {
557            /*
558             * Differentiate between a namespace "create" operation
559             * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
560             * IMODE_EXECUTE) in order to support the creation of
561             * namespace objects during the execution of control methods.
562             */
563            ParentOp = Arg->Common.Parent;
564            OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
565            if ((OpInfo->Flags & AML_NSNODE) &&
566                (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
567                (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
568                (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
569            {
570                /* Enter name into namespace if not found */
571
572                InterpreterMode = ACPI_IMODE_LOAD_PASS2;
573            }
574            else
575            {
576                /* Return a failure if name not found */
577
578                InterpreterMode = ACPI_IMODE_EXECUTE;
579            }
580
581            Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
582                        ACPI_TYPE_ANY, InterpreterMode,
583                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
584                        WalkState,
585                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
586            /*
587             * The only case where we pass through (ignore) a NOT_FOUND
588             * error is for the CondRefOf opcode.
589             */
590            if (Status == AE_NOT_FOUND)
591            {
592                if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP)
593                {
594                    /*
595                     * For the Conditional Reference op, it's OK if
596                     * the name is not found;  We just need a way to
597                     * indicate this to the interpreter, set the
598                     * object to the root
599                     */
600                    ObjDesc = ACPI_CAST_PTR (
601                                ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
602                    Status = AE_OK;
603                }
604                else
605                {
606                    /*
607                     * We just plain didn't find it -- which is a
608                     * very serious error at this point
609                     */
610                    Status = AE_AML_NAME_NOT_FOUND;
611                }
612            }
613
614            if (ACPI_FAILURE (Status))
615            {
616                ACPI_ERROR_NAMESPACE (NameString, Status);
617            }
618        }
619
620        /* Free the namestring created above */
621
622        ACPI_FREE (NameString);
623
624        /* Check status from the lookup */
625
626        if (ACPI_FAILURE (Status))
627        {
628            return_ACPI_STATUS (Status);
629        }
630
631        /* Put the resulting object onto the current object stack */
632
633        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
634        if (ACPI_FAILURE (Status))
635        {
636            return_ACPI_STATUS (Status);
637        }
638        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
639    }
640    else
641    {
642        /* Check for null name case */
643
644        if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
645            !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
646        {
647            /*
648             * If the name is null, this means that this is an
649             * optional result parameter that was not specified
650             * in the original ASL. Create a Zero Constant for a
651             * placeholder. (Store to a constant is a Noop.)
652             */
653            Opcode = AML_ZERO_OP;       /* Has no arguments! */
654
655            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
656                "Null namepath: Arg=%p\n", Arg));
657        }
658        else
659        {
660            Opcode = Arg->Common.AmlOpcode;
661        }
662
663        /* Get the object type of the argument */
664
665        OpInfo = AcpiPsGetOpcodeInfo (Opcode);
666        if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
667        {
668            return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
669        }
670
671        if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
672        {
673            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
674                "Argument previously created, already stacked\n"));
675
676            ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (
677                WalkState->Operands [WalkState->NumOperands - 1], WalkState));
678
679            /*
680             * Use value that was already previously returned
681             * by the evaluation of this argument
682             */
683            Status = AcpiDsResultPop (&ObjDesc, WalkState);
684            if (ACPI_FAILURE (Status))
685            {
686                /*
687                 * Only error is underflow, and this indicates
688                 * a missing or null operand!
689                 */
690                ACPI_EXCEPTION ((AE_INFO, Status,
691                    "Missing or null operand"));
692                return_ACPI_STATUS (Status);
693            }
694        }
695        else
696        {
697            /* Create an ACPI_INTERNAL_OBJECT for the argument */
698
699            ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
700            if (!ObjDesc)
701            {
702                return_ACPI_STATUS (AE_NO_MEMORY);
703            }
704
705            /* Initialize the new object */
706
707            Status = AcpiDsInitObjectFromOp (
708                        WalkState, Arg, Opcode, &ObjDesc);
709            if (ACPI_FAILURE (Status))
710            {
711                AcpiUtDeleteObjectDesc (ObjDesc);
712                return_ACPI_STATUS (Status);
713            }
714        }
715
716        /* Put the operand object on the object stack */
717
718        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
719        if (ACPI_FAILURE (Status))
720        {
721            return_ACPI_STATUS (Status);
722        }
723
724        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
725    }
726
727    return_ACPI_STATUS (AE_OK);
728}
729
730
731/*******************************************************************************
732 *
733 * FUNCTION:    AcpiDsCreateOperands
734 *
735 * PARAMETERS:  WalkState           - Current state
736 *              FirstArg            - First argument of a parser argument tree
737 *
738 * RETURN:      Status
739 *
740 * DESCRIPTION: Convert an operator's arguments from a parse tree format to
741 *              namespace objects and place those argument object on the object
742 *              stack in preparation for evaluation by the interpreter.
743 *
744 ******************************************************************************/
745
746ACPI_STATUS
747AcpiDsCreateOperands (
748    ACPI_WALK_STATE         *WalkState,
749    ACPI_PARSE_OBJECT       *FirstArg)
750{
751    ACPI_STATUS             Status = AE_OK;
752    ACPI_PARSE_OBJECT       *Arg;
753    ACPI_PARSE_OBJECT       *Arguments[ACPI_OBJ_NUM_OPERANDS];
754    UINT32                  ArgCount = 0;
755    UINT32                  Index = WalkState->NumOperands;
756    UINT32                  i;
757
758
759    ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
760
761
762    /* Get all arguments in the list */
763
764    Arg = FirstArg;
765    while (Arg)
766    {
767        if (Index >= ACPI_OBJ_NUM_OPERANDS)
768        {
769            return_ACPI_STATUS (AE_BAD_DATA);
770        }
771
772        Arguments[Index] = Arg;
773        WalkState->Operands [Index] = NULL;
774
775        /* Move on to next argument, if any */
776
777        Arg = Arg->Common.Next;
778        ArgCount++;
779        Index++;
780    }
781
782    Index--;
783
784    /* It is the appropriate order to get objects from the Result stack */
785
786    for (i = 0; i < ArgCount; i++)
787    {
788        Arg = Arguments[Index];
789
790        /* Force the filling of the operand stack in inverse order */
791
792        WalkState->OperandIndex = (UINT8) Index;
793
794        Status = AcpiDsCreateOperand (WalkState, Arg, Index);
795        if (ACPI_FAILURE (Status))
796        {
797            goto Cleanup;
798        }
799
800        Index--;
801
802        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%u (%p) done, Arg1=%p\n",
803            Index, Arg, FirstArg));
804    }
805
806    return_ACPI_STATUS (Status);
807
808
809Cleanup:
810    /*
811     * We must undo everything done above; meaning that we must
812     * pop everything off of the operand stack and delete those
813     * objects
814     */
815    AcpiDsObjStackPopAndDelete (ArgCount, WalkState);
816
817    ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
818    return_ACPI_STATUS (Status);
819}
820
821
822/*****************************************************************************
823 *
824 * FUNCTION:    AcpiDsEvaluateNamePath
825 *
826 * PARAMETERS:  WalkState       - Current state of the parse tree walk,
827 *                                the opcode of current operation should be
828 *                                AML_INT_NAMEPATH_OP
829 *
830 * RETURN:      Status
831 *
832 * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
833 *              interpreter object, convert it to value, if needed, duplicate
834 *              it, if needed, and push it onto the current result stack.
835 *
836 ****************************************************************************/
837
838ACPI_STATUS
839AcpiDsEvaluateNamePath (
840    ACPI_WALK_STATE         *WalkState)
841{
842    ACPI_STATUS             Status = AE_OK;
843    ACPI_PARSE_OBJECT       *Op = WalkState->Op;
844    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
845    ACPI_OPERAND_OBJECT     *NewObjDesc;
846    UINT8                   Type;
847
848
849    ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
850
851
852    if (!Op->Common.Parent)
853    {
854        /* This happens after certain exception processing */
855
856        goto Exit;
857    }
858
859    if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
860        (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) ||
861        (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
862    {
863        /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
864
865        goto Exit;
866    }
867
868    Status = AcpiDsCreateOperand (WalkState, Op, 0);
869    if (ACPI_FAILURE (Status))
870    {
871        goto Exit;
872    }
873
874    if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
875    {
876        NewObjDesc = *Operand;
877        goto PushResult;
878    }
879
880    Type = (*Operand)->Common.Type;
881
882    Status = AcpiExResolveToValue (Operand, WalkState);
883    if (ACPI_FAILURE (Status))
884    {
885        goto Exit;
886    }
887
888    if (Type == ACPI_TYPE_INTEGER)
889    {
890        /* It was incremented by AcpiExResolveToValue */
891
892        AcpiUtRemoveReference (*Operand);
893
894        Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState);
895        if (ACPI_FAILURE (Status))
896        {
897            goto Exit;
898        }
899    }
900    else
901    {
902        /*
903         * The object either was anew created or is
904         * a Namespace node - don't decrement it.
905         */
906        NewObjDesc = *Operand;
907    }
908
909    /* Cleanup for name-path operand */
910
911    Status = AcpiDsObjStackPop (1, WalkState);
912    if (ACPI_FAILURE (Status))
913    {
914        WalkState->ResultObj = NewObjDesc;
915        goto Exit;
916    }
917
918PushResult:
919
920    WalkState->ResultObj = NewObjDesc;
921
922    Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
923    if (ACPI_SUCCESS (Status))
924    {
925        /* Force to take it from stack */
926
927        Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
928    }
929
930Exit:
931
932    return_ACPI_STATUS (Status);
933}
934