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