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