1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: dswexec - Dispatcher method execution callbacks;
5*4882a593Smuzhiyun * dispatch to interpreter.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 2000 - 2020, Intel Corp.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun *****************************************************************************/
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <acpi/acpi.h>
12*4882a593Smuzhiyun #include "accommon.h"
13*4882a593Smuzhiyun #include "acparser.h"
14*4882a593Smuzhiyun #include "amlcode.h"
15*4882a593Smuzhiyun #include "acdispat.h"
16*4882a593Smuzhiyun #include "acinterp.h"
17*4882a593Smuzhiyun #include "acnamesp.h"
18*4882a593Smuzhiyun #include "acdebug.h"
19*4882a593Smuzhiyun #ifdef ACPI_EXEC_APP
20*4882a593Smuzhiyun #include "aecommon.h"
21*4882a593Smuzhiyun #endif
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #define _COMPONENT ACPI_DISPATCHER
24*4882a593Smuzhiyun ACPI_MODULE_NAME("dswexec")
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /*
27*4882a593Smuzhiyun * Dispatch table for opcode classes
28*4882a593Smuzhiyun */
29*4882a593Smuzhiyun static acpi_execute_op acpi_gbl_op_type_dispatch[] = {
30*4882a593Smuzhiyun acpi_ex_opcode_0A_0T_1R,
31*4882a593Smuzhiyun acpi_ex_opcode_1A_0T_0R,
32*4882a593Smuzhiyun acpi_ex_opcode_1A_0T_1R,
33*4882a593Smuzhiyun acpi_ex_opcode_1A_1T_0R,
34*4882a593Smuzhiyun acpi_ex_opcode_1A_1T_1R,
35*4882a593Smuzhiyun acpi_ex_opcode_2A_0T_0R,
36*4882a593Smuzhiyun acpi_ex_opcode_2A_0T_1R,
37*4882a593Smuzhiyun acpi_ex_opcode_2A_1T_1R,
38*4882a593Smuzhiyun acpi_ex_opcode_2A_2T_1R,
39*4882a593Smuzhiyun acpi_ex_opcode_3A_0T_0R,
40*4882a593Smuzhiyun acpi_ex_opcode_3A_1T_1R,
41*4882a593Smuzhiyun acpi_ex_opcode_6A_0T_1R
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun /*****************************************************************************
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun * FUNCTION: acpi_ds_get_predicate_value
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun * PARAMETERS: walk_state - Current state of the parse tree walk
49*4882a593Smuzhiyun * result_obj - if non-zero, pop result from result stack
50*4882a593Smuzhiyun *
51*4882a593Smuzhiyun * RETURN: Status
52*4882a593Smuzhiyun *
53*4882a593Smuzhiyun * DESCRIPTION: Get the result of a predicate evaluation
54*4882a593Smuzhiyun *
55*4882a593Smuzhiyun ****************************************************************************/
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun acpi_status
acpi_ds_get_predicate_value(struct acpi_walk_state * walk_state,union acpi_operand_object * result_obj)58*4882a593Smuzhiyun acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
59*4882a593Smuzhiyun union acpi_operand_object *result_obj)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun acpi_status status = AE_OK;
62*4882a593Smuzhiyun union acpi_operand_object *obj_desc;
63*4882a593Smuzhiyun union acpi_operand_object *local_obj_desc = NULL;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state);
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun walk_state->control_state->common.state = 0;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun if (result_obj) {
70*4882a593Smuzhiyun status = acpi_ds_result_pop(&obj_desc, walk_state);
71*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
72*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
73*4882a593Smuzhiyun "Could not get result from predicate evaluation"));
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun return_ACPI_STATUS(status);
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun } else {
78*4882a593Smuzhiyun status = acpi_ds_create_operand(walk_state, walk_state->op, 0);
79*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
80*4882a593Smuzhiyun return_ACPI_STATUS(status);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun status =
84*4882a593Smuzhiyun acpi_ex_resolve_to_value(&walk_state->operands[0],
85*4882a593Smuzhiyun walk_state);
86*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
87*4882a593Smuzhiyun return_ACPI_STATUS(status);
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun obj_desc = walk_state->operands[0];
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun if (!obj_desc) {
94*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
95*4882a593Smuzhiyun "No predicate ObjDesc=%p State=%p",
96*4882a593Smuzhiyun obj_desc, walk_state));
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_NO_OPERAND);
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun /*
102*4882a593Smuzhiyun * Result of predicate evaluation must be an Integer
103*4882a593Smuzhiyun * object. Implicitly convert the argument if necessary.
104*4882a593Smuzhiyun */
105*4882a593Smuzhiyun status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc,
106*4882a593Smuzhiyun ACPI_IMPLICIT_CONVERSION);
107*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
108*4882a593Smuzhiyun goto cleanup;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun if (local_obj_desc->common.type != ACPI_TYPE_INTEGER) {
112*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
113*4882a593Smuzhiyun "Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X",
114*4882a593Smuzhiyun obj_desc, walk_state, obj_desc->common.type));
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun status = AE_AML_OPERAND_TYPE;
117*4882a593Smuzhiyun goto cleanup;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* Truncate the predicate to 32-bits if necessary */
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun (void)acpi_ex_truncate_for32bit_table(local_obj_desc);
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /*
125*4882a593Smuzhiyun * Save the result of the predicate evaluation on
126*4882a593Smuzhiyun * the control stack
127*4882a593Smuzhiyun */
128*4882a593Smuzhiyun if (local_obj_desc->integer.value) {
129*4882a593Smuzhiyun walk_state->control_state->common.value = TRUE;
130*4882a593Smuzhiyun } else {
131*4882a593Smuzhiyun /*
132*4882a593Smuzhiyun * Predicate is FALSE, we will just toss the
133*4882a593Smuzhiyun * rest of the package
134*4882a593Smuzhiyun */
135*4882a593Smuzhiyun walk_state->control_state->common.value = FALSE;
136*4882a593Smuzhiyun status = AE_CTRL_FALSE;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* Predicate can be used for an implicit return value */
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE);
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun cleanup:
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
146*4882a593Smuzhiyun "Completed a predicate eval=%X Op=%p\n",
147*4882a593Smuzhiyun walk_state->control_state->common.value,
148*4882a593Smuzhiyun walk_state->op));
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /* Break to debugger to display result */
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun acpi_db_display_result_object(local_obj_desc, walk_state);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /*
155*4882a593Smuzhiyun * Delete the predicate result object (we know that
156*4882a593Smuzhiyun * we don't need it anymore)
157*4882a593Smuzhiyun */
158*4882a593Smuzhiyun if (local_obj_desc != obj_desc) {
159*4882a593Smuzhiyun acpi_ut_remove_reference(local_obj_desc);
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun acpi_ut_remove_reference(obj_desc);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
164*4882a593Smuzhiyun return_ACPI_STATUS(status);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun /*****************************************************************************
168*4882a593Smuzhiyun *
169*4882a593Smuzhiyun * FUNCTION: acpi_ds_exec_begin_op
170*4882a593Smuzhiyun *
171*4882a593Smuzhiyun * PARAMETERS: walk_state - Current state of the parse tree walk
172*4882a593Smuzhiyun * out_op - Where to return op if a new one is created
173*4882a593Smuzhiyun *
174*4882a593Smuzhiyun * RETURN: Status
175*4882a593Smuzhiyun *
176*4882a593Smuzhiyun * DESCRIPTION: Descending callback used during the execution of control
177*4882a593Smuzhiyun * methods. This is where most operators and operands are
178*4882a593Smuzhiyun * dispatched to the interpreter.
179*4882a593Smuzhiyun *
180*4882a593Smuzhiyun ****************************************************************************/
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun acpi_status
acpi_ds_exec_begin_op(struct acpi_walk_state * walk_state,union acpi_parse_object ** out_op)183*4882a593Smuzhiyun acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
184*4882a593Smuzhiyun union acpi_parse_object **out_op)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun union acpi_parse_object *op;
187*4882a593Smuzhiyun acpi_status status = AE_OK;
188*4882a593Smuzhiyun u32 opcode_class;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun op = walk_state->op;
193*4882a593Smuzhiyun if (!op) {
194*4882a593Smuzhiyun status = acpi_ds_load2_begin_op(walk_state, out_op);
195*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
196*4882a593Smuzhiyun goto error_exit;
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun op = *out_op;
200*4882a593Smuzhiyun walk_state->op = op;
201*4882a593Smuzhiyun walk_state->opcode = op->common.aml_opcode;
202*4882a593Smuzhiyun walk_state->op_info =
203*4882a593Smuzhiyun acpi_ps_get_opcode_info(op->common.aml_opcode);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun if (acpi_ns_opens_scope(walk_state->op_info->object_type)) {
206*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
207*4882a593Smuzhiyun "(%s) Popping scope for Op %p\n",
208*4882a593Smuzhiyun acpi_ut_get_type_name(walk_state->
209*4882a593Smuzhiyun op_info->
210*4882a593Smuzhiyun object_type),
211*4882a593Smuzhiyun op));
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun status = acpi_ds_scope_stack_pop(walk_state);
214*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
215*4882a593Smuzhiyun goto error_exit;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if (op == walk_state->origin) {
221*4882a593Smuzhiyun if (out_op) {
222*4882a593Smuzhiyun *out_op = op;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /*
229*4882a593Smuzhiyun * If the previous opcode was a conditional, this opcode
230*4882a593Smuzhiyun * must be the beginning of the associated predicate.
231*4882a593Smuzhiyun * Save this knowledge in the current scope descriptor
232*4882a593Smuzhiyun */
233*4882a593Smuzhiyun if ((walk_state->control_state) &&
234*4882a593Smuzhiyun (walk_state->control_state->common.state ==
235*4882a593Smuzhiyun ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
236*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
237*4882a593Smuzhiyun "Exec predicate Op=%p State=%p\n",
238*4882a593Smuzhiyun op, walk_state));
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun walk_state->control_state->common.state =
241*4882a593Smuzhiyun ACPI_CONTROL_PREDICATE_EXECUTING;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /* Save start of predicate */
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun walk_state->control_state->control.predicate_op = op;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun opcode_class = walk_state->op_info->class;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun /* We want to send namepaths to the load code */
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
253*4882a593Smuzhiyun opcode_class = AML_CLASS_NAMED_OBJECT;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /*
257*4882a593Smuzhiyun * Handle the opcode based upon the opcode type
258*4882a593Smuzhiyun */
259*4882a593Smuzhiyun switch (opcode_class) {
260*4882a593Smuzhiyun case AML_CLASS_CONTROL:
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun status = acpi_ds_exec_begin_control_op(walk_state, op);
263*4882a593Smuzhiyun break;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun case AML_CLASS_NAMED_OBJECT:
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun if (walk_state->walk_type & ACPI_WALK_METHOD) {
268*4882a593Smuzhiyun /*
269*4882a593Smuzhiyun * Found a named object declaration during method execution;
270*4882a593Smuzhiyun * we must enter this object into the namespace. The created
271*4882a593Smuzhiyun * object is temporary and will be deleted upon completion of
272*4882a593Smuzhiyun * the execution of this method.
273*4882a593Smuzhiyun *
274*4882a593Smuzhiyun * Note 10/2010: Except for the Scope() op. This opcode does
275*4882a593Smuzhiyun * not actually create a new object, it refers to an existing
276*4882a593Smuzhiyun * object. However, for Scope(), we want to indeed open a
277*4882a593Smuzhiyun * new scope.
278*4882a593Smuzhiyun */
279*4882a593Smuzhiyun if (op->common.aml_opcode != AML_SCOPE_OP) {
280*4882a593Smuzhiyun status =
281*4882a593Smuzhiyun acpi_ds_load2_begin_op(walk_state, NULL);
282*4882a593Smuzhiyun } else {
283*4882a593Smuzhiyun status =
284*4882a593Smuzhiyun acpi_ds_scope_stack_push(op->named.node,
285*4882a593Smuzhiyun op->named.node->
286*4882a593Smuzhiyun type, walk_state);
287*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
288*4882a593Smuzhiyun return_ACPI_STATUS(status);
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun break;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun case AML_CLASS_EXECUTE:
295*4882a593Smuzhiyun case AML_CLASS_CREATE:
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun break;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun default:
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun break;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /* Nothing to do here during method execution */
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun return_ACPI_STATUS(status);
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun error_exit:
309*4882a593Smuzhiyun status = acpi_ds_method_error(status, walk_state);
310*4882a593Smuzhiyun return_ACPI_STATUS(status);
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun /*****************************************************************************
314*4882a593Smuzhiyun *
315*4882a593Smuzhiyun * FUNCTION: acpi_ds_exec_end_op
316*4882a593Smuzhiyun *
317*4882a593Smuzhiyun * PARAMETERS: walk_state - Current state of the parse tree walk
318*4882a593Smuzhiyun *
319*4882a593Smuzhiyun * RETURN: Status
320*4882a593Smuzhiyun *
321*4882a593Smuzhiyun * DESCRIPTION: Ascending callback used during the execution of control
322*4882a593Smuzhiyun * methods. The only thing we really need to do here is to
323*4882a593Smuzhiyun * notice the beginning of IF, ELSE, and WHILE blocks.
324*4882a593Smuzhiyun *
325*4882a593Smuzhiyun ****************************************************************************/
326*4882a593Smuzhiyun
acpi_ds_exec_end_op(struct acpi_walk_state * walk_state)327*4882a593Smuzhiyun acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun union acpi_parse_object *op;
330*4882a593Smuzhiyun acpi_status status = AE_OK;
331*4882a593Smuzhiyun u32 op_type;
332*4882a593Smuzhiyun u32 op_class;
333*4882a593Smuzhiyun union acpi_parse_object *next_op;
334*4882a593Smuzhiyun union acpi_parse_object *first_arg;
335*4882a593Smuzhiyun #ifdef ACPI_EXEC_APP
336*4882a593Smuzhiyun char *namepath;
337*4882a593Smuzhiyun union acpi_operand_object *obj_desc;
338*4882a593Smuzhiyun #endif
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state);
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun op = walk_state->op;
343*4882a593Smuzhiyun op_type = walk_state->op_info->type;
344*4882a593Smuzhiyun op_class = walk_state->op_info->class;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun if (op_class == AML_CLASS_UNKNOWN) {
347*4882a593Smuzhiyun ACPI_ERROR((AE_INFO, "Unknown opcode 0x%X",
348*4882a593Smuzhiyun op->common.aml_opcode));
349*4882a593Smuzhiyun return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun first_arg = op->common.value.arg;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun /* Init the walk state */
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun walk_state->num_operands = 0;
357*4882a593Smuzhiyun walk_state->operand_index = 0;
358*4882a593Smuzhiyun walk_state->return_desc = NULL;
359*4882a593Smuzhiyun walk_state->result_obj = NULL;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun /* Call debugger for single step support (DEBUG build only) */
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun status = acpi_db_single_step(walk_state, op, op_class);
364*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
365*4882a593Smuzhiyun return_ACPI_STATUS(status);
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /* Decode the Opcode Class */
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun switch (op_class) {
371*4882a593Smuzhiyun case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
374*4882a593Smuzhiyun status = acpi_ds_evaluate_name_path(walk_state);
375*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
376*4882a593Smuzhiyun goto cleanup;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun break;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun case AML_CLASS_EXECUTE: /* Most operators with arguments */
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun /* Build resolved operand stack */
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun status = acpi_ds_create_operands(walk_state, first_arg);
386*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
387*4882a593Smuzhiyun goto cleanup;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun /*
391*4882a593Smuzhiyun * All opcodes require operand resolution, with the only exceptions
392*4882a593Smuzhiyun * being the object_type and size_of operators.
393*4882a593Smuzhiyun */
394*4882a593Smuzhiyun if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /* Resolve all operands */
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun status = acpi_ex_resolve_operands(walk_state->opcode,
399*4882a593Smuzhiyun &(walk_state->
400*4882a593Smuzhiyun operands
401*4882a593Smuzhiyun [walk_state->
402*4882a593Smuzhiyun num_operands - 1]),
403*4882a593Smuzhiyun walk_state);
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
407*4882a593Smuzhiyun /*
408*4882a593Smuzhiyun * Dispatch the request to the appropriate interpreter handler
409*4882a593Smuzhiyun * routine. There is one routine per opcode "type" based upon the
410*4882a593Smuzhiyun * number of opcode arguments and return type.
411*4882a593Smuzhiyun */
412*4882a593Smuzhiyun status =
413*4882a593Smuzhiyun acpi_gbl_op_type_dispatch[op_type] (walk_state);
414*4882a593Smuzhiyun } else {
415*4882a593Smuzhiyun /*
416*4882a593Smuzhiyun * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the
417*4882a593Smuzhiyun * Local is uninitialized.
418*4882a593Smuzhiyun */
419*4882a593Smuzhiyun if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
420*4882a593Smuzhiyun (walk_state->opcode == AML_STORE_OP) &&
421*4882a593Smuzhiyun (walk_state->operands[0]->common.type ==
422*4882a593Smuzhiyun ACPI_TYPE_LOCAL_REFERENCE)
423*4882a593Smuzhiyun && (walk_state->operands[1]->common.type ==
424*4882a593Smuzhiyun ACPI_TYPE_LOCAL_REFERENCE)
425*4882a593Smuzhiyun && (walk_state->operands[0]->reference.class ==
426*4882a593Smuzhiyun walk_state->operands[1]->reference.class)
427*4882a593Smuzhiyun && (walk_state->operands[0]->reference.value ==
428*4882a593Smuzhiyun walk_state->operands[1]->reference.value)) {
429*4882a593Smuzhiyun status = AE_OK;
430*4882a593Smuzhiyun } else {
431*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
432*4882a593Smuzhiyun "While resolving operands for [%s]",
433*4882a593Smuzhiyun acpi_ps_get_opcode_name
434*4882a593Smuzhiyun (walk_state->opcode)));
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /* Always delete the argument objects and clear the operand stack */
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun acpi_ds_clear_operands(walk_state);
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun /*
443*4882a593Smuzhiyun * If a result object was returned from above, push it on the
444*4882a593Smuzhiyun * current result stack
445*4882a593Smuzhiyun */
446*4882a593Smuzhiyun if (ACPI_SUCCESS(status) && walk_state->result_obj) {
447*4882a593Smuzhiyun status =
448*4882a593Smuzhiyun acpi_ds_result_push(walk_state->result_obj,
449*4882a593Smuzhiyun walk_state);
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun break;
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun default:
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun switch (op_type) {
456*4882a593Smuzhiyun case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun /* 1 Operand, 0 external_result, 0 internal_result */
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun status = acpi_ds_exec_end_control_op(walk_state, op);
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun break;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun case AML_TYPE_METHOD_CALL:
465*4882a593Smuzhiyun /*
466*4882a593Smuzhiyun * If the method is referenced from within a package
467*4882a593Smuzhiyun * declaration, it is not a invocation of the method, just
468*4882a593Smuzhiyun * a reference to it.
469*4882a593Smuzhiyun */
470*4882a593Smuzhiyun if ((op->asl.parent) &&
471*4882a593Smuzhiyun ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP)
472*4882a593Smuzhiyun || (op->asl.parent->asl.aml_opcode ==
473*4882a593Smuzhiyun AML_VARIABLE_PACKAGE_OP))) {
474*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
475*4882a593Smuzhiyun "Method Reference in a Package, Op=%p\n",
476*4882a593Smuzhiyun op));
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun op->common.node = (struct acpi_namespace_node *)
479*4882a593Smuzhiyun op->asl.value.arg->asl.node;
480*4882a593Smuzhiyun acpi_ut_add_reference(op->asl.value.arg->asl.
481*4882a593Smuzhiyun node->object);
482*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
486*4882a593Smuzhiyun "Method invocation, Op=%p\n", op));
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun /*
489*4882a593Smuzhiyun * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
490*4882a593Smuzhiyun * the method Node pointer
491*4882a593Smuzhiyun */
492*4882a593Smuzhiyun /* next_op points to the op that holds the method name */
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun next_op = first_arg;
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun /* next_op points to first argument op */
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun next_op = next_op->common.next;
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun /*
501*4882a593Smuzhiyun * Get the method's arguments and put them on the operand stack
502*4882a593Smuzhiyun */
503*4882a593Smuzhiyun status = acpi_ds_create_operands(walk_state, next_op);
504*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
505*4882a593Smuzhiyun break;
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun /*
509*4882a593Smuzhiyun * Since the operands will be passed to another control method,
510*4882a593Smuzhiyun * we must resolve all local references here (Local variables,
511*4882a593Smuzhiyun * arguments to *this* method, etc.)
512*4882a593Smuzhiyun */
513*4882a593Smuzhiyun status = acpi_ds_resolve_operands(walk_state);
514*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun /* On error, clear all resolved operands */
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun acpi_ds_clear_operands(walk_state);
519*4882a593Smuzhiyun break;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun /*
523*4882a593Smuzhiyun * Tell the walk loop to preempt this running method and
524*4882a593Smuzhiyun * execute the new method
525*4882a593Smuzhiyun */
526*4882a593Smuzhiyun status = AE_CTRL_TRANSFER;
527*4882a593Smuzhiyun
528*4882a593Smuzhiyun /*
529*4882a593Smuzhiyun * Return now; we don't want to disturb anything,
530*4882a593Smuzhiyun * especially the operand count!
531*4882a593Smuzhiyun */
532*4882a593Smuzhiyun return_ACPI_STATUS(status);
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun case AML_TYPE_CREATE_FIELD:
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
537*4882a593Smuzhiyun "Executing CreateField Buffer/Index Op=%p\n",
538*4882a593Smuzhiyun op));
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun status = acpi_ds_load2_end_op(walk_state);
541*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
542*4882a593Smuzhiyun break;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun status =
546*4882a593Smuzhiyun acpi_ds_eval_buffer_field_operands(walk_state, op);
547*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
548*4882a593Smuzhiyun break;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun #ifdef ACPI_EXEC_APP
551*4882a593Smuzhiyun /*
552*4882a593Smuzhiyun * acpi_exec support for namespace initialization file (initialize
553*4882a593Smuzhiyun * buffer_fields in this code.)
554*4882a593Smuzhiyun */
555*4882a593Smuzhiyun namepath =
556*4882a593Smuzhiyun acpi_ns_get_external_pathname(op->common.node);
557*4882a593Smuzhiyun status = ae_lookup_init_file_entry(namepath, &obj_desc);
558*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
559*4882a593Smuzhiyun status =
560*4882a593Smuzhiyun acpi_ex_write_data_to_field(obj_desc,
561*4882a593Smuzhiyun op->common.
562*4882a593Smuzhiyun node->object,
563*4882a593Smuzhiyun NULL);
564*4882a593Smuzhiyun if ACPI_FAILURE
565*4882a593Smuzhiyun (status) {
566*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
567*4882a593Smuzhiyun "While writing to buffer field"));
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun ACPI_FREE(namepath);
571*4882a593Smuzhiyun status = AE_OK;
572*4882a593Smuzhiyun #endif
573*4882a593Smuzhiyun break;
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun case AML_TYPE_CREATE_OBJECT:
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
578*4882a593Smuzhiyun "Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n",
579*4882a593Smuzhiyun op, op->named.value.arg,
580*4882a593Smuzhiyun op->common.parent->common.
581*4882a593Smuzhiyun aml_opcode));
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun switch (op->common.parent->common.aml_opcode) {
584*4882a593Smuzhiyun case AML_NAME_OP:
585*4882a593Smuzhiyun /*
586*4882a593Smuzhiyun * Put the Node on the object stack (Contains the ACPI Name
587*4882a593Smuzhiyun * of this object)
588*4882a593Smuzhiyun */
589*4882a593Smuzhiyun walk_state->operands[0] = (void *)
590*4882a593Smuzhiyun op->common.parent->common.node;
591*4882a593Smuzhiyun walk_state->num_operands = 1;
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun status = acpi_ds_create_node(walk_state,
594*4882a593Smuzhiyun op->common.parent->
595*4882a593Smuzhiyun common.node,
596*4882a593Smuzhiyun op->common.parent);
597*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
598*4882a593Smuzhiyun break;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun /* Fall through */
602*4882a593Smuzhiyun /*lint -fallthrough */
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun case AML_INT_EVAL_SUBTREE_OP:
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun status =
607*4882a593Smuzhiyun acpi_ds_eval_data_object_operands
608*4882a593Smuzhiyun (walk_state, op,
609*4882a593Smuzhiyun acpi_ns_get_attached_object(op->common.
610*4882a593Smuzhiyun parent->common.
611*4882a593Smuzhiyun node));
612*4882a593Smuzhiyun break;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun default:
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun status =
617*4882a593Smuzhiyun acpi_ds_eval_data_object_operands
618*4882a593Smuzhiyun (walk_state, op, NULL);
619*4882a593Smuzhiyun break;
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun /*
623*4882a593Smuzhiyun * If a result object was returned from above, push it on the
624*4882a593Smuzhiyun * current result stack
625*4882a593Smuzhiyun */
626*4882a593Smuzhiyun if (walk_state->result_obj) {
627*4882a593Smuzhiyun status =
628*4882a593Smuzhiyun acpi_ds_result_push(walk_state->result_obj,
629*4882a593Smuzhiyun walk_state);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun break;
632*4882a593Smuzhiyun
633*4882a593Smuzhiyun case AML_TYPE_NAMED_FIELD:
634*4882a593Smuzhiyun case AML_TYPE_NAMED_COMPLEX:
635*4882a593Smuzhiyun case AML_TYPE_NAMED_SIMPLE:
636*4882a593Smuzhiyun case AML_TYPE_NAMED_NO_OBJ:
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun status = acpi_ds_load2_end_op(walk_state);
639*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
640*4882a593Smuzhiyun break;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun if (op->common.aml_opcode == AML_REGION_OP) {
644*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
645*4882a593Smuzhiyun "Executing OpRegion Address/Length Op=%p\n",
646*4882a593Smuzhiyun op));
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun status =
649*4882a593Smuzhiyun acpi_ds_eval_region_operands(walk_state,
650*4882a593Smuzhiyun op);
651*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
652*4882a593Smuzhiyun break;
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun } else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
655*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
656*4882a593Smuzhiyun "Executing DataTableRegion Strings Op=%p\n",
657*4882a593Smuzhiyun op));
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun status =
660*4882a593Smuzhiyun acpi_ds_eval_table_region_operands
661*4882a593Smuzhiyun (walk_state, op);
662*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
663*4882a593Smuzhiyun break;
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
666*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
667*4882a593Smuzhiyun "Executing BankField Op=%p\n",
668*4882a593Smuzhiyun op));
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun status =
671*4882a593Smuzhiyun acpi_ds_eval_bank_field_operands(walk_state,
672*4882a593Smuzhiyun op);
673*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
674*4882a593Smuzhiyun break;
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun break;
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun case AML_TYPE_UNDEFINED:
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
682*4882a593Smuzhiyun "Undefined opcode type Op=%p", op));
683*4882a593Smuzhiyun return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun case AML_TYPE_BOGUS:
686*4882a593Smuzhiyun
687*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
688*4882a593Smuzhiyun "Internal opcode=%X type Op=%p\n",
689*4882a593Smuzhiyun walk_state->opcode, op));
690*4882a593Smuzhiyun break;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun default:
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
695*4882a593Smuzhiyun "Unimplemented opcode, class=0x%X "
696*4882a593Smuzhiyun "type=0x%X Opcode=0x%X Op=%p",
697*4882a593Smuzhiyun op_class, op_type, op->common.aml_opcode,
698*4882a593Smuzhiyun op));
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun status = AE_NOT_IMPLEMENTED;
701*4882a593Smuzhiyun break;
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /*
706*4882a593Smuzhiyun * ACPI 2.0 support for 64-bit integers: Truncate numeric
707*4882a593Smuzhiyun * result value if we are executing from a 32-bit ACPI table
708*4882a593Smuzhiyun */
709*4882a593Smuzhiyun (void)acpi_ex_truncate_for32bit_table(walk_state->result_obj);
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun /*
712*4882a593Smuzhiyun * Check if we just completed the evaluation of a
713*4882a593Smuzhiyun * conditional predicate
714*4882a593Smuzhiyun */
715*4882a593Smuzhiyun if ((ACPI_SUCCESS(status)) &&
716*4882a593Smuzhiyun (walk_state->control_state) &&
717*4882a593Smuzhiyun (walk_state->control_state->common.state ==
718*4882a593Smuzhiyun ACPI_CONTROL_PREDICATE_EXECUTING) &&
719*4882a593Smuzhiyun (walk_state->control_state->control.predicate_op == op)) {
720*4882a593Smuzhiyun status =
721*4882a593Smuzhiyun acpi_ds_get_predicate_value(walk_state,
722*4882a593Smuzhiyun walk_state->result_obj);
723*4882a593Smuzhiyun walk_state->result_obj = NULL;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun cleanup:
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun if (walk_state->result_obj) {
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun /* Break to debugger to display result */
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun acpi_db_display_result_object(walk_state->result_obj,
733*4882a593Smuzhiyun walk_state);
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun /*
736*4882a593Smuzhiyun * Delete the result op if and only if:
737*4882a593Smuzhiyun * Parent will not use the result -- such as any
738*4882a593Smuzhiyun * non-nested type2 op in a method (parent will be method)
739*4882a593Smuzhiyun */
740*4882a593Smuzhiyun acpi_ds_delete_result_if_not_used(op, walk_state->result_obj,
741*4882a593Smuzhiyun walk_state);
742*4882a593Smuzhiyun }
743*4882a593Smuzhiyun #ifdef _UNDER_DEVELOPMENT
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) {
746*4882a593Smuzhiyun acpi_db_method_end(walk_state);
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun #endif
749*4882a593Smuzhiyun
750*4882a593Smuzhiyun /* Invoke exception handler on error */
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
753*4882a593Smuzhiyun status = acpi_ds_method_error(status, walk_state);
754*4882a593Smuzhiyun }
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun /* Always clear the object stack */
757*4882a593Smuzhiyun
758*4882a593Smuzhiyun walk_state->num_operands = 0;
759*4882a593Smuzhiyun return_ACPI_STATUS(status);
760*4882a593Smuzhiyun }
761