1c2c66affSColin Finck /******************************************************************************
2c2c66affSColin Finck *
3c2c66affSColin Finck * Module Name: dswexec - Dispatcher method execution callbacks;
4c2c66affSColin Finck * dispatch to interpreter.
5c2c66affSColin Finck *
6c2c66affSColin Finck *****************************************************************************/
7c2c66affSColin Finck
8c2c66affSColin Finck /*
9*03b24380SThomas Faber * Copyright (C) 2000 - 2022, Intel Corp.
10c2c66affSColin Finck * All rights reserved.
11c2c66affSColin Finck *
12c2c66affSColin Finck * Redistribution and use in source and binary forms, with or without
13c2c66affSColin Finck * modification, are permitted provided that the following conditions
14c2c66affSColin Finck * are met:
15c2c66affSColin Finck * 1. Redistributions of source code must retain the above copyright
16c2c66affSColin Finck * notice, this list of conditions, and the following disclaimer,
17c2c66affSColin Finck * without modification.
18c2c66affSColin Finck * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19c2c66affSColin Finck * substantially similar to the "NO WARRANTY" disclaimer below
20c2c66affSColin Finck * ("Disclaimer") and any redistribution must be conditioned upon
21c2c66affSColin Finck * including a substantially similar Disclaimer requirement for further
22c2c66affSColin Finck * binary redistribution.
23c2c66affSColin Finck * 3. Neither the names of the above-listed copyright holders nor the names
24c2c66affSColin Finck * of any contributors may be used to endorse or promote products derived
25c2c66affSColin Finck * from this software without specific prior written permission.
26c2c66affSColin Finck *
27c2c66affSColin Finck * Alternatively, this software may be distributed under the terms of the
28c2c66affSColin Finck * GNU General Public License ("GPL") version 2 as published by the Free
29c2c66affSColin Finck * Software Foundation.
30c2c66affSColin Finck *
31c2c66affSColin Finck * NO WARRANTY
32c2c66affSColin Finck * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33c2c66affSColin Finck * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
346eb8cc49SThomas Faber * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
35c2c66affSColin Finck * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36c2c66affSColin Finck * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37c2c66affSColin Finck * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38c2c66affSColin Finck * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39c2c66affSColin Finck * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40c2c66affSColin Finck * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41c2c66affSColin Finck * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42c2c66affSColin Finck * POSSIBILITY OF SUCH DAMAGES.
43c2c66affSColin Finck */
44c2c66affSColin Finck
45c2c66affSColin Finck #include "acpi.h"
46c2c66affSColin Finck #include "accommon.h"
47c2c66affSColin Finck #include "acparser.h"
48c2c66affSColin Finck #include "amlcode.h"
49c2c66affSColin Finck #include "acdispat.h"
50c2c66affSColin Finck #include "acinterp.h"
51c2c66affSColin Finck #include "acnamesp.h"
52c2c66affSColin Finck #include "acdebug.h"
53040546d8SThomas Faber #ifdef ACPI_EXEC_APP
54040546d8SThomas Faber #include "aecommon.h"
55040546d8SThomas Faber #endif
56c2c66affSColin Finck
57c2c66affSColin Finck #define _COMPONENT ACPI_DISPATCHER
58c2c66affSColin Finck ACPI_MODULE_NAME ("dswexec")
59c2c66affSColin Finck
60c2c66affSColin Finck /*
61c2c66affSColin Finck * Dispatch table for opcode classes
62c2c66affSColin Finck */
63c2c66affSColin Finck static ACPI_EXECUTE_OP AcpiGbl_OpTypeDispatch [] =
64c2c66affSColin Finck {
65c2c66affSColin Finck AcpiExOpcode_0A_0T_1R,
66c2c66affSColin Finck AcpiExOpcode_1A_0T_0R,
67c2c66affSColin Finck AcpiExOpcode_1A_0T_1R,
68*03b24380SThomas Faber NULL, /* Was: AcpiExOpcode_1A_0T_0R (Was for Load operator) */
69c2c66affSColin Finck AcpiExOpcode_1A_1T_1R,
70c2c66affSColin Finck AcpiExOpcode_2A_0T_0R,
71c2c66affSColin Finck AcpiExOpcode_2A_0T_1R,
72c2c66affSColin Finck AcpiExOpcode_2A_1T_1R,
73c2c66affSColin Finck AcpiExOpcode_2A_2T_1R,
74c2c66affSColin Finck AcpiExOpcode_3A_0T_0R,
75c2c66affSColin Finck AcpiExOpcode_3A_1T_1R,
76c2c66affSColin Finck AcpiExOpcode_6A_0T_1R
77c2c66affSColin Finck };
78c2c66affSColin Finck
79c2c66affSColin Finck
80c2c66affSColin Finck /*****************************************************************************
81c2c66affSColin Finck *
82c2c66affSColin Finck * FUNCTION: AcpiDsGetPredicateValue
83c2c66affSColin Finck *
84c2c66affSColin Finck * PARAMETERS: WalkState - Current state of the parse tree walk
85c2c66affSColin Finck * ResultObj - if non-zero, pop result from result stack
86c2c66affSColin Finck *
87c2c66affSColin Finck * RETURN: Status
88c2c66affSColin Finck *
89c2c66affSColin Finck * DESCRIPTION: Get the result of a predicate evaluation
90c2c66affSColin Finck *
91c2c66affSColin Finck ****************************************************************************/
92c2c66affSColin Finck
93c2c66affSColin Finck ACPI_STATUS
AcpiDsGetPredicateValue(ACPI_WALK_STATE * WalkState,ACPI_OPERAND_OBJECT * ResultObj)94c2c66affSColin Finck AcpiDsGetPredicateValue (
95c2c66affSColin Finck ACPI_WALK_STATE *WalkState,
96c2c66affSColin Finck ACPI_OPERAND_OBJECT *ResultObj)
97c2c66affSColin Finck {
98c2c66affSColin Finck ACPI_STATUS Status = AE_OK;
99c2c66affSColin Finck ACPI_OPERAND_OBJECT *ObjDesc;
100c2c66affSColin Finck ACPI_OPERAND_OBJECT *LocalObjDesc = NULL;
101c2c66affSColin Finck
102c2c66affSColin Finck
103c2c66affSColin Finck ACPI_FUNCTION_TRACE_PTR (DsGetPredicateValue, WalkState);
104c2c66affSColin Finck
105c2c66affSColin Finck
106c2c66affSColin Finck WalkState->ControlState->Common.State = 0;
107c2c66affSColin Finck
108c2c66affSColin Finck if (ResultObj)
109c2c66affSColin Finck {
110c2c66affSColin Finck Status = AcpiDsResultPop (&ObjDesc, WalkState);
111c2c66affSColin Finck if (ACPI_FAILURE (Status))
112c2c66affSColin Finck {
113c2c66affSColin Finck ACPI_EXCEPTION ((AE_INFO, Status,
114c2c66affSColin Finck "Could not get result from predicate evaluation"));
115c2c66affSColin Finck
116c2c66affSColin Finck return_ACPI_STATUS (Status);
117c2c66affSColin Finck }
118c2c66affSColin Finck }
119c2c66affSColin Finck else
120c2c66affSColin Finck {
121c2c66affSColin Finck Status = AcpiDsCreateOperand (WalkState, WalkState->Op, 0);
122c2c66affSColin Finck if (ACPI_FAILURE (Status))
123c2c66affSColin Finck {
124c2c66affSColin Finck return_ACPI_STATUS (Status);
125c2c66affSColin Finck }
126c2c66affSColin Finck
127c2c66affSColin Finck Status = AcpiExResolveToValue (&WalkState->Operands [0], WalkState);
128c2c66affSColin Finck if (ACPI_FAILURE (Status))
129c2c66affSColin Finck {
130c2c66affSColin Finck return_ACPI_STATUS (Status);
131c2c66affSColin Finck }
132c2c66affSColin Finck
133c2c66affSColin Finck ObjDesc = WalkState->Operands [0];
134c2c66affSColin Finck }
135c2c66affSColin Finck
136c2c66affSColin Finck if (!ObjDesc)
137c2c66affSColin Finck {
138c2c66affSColin Finck ACPI_ERROR ((AE_INFO,
139c2c66affSColin Finck "No predicate ObjDesc=%p State=%p",
140c2c66affSColin Finck ObjDesc, WalkState));
141c2c66affSColin Finck
142c2c66affSColin Finck return_ACPI_STATUS (AE_AML_NO_OPERAND);
143c2c66affSColin Finck }
144c2c66affSColin Finck
145c2c66affSColin Finck /*
146c2c66affSColin Finck * Result of predicate evaluation must be an Integer
147c2c66affSColin Finck * object. Implicitly convert the argument if necessary.
148c2c66affSColin Finck */
149c2c66affSColin Finck Status = AcpiExConvertToInteger (ObjDesc, &LocalObjDesc,
150ec55f0ebSThomas Faber ACPI_IMPLICIT_CONVERSION);
151c2c66affSColin Finck if (ACPI_FAILURE (Status))
152c2c66affSColin Finck {
153c2c66affSColin Finck goto Cleanup;
154c2c66affSColin Finck }
155c2c66affSColin Finck
156c2c66affSColin Finck if (LocalObjDesc->Common.Type != ACPI_TYPE_INTEGER)
157c2c66affSColin Finck {
158c2c66affSColin Finck ACPI_ERROR ((AE_INFO,
159c2c66affSColin Finck "Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X",
160c2c66affSColin Finck ObjDesc, WalkState, ObjDesc->Common.Type));
161c2c66affSColin Finck
162c2c66affSColin Finck Status = AE_AML_OPERAND_TYPE;
163c2c66affSColin Finck goto Cleanup;
164c2c66affSColin Finck }
165c2c66affSColin Finck
166c2c66affSColin Finck /* Truncate the predicate to 32-bits if necessary */
167c2c66affSColin Finck
168c2c66affSColin Finck (void) AcpiExTruncateFor32bitTable (LocalObjDesc);
169c2c66affSColin Finck
170c2c66affSColin Finck /*
171c2c66affSColin Finck * Save the result of the predicate evaluation on
172c2c66affSColin Finck * the control stack
173c2c66affSColin Finck */
174c2c66affSColin Finck if (LocalObjDesc->Integer.Value)
175c2c66affSColin Finck {
176c2c66affSColin Finck WalkState->ControlState->Common.Value = TRUE;
177c2c66affSColin Finck }
178c2c66affSColin Finck else
179c2c66affSColin Finck {
180c2c66affSColin Finck /*
181c2c66affSColin Finck * Predicate is FALSE, we will just toss the
182c2c66affSColin Finck * rest of the package
183c2c66affSColin Finck */
184c2c66affSColin Finck WalkState->ControlState->Common.Value = FALSE;
185c2c66affSColin Finck Status = AE_CTRL_FALSE;
186c2c66affSColin Finck }
187c2c66affSColin Finck
188c2c66affSColin Finck /* Predicate can be used for an implicit return value */
189c2c66affSColin Finck
190c2c66affSColin Finck (void) AcpiDsDoImplicitReturn (LocalObjDesc, WalkState, TRUE);
191c2c66affSColin Finck
192c2c66affSColin Finck
193c2c66affSColin Finck Cleanup:
194c2c66affSColin Finck
195c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
196c2c66affSColin Finck "Completed a predicate eval=%X Op=%p\n",
197c2c66affSColin Finck WalkState->ControlState->Common.Value, WalkState->Op));
198c2c66affSColin Finck
199c2c66affSColin Finck /* Break to debugger to display result */
200c2c66affSColin Finck
201c2c66affSColin Finck AcpiDbDisplayResultObject (LocalObjDesc, WalkState);
202c2c66affSColin Finck
203c2c66affSColin Finck /*
204c2c66affSColin Finck * Delete the predicate result object (we know that
205c2c66affSColin Finck * we don't need it anymore)
206c2c66affSColin Finck */
207c2c66affSColin Finck if (LocalObjDesc != ObjDesc)
208c2c66affSColin Finck {
209c2c66affSColin Finck AcpiUtRemoveReference (LocalObjDesc);
210c2c66affSColin Finck }
211c2c66affSColin Finck AcpiUtRemoveReference (ObjDesc);
212c2c66affSColin Finck
213c2c66affSColin Finck WalkState->ControlState->Common.State = ACPI_CONTROL_NORMAL;
214c2c66affSColin Finck return_ACPI_STATUS (Status);
215c2c66affSColin Finck }
216c2c66affSColin Finck
217c2c66affSColin Finck
218c2c66affSColin Finck /*****************************************************************************
219c2c66affSColin Finck *
220c2c66affSColin Finck * FUNCTION: AcpiDsExecBeginOp
221c2c66affSColin Finck *
222c2c66affSColin Finck * PARAMETERS: WalkState - Current state of the parse tree walk
223c2c66affSColin Finck * OutOp - Where to return op if a new one is created
224c2c66affSColin Finck *
225c2c66affSColin Finck * RETURN: Status
226c2c66affSColin Finck *
227c2c66affSColin Finck * DESCRIPTION: Descending callback used during the execution of control
228c2c66affSColin Finck * methods. This is where most operators and operands are
229c2c66affSColin Finck * dispatched to the interpreter.
230c2c66affSColin Finck *
231c2c66affSColin Finck ****************************************************************************/
232c2c66affSColin Finck
233c2c66affSColin Finck ACPI_STATUS
AcpiDsExecBeginOp(ACPI_WALK_STATE * WalkState,ACPI_PARSE_OBJECT ** OutOp)234c2c66affSColin Finck AcpiDsExecBeginOp (
235c2c66affSColin Finck ACPI_WALK_STATE *WalkState,
236c2c66affSColin Finck ACPI_PARSE_OBJECT **OutOp)
237c2c66affSColin Finck {
238c2c66affSColin Finck ACPI_PARSE_OBJECT *Op;
239c2c66affSColin Finck ACPI_STATUS Status = AE_OK;
240c2c66affSColin Finck UINT32 OpcodeClass;
241c2c66affSColin Finck
242c2c66affSColin Finck
243c2c66affSColin Finck ACPI_FUNCTION_TRACE_PTR (DsExecBeginOp, WalkState);
244c2c66affSColin Finck
245c2c66affSColin Finck
246c2c66affSColin Finck Op = WalkState->Op;
247c2c66affSColin Finck if (!Op)
248c2c66affSColin Finck {
249c2c66affSColin Finck Status = AcpiDsLoad2BeginOp (WalkState, OutOp);
250c2c66affSColin Finck if (ACPI_FAILURE (Status))
251c2c66affSColin Finck {
252c2c66affSColin Finck goto ErrorExit;
253c2c66affSColin Finck }
254c2c66affSColin Finck
255c2c66affSColin Finck Op = *OutOp;
256c2c66affSColin Finck WalkState->Op = Op;
257c2c66affSColin Finck WalkState->Opcode = Op->Common.AmlOpcode;
258c2c66affSColin Finck WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
259c2c66affSColin Finck
260c2c66affSColin Finck if (AcpiNsOpensScope (WalkState->OpInfo->ObjectType))
261c2c66affSColin Finck {
262c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
263c2c66affSColin Finck "(%s) Popping scope for Op %p\n",
264c2c66affSColin Finck AcpiUtGetTypeName (WalkState->OpInfo->ObjectType), Op));
265c2c66affSColin Finck
266c2c66affSColin Finck Status = AcpiDsScopeStackPop (WalkState);
267c2c66affSColin Finck if (ACPI_FAILURE (Status))
268c2c66affSColin Finck {
269c2c66affSColin Finck goto ErrorExit;
270c2c66affSColin Finck }
271c2c66affSColin Finck }
272c2c66affSColin Finck }
273c2c66affSColin Finck
274c2c66affSColin Finck if (Op == WalkState->Origin)
275c2c66affSColin Finck {
276c2c66affSColin Finck if (OutOp)
277c2c66affSColin Finck {
278c2c66affSColin Finck *OutOp = Op;
279c2c66affSColin Finck }
280c2c66affSColin Finck
281c2c66affSColin Finck return_ACPI_STATUS (AE_OK);
282c2c66affSColin Finck }
283c2c66affSColin Finck
284c2c66affSColin Finck /*
285c2c66affSColin Finck * If the previous opcode was a conditional, this opcode
286c2c66affSColin Finck * must be the beginning of the associated predicate.
287c2c66affSColin Finck * Save this knowledge in the current scope descriptor
288c2c66affSColin Finck */
289c2c66affSColin Finck if ((WalkState->ControlState) &&
290c2c66affSColin Finck (WalkState->ControlState->Common.State ==
291c2c66affSColin Finck ACPI_CONTROL_CONDITIONAL_EXECUTING))
292c2c66affSColin Finck {
293c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
294c2c66affSColin Finck "Exec predicate Op=%p State=%p\n",
295c2c66affSColin Finck Op, WalkState));
296c2c66affSColin Finck
297c2c66affSColin Finck WalkState->ControlState->Common.State =
298c2c66affSColin Finck ACPI_CONTROL_PREDICATE_EXECUTING;
299c2c66affSColin Finck
300c2c66affSColin Finck /* Save start of predicate */
301c2c66affSColin Finck
302c2c66affSColin Finck WalkState->ControlState->Control.PredicateOp = Op;
303c2c66affSColin Finck }
304c2c66affSColin Finck
305c2c66affSColin Finck
306c2c66affSColin Finck OpcodeClass = WalkState->OpInfo->Class;
307c2c66affSColin Finck
308c2c66affSColin Finck /* We want to send namepaths to the load code */
309c2c66affSColin Finck
310c2c66affSColin Finck if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
311c2c66affSColin Finck {
312c2c66affSColin Finck OpcodeClass = AML_CLASS_NAMED_OBJECT;
313c2c66affSColin Finck }
314c2c66affSColin Finck
315c2c66affSColin Finck /*
316c2c66affSColin Finck * Handle the opcode based upon the opcode type
317c2c66affSColin Finck */
318c2c66affSColin Finck switch (OpcodeClass)
319c2c66affSColin Finck {
320c2c66affSColin Finck case AML_CLASS_CONTROL:
321c2c66affSColin Finck
322c2c66affSColin Finck Status = AcpiDsExecBeginControlOp (WalkState, Op);
323c2c66affSColin Finck break;
324c2c66affSColin Finck
325c2c66affSColin Finck case AML_CLASS_NAMED_OBJECT:
326c2c66affSColin Finck
327c2c66affSColin Finck if (WalkState->WalkType & ACPI_WALK_METHOD)
328c2c66affSColin Finck {
329c2c66affSColin Finck /*
330c2c66affSColin Finck * Found a named object declaration during method execution;
331c2c66affSColin Finck * we must enter this object into the namespace. The created
332c2c66affSColin Finck * object is temporary and will be deleted upon completion of
333c2c66affSColin Finck * the execution of this method.
334c2c66affSColin Finck *
335c2c66affSColin Finck * Note 10/2010: Except for the Scope() op. This opcode does
336c2c66affSColin Finck * not actually create a new object, it refers to an existing
337c2c66affSColin Finck * object. However, for Scope(), we want to indeed open a
338c2c66affSColin Finck * new scope.
339c2c66affSColin Finck */
340c2c66affSColin Finck if (Op->Common.AmlOpcode != AML_SCOPE_OP)
341c2c66affSColin Finck {
342c2c66affSColin Finck Status = AcpiDsLoad2BeginOp (WalkState, NULL);
343c2c66affSColin Finck }
344c2c66affSColin Finck else
345c2c66affSColin Finck {
346c2c66affSColin Finck Status = AcpiDsScopeStackPush (
347c2c66affSColin Finck Op->Named.Node, Op->Named.Node->Type, WalkState);
348c2c66affSColin Finck if (ACPI_FAILURE (Status))
349c2c66affSColin Finck {
350c2c66affSColin Finck return_ACPI_STATUS (Status);
351c2c66affSColin Finck }
352c2c66affSColin Finck }
353c2c66affSColin Finck }
354c2c66affSColin Finck break;
355c2c66affSColin Finck
356c2c66affSColin Finck case AML_CLASS_EXECUTE:
357c2c66affSColin Finck case AML_CLASS_CREATE:
358c2c66affSColin Finck
359c2c66affSColin Finck break;
360c2c66affSColin Finck
361c2c66affSColin Finck default:
362c2c66affSColin Finck
363c2c66affSColin Finck break;
364c2c66affSColin Finck }
365c2c66affSColin Finck
366c2c66affSColin Finck /* Nothing to do here during method execution */
367c2c66affSColin Finck
368c2c66affSColin Finck return_ACPI_STATUS (Status);
369c2c66affSColin Finck
370c2c66affSColin Finck
371c2c66affSColin Finck ErrorExit:
372c2c66affSColin Finck Status = AcpiDsMethodError (Status, WalkState);
373c2c66affSColin Finck return_ACPI_STATUS (Status);
374c2c66affSColin Finck }
375c2c66affSColin Finck
376c2c66affSColin Finck
377c2c66affSColin Finck /*****************************************************************************
378c2c66affSColin Finck *
379c2c66affSColin Finck * FUNCTION: AcpiDsExecEndOp
380c2c66affSColin Finck *
381c2c66affSColin Finck * PARAMETERS: WalkState - Current state of the parse tree walk
382c2c66affSColin Finck *
383c2c66affSColin Finck * RETURN: Status
384c2c66affSColin Finck *
385c2c66affSColin Finck * DESCRIPTION: Ascending callback used during the execution of control
386c2c66affSColin Finck * methods. The only thing we really need to do here is to
387c2c66affSColin Finck * notice the beginning of IF, ELSE, and WHILE blocks.
388c2c66affSColin Finck *
389c2c66affSColin Finck ****************************************************************************/
390c2c66affSColin Finck
391c2c66affSColin Finck ACPI_STATUS
AcpiDsExecEndOp(ACPI_WALK_STATE * WalkState)392c2c66affSColin Finck AcpiDsExecEndOp (
393c2c66affSColin Finck ACPI_WALK_STATE *WalkState)
394c2c66affSColin Finck {
395c2c66affSColin Finck ACPI_PARSE_OBJECT *Op;
396c2c66affSColin Finck ACPI_STATUS Status = AE_OK;
397c2c66affSColin Finck UINT32 OpType;
398c2c66affSColin Finck UINT32 OpClass;
399c2c66affSColin Finck ACPI_PARSE_OBJECT *NextOp;
400c2c66affSColin Finck ACPI_PARSE_OBJECT *FirstArg;
401040546d8SThomas Faber #ifdef ACPI_EXEC_APP
402040546d8SThomas Faber char *Namepath;
403040546d8SThomas Faber ACPI_OPERAND_OBJECT *ObjDesc;
404040546d8SThomas Faber #endif
405c2c66affSColin Finck
406c2c66affSColin Finck ACPI_FUNCTION_TRACE_PTR (DsExecEndOp, WalkState);
407c2c66affSColin Finck
408c2c66affSColin Finck
409c2c66affSColin Finck Op = WalkState->Op;
410c2c66affSColin Finck OpType = WalkState->OpInfo->Type;
411c2c66affSColin Finck OpClass = WalkState->OpInfo->Class;
412c2c66affSColin Finck
413c2c66affSColin Finck if (OpClass == AML_CLASS_UNKNOWN)
414c2c66affSColin Finck {
415c2c66affSColin Finck ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%X", Op->Common.AmlOpcode));
416c2c66affSColin Finck return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
417c2c66affSColin Finck }
418c2c66affSColin Finck
419c2c66affSColin Finck FirstArg = Op->Common.Value.Arg;
420c2c66affSColin Finck
421c2c66affSColin Finck /* Init the walk state */
422c2c66affSColin Finck
423c2c66affSColin Finck WalkState->NumOperands = 0;
424c2c66affSColin Finck WalkState->OperandIndex = 0;
425c2c66affSColin Finck WalkState->ReturnDesc = NULL;
426c2c66affSColin Finck WalkState->ResultObj = NULL;
427c2c66affSColin Finck
428c2c66affSColin Finck /* Call debugger for single step support (DEBUG build only) */
429c2c66affSColin Finck
430c2c66affSColin Finck Status = AcpiDbSingleStep (WalkState, Op, OpClass);
431c2c66affSColin Finck if (ACPI_FAILURE (Status))
432c2c66affSColin Finck {
433c2c66affSColin Finck return_ACPI_STATUS (Status);
434c2c66affSColin Finck }
435c2c66affSColin Finck
436c2c66affSColin Finck /* Decode the Opcode Class */
437c2c66affSColin Finck
438c2c66affSColin Finck switch (OpClass)
439c2c66affSColin Finck {
440c2c66affSColin Finck case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */
441c2c66affSColin Finck
442c2c66affSColin Finck if (WalkState->Opcode == AML_INT_NAMEPATH_OP)
443c2c66affSColin Finck {
444c2c66affSColin Finck Status = AcpiDsEvaluateNamePath (WalkState);
445c2c66affSColin Finck if (ACPI_FAILURE (Status))
446c2c66affSColin Finck {
447c2c66affSColin Finck goto Cleanup;
448c2c66affSColin Finck }
449c2c66affSColin Finck }
450c2c66affSColin Finck break;
451c2c66affSColin Finck
452c2c66affSColin Finck case AML_CLASS_EXECUTE: /* Most operators with arguments */
453c2c66affSColin Finck
454c2c66affSColin Finck /* Build resolved operand stack */
455c2c66affSColin Finck
456c2c66affSColin Finck Status = AcpiDsCreateOperands (WalkState, FirstArg);
457c2c66affSColin Finck if (ACPI_FAILURE (Status))
458c2c66affSColin Finck {
459c2c66affSColin Finck goto Cleanup;
460c2c66affSColin Finck }
461c2c66affSColin Finck
462c2c66affSColin Finck /*
463c2c66affSColin Finck * All opcodes require operand resolution, with the only exceptions
464c2c66affSColin Finck * being the ObjectType and SizeOf operators.
465c2c66affSColin Finck */
466c2c66affSColin Finck if (!(WalkState->OpInfo->Flags & AML_NO_OPERAND_RESOLVE))
467c2c66affSColin Finck {
468c2c66affSColin Finck /* Resolve all operands */
469c2c66affSColin Finck
470c2c66affSColin Finck Status = AcpiExResolveOperands (WalkState->Opcode,
471c2c66affSColin Finck &(WalkState->Operands [WalkState->NumOperands -1]),
472c2c66affSColin Finck WalkState);
473c2c66affSColin Finck }
474c2c66affSColin Finck
475c2c66affSColin Finck if (ACPI_SUCCESS (Status))
476c2c66affSColin Finck {
477c2c66affSColin Finck /*
478c2c66affSColin Finck * Dispatch the request to the appropriate interpreter handler
479c2c66affSColin Finck * routine. There is one routine per opcode "type" based upon the
480c2c66affSColin Finck * number of opcode arguments and return type.
481c2c66affSColin Finck */
482c2c66affSColin Finck Status = AcpiGbl_OpTypeDispatch[OpType] (WalkState);
483c2c66affSColin Finck }
484c2c66affSColin Finck else
485c2c66affSColin Finck {
486c2c66affSColin Finck /*
487c2c66affSColin Finck * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the
488c2c66affSColin Finck * Local is uninitialized.
489c2c66affSColin Finck */
490c2c66affSColin Finck if ((Status == AE_AML_UNINITIALIZED_LOCAL) &&
491c2c66affSColin Finck (WalkState->Opcode == AML_STORE_OP) &&
492c2c66affSColin Finck (WalkState->Operands[0]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) &&
493c2c66affSColin Finck (WalkState->Operands[1]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) &&
494c2c66affSColin Finck (WalkState->Operands[0]->Reference.Class ==
495c2c66affSColin Finck WalkState->Operands[1]->Reference.Class) &&
496c2c66affSColin Finck (WalkState->Operands[0]->Reference.Value ==
497c2c66affSColin Finck WalkState->Operands[1]->Reference.Value))
498c2c66affSColin Finck {
499c2c66affSColin Finck Status = AE_OK;
500c2c66affSColin Finck }
501c2c66affSColin Finck else
502c2c66affSColin Finck {
503c2c66affSColin Finck ACPI_EXCEPTION ((AE_INFO, Status,
504c2c66affSColin Finck "While resolving operands for [%s]",
505c2c66affSColin Finck AcpiPsGetOpcodeName (WalkState->Opcode)));
506c2c66affSColin Finck }
507c2c66affSColin Finck }
508c2c66affSColin Finck
509c2c66affSColin Finck /* Always delete the argument objects and clear the operand stack */
510c2c66affSColin Finck
511c2c66affSColin Finck AcpiDsClearOperands (WalkState);
512c2c66affSColin Finck
513c2c66affSColin Finck /*
514c2c66affSColin Finck * If a result object was returned from above, push it on the
515c2c66affSColin Finck * current result stack
516c2c66affSColin Finck */
517c2c66affSColin Finck if (ACPI_SUCCESS (Status) &&
518c2c66affSColin Finck WalkState->ResultObj)
519c2c66affSColin Finck {
520c2c66affSColin Finck Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
521c2c66affSColin Finck }
522c2c66affSColin Finck break;
523c2c66affSColin Finck
524c2c66affSColin Finck default:
525c2c66affSColin Finck
526c2c66affSColin Finck switch (OpType)
527c2c66affSColin Finck {
528c2c66affSColin Finck case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
529c2c66affSColin Finck
530c2c66affSColin Finck /* 1 Operand, 0 ExternalResult, 0 InternalResult */
531c2c66affSColin Finck
532c2c66affSColin Finck Status = AcpiDsExecEndControlOp (WalkState, Op);
533c2c66affSColin Finck
534c2c66affSColin Finck break;
535c2c66affSColin Finck
536c2c66affSColin Finck case AML_TYPE_METHOD_CALL:
537c2c66affSColin Finck /*
538c2c66affSColin Finck * If the method is referenced from within a package
539c2c66affSColin Finck * declaration, it is not a invocation of the method, just
540c2c66affSColin Finck * a reference to it.
541c2c66affSColin Finck */
542c2c66affSColin Finck if ((Op->Asl.Parent) &&
543c2c66affSColin Finck ((Op->Asl.Parent->Asl.AmlOpcode == AML_PACKAGE_OP) ||
544c2c66affSColin Finck (Op->Asl.Parent->Asl.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
545c2c66affSColin Finck {
546c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
547c2c66affSColin Finck "Method Reference in a Package, Op=%p\n", Op));
548c2c66affSColin Finck
549c2c66affSColin Finck Op->Common.Node = (ACPI_NAMESPACE_NODE *)
550c2c66affSColin Finck Op->Asl.Value.Arg->Asl.Node;
551c2c66affSColin Finck AcpiUtAddReference (Op->Asl.Value.Arg->Asl.Node->Object);
552c2c66affSColin Finck return_ACPI_STATUS (AE_OK);
553c2c66affSColin Finck }
554c2c66affSColin Finck
555c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
556c2c66affSColin Finck "Method invocation, Op=%p\n", Op));
557c2c66affSColin Finck
558c2c66affSColin Finck /*
559c2c66affSColin Finck * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
560c2c66affSColin Finck * the method Node pointer
561c2c66affSColin Finck */
562c2c66affSColin Finck /* NextOp points to the op that holds the method name */
563c2c66affSColin Finck
564c2c66affSColin Finck NextOp = FirstArg;
565c2c66affSColin Finck
566c2c66affSColin Finck /* NextOp points to first argument op */
567c2c66affSColin Finck
568c2c66affSColin Finck NextOp = NextOp->Common.Next;
569c2c66affSColin Finck
570c2c66affSColin Finck /*
571c2c66affSColin Finck * Get the method's arguments and put them on the operand stack
572c2c66affSColin Finck */
573c2c66affSColin Finck Status = AcpiDsCreateOperands (WalkState, NextOp);
574c2c66affSColin Finck if (ACPI_FAILURE (Status))
575c2c66affSColin Finck {
576c2c66affSColin Finck break;
577c2c66affSColin Finck }
578c2c66affSColin Finck
579c2c66affSColin Finck /*
580c2c66affSColin Finck * Since the operands will be passed to another control method,
581c2c66affSColin Finck * we must resolve all local references here (Local variables,
582c2c66affSColin Finck * arguments to *this* method, etc.)
583c2c66affSColin Finck */
584c2c66affSColin Finck Status = AcpiDsResolveOperands (WalkState);
585c2c66affSColin Finck if (ACPI_FAILURE (Status))
586c2c66affSColin Finck {
587c2c66affSColin Finck /* On error, clear all resolved operands */
588c2c66affSColin Finck
589c2c66affSColin Finck AcpiDsClearOperands (WalkState);
590c2c66affSColin Finck break;
591c2c66affSColin Finck }
592c2c66affSColin Finck
593c2c66affSColin Finck /*
594c2c66affSColin Finck * Tell the walk loop to preempt this running method and
595c2c66affSColin Finck * execute the new method
596c2c66affSColin Finck */
597c2c66affSColin Finck Status = AE_CTRL_TRANSFER;
598c2c66affSColin Finck
599c2c66affSColin Finck /*
600c2c66affSColin Finck * Return now; we don't want to disturb anything,
601c2c66affSColin Finck * especially the operand count!
602c2c66affSColin Finck */
603c2c66affSColin Finck return_ACPI_STATUS (Status);
604c2c66affSColin Finck
605c2c66affSColin Finck case AML_TYPE_CREATE_FIELD:
606c2c66affSColin Finck
607c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
608c2c66affSColin Finck "Executing CreateField Buffer/Index Op=%p\n", Op));
609c2c66affSColin Finck
610c2c66affSColin Finck Status = AcpiDsLoad2EndOp (WalkState);
611c2c66affSColin Finck if (ACPI_FAILURE (Status))
612c2c66affSColin Finck {
613c2c66affSColin Finck break;
614c2c66affSColin Finck }
615c2c66affSColin Finck
616c2c66affSColin Finck Status = AcpiDsEvalBufferFieldOperands (WalkState, Op);
617040546d8SThomas Faber if (ACPI_FAILURE (Status))
618040546d8SThomas Faber {
619040546d8SThomas Faber break;
620040546d8SThomas Faber }
621040546d8SThomas Faber
622040546d8SThomas Faber #ifdef ACPI_EXEC_APP
623040546d8SThomas Faber /*
624040546d8SThomas Faber * AcpiExec support for namespace initialization file (initialize
625040546d8SThomas Faber * BufferFields in this code.)
626040546d8SThomas Faber */
627040546d8SThomas Faber Namepath = AcpiNsGetExternalPathname (Op->Common.Node);
628040546d8SThomas Faber Status = AeLookupInitFileEntry (Namepath, &ObjDesc);
629040546d8SThomas Faber if (ACPI_SUCCESS (Status))
630040546d8SThomas Faber {
631040546d8SThomas Faber Status = AcpiExWriteDataToField (ObjDesc, Op->Common.Node->Object, NULL);
6320a656b57SThomas Faber if (ACPI_FAILURE (Status))
633040546d8SThomas Faber {
634040546d8SThomas Faber ACPI_EXCEPTION ((AE_INFO, Status, "While writing to buffer field"));
635040546d8SThomas Faber }
636040546d8SThomas Faber }
637040546d8SThomas Faber ACPI_FREE (Namepath);
638040546d8SThomas Faber Status = AE_OK;
639040546d8SThomas Faber #endif
640c2c66affSColin Finck break;
641c2c66affSColin Finck
642c2c66affSColin Finck
643c2c66affSColin Finck case AML_TYPE_CREATE_OBJECT:
644c2c66affSColin Finck
645c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
6466847cc3aSThomas Faber "Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n",
6476847cc3aSThomas Faber Op, Op->Named.Value.Arg, Op->Common.Parent->Common.AmlOpcode));
648c2c66affSColin Finck
649c2c66affSColin Finck switch (Op->Common.Parent->Common.AmlOpcode)
650c2c66affSColin Finck {
651c2c66affSColin Finck case AML_NAME_OP:
652c2c66affSColin Finck /*
653c2c66affSColin Finck * Put the Node on the object stack (Contains the ACPI Name
654c2c66affSColin Finck * of this object)
655c2c66affSColin Finck */
656c2c66affSColin Finck WalkState->Operands[0] = (void *)
657c2c66affSColin Finck Op->Common.Parent->Common.Node;
658c2c66affSColin Finck WalkState->NumOperands = 1;
659c2c66affSColin Finck
660c2c66affSColin Finck Status = AcpiDsCreateNode (WalkState,
661c2c66affSColin Finck Op->Common.Parent->Common.Node, Op->Common.Parent);
662c2c66affSColin Finck if (ACPI_FAILURE (Status))
663c2c66affSColin Finck {
664c2c66affSColin Finck break;
665c2c66affSColin Finck }
666c2c66affSColin Finck
6679587fe1cSThomas Faber ACPI_FALLTHROUGH;
668c2c66affSColin Finck
669c2c66affSColin Finck case AML_INT_EVAL_SUBTREE_OP:
670c2c66affSColin Finck
671c2c66affSColin Finck Status = AcpiDsEvalDataObjectOperands (WalkState, Op,
672c2c66affSColin Finck AcpiNsGetAttachedObject (Op->Common.Parent->Common.Node));
673c2c66affSColin Finck break;
674c2c66affSColin Finck
675c2c66affSColin Finck default:
676c2c66affSColin Finck
677c2c66affSColin Finck Status = AcpiDsEvalDataObjectOperands (WalkState, Op, NULL);
678c2c66affSColin Finck break;
679c2c66affSColin Finck }
680c2c66affSColin Finck
681c2c66affSColin Finck /*
682c2c66affSColin Finck * If a result object was returned from above, push it on the
683c2c66affSColin Finck * current result stack
684c2c66affSColin Finck */
685c2c66affSColin Finck if (WalkState->ResultObj)
686c2c66affSColin Finck {
687c2c66affSColin Finck Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
688c2c66affSColin Finck }
689c2c66affSColin Finck break;
690c2c66affSColin Finck
691c2c66affSColin Finck case AML_TYPE_NAMED_FIELD:
692c2c66affSColin Finck case AML_TYPE_NAMED_COMPLEX:
693c2c66affSColin Finck case AML_TYPE_NAMED_SIMPLE:
694c2c66affSColin Finck case AML_TYPE_NAMED_NO_OBJ:
695c2c66affSColin Finck
696c2c66affSColin Finck Status = AcpiDsLoad2EndOp (WalkState);
697c2c66affSColin Finck if (ACPI_FAILURE (Status))
698c2c66affSColin Finck {
699c2c66affSColin Finck break;
700c2c66affSColin Finck }
701c2c66affSColin Finck
702c2c66affSColin Finck if (Op->Common.AmlOpcode == AML_REGION_OP)
703c2c66affSColin Finck {
704c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
705c2c66affSColin Finck "Executing OpRegion Address/Length Op=%p\n", Op));
706c2c66affSColin Finck
707c2c66affSColin Finck Status = AcpiDsEvalRegionOperands (WalkState, Op);
708c2c66affSColin Finck if (ACPI_FAILURE (Status))
709c2c66affSColin Finck {
710c2c66affSColin Finck break;
711c2c66affSColin Finck }
712c2c66affSColin Finck }
713c2c66affSColin Finck else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP)
714c2c66affSColin Finck {
715c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
716c2c66affSColin Finck "Executing DataTableRegion Strings Op=%p\n", Op));
717c2c66affSColin Finck
718c2c66affSColin Finck Status = AcpiDsEvalTableRegionOperands (WalkState, Op);
719c2c66affSColin Finck if (ACPI_FAILURE (Status))
720c2c66affSColin Finck {
721c2c66affSColin Finck break;
722c2c66affSColin Finck }
723c2c66affSColin Finck }
724c2c66affSColin Finck else if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
725c2c66affSColin Finck {
726c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
727c2c66affSColin Finck "Executing BankField Op=%p\n", Op));
728c2c66affSColin Finck
729c2c66affSColin Finck Status = AcpiDsEvalBankFieldOperands (WalkState, Op);
730c2c66affSColin Finck if (ACPI_FAILURE (Status))
731c2c66affSColin Finck {
732c2c66affSColin Finck break;
733c2c66affSColin Finck }
734c2c66affSColin Finck }
735c2c66affSColin Finck break;
736c2c66affSColin Finck
737c2c66affSColin Finck case AML_TYPE_UNDEFINED:
738c2c66affSColin Finck
739c2c66affSColin Finck ACPI_ERROR ((AE_INFO,
740c2c66affSColin Finck "Undefined opcode type Op=%p", Op));
741c2c66affSColin Finck return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
742c2c66affSColin Finck
743c2c66affSColin Finck case AML_TYPE_BOGUS:
744c2c66affSColin Finck
745c2c66affSColin Finck ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
746c2c66affSColin Finck "Internal opcode=%X type Op=%p\n",
747c2c66affSColin Finck WalkState->Opcode, Op));
748c2c66affSColin Finck break;
749c2c66affSColin Finck
750c2c66affSColin Finck default:
751c2c66affSColin Finck
752c2c66affSColin Finck ACPI_ERROR ((AE_INFO,
753c2c66affSColin Finck "Unimplemented opcode, class=0x%X "
754c2c66affSColin Finck "type=0x%X Opcode=0x%X Op=%p",
755c2c66affSColin Finck OpClass, OpType, Op->Common.AmlOpcode, Op));
756c2c66affSColin Finck
757c2c66affSColin Finck Status = AE_NOT_IMPLEMENTED;
758c2c66affSColin Finck break;
759c2c66affSColin Finck }
760c2c66affSColin Finck }
761c2c66affSColin Finck
762c2c66affSColin Finck /*
763c2c66affSColin Finck * ACPI 2.0 support for 64-bit integers: Truncate numeric
764c2c66affSColin Finck * result value if we are executing from a 32-bit ACPI table
765c2c66affSColin Finck */
766c2c66affSColin Finck (void) AcpiExTruncateFor32bitTable (WalkState->ResultObj);
767c2c66affSColin Finck
768c2c66affSColin Finck /*
769c2c66affSColin Finck * Check if we just completed the evaluation of a
770c2c66affSColin Finck * conditional predicate
771c2c66affSColin Finck */
772c2c66affSColin Finck if ((ACPI_SUCCESS (Status)) &&
773c2c66affSColin Finck (WalkState->ControlState) &&
774c2c66affSColin Finck (WalkState->ControlState->Common.State ==
775c2c66affSColin Finck ACPI_CONTROL_PREDICATE_EXECUTING) &&
776c2c66affSColin Finck (WalkState->ControlState->Control.PredicateOp == Op))
777c2c66affSColin Finck {
778c2c66affSColin Finck Status = AcpiDsGetPredicateValue (WalkState, WalkState->ResultObj);
779c2c66affSColin Finck WalkState->ResultObj = NULL;
780c2c66affSColin Finck }
781c2c66affSColin Finck
782c2c66affSColin Finck
783c2c66affSColin Finck Cleanup:
784c2c66affSColin Finck
785c2c66affSColin Finck if (WalkState->ResultObj)
786c2c66affSColin Finck {
787c2c66affSColin Finck /* Break to debugger to display result */
788c2c66affSColin Finck
789c2c66affSColin Finck AcpiDbDisplayResultObject (WalkState->ResultObj,WalkState);
790c2c66affSColin Finck
791c2c66affSColin Finck /*
792c2c66affSColin Finck * Delete the result op if and only if:
793c2c66affSColin Finck * Parent will not use the result -- such as any
794c2c66affSColin Finck * non-nested type2 op in a method (parent will be method)
795c2c66affSColin Finck */
796c2c66affSColin Finck AcpiDsDeleteResultIfNotUsed (Op, WalkState->ResultObj, WalkState);
797c2c66affSColin Finck }
798c2c66affSColin Finck
799c2c66affSColin Finck #ifdef _UNDER_DEVELOPMENT
800c2c66affSColin Finck
801c2c66affSColin Finck if (WalkState->ParserState.Aml == WalkState->ParserState.AmlEnd)
802c2c66affSColin Finck {
803c2c66affSColin Finck AcpiDbMethodEnd (WalkState);
804c2c66affSColin Finck }
805c2c66affSColin Finck #endif
806c2c66affSColin Finck
807c2c66affSColin Finck /* Invoke exception handler on error */
808c2c66affSColin Finck
809c2c66affSColin Finck if (ACPI_FAILURE (Status))
810c2c66affSColin Finck {
811c2c66affSColin Finck Status = AcpiDsMethodError (Status, WalkState);
812c2c66affSColin Finck }
813c2c66affSColin Finck
814c2c66affSColin Finck /* Always clear the object stack */
815c2c66affSColin Finck
816c2c66affSColin Finck WalkState->NumOperands = 0;
817c2c66affSColin Finck return_ACPI_STATUS (Status);
818c2c66affSColin Finck }
819