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