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