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