1433d6423SLionel Sambuc /*******************************************************************************
2433d6423SLionel Sambuc *
3433d6423SLionel Sambuc * Module Name: dsutils - Dispatcher utilities
4433d6423SLionel Sambuc *
5433d6423SLionel Sambuc ******************************************************************************/
6433d6423SLionel Sambuc
7*29492bb7SDavid van Moolenbroek /*
8*29492bb7SDavid van Moolenbroek * Copyright (C) 2000 - 2014, Intel Corp.
9433d6423SLionel Sambuc * All rights reserved.
10433d6423SLionel Sambuc *
11*29492bb7SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
12*29492bb7SDavid van Moolenbroek * modification, are permitted provided that the following conditions
13*29492bb7SDavid van Moolenbroek * are met:
14*29492bb7SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
15*29492bb7SDavid van Moolenbroek * notice, this list of conditions, and the following disclaimer,
16*29492bb7SDavid van Moolenbroek * without modification.
17*29492bb7SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*29492bb7SDavid van Moolenbroek * substantially similar to the "NO WARRANTY" disclaimer below
19*29492bb7SDavid van Moolenbroek * ("Disclaimer") and any redistribution must be conditioned upon
20*29492bb7SDavid van Moolenbroek * including a substantially similar Disclaimer requirement for further
21*29492bb7SDavid van Moolenbroek * binary redistribution.
22*29492bb7SDavid van Moolenbroek * 3. Neither the names of the above-listed copyright holders nor the names
23*29492bb7SDavid van Moolenbroek * of any contributors may be used to endorse or promote products derived
24*29492bb7SDavid van Moolenbroek * from this software without specific prior written permission.
25433d6423SLionel Sambuc *
26*29492bb7SDavid van Moolenbroek * Alternatively, this software may be distributed under the terms of the
27*29492bb7SDavid van Moolenbroek * GNU General Public License ("GPL") version 2 as published by the Free
28*29492bb7SDavid van Moolenbroek * Software Foundation.
29433d6423SLionel Sambuc *
30*29492bb7SDavid van Moolenbroek * NO WARRANTY
31*29492bb7SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*29492bb7SDavid van Moolenbroek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*29492bb7SDavid van Moolenbroek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*29492bb7SDavid van Moolenbroek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*29492bb7SDavid van Moolenbroek * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*29492bb7SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*29492bb7SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*29492bb7SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*29492bb7SDavid van Moolenbroek * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*29492bb7SDavid van Moolenbroek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*29492bb7SDavid van Moolenbroek * POSSIBILITY OF SUCH DAMAGES.
42*29492bb7SDavid van Moolenbroek */
43433d6423SLionel Sambuc
44433d6423SLionel Sambuc #include "acpi.h"
45433d6423SLionel Sambuc #include "accommon.h"
46433d6423SLionel Sambuc #include "acparser.h"
47433d6423SLionel Sambuc #include "amlcode.h"
48433d6423SLionel Sambuc #include "acdispat.h"
49433d6423SLionel Sambuc #include "acinterp.h"
50433d6423SLionel Sambuc #include "acnamesp.h"
51433d6423SLionel Sambuc #include "acdebug.h"
52433d6423SLionel Sambuc
53433d6423SLionel Sambuc #define _COMPONENT ACPI_DISPATCHER
54433d6423SLionel Sambuc ACPI_MODULE_NAME ("dsutils")
55433d6423SLionel Sambuc
56433d6423SLionel Sambuc
57433d6423SLionel Sambuc /*******************************************************************************
58433d6423SLionel Sambuc *
59433d6423SLionel Sambuc * FUNCTION: AcpiDsClearImplicitReturn
60433d6423SLionel Sambuc *
61433d6423SLionel Sambuc * PARAMETERS: WalkState - Current State
62433d6423SLionel Sambuc *
63433d6423SLionel Sambuc * RETURN: None.
64433d6423SLionel Sambuc *
65433d6423SLionel Sambuc * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
66433d6423SLionel Sambuc * to delete "stale" return values (if enabled, the return value
67433d6423SLionel Sambuc * from every operator is saved at least momentarily, in case the
68433d6423SLionel Sambuc * parent method exits.)
69433d6423SLionel Sambuc *
70433d6423SLionel Sambuc ******************************************************************************/
71433d6423SLionel Sambuc
72433d6423SLionel Sambuc void
AcpiDsClearImplicitReturn(ACPI_WALK_STATE * WalkState)73433d6423SLionel Sambuc AcpiDsClearImplicitReturn (
74433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState)
75433d6423SLionel Sambuc {
76433d6423SLionel Sambuc ACPI_FUNCTION_NAME (DsClearImplicitReturn);
77433d6423SLionel Sambuc
78433d6423SLionel Sambuc
79433d6423SLionel Sambuc /*
80433d6423SLionel Sambuc * Slack must be enabled for this feature
81433d6423SLionel Sambuc */
82433d6423SLionel Sambuc if (!AcpiGbl_EnableInterpreterSlack)
83433d6423SLionel Sambuc {
84433d6423SLionel Sambuc return;
85433d6423SLionel Sambuc }
86433d6423SLionel Sambuc
87433d6423SLionel Sambuc if (WalkState->ImplicitReturnObj)
88433d6423SLionel Sambuc {
89433d6423SLionel Sambuc /*
90433d6423SLionel Sambuc * Delete any "stale" implicit return. However, in
91433d6423SLionel Sambuc * complex statements, the implicit return value can be
92433d6423SLionel Sambuc * bubbled up several levels.
93433d6423SLionel Sambuc */
94433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
95433d6423SLionel Sambuc "Removing reference on stale implicit return obj %p\n",
96433d6423SLionel Sambuc WalkState->ImplicitReturnObj));
97433d6423SLionel Sambuc
98433d6423SLionel Sambuc AcpiUtRemoveReference (WalkState->ImplicitReturnObj);
99433d6423SLionel Sambuc WalkState->ImplicitReturnObj = NULL;
100433d6423SLionel Sambuc }
101433d6423SLionel Sambuc }
102433d6423SLionel Sambuc
103433d6423SLionel Sambuc
104433d6423SLionel Sambuc #ifndef ACPI_NO_METHOD_EXECUTION
105433d6423SLionel Sambuc /*******************************************************************************
106433d6423SLionel Sambuc *
107433d6423SLionel Sambuc * FUNCTION: AcpiDsDoImplicitReturn
108433d6423SLionel Sambuc *
109433d6423SLionel Sambuc * PARAMETERS: ReturnDesc - The return value
110433d6423SLionel Sambuc * WalkState - Current State
111433d6423SLionel Sambuc * AddReference - True if a reference should be added to the
112433d6423SLionel Sambuc * return object
113433d6423SLionel Sambuc *
114433d6423SLionel Sambuc * RETURN: TRUE if implicit return enabled, FALSE otherwise
115433d6423SLionel Sambuc *
116433d6423SLionel Sambuc * DESCRIPTION: Implements the optional "implicit return". We save the result
117433d6423SLionel Sambuc * of every ASL operator and control method invocation in case the
118433d6423SLionel Sambuc * parent method exit. Before storing a new return value, we
119433d6423SLionel Sambuc * delete the previous return value.
120433d6423SLionel Sambuc *
121433d6423SLionel Sambuc ******************************************************************************/
122433d6423SLionel Sambuc
123433d6423SLionel Sambuc BOOLEAN
AcpiDsDoImplicitReturn(ACPI_OPERAND_OBJECT * ReturnDesc,ACPI_WALK_STATE * WalkState,BOOLEAN AddReference)124433d6423SLionel Sambuc AcpiDsDoImplicitReturn (
125433d6423SLionel Sambuc ACPI_OPERAND_OBJECT *ReturnDesc,
126433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState,
127433d6423SLionel Sambuc BOOLEAN AddReference)
128433d6423SLionel Sambuc {
129433d6423SLionel Sambuc ACPI_FUNCTION_NAME (DsDoImplicitReturn);
130433d6423SLionel Sambuc
131433d6423SLionel Sambuc
132433d6423SLionel Sambuc /*
133433d6423SLionel Sambuc * Slack must be enabled for this feature, and we must
134433d6423SLionel Sambuc * have a valid return object
135433d6423SLionel Sambuc */
136433d6423SLionel Sambuc if ((!AcpiGbl_EnableInterpreterSlack) ||
137433d6423SLionel Sambuc (!ReturnDesc))
138433d6423SLionel Sambuc {
139433d6423SLionel Sambuc return (FALSE);
140433d6423SLionel Sambuc }
141433d6423SLionel Sambuc
142433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
143433d6423SLionel Sambuc "Result %p will be implicitly returned; Prev=%p\n",
144433d6423SLionel Sambuc ReturnDesc,
145433d6423SLionel Sambuc WalkState->ImplicitReturnObj));
146433d6423SLionel Sambuc
147433d6423SLionel Sambuc /*
148433d6423SLionel Sambuc * Delete any "stale" implicit return value first. However, in
149433d6423SLionel Sambuc * complex statements, the implicit return value can be
150433d6423SLionel Sambuc * bubbled up several levels, so we don't clear the value if it
151433d6423SLionel Sambuc * is the same as the ReturnDesc.
152433d6423SLionel Sambuc */
153433d6423SLionel Sambuc if (WalkState->ImplicitReturnObj)
154433d6423SLionel Sambuc {
155433d6423SLionel Sambuc if (WalkState->ImplicitReturnObj == ReturnDesc)
156433d6423SLionel Sambuc {
157433d6423SLionel Sambuc return (TRUE);
158433d6423SLionel Sambuc }
159433d6423SLionel Sambuc AcpiDsClearImplicitReturn (WalkState);
160433d6423SLionel Sambuc }
161433d6423SLionel Sambuc
162433d6423SLionel Sambuc /* Save the implicit return value, add a reference if requested */
163433d6423SLionel Sambuc
164433d6423SLionel Sambuc WalkState->ImplicitReturnObj = ReturnDesc;
165433d6423SLionel Sambuc if (AddReference)
166433d6423SLionel Sambuc {
167433d6423SLionel Sambuc AcpiUtAddReference (ReturnDesc);
168433d6423SLionel Sambuc }
169433d6423SLionel Sambuc
170433d6423SLionel Sambuc return (TRUE);
171433d6423SLionel Sambuc }
172433d6423SLionel Sambuc
173433d6423SLionel Sambuc
174433d6423SLionel Sambuc /*******************************************************************************
175433d6423SLionel Sambuc *
176433d6423SLionel Sambuc * FUNCTION: AcpiDsIsResultUsed
177433d6423SLionel Sambuc *
178433d6423SLionel Sambuc * PARAMETERS: Op - Current Op
179433d6423SLionel Sambuc * WalkState - Current State
180433d6423SLionel Sambuc *
181433d6423SLionel Sambuc * RETURN: TRUE if result is used, FALSE otherwise
182433d6423SLionel Sambuc *
183433d6423SLionel Sambuc * DESCRIPTION: Check if a result object will be used by the parent
184433d6423SLionel Sambuc *
185433d6423SLionel Sambuc ******************************************************************************/
186433d6423SLionel Sambuc
187433d6423SLionel Sambuc BOOLEAN
AcpiDsIsResultUsed(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState)188433d6423SLionel Sambuc AcpiDsIsResultUsed (
189433d6423SLionel Sambuc ACPI_PARSE_OBJECT *Op,
190433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState)
191433d6423SLionel Sambuc {
192433d6423SLionel Sambuc const ACPI_OPCODE_INFO *ParentInfo;
193433d6423SLionel Sambuc
194433d6423SLionel Sambuc ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);
195433d6423SLionel Sambuc
196433d6423SLionel Sambuc
197433d6423SLionel Sambuc /* Must have both an Op and a Result Object */
198433d6423SLionel Sambuc
199433d6423SLionel Sambuc if (!Op)
200433d6423SLionel Sambuc {
201433d6423SLionel Sambuc ACPI_ERROR ((AE_INFO, "Null Op"));
202433d6423SLionel Sambuc return_UINT8 (TRUE);
203433d6423SLionel Sambuc }
204433d6423SLionel Sambuc
205433d6423SLionel Sambuc /*
206433d6423SLionel Sambuc * We know that this operator is not a
207433d6423SLionel Sambuc * Return() operator (would not come here.) The following code is the
208433d6423SLionel Sambuc * optional support for a so-called "implicit return". Some AML code
209433d6423SLionel Sambuc * assumes that the last value of the method is "implicitly" returned
210433d6423SLionel Sambuc * to the caller. Just save the last result as the return value.
211433d6423SLionel Sambuc * NOTE: this is optional because the ASL language does not actually
212433d6423SLionel Sambuc * support this behavior.
213433d6423SLionel Sambuc */
214433d6423SLionel Sambuc (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);
215433d6423SLionel Sambuc
216433d6423SLionel Sambuc /*
217433d6423SLionel Sambuc * Now determine if the parent will use the result
218433d6423SLionel Sambuc *
219433d6423SLionel Sambuc * If there is no parent, or the parent is a ScopeOp, we are executing
220433d6423SLionel Sambuc * at the method level. An executing method typically has no parent,
221433d6423SLionel Sambuc * since each method is parsed separately. A method invoked externally
222433d6423SLionel Sambuc * via ExecuteControlMethod has a ScopeOp as the parent.
223433d6423SLionel Sambuc */
224433d6423SLionel Sambuc if ((!Op->Common.Parent) ||
225433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
226433d6423SLionel Sambuc {
227433d6423SLionel Sambuc /* No parent, the return value cannot possibly be used */
228433d6423SLionel Sambuc
229433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
230433d6423SLionel Sambuc "At Method level, result of [%s] not used\n",
231433d6423SLionel Sambuc AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
232433d6423SLionel Sambuc return_UINT8 (FALSE);
233433d6423SLionel Sambuc }
234433d6423SLionel Sambuc
235433d6423SLionel Sambuc /* Get info on the parent. The RootOp is AML_SCOPE */
236433d6423SLionel Sambuc
237433d6423SLionel Sambuc ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
238433d6423SLionel Sambuc if (ParentInfo->Class == AML_CLASS_UNKNOWN)
239433d6423SLionel Sambuc {
240433d6423SLionel Sambuc ACPI_ERROR ((AE_INFO,
241433d6423SLionel Sambuc "Unknown parent opcode Op=%p", Op));
242433d6423SLionel Sambuc return_UINT8 (FALSE);
243433d6423SLionel Sambuc }
244433d6423SLionel Sambuc
245433d6423SLionel Sambuc /*
246433d6423SLionel Sambuc * Decide what to do with the result based on the parent. If
247433d6423SLionel Sambuc * the parent opcode will not use the result, delete the object.
248433d6423SLionel Sambuc * Otherwise leave it as is, it will be deleted when it is used
249433d6423SLionel Sambuc * as an operand later.
250433d6423SLionel Sambuc */
251433d6423SLionel Sambuc switch (ParentInfo->Class)
252433d6423SLionel Sambuc {
253433d6423SLionel Sambuc case AML_CLASS_CONTROL:
254433d6423SLionel Sambuc
255433d6423SLionel Sambuc switch (Op->Common.Parent->Common.AmlOpcode)
256433d6423SLionel Sambuc {
257433d6423SLionel Sambuc case AML_RETURN_OP:
258433d6423SLionel Sambuc
259433d6423SLionel Sambuc /* Never delete the return value associated with a return opcode */
260433d6423SLionel Sambuc
261433d6423SLionel Sambuc goto ResultUsed;
262433d6423SLionel Sambuc
263433d6423SLionel Sambuc case AML_IF_OP:
264433d6423SLionel Sambuc case AML_WHILE_OP:
265433d6423SLionel Sambuc /*
266433d6423SLionel Sambuc * If we are executing the predicate AND this is the predicate op,
267433d6423SLionel Sambuc * we will use the return value
268433d6423SLionel Sambuc */
269433d6423SLionel Sambuc if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) &&
270433d6423SLionel Sambuc (WalkState->ControlState->Control.PredicateOp == Op))
271433d6423SLionel Sambuc {
272433d6423SLionel Sambuc goto ResultUsed;
273433d6423SLionel Sambuc }
274433d6423SLionel Sambuc break;
275433d6423SLionel Sambuc
276433d6423SLionel Sambuc default:
277*29492bb7SDavid van Moolenbroek
278433d6423SLionel Sambuc /* Ignore other control opcodes */
279*29492bb7SDavid van Moolenbroek
280433d6423SLionel Sambuc break;
281433d6423SLionel Sambuc }
282433d6423SLionel Sambuc
283433d6423SLionel Sambuc /* The general control opcode returns no result */
284433d6423SLionel Sambuc
285433d6423SLionel Sambuc goto ResultNotUsed;
286433d6423SLionel Sambuc
287433d6423SLionel Sambuc case AML_CLASS_CREATE:
288433d6423SLionel Sambuc /*
289433d6423SLionel Sambuc * These opcodes allow TermArg(s) as operands and therefore
290433d6423SLionel Sambuc * the operands can be method calls. The result is used.
291433d6423SLionel Sambuc */
292433d6423SLionel Sambuc goto ResultUsed;
293433d6423SLionel Sambuc
294433d6423SLionel Sambuc case AML_CLASS_NAMED_OBJECT:
295433d6423SLionel Sambuc
296433d6423SLionel Sambuc if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) ||
297433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) ||
298433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
299433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) ||
300433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) ||
301433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
302433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
303433d6423SLionel Sambuc {
304433d6423SLionel Sambuc /*
305433d6423SLionel Sambuc * These opcodes allow TermArg(s) as operands and therefore
306433d6423SLionel Sambuc * the operands can be method calls. The result is used.
307433d6423SLionel Sambuc */
308433d6423SLionel Sambuc goto ResultUsed;
309433d6423SLionel Sambuc }
310433d6423SLionel Sambuc
311433d6423SLionel Sambuc goto ResultNotUsed;
312433d6423SLionel Sambuc
313433d6423SLionel Sambuc default:
314433d6423SLionel Sambuc /*
315433d6423SLionel Sambuc * In all other cases. the parent will actually use the return
316433d6423SLionel Sambuc * object, so keep it.
317433d6423SLionel Sambuc */
318433d6423SLionel Sambuc goto ResultUsed;
319433d6423SLionel Sambuc }
320433d6423SLionel Sambuc
321433d6423SLionel Sambuc
322433d6423SLionel Sambuc ResultUsed:
323433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
324433d6423SLionel Sambuc "Result of [%s] used by Parent [%s] Op=%p\n",
325433d6423SLionel Sambuc AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
326433d6423SLionel Sambuc AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
327433d6423SLionel Sambuc
328433d6423SLionel Sambuc return_UINT8 (TRUE);
329433d6423SLionel Sambuc
330433d6423SLionel Sambuc
331433d6423SLionel Sambuc ResultNotUsed:
332433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
333433d6423SLionel Sambuc "Result of [%s] not used by Parent [%s] Op=%p\n",
334433d6423SLionel Sambuc AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
335433d6423SLionel Sambuc AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));
336433d6423SLionel Sambuc
337433d6423SLionel Sambuc return_UINT8 (FALSE);
338433d6423SLionel Sambuc }
339433d6423SLionel Sambuc
340433d6423SLionel Sambuc
341433d6423SLionel Sambuc /*******************************************************************************
342433d6423SLionel Sambuc *
343433d6423SLionel Sambuc * FUNCTION: AcpiDsDeleteResultIfNotUsed
344433d6423SLionel Sambuc *
345433d6423SLionel Sambuc * PARAMETERS: Op - Current parse Op
346433d6423SLionel Sambuc * ResultObj - Result of the operation
347433d6423SLionel Sambuc * WalkState - Current state
348433d6423SLionel Sambuc *
349433d6423SLionel Sambuc * RETURN: Status
350433d6423SLionel Sambuc *
351433d6423SLionel Sambuc * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
352433d6423SLionel Sambuc * result descriptor, check if the parent opcode will actually use
353433d6423SLionel Sambuc * this result. If not, delete the result now so that it will
354433d6423SLionel Sambuc * not become orphaned.
355433d6423SLionel Sambuc *
356433d6423SLionel Sambuc ******************************************************************************/
357433d6423SLionel Sambuc
358433d6423SLionel Sambuc void
AcpiDsDeleteResultIfNotUsed(ACPI_PARSE_OBJECT * Op,ACPI_OPERAND_OBJECT * ResultObj,ACPI_WALK_STATE * WalkState)359433d6423SLionel Sambuc AcpiDsDeleteResultIfNotUsed (
360433d6423SLionel Sambuc ACPI_PARSE_OBJECT *Op,
361433d6423SLionel Sambuc ACPI_OPERAND_OBJECT *ResultObj,
362433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState)
363433d6423SLionel Sambuc {
364433d6423SLionel Sambuc ACPI_OPERAND_OBJECT *ObjDesc;
365433d6423SLionel Sambuc ACPI_STATUS Status;
366433d6423SLionel Sambuc
367433d6423SLionel Sambuc
368433d6423SLionel Sambuc ACPI_FUNCTION_TRACE_PTR (DsDeleteResultIfNotUsed, ResultObj);
369433d6423SLionel Sambuc
370433d6423SLionel Sambuc
371433d6423SLionel Sambuc if (!Op)
372433d6423SLionel Sambuc {
373433d6423SLionel Sambuc ACPI_ERROR ((AE_INFO, "Null Op"));
374433d6423SLionel Sambuc return_VOID;
375433d6423SLionel Sambuc }
376433d6423SLionel Sambuc
377433d6423SLionel Sambuc if (!ResultObj)
378433d6423SLionel Sambuc {
379433d6423SLionel Sambuc return_VOID;
380433d6423SLionel Sambuc }
381433d6423SLionel Sambuc
382433d6423SLionel Sambuc if (!AcpiDsIsResultUsed (Op, WalkState))
383433d6423SLionel Sambuc {
384433d6423SLionel Sambuc /* Must pop the result stack (ObjDesc should be equal to ResultObj) */
385433d6423SLionel Sambuc
386433d6423SLionel Sambuc Status = AcpiDsResultPop (&ObjDesc, WalkState);
387433d6423SLionel Sambuc if (ACPI_SUCCESS (Status))
388433d6423SLionel Sambuc {
389433d6423SLionel Sambuc AcpiUtRemoveReference (ResultObj);
390433d6423SLionel Sambuc }
391433d6423SLionel Sambuc }
392433d6423SLionel Sambuc
393433d6423SLionel Sambuc return_VOID;
394433d6423SLionel Sambuc }
395433d6423SLionel Sambuc
396433d6423SLionel Sambuc
397433d6423SLionel Sambuc /*******************************************************************************
398433d6423SLionel Sambuc *
399433d6423SLionel Sambuc * FUNCTION: AcpiDsResolveOperands
400433d6423SLionel Sambuc *
401433d6423SLionel Sambuc * PARAMETERS: WalkState - Current walk state with operands on stack
402433d6423SLionel Sambuc *
403433d6423SLionel Sambuc * RETURN: Status
404433d6423SLionel Sambuc *
405433d6423SLionel Sambuc * DESCRIPTION: Resolve all operands to their values. Used to prepare
406433d6423SLionel Sambuc * arguments to a control method invocation (a call from one
407433d6423SLionel Sambuc * method to another.)
408433d6423SLionel Sambuc *
409433d6423SLionel Sambuc ******************************************************************************/
410433d6423SLionel Sambuc
411433d6423SLionel Sambuc ACPI_STATUS
AcpiDsResolveOperands(ACPI_WALK_STATE * WalkState)412433d6423SLionel Sambuc AcpiDsResolveOperands (
413433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState)
414433d6423SLionel Sambuc {
415433d6423SLionel Sambuc UINT32 i;
416433d6423SLionel Sambuc ACPI_STATUS Status = AE_OK;
417433d6423SLionel Sambuc
418433d6423SLionel Sambuc
419433d6423SLionel Sambuc ACPI_FUNCTION_TRACE_PTR (DsResolveOperands, WalkState);
420433d6423SLionel Sambuc
421433d6423SLionel Sambuc
422433d6423SLionel Sambuc /*
423433d6423SLionel Sambuc * Attempt to resolve each of the valid operands
424433d6423SLionel Sambuc * Method arguments are passed by reference, not by value. This means
425433d6423SLionel Sambuc * that the actual objects are passed, not copies of the objects.
426433d6423SLionel Sambuc */
427433d6423SLionel Sambuc for (i = 0; i < WalkState->NumOperands; i++)
428433d6423SLionel Sambuc {
429433d6423SLionel Sambuc Status = AcpiExResolveToValue (&WalkState->Operands[i], WalkState);
430433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
431433d6423SLionel Sambuc {
432433d6423SLionel Sambuc break;
433433d6423SLionel Sambuc }
434433d6423SLionel Sambuc }
435433d6423SLionel Sambuc
436433d6423SLionel Sambuc return_ACPI_STATUS (Status);
437433d6423SLionel Sambuc }
438433d6423SLionel Sambuc
439433d6423SLionel Sambuc
440433d6423SLionel Sambuc /*******************************************************************************
441433d6423SLionel Sambuc *
442433d6423SLionel Sambuc * FUNCTION: AcpiDsClearOperands
443433d6423SLionel Sambuc *
444433d6423SLionel Sambuc * PARAMETERS: WalkState - Current walk state with operands on stack
445433d6423SLionel Sambuc *
446433d6423SLionel Sambuc * RETURN: None
447433d6423SLionel Sambuc *
448433d6423SLionel Sambuc * DESCRIPTION: Clear all operands on the current walk state operand stack.
449433d6423SLionel Sambuc *
450433d6423SLionel Sambuc ******************************************************************************/
451433d6423SLionel Sambuc
452433d6423SLionel Sambuc void
AcpiDsClearOperands(ACPI_WALK_STATE * WalkState)453433d6423SLionel Sambuc AcpiDsClearOperands (
454433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState)
455433d6423SLionel Sambuc {
456433d6423SLionel Sambuc UINT32 i;
457433d6423SLionel Sambuc
458433d6423SLionel Sambuc
459433d6423SLionel Sambuc ACPI_FUNCTION_TRACE_PTR (DsClearOperands, WalkState);
460433d6423SLionel Sambuc
461433d6423SLionel Sambuc
462433d6423SLionel Sambuc /* Remove a reference on each operand on the stack */
463433d6423SLionel Sambuc
464433d6423SLionel Sambuc for (i = 0; i < WalkState->NumOperands; i++)
465433d6423SLionel Sambuc {
466433d6423SLionel Sambuc /*
467433d6423SLionel Sambuc * Remove a reference to all operands, including both
468433d6423SLionel Sambuc * "Arguments" and "Targets".
469433d6423SLionel Sambuc */
470433d6423SLionel Sambuc AcpiUtRemoveReference (WalkState->Operands[i]);
471433d6423SLionel Sambuc WalkState->Operands[i] = NULL;
472433d6423SLionel Sambuc }
473433d6423SLionel Sambuc
474433d6423SLionel Sambuc WalkState->NumOperands = 0;
475433d6423SLionel Sambuc return_VOID;
476433d6423SLionel Sambuc }
477433d6423SLionel Sambuc #endif
478433d6423SLionel Sambuc
479433d6423SLionel Sambuc
480433d6423SLionel Sambuc /*******************************************************************************
481433d6423SLionel Sambuc *
482433d6423SLionel Sambuc * FUNCTION: AcpiDsCreateOperand
483433d6423SLionel Sambuc *
484433d6423SLionel Sambuc * PARAMETERS: WalkState - Current walk state
485433d6423SLionel Sambuc * Arg - Parse object for the argument
486433d6423SLionel Sambuc * ArgIndex - Which argument (zero based)
487433d6423SLionel Sambuc *
488433d6423SLionel Sambuc * RETURN: Status
489433d6423SLionel Sambuc *
490433d6423SLionel Sambuc * DESCRIPTION: Translate a parse tree object that is an argument to an AML
491433d6423SLionel Sambuc * opcode to the equivalent interpreter object. This may include
492433d6423SLionel Sambuc * looking up a name or entering a new name into the internal
493433d6423SLionel Sambuc * namespace.
494433d6423SLionel Sambuc *
495433d6423SLionel Sambuc ******************************************************************************/
496433d6423SLionel Sambuc
497433d6423SLionel Sambuc ACPI_STATUS
AcpiDsCreateOperand(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT * Arg,UINT32 ArgIndex)498433d6423SLionel Sambuc AcpiDsCreateOperand (
499433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState,
500433d6423SLionel Sambuc ACPI_PARSE_OBJECT *Arg,
501433d6423SLionel Sambuc UINT32 ArgIndex)
502433d6423SLionel Sambuc {
503433d6423SLionel Sambuc ACPI_STATUS Status = AE_OK;
504433d6423SLionel Sambuc char *NameString;
505433d6423SLionel Sambuc UINT32 NameLength;
506433d6423SLionel Sambuc ACPI_OPERAND_OBJECT *ObjDesc;
507433d6423SLionel Sambuc ACPI_PARSE_OBJECT *ParentOp;
508433d6423SLionel Sambuc UINT16 Opcode;
509433d6423SLionel Sambuc ACPI_INTERPRETER_MODE InterpreterMode;
510433d6423SLionel Sambuc const ACPI_OPCODE_INFO *OpInfo;
511433d6423SLionel Sambuc
512433d6423SLionel Sambuc
513433d6423SLionel Sambuc ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);
514433d6423SLionel Sambuc
515433d6423SLionel Sambuc
516433d6423SLionel Sambuc /* A valid name must be looked up in the namespace */
517433d6423SLionel Sambuc
518433d6423SLionel Sambuc if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
519433d6423SLionel Sambuc (Arg->Common.Value.String) &&
520433d6423SLionel Sambuc !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
521433d6423SLionel Sambuc {
522433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));
523433d6423SLionel Sambuc
524433d6423SLionel Sambuc /* Get the entire name string from the AML stream */
525433d6423SLionel Sambuc
526433d6423SLionel Sambuc Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer,
527433d6423SLionel Sambuc &NameString, &NameLength);
528433d6423SLionel Sambuc
529433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
530433d6423SLionel Sambuc {
531433d6423SLionel Sambuc return_ACPI_STATUS (Status);
532433d6423SLionel Sambuc }
533433d6423SLionel Sambuc
534433d6423SLionel Sambuc /* All prefixes have been handled, and the name is in NameString */
535433d6423SLionel Sambuc
536433d6423SLionel Sambuc /*
537433d6423SLionel Sambuc * Special handling for BufferField declarations. This is a deferred
538433d6423SLionel Sambuc * opcode that unfortunately defines the field name as the last
539433d6423SLionel Sambuc * parameter instead of the first. We get here when we are performing
540433d6423SLionel Sambuc * the deferred execution, so the actual name of the field is already
541433d6423SLionel Sambuc * in the namespace. We don't want to attempt to look it up again
542433d6423SLionel Sambuc * because we may be executing in a different scope than where the
543433d6423SLionel Sambuc * actual opcode exists.
544433d6423SLionel Sambuc */
545433d6423SLionel Sambuc if ((WalkState->DeferredNode) &&
546433d6423SLionel Sambuc (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
547433d6423SLionel Sambuc (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
548433d6423SLionel Sambuc {
549433d6423SLionel Sambuc ObjDesc = ACPI_CAST_PTR (
550433d6423SLionel Sambuc ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
551433d6423SLionel Sambuc Status = AE_OK;
552433d6423SLionel Sambuc }
553433d6423SLionel Sambuc else /* All other opcodes */
554433d6423SLionel Sambuc {
555433d6423SLionel Sambuc /*
556433d6423SLionel Sambuc * Differentiate between a namespace "create" operation
557433d6423SLionel Sambuc * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
558433d6423SLionel Sambuc * IMODE_EXECUTE) in order to support the creation of
559433d6423SLionel Sambuc * namespace objects during the execution of control methods.
560433d6423SLionel Sambuc */
561433d6423SLionel Sambuc ParentOp = Arg->Common.Parent;
562433d6423SLionel Sambuc OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
563433d6423SLionel Sambuc if ((OpInfo->Flags & AML_NSNODE) &&
564433d6423SLionel Sambuc (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
565433d6423SLionel Sambuc (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
566433d6423SLionel Sambuc (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
567433d6423SLionel Sambuc {
568433d6423SLionel Sambuc /* Enter name into namespace if not found */
569433d6423SLionel Sambuc
570433d6423SLionel Sambuc InterpreterMode = ACPI_IMODE_LOAD_PASS2;
571433d6423SLionel Sambuc }
572433d6423SLionel Sambuc else
573433d6423SLionel Sambuc {
574433d6423SLionel Sambuc /* Return a failure if name not found */
575433d6423SLionel Sambuc
576433d6423SLionel Sambuc InterpreterMode = ACPI_IMODE_EXECUTE;
577433d6423SLionel Sambuc }
578433d6423SLionel Sambuc
579433d6423SLionel Sambuc Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
580433d6423SLionel Sambuc ACPI_TYPE_ANY, InterpreterMode,
581433d6423SLionel Sambuc ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
582433d6423SLionel Sambuc WalkState,
583433d6423SLionel Sambuc ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
584433d6423SLionel Sambuc /*
585433d6423SLionel Sambuc * The only case where we pass through (ignore) a NOT_FOUND
586433d6423SLionel Sambuc * error is for the CondRefOf opcode.
587433d6423SLionel Sambuc */
588433d6423SLionel Sambuc if (Status == AE_NOT_FOUND)
589433d6423SLionel Sambuc {
590433d6423SLionel Sambuc if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP)
591433d6423SLionel Sambuc {
592433d6423SLionel Sambuc /*
593433d6423SLionel Sambuc * For the Conditional Reference op, it's OK if
594433d6423SLionel Sambuc * the name is not found; We just need a way to
595433d6423SLionel Sambuc * indicate this to the interpreter, set the
596433d6423SLionel Sambuc * object to the root
597433d6423SLionel Sambuc */
598433d6423SLionel Sambuc ObjDesc = ACPI_CAST_PTR (
599433d6423SLionel Sambuc ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
600433d6423SLionel Sambuc Status = AE_OK;
601433d6423SLionel Sambuc }
602433d6423SLionel Sambuc else
603433d6423SLionel Sambuc {
604433d6423SLionel Sambuc /*
605433d6423SLionel Sambuc * We just plain didn't find it -- which is a
606433d6423SLionel Sambuc * very serious error at this point
607433d6423SLionel Sambuc */
608433d6423SLionel Sambuc Status = AE_AML_NAME_NOT_FOUND;
609433d6423SLionel Sambuc }
610433d6423SLionel Sambuc }
611433d6423SLionel Sambuc
612433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
613433d6423SLionel Sambuc {
614433d6423SLionel Sambuc ACPI_ERROR_NAMESPACE (NameString, Status);
615433d6423SLionel Sambuc }
616433d6423SLionel Sambuc }
617433d6423SLionel Sambuc
618433d6423SLionel Sambuc /* Free the namestring created above */
619433d6423SLionel Sambuc
620433d6423SLionel Sambuc ACPI_FREE (NameString);
621433d6423SLionel Sambuc
622433d6423SLionel Sambuc /* Check status from the lookup */
623433d6423SLionel Sambuc
624433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
625433d6423SLionel Sambuc {
626433d6423SLionel Sambuc return_ACPI_STATUS (Status);
627433d6423SLionel Sambuc }
628433d6423SLionel Sambuc
629433d6423SLionel Sambuc /* Put the resulting object onto the current object stack */
630433d6423SLionel Sambuc
631433d6423SLionel Sambuc Status = AcpiDsObjStackPush (ObjDesc, WalkState);
632433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
633433d6423SLionel Sambuc {
634433d6423SLionel Sambuc return_ACPI_STATUS (Status);
635433d6423SLionel Sambuc }
636433d6423SLionel Sambuc ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
637433d6423SLionel Sambuc }
638433d6423SLionel Sambuc else
639433d6423SLionel Sambuc {
640433d6423SLionel Sambuc /* Check for null name case */
641433d6423SLionel Sambuc
642433d6423SLionel Sambuc if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
643433d6423SLionel Sambuc !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
644433d6423SLionel Sambuc {
645433d6423SLionel Sambuc /*
646433d6423SLionel Sambuc * If the name is null, this means that this is an
647433d6423SLionel Sambuc * optional result parameter that was not specified
648433d6423SLionel Sambuc * in the original ASL. Create a Zero Constant for a
649433d6423SLionel Sambuc * placeholder. (Store to a constant is a Noop.)
650433d6423SLionel Sambuc */
651433d6423SLionel Sambuc Opcode = AML_ZERO_OP; /* Has no arguments! */
652433d6423SLionel Sambuc
653433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
654433d6423SLionel Sambuc "Null namepath: Arg=%p\n", Arg));
655433d6423SLionel Sambuc }
656433d6423SLionel Sambuc else
657433d6423SLionel Sambuc {
658433d6423SLionel Sambuc Opcode = Arg->Common.AmlOpcode;
659433d6423SLionel Sambuc }
660433d6423SLionel Sambuc
661433d6423SLionel Sambuc /* Get the object type of the argument */
662433d6423SLionel Sambuc
663433d6423SLionel Sambuc OpInfo = AcpiPsGetOpcodeInfo (Opcode);
664433d6423SLionel Sambuc if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
665433d6423SLionel Sambuc {
666433d6423SLionel Sambuc return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
667433d6423SLionel Sambuc }
668433d6423SLionel Sambuc
669433d6423SLionel Sambuc if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
670433d6423SLionel Sambuc {
671433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
672433d6423SLionel Sambuc "Argument previously created, already stacked\n"));
673433d6423SLionel Sambuc
674433d6423SLionel Sambuc ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (
675433d6423SLionel Sambuc WalkState->Operands [WalkState->NumOperands - 1], WalkState));
676433d6423SLionel Sambuc
677433d6423SLionel Sambuc /*
678433d6423SLionel Sambuc * Use value that was already previously returned
679433d6423SLionel Sambuc * by the evaluation of this argument
680433d6423SLionel Sambuc */
681433d6423SLionel Sambuc Status = AcpiDsResultPop (&ObjDesc, WalkState);
682433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
683433d6423SLionel Sambuc {
684433d6423SLionel Sambuc /*
685433d6423SLionel Sambuc * Only error is underflow, and this indicates
686433d6423SLionel Sambuc * a missing or null operand!
687433d6423SLionel Sambuc */
688433d6423SLionel Sambuc ACPI_EXCEPTION ((AE_INFO, Status,
689433d6423SLionel Sambuc "Missing or null operand"));
690433d6423SLionel Sambuc return_ACPI_STATUS (Status);
691433d6423SLionel Sambuc }
692433d6423SLionel Sambuc }
693433d6423SLionel Sambuc else
694433d6423SLionel Sambuc {
695433d6423SLionel Sambuc /* Create an ACPI_INTERNAL_OBJECT for the argument */
696433d6423SLionel Sambuc
697433d6423SLionel Sambuc ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
698433d6423SLionel Sambuc if (!ObjDesc)
699433d6423SLionel Sambuc {
700433d6423SLionel Sambuc return_ACPI_STATUS (AE_NO_MEMORY);
701433d6423SLionel Sambuc }
702433d6423SLionel Sambuc
703433d6423SLionel Sambuc /* Initialize the new object */
704433d6423SLionel Sambuc
705433d6423SLionel Sambuc Status = AcpiDsInitObjectFromOp (
706433d6423SLionel Sambuc WalkState, Arg, Opcode, &ObjDesc);
707433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
708433d6423SLionel Sambuc {
709433d6423SLionel Sambuc AcpiUtDeleteObjectDesc (ObjDesc);
710433d6423SLionel Sambuc return_ACPI_STATUS (Status);
711433d6423SLionel Sambuc }
712433d6423SLionel Sambuc }
713433d6423SLionel Sambuc
714433d6423SLionel Sambuc /* Put the operand object on the object stack */
715433d6423SLionel Sambuc
716433d6423SLionel Sambuc Status = AcpiDsObjStackPush (ObjDesc, WalkState);
717433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
718433d6423SLionel Sambuc {
719433d6423SLionel Sambuc return_ACPI_STATUS (Status);
720433d6423SLionel Sambuc }
721433d6423SLionel Sambuc
722433d6423SLionel Sambuc ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
723433d6423SLionel Sambuc }
724433d6423SLionel Sambuc
725433d6423SLionel Sambuc return_ACPI_STATUS (AE_OK);
726433d6423SLionel Sambuc }
727433d6423SLionel Sambuc
728433d6423SLionel Sambuc
729433d6423SLionel Sambuc /*******************************************************************************
730433d6423SLionel Sambuc *
731433d6423SLionel Sambuc * FUNCTION: AcpiDsCreateOperands
732433d6423SLionel Sambuc *
733433d6423SLionel Sambuc * PARAMETERS: WalkState - Current state
734433d6423SLionel Sambuc * FirstArg - First argument of a parser argument tree
735433d6423SLionel Sambuc *
736433d6423SLionel Sambuc * RETURN: Status
737433d6423SLionel Sambuc *
738433d6423SLionel Sambuc * DESCRIPTION: Convert an operator's arguments from a parse tree format to
739433d6423SLionel Sambuc * namespace objects and place those argument object on the object
740433d6423SLionel Sambuc * stack in preparation for evaluation by the interpreter.
741433d6423SLionel Sambuc *
742433d6423SLionel Sambuc ******************************************************************************/
743433d6423SLionel Sambuc
744433d6423SLionel Sambuc ACPI_STATUS
AcpiDsCreateOperands(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT * FirstArg)745433d6423SLionel Sambuc AcpiDsCreateOperands (
746433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState,
747433d6423SLionel Sambuc ACPI_PARSE_OBJECT *FirstArg)
748433d6423SLionel Sambuc {
749433d6423SLionel Sambuc ACPI_STATUS Status = AE_OK;
750433d6423SLionel Sambuc ACPI_PARSE_OBJECT *Arg;
751433d6423SLionel Sambuc ACPI_PARSE_OBJECT *Arguments[ACPI_OBJ_NUM_OPERANDS];
752433d6423SLionel Sambuc UINT32 ArgCount = 0;
753433d6423SLionel Sambuc UINT32 Index = WalkState->NumOperands;
754433d6423SLionel Sambuc UINT32 i;
755433d6423SLionel Sambuc
756433d6423SLionel Sambuc
757433d6423SLionel Sambuc ACPI_FUNCTION_TRACE_PTR (DsCreateOperands, FirstArg);
758433d6423SLionel Sambuc
759433d6423SLionel Sambuc
760433d6423SLionel Sambuc /* Get all arguments in the list */
761433d6423SLionel Sambuc
762433d6423SLionel Sambuc Arg = FirstArg;
763433d6423SLionel Sambuc while (Arg)
764433d6423SLionel Sambuc {
765433d6423SLionel Sambuc if (Index >= ACPI_OBJ_NUM_OPERANDS)
766433d6423SLionel Sambuc {
767433d6423SLionel Sambuc return_ACPI_STATUS (AE_BAD_DATA);
768433d6423SLionel Sambuc }
769433d6423SLionel Sambuc
770433d6423SLionel Sambuc Arguments[Index] = Arg;
771433d6423SLionel Sambuc WalkState->Operands [Index] = NULL;
772433d6423SLionel Sambuc
773433d6423SLionel Sambuc /* Move on to next argument, if any */
774433d6423SLionel Sambuc
775433d6423SLionel Sambuc Arg = Arg->Common.Next;
776433d6423SLionel Sambuc ArgCount++;
777433d6423SLionel Sambuc Index++;
778433d6423SLionel Sambuc }
779433d6423SLionel Sambuc
780*29492bb7SDavid van Moolenbroek ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
781*29492bb7SDavid van Moolenbroek "NumOperands %d, ArgCount %d, Index %d\n",
782*29492bb7SDavid van Moolenbroek WalkState->NumOperands, ArgCount, Index));
783*29492bb7SDavid van Moolenbroek
784*29492bb7SDavid van Moolenbroek /* Create the interpreter arguments, in reverse order */
785*29492bb7SDavid van Moolenbroek
786433d6423SLionel Sambuc Index--;
787433d6423SLionel Sambuc for (i = 0; i < ArgCount; i++)
788433d6423SLionel Sambuc {
789433d6423SLionel Sambuc Arg = Arguments[Index];
790433d6423SLionel Sambuc WalkState->OperandIndex = (UINT8) Index;
791433d6423SLionel Sambuc
792433d6423SLionel Sambuc Status = AcpiDsCreateOperand (WalkState, Arg, Index);
793433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
794433d6423SLionel Sambuc {
795433d6423SLionel Sambuc goto Cleanup;
796433d6423SLionel Sambuc }
797433d6423SLionel Sambuc
798*29492bb7SDavid van Moolenbroek ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
799*29492bb7SDavid van Moolenbroek "Created Arg #%u (%p) %u args total\n",
800*29492bb7SDavid van Moolenbroek Index, Arg, ArgCount));
801433d6423SLionel Sambuc Index--;
802433d6423SLionel Sambuc }
803433d6423SLionel Sambuc
804433d6423SLionel Sambuc return_ACPI_STATUS (Status);
805433d6423SLionel Sambuc
806433d6423SLionel Sambuc
807433d6423SLionel Sambuc Cleanup:
808433d6423SLionel Sambuc /*
809433d6423SLionel Sambuc * We must undo everything done above; meaning that we must
810433d6423SLionel Sambuc * pop everything off of the operand stack and delete those
811433d6423SLionel Sambuc * objects
812433d6423SLionel Sambuc */
813433d6423SLionel Sambuc AcpiDsObjStackPopAndDelete (ArgCount, WalkState);
814433d6423SLionel Sambuc
815433d6423SLionel Sambuc ACPI_EXCEPTION ((AE_INFO, Status, "While creating Arg %u", Index));
816433d6423SLionel Sambuc return_ACPI_STATUS (Status);
817433d6423SLionel Sambuc }
818433d6423SLionel Sambuc
819433d6423SLionel Sambuc
820433d6423SLionel Sambuc /*****************************************************************************
821433d6423SLionel Sambuc *
822433d6423SLionel Sambuc * FUNCTION: AcpiDsEvaluateNamePath
823433d6423SLionel Sambuc *
824433d6423SLionel Sambuc * PARAMETERS: WalkState - Current state of the parse tree walk,
825433d6423SLionel Sambuc * the opcode of current operation should be
826433d6423SLionel Sambuc * AML_INT_NAMEPATH_OP
827433d6423SLionel Sambuc *
828433d6423SLionel Sambuc * RETURN: Status
829433d6423SLionel Sambuc *
830433d6423SLionel Sambuc * DESCRIPTION: Translate the -NamePath- parse tree object to the equivalent
831433d6423SLionel Sambuc * interpreter object, convert it to value, if needed, duplicate
832433d6423SLionel Sambuc * it, if needed, and push it onto the current result stack.
833433d6423SLionel Sambuc *
834433d6423SLionel Sambuc ****************************************************************************/
835433d6423SLionel Sambuc
836433d6423SLionel Sambuc ACPI_STATUS
AcpiDsEvaluateNamePath(ACPI_WALK_STATE * WalkState)837433d6423SLionel Sambuc AcpiDsEvaluateNamePath (
838433d6423SLionel Sambuc ACPI_WALK_STATE *WalkState)
839433d6423SLionel Sambuc {
840433d6423SLionel Sambuc ACPI_STATUS Status = AE_OK;
841433d6423SLionel Sambuc ACPI_PARSE_OBJECT *Op = WalkState->Op;
842433d6423SLionel Sambuc ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
843433d6423SLionel Sambuc ACPI_OPERAND_OBJECT *NewObjDesc;
844433d6423SLionel Sambuc UINT8 Type;
845433d6423SLionel Sambuc
846433d6423SLionel Sambuc
847433d6423SLionel Sambuc ACPI_FUNCTION_TRACE_PTR (DsEvaluateNamePath, WalkState);
848433d6423SLionel Sambuc
849433d6423SLionel Sambuc
850433d6423SLionel Sambuc if (!Op->Common.Parent)
851433d6423SLionel Sambuc {
852433d6423SLionel Sambuc /* This happens after certain exception processing */
853433d6423SLionel Sambuc
854433d6423SLionel Sambuc goto Exit;
855433d6423SLionel Sambuc }
856433d6423SLionel Sambuc
857433d6423SLionel Sambuc if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
858433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) ||
859433d6423SLionel Sambuc (Op->Common.Parent->Common.AmlOpcode == AML_REF_OF_OP))
860433d6423SLionel Sambuc {
861433d6423SLionel Sambuc /* TBD: Should we specify this feature as a bit of OpInfo->Flags of these opcodes? */
862433d6423SLionel Sambuc
863433d6423SLionel Sambuc goto Exit;
864433d6423SLionel Sambuc }
865433d6423SLionel Sambuc
866433d6423SLionel Sambuc Status = AcpiDsCreateOperand (WalkState, Op, 0);
867433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
868433d6423SLionel Sambuc {
869433d6423SLionel Sambuc goto Exit;
870433d6423SLionel Sambuc }
871433d6423SLionel Sambuc
872433d6423SLionel Sambuc if (Op->Common.Flags & ACPI_PARSEOP_TARGET)
873433d6423SLionel Sambuc {
874433d6423SLionel Sambuc NewObjDesc = *Operand;
875433d6423SLionel Sambuc goto PushResult;
876433d6423SLionel Sambuc }
877433d6423SLionel Sambuc
878433d6423SLionel Sambuc Type = (*Operand)->Common.Type;
879433d6423SLionel Sambuc
880433d6423SLionel Sambuc Status = AcpiExResolveToValue (Operand, WalkState);
881433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
882433d6423SLionel Sambuc {
883433d6423SLionel Sambuc goto Exit;
884433d6423SLionel Sambuc }
885433d6423SLionel Sambuc
886433d6423SLionel Sambuc if (Type == ACPI_TYPE_INTEGER)
887433d6423SLionel Sambuc {
888433d6423SLionel Sambuc /* It was incremented by AcpiExResolveToValue */
889433d6423SLionel Sambuc
890433d6423SLionel Sambuc AcpiUtRemoveReference (*Operand);
891433d6423SLionel Sambuc
892433d6423SLionel Sambuc Status = AcpiUtCopyIobjectToIobject (*Operand, &NewObjDesc, WalkState);
893433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
894433d6423SLionel Sambuc {
895433d6423SLionel Sambuc goto Exit;
896433d6423SLionel Sambuc }
897433d6423SLionel Sambuc }
898433d6423SLionel Sambuc else
899433d6423SLionel Sambuc {
900433d6423SLionel Sambuc /*
901433d6423SLionel Sambuc * The object either was anew created or is
902433d6423SLionel Sambuc * a Namespace node - don't decrement it.
903433d6423SLionel Sambuc */
904433d6423SLionel Sambuc NewObjDesc = *Operand;
905433d6423SLionel Sambuc }
906433d6423SLionel Sambuc
907433d6423SLionel Sambuc /* Cleanup for name-path operand */
908433d6423SLionel Sambuc
909433d6423SLionel Sambuc Status = AcpiDsObjStackPop (1, WalkState);
910433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
911433d6423SLionel Sambuc {
912433d6423SLionel Sambuc WalkState->ResultObj = NewObjDesc;
913433d6423SLionel Sambuc goto Exit;
914433d6423SLionel Sambuc }
915433d6423SLionel Sambuc
916433d6423SLionel Sambuc PushResult:
917433d6423SLionel Sambuc
918433d6423SLionel Sambuc WalkState->ResultObj = NewObjDesc;
919433d6423SLionel Sambuc
920433d6423SLionel Sambuc Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
921433d6423SLionel Sambuc if (ACPI_SUCCESS (Status))
922433d6423SLionel Sambuc {
923433d6423SLionel Sambuc /* Force to take it from stack */
924433d6423SLionel Sambuc
925433d6423SLionel Sambuc Op->Common.Flags |= ACPI_PARSEOP_IN_STACK;
926433d6423SLionel Sambuc }
927433d6423SLionel Sambuc
928433d6423SLionel Sambuc Exit:
929433d6423SLionel Sambuc
930433d6423SLionel Sambuc return_ACPI_STATUS (Status);
931433d6423SLionel Sambuc }
932