xref: /linux/drivers/acpi/acpica/dswexec.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: dswexec - Dispatcher method execution callbacks;
595b482a8SLen Brown  *                        dispatch to interpreter.
695b482a8SLen Brown  *
7*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
895b482a8SLen Brown  *
995857638SErik Schmauss  *****************************************************************************/
1095b482a8SLen Brown 
1195b482a8SLen Brown #include <acpi/acpi.h>
12e2f7a777SLen Brown #include "accommon.h"
13e2f7a777SLen Brown #include "acparser.h"
14e2f7a777SLen Brown #include "amlcode.h"
15e2f7a777SLen Brown #include "acdispat.h"
16e2f7a777SLen Brown #include "acinterp.h"
17e2f7a777SLen Brown #include "acnamesp.h"
18e2f7a777SLen Brown #include "acdebug.h"
199a1ae804SBob Moore #ifdef ACPI_EXEC_APP
209a1ae804SBob Moore #include "aecommon.h"
219a1ae804SBob Moore #endif
2295b482a8SLen Brown 
2395b482a8SLen Brown #define _COMPONENT          ACPI_DISPATCHER
2495b482a8SLen Brown ACPI_MODULE_NAME("dswexec")
2595b482a8SLen Brown 
2695b482a8SLen Brown /*
2795b482a8SLen Brown  * Dispatch table for opcode classes
2895b482a8SLen Brown  */
29644ef74eSLv Zheng static acpi_execute_op acpi_gbl_op_type_dispatch[] = {
3095b482a8SLen Brown 	acpi_ex_opcode_0A_0T_1R,
3195b482a8SLen Brown 	acpi_ex_opcode_1A_0T_0R,
3295b482a8SLen Brown 	acpi_ex_opcode_1A_0T_1R,
3339ea1bbfSBob Moore 	NULL,			/* Was: acpi_ex_opcode_1A_0T_0R (Was for Load operator) */
3495b482a8SLen Brown 	acpi_ex_opcode_1A_1T_1R,
3595b482a8SLen Brown 	acpi_ex_opcode_2A_0T_0R,
3695b482a8SLen Brown 	acpi_ex_opcode_2A_0T_1R,
3795b482a8SLen Brown 	acpi_ex_opcode_2A_1T_1R,
3895b482a8SLen Brown 	acpi_ex_opcode_2A_2T_1R,
3995b482a8SLen Brown 	acpi_ex_opcode_3A_0T_0R,
4095b482a8SLen Brown 	acpi_ex_opcode_3A_1T_1R,
4195b482a8SLen Brown 	acpi_ex_opcode_6A_0T_1R
4295b482a8SLen Brown };
4395b482a8SLen Brown 
4495b482a8SLen Brown /*****************************************************************************
4595b482a8SLen Brown  *
4695b482a8SLen Brown  * FUNCTION:    acpi_ds_get_predicate_value
4795b482a8SLen Brown  *
4895b482a8SLen Brown  * PARAMETERS:  walk_state      - Current state of the parse tree walk
4995b482a8SLen Brown  *              result_obj      - if non-zero, pop result from result stack
5095b482a8SLen Brown  *
5195b482a8SLen Brown  * RETURN:      Status
5295b482a8SLen Brown  *
5395b482a8SLen Brown  * DESCRIPTION: Get the result of a predicate evaluation
5495b482a8SLen Brown  *
5595b482a8SLen Brown  ****************************************************************************/
5695b482a8SLen Brown 
5795b482a8SLen Brown acpi_status
acpi_ds_get_predicate_value(struct acpi_walk_state * walk_state,union acpi_operand_object * result_obj)5895b482a8SLen Brown acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state,
5995b482a8SLen Brown 			    union acpi_operand_object *result_obj)
6095b482a8SLen Brown {
6195b482a8SLen Brown 	acpi_status status = AE_OK;
6295b482a8SLen Brown 	union acpi_operand_object *obj_desc;
6395b482a8SLen Brown 	union acpi_operand_object *local_obj_desc = NULL;
6495b482a8SLen Brown 
6595b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state);
6695b482a8SLen Brown 
6795b482a8SLen Brown 	walk_state->control_state->common.state = 0;
6895b482a8SLen Brown 
6995b482a8SLen Brown 	if (result_obj) {
7095b482a8SLen Brown 		status = acpi_ds_result_pop(&obj_desc, walk_state);
7195b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
7295b482a8SLen Brown 			ACPI_EXCEPTION((AE_INFO, status,
7395b482a8SLen Brown 					"Could not get result from predicate evaluation"));
7495b482a8SLen Brown 
7595b482a8SLen Brown 			return_ACPI_STATUS(status);
7695b482a8SLen Brown 		}
7795b482a8SLen Brown 	} else {
7895b482a8SLen Brown 		status = acpi_ds_create_operand(walk_state, walk_state->op, 0);
7995b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
8095b482a8SLen Brown 			return_ACPI_STATUS(status);
8195b482a8SLen Brown 		}
8295b482a8SLen Brown 
8395b482a8SLen Brown 		status =
8495b482a8SLen Brown 		    acpi_ex_resolve_to_value(&walk_state->operands[0],
8595b482a8SLen Brown 					     walk_state);
8695b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
8795b482a8SLen Brown 			return_ACPI_STATUS(status);
8895b482a8SLen Brown 		}
8995b482a8SLen Brown 
9095b482a8SLen Brown 		obj_desc = walk_state->operands[0];
9195b482a8SLen Brown 	}
9295b482a8SLen Brown 
9395b482a8SLen Brown 	if (!obj_desc) {
9495b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
9595b482a8SLen Brown 			    "No predicate ObjDesc=%p State=%p",
9695b482a8SLen Brown 			    obj_desc, walk_state));
9795b482a8SLen Brown 
9895b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
9995b482a8SLen Brown 	}
10095b482a8SLen Brown 
10195b482a8SLen Brown 	/*
10295b482a8SLen Brown 	 * Result of predicate evaluation must be an Integer
10395b482a8SLen Brown 	 * object. Implicitly convert the argument if necessary.
10495b482a8SLen Brown 	 */
1055ebd2eaaSBob Moore 	status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc,
106fe97d287SBob Moore 					    ACPI_IMPLICIT_CONVERSION);
10795b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
10895b482a8SLen Brown 		goto cleanup;
10995b482a8SLen Brown 	}
11095b482a8SLen Brown 
1113371c19cSBob Moore 	if (local_obj_desc->common.type != ACPI_TYPE_INTEGER) {
11295b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
113f6a22b0bSBob Moore 			    "Bad predicate (not an integer) ObjDesc=%p State=%p Type=0x%X",
1143371c19cSBob Moore 			    obj_desc, walk_state, obj_desc->common.type));
11595b482a8SLen Brown 
11695b482a8SLen Brown 		status = AE_AML_OPERAND_TYPE;
11795b482a8SLen Brown 		goto cleanup;
11895b482a8SLen Brown 	}
11995b482a8SLen Brown 
12095b482a8SLen Brown 	/* Truncate the predicate to 32-bits if necessary */
12195b482a8SLen Brown 
122ef42e53fSBob Moore 	(void)acpi_ex_truncate_for32bit_table(local_obj_desc);
12395b482a8SLen Brown 
12495b482a8SLen Brown 	/*
12595b482a8SLen Brown 	 * Save the result of the predicate evaluation on
12695b482a8SLen Brown 	 * the control stack
12795b482a8SLen Brown 	 */
12895b482a8SLen Brown 	if (local_obj_desc->integer.value) {
12995b482a8SLen Brown 		walk_state->control_state->common.value = TRUE;
13095b482a8SLen Brown 	} else {
13195b482a8SLen Brown 		/*
13295b482a8SLen Brown 		 * Predicate is FALSE, we will just toss the
13395b482a8SLen Brown 		 * rest of the package
13495b482a8SLen Brown 		 */
13595b482a8SLen Brown 		walk_state->control_state->common.value = FALSE;
13695b482a8SLen Brown 		status = AE_CTRL_FALSE;
13795b482a8SLen Brown 	}
13895b482a8SLen Brown 
13995b482a8SLen Brown 	/* Predicate can be used for an implicit return value */
14095b482a8SLen Brown 
14195b482a8SLen Brown 	(void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE);
14295b482a8SLen Brown 
14395b482a8SLen Brown cleanup:
14495b482a8SLen Brown 
1451fad8738SBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
1461fad8738SBob Moore 			  "Completed a predicate eval=%X Op=%p\n",
14795b482a8SLen Brown 			  walk_state->control_state->common.value,
14895b482a8SLen Brown 			  walk_state->op));
14995b482a8SLen Brown 
15095b482a8SLen Brown 	/* Break to debugger to display result */
15195b482a8SLen Brown 
1528a2a2501SLv Zheng 	acpi_db_display_result_object(local_obj_desc, walk_state);
15395b482a8SLen Brown 
15495b482a8SLen Brown 	/*
15595b482a8SLen Brown 	 * Delete the predicate result object (we know that
15695b482a8SLen Brown 	 * we don't need it anymore)
15795b482a8SLen Brown 	 */
15895b482a8SLen Brown 	if (local_obj_desc != obj_desc) {
15995b482a8SLen Brown 		acpi_ut_remove_reference(local_obj_desc);
16095b482a8SLen Brown 	}
16195b482a8SLen Brown 	acpi_ut_remove_reference(obj_desc);
16295b482a8SLen Brown 
16395b482a8SLen Brown 	walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
16495b482a8SLen Brown 	return_ACPI_STATUS(status);
16595b482a8SLen Brown }
16695b482a8SLen Brown 
16795b482a8SLen Brown /*****************************************************************************
16895b482a8SLen Brown  *
16995b482a8SLen Brown  * FUNCTION:    acpi_ds_exec_begin_op
17095b482a8SLen Brown  *
17195b482a8SLen Brown  * PARAMETERS:  walk_state      - Current state of the parse tree walk
17295b482a8SLen Brown  *              out_op          - Where to return op if a new one is created
17395b482a8SLen Brown  *
17495b482a8SLen Brown  * RETURN:      Status
17595b482a8SLen Brown  *
17695b482a8SLen Brown  * DESCRIPTION: Descending callback used during the execution of control
17795b482a8SLen Brown  *              methods. This is where most operators and operands are
17895b482a8SLen Brown  *              dispatched to the interpreter.
17995b482a8SLen Brown  *
18095b482a8SLen Brown  ****************************************************************************/
18195b482a8SLen Brown 
18295b482a8SLen Brown acpi_status
acpi_ds_exec_begin_op(struct acpi_walk_state * walk_state,union acpi_parse_object ** out_op)18395b482a8SLen Brown acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
18495b482a8SLen Brown 		      union acpi_parse_object **out_op)
18595b482a8SLen Brown {
18695b482a8SLen Brown 	union acpi_parse_object *op;
18795b482a8SLen Brown 	acpi_status status = AE_OK;
18895b482a8SLen Brown 	u32 opcode_class;
18995b482a8SLen Brown 
19095b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state);
19195b482a8SLen Brown 
19295b482a8SLen Brown 	op = walk_state->op;
19395b482a8SLen Brown 	if (!op) {
19495b482a8SLen Brown 		status = acpi_ds_load2_begin_op(walk_state, out_op);
19595b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
19695b482a8SLen Brown 			goto error_exit;
19795b482a8SLen Brown 		}
19895b482a8SLen Brown 
19995b482a8SLen Brown 		op = *out_op;
20095b482a8SLen Brown 		walk_state->op = op;
20195b482a8SLen Brown 		walk_state->opcode = op->common.aml_opcode;
20295b482a8SLen Brown 		walk_state->op_info =
20395b482a8SLen Brown 		    acpi_ps_get_opcode_info(op->common.aml_opcode);
20495b482a8SLen Brown 
20595b482a8SLen Brown 		if (acpi_ns_opens_scope(walk_state->op_info->object_type)) {
20695b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
20795b482a8SLen Brown 					  "(%s) Popping scope for Op %p\n",
20895b482a8SLen Brown 					  acpi_ut_get_type_name(walk_state->
20995b482a8SLen Brown 								op_info->
21095b482a8SLen Brown 								object_type),
21195b482a8SLen Brown 					  op));
21295b482a8SLen Brown 
21395b482a8SLen Brown 			status = acpi_ds_scope_stack_pop(walk_state);
21495b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
21595b482a8SLen Brown 				goto error_exit;
21695b482a8SLen Brown 			}
21795b482a8SLen Brown 		}
21895b482a8SLen Brown 	}
21995b482a8SLen Brown 
22095b482a8SLen Brown 	if (op == walk_state->origin) {
22195b482a8SLen Brown 		if (out_op) {
22295b482a8SLen Brown 			*out_op = op;
22395b482a8SLen Brown 		}
22495b482a8SLen Brown 
22595b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
22695b482a8SLen Brown 	}
22795b482a8SLen Brown 
22895b482a8SLen Brown 	/*
22995b482a8SLen Brown 	 * If the previous opcode was a conditional, this opcode
23095b482a8SLen Brown 	 * must be the beginning of the associated predicate.
23195b482a8SLen Brown 	 * Save this knowledge in the current scope descriptor
23295b482a8SLen Brown 	 */
23395b482a8SLen Brown 	if ((walk_state->control_state) &&
23495b482a8SLen Brown 	    (walk_state->control_state->common.state ==
23595b482a8SLen Brown 	     ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
23695b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
2371fad8738SBob Moore 				  "Exec predicate Op=%p State=%p\n",
2381fad8738SBob Moore 				  op, walk_state));
23995b482a8SLen Brown 
24095b482a8SLen Brown 		walk_state->control_state->common.state =
24195b482a8SLen Brown 		    ACPI_CONTROL_PREDICATE_EXECUTING;
24295b482a8SLen Brown 
24395b482a8SLen Brown 		/* Save start of predicate */
24495b482a8SLen Brown 
24595b482a8SLen Brown 		walk_state->control_state->control.predicate_op = op;
24695b482a8SLen Brown 	}
24795b482a8SLen Brown 
24895b482a8SLen Brown 	opcode_class = walk_state->op_info->class;
24995b482a8SLen Brown 
25095b482a8SLen Brown 	/* We want to send namepaths to the load code */
25195b482a8SLen Brown 
25295b482a8SLen Brown 	if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
25395b482a8SLen Brown 		opcode_class = AML_CLASS_NAMED_OBJECT;
25495b482a8SLen Brown 	}
25595b482a8SLen Brown 
25695b482a8SLen Brown 	/*
25795b482a8SLen Brown 	 * Handle the opcode based upon the opcode type
25895b482a8SLen Brown 	 */
25995b482a8SLen Brown 	switch (opcode_class) {
26095b482a8SLen Brown 	case AML_CLASS_CONTROL:
26195b482a8SLen Brown 
26295b482a8SLen Brown 		status = acpi_ds_exec_begin_control_op(walk_state, op);
26395b482a8SLen Brown 		break;
26495b482a8SLen Brown 
26595b482a8SLen Brown 	case AML_CLASS_NAMED_OBJECT:
26695b482a8SLen Brown 
26795b482a8SLen Brown 		if (walk_state->walk_type & ACPI_WALK_METHOD) {
26895b482a8SLen Brown 			/*
26995b482a8SLen Brown 			 * Found a named object declaration during method execution;
27095b482a8SLen Brown 			 * we must enter this object into the namespace. The created
27195b482a8SLen Brown 			 * object is temporary and will be deleted upon completion of
27295b482a8SLen Brown 			 * the execution of this method.
2738df3fc98SBob Moore 			 *
2748df3fc98SBob Moore 			 * Note 10/2010: Except for the Scope() op. This opcode does
2758df3fc98SBob Moore 			 * not actually create a new object, it refers to an existing
2768df3fc98SBob Moore 			 * object. However, for Scope(), we want to indeed open a
2778df3fc98SBob Moore 			 * new scope.
27895b482a8SLen Brown 			 */
2798df3fc98SBob Moore 			if (op->common.aml_opcode != AML_SCOPE_OP) {
2808df3fc98SBob Moore 				status =
2818df3fc98SBob Moore 				    acpi_ds_load2_begin_op(walk_state, NULL);
2828df3fc98SBob Moore 			} else {
2838df3fc98SBob Moore 				status =
2848df3fc98SBob Moore 				    acpi_ds_scope_stack_push(op->named.node,
2858df3fc98SBob Moore 							     op->named.node->
2868df3fc98SBob Moore 							     type, walk_state);
2878df3fc98SBob Moore 				if (ACPI_FAILURE(status)) {
2888df3fc98SBob Moore 					return_ACPI_STATUS(status);
28995b482a8SLen Brown 				}
2908df3fc98SBob Moore 			}
2918df3fc98SBob Moore 		}
29295b482a8SLen Brown 		break;
29395b482a8SLen Brown 
29495b482a8SLen Brown 	case AML_CLASS_EXECUTE:
29595b482a8SLen Brown 	case AML_CLASS_CREATE:
29695b482a8SLen Brown 
29795b482a8SLen Brown 		break;
29895b482a8SLen Brown 
29995b482a8SLen Brown 	default:
3001d1ea1b7SChao Guan 
30195b482a8SLen Brown 		break;
30295b482a8SLen Brown 	}
30395b482a8SLen Brown 
30495b482a8SLen Brown 	/* Nothing to do here during method execution */
30595b482a8SLen Brown 
30695b482a8SLen Brown 	return_ACPI_STATUS(status);
30795b482a8SLen Brown 
30895b482a8SLen Brown error_exit:
30995b482a8SLen Brown 	status = acpi_ds_method_error(status, walk_state);
31095b482a8SLen Brown 	return_ACPI_STATUS(status);
31195b482a8SLen Brown }
31295b482a8SLen Brown 
31395b482a8SLen Brown /*****************************************************************************
31495b482a8SLen Brown  *
31595b482a8SLen Brown  * FUNCTION:    acpi_ds_exec_end_op
31695b482a8SLen Brown  *
31795b482a8SLen Brown  * PARAMETERS:  walk_state      - Current state of the parse tree walk
31895b482a8SLen Brown  *
31995b482a8SLen Brown  * RETURN:      Status
32095b482a8SLen Brown  *
32195b482a8SLen Brown  * DESCRIPTION: Ascending callback used during the execution of control
32295b482a8SLen Brown  *              methods. The only thing we really need to do here is to
32395b482a8SLen Brown  *              notice the beginning of IF, ELSE, and WHILE blocks.
32495b482a8SLen Brown  *
32595b482a8SLen Brown  ****************************************************************************/
32695b482a8SLen Brown 
acpi_ds_exec_end_op(struct acpi_walk_state * walk_state)32795b482a8SLen Brown acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
32895b482a8SLen Brown {
32995b482a8SLen Brown 	union acpi_parse_object *op;
33095b482a8SLen Brown 	acpi_status status = AE_OK;
33195b482a8SLen Brown 	u32 op_type;
33295b482a8SLen Brown 	u32 op_class;
33395b482a8SLen Brown 	union acpi_parse_object *next_op;
33495b482a8SLen Brown 	union acpi_parse_object *first_arg;
3359a1ae804SBob Moore #ifdef ACPI_EXEC_APP
3369a1ae804SBob Moore 	char *namepath;
3379a1ae804SBob Moore 	union acpi_operand_object *obj_desc;
3389a1ae804SBob Moore #endif
33995b482a8SLen Brown 
34095b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state);
34195b482a8SLen Brown 
34295b482a8SLen Brown 	op = walk_state->op;
34395b482a8SLen Brown 	op_type = walk_state->op_info->type;
34495b482a8SLen Brown 	op_class = walk_state->op_info->class;
34595b482a8SLen Brown 
34695b482a8SLen Brown 	if (op_class == AML_CLASS_UNKNOWN) {
347f6a22b0bSBob Moore 		ACPI_ERROR((AE_INFO, "Unknown opcode 0x%X",
34895b482a8SLen Brown 			    op->common.aml_opcode));
34995b482a8SLen Brown 		return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
35095b482a8SLen Brown 	}
35195b482a8SLen Brown 
35295b482a8SLen Brown 	first_arg = op->common.value.arg;
35395b482a8SLen Brown 
35495b482a8SLen Brown 	/* Init the walk state */
35595b482a8SLen Brown 
35695b482a8SLen Brown 	walk_state->num_operands = 0;
35795b482a8SLen Brown 	walk_state->operand_index = 0;
35895b482a8SLen Brown 	walk_state->return_desc = NULL;
35995b482a8SLen Brown 	walk_state->result_obj = NULL;
36095b482a8SLen Brown 
36195b482a8SLen Brown 	/* Call debugger for single step support (DEBUG build only) */
36295b482a8SLen Brown 
3638a2a2501SLv Zheng 	status = acpi_db_single_step(walk_state, op, op_class);
3648a2a2501SLv Zheng 	if (ACPI_FAILURE(status)) {
3658a2a2501SLv Zheng 		return_ACPI_STATUS(status);
3668a2a2501SLv Zheng 	}
36795b482a8SLen Brown 
36895b482a8SLen Brown 	/* Decode the Opcode Class */
36995b482a8SLen Brown 
37095b482a8SLen Brown 	switch (op_class) {
37195b482a8SLen Brown 	case AML_CLASS_ARGUMENT:	/* Constants, literals, etc. */
37295b482a8SLen Brown 
37395b482a8SLen Brown 		if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
37495b482a8SLen Brown 			status = acpi_ds_evaluate_name_path(walk_state);
37595b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
37695b482a8SLen Brown 				goto cleanup;
37795b482a8SLen Brown 			}
37895b482a8SLen Brown 		}
37995b482a8SLen Brown 		break;
38095b482a8SLen Brown 
38195b482a8SLen Brown 	case AML_CLASS_EXECUTE:	/* Most operators with arguments */
38295b482a8SLen Brown 
38395b482a8SLen Brown 		/* Build resolved operand stack */
38495b482a8SLen Brown 
38595b482a8SLen Brown 		status = acpi_ds_create_operands(walk_state, first_arg);
38695b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
38795b482a8SLen Brown 			goto cleanup;
38895b482a8SLen Brown 		}
38995b482a8SLen Brown 
39095b482a8SLen Brown 		/*
39195b482a8SLen Brown 		 * All opcodes require operand resolution, with the only exceptions
3927dfb216eSAmadeusz Sławiński 		 * being the object_type and size_of operators as well as opcodes that
3937dfb216eSAmadeusz Sławiński 		 * take no arguments.
39495b482a8SLen Brown 		 */
3957dfb216eSAmadeusz Sławiński 		if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE) &&
3967dfb216eSAmadeusz Sławiński 		    (walk_state->op_info->flags & AML_HAS_ARGS)) {
39795b482a8SLen Brown 
39895b482a8SLen Brown 			/* Resolve all operands */
39995b482a8SLen Brown 
40095b482a8SLen Brown 			status = acpi_ex_resolve_operands(walk_state->opcode,
40195b482a8SLen Brown 							  &(walk_state->
40295b482a8SLen Brown 							    operands
40395b482a8SLen Brown 							    [walk_state->
40495b482a8SLen Brown 							     num_operands - 1]),
40595b482a8SLen Brown 							  walk_state);
40695b482a8SLen Brown 		}
40795b482a8SLen Brown 
40895b482a8SLen Brown 		if (ACPI_SUCCESS(status)) {
40995b482a8SLen Brown 			/*
41095b482a8SLen Brown 			 * Dispatch the request to the appropriate interpreter handler
41195b482a8SLen Brown 			 * routine. There is one routine per opcode "type" based upon the
41295b482a8SLen Brown 			 * number of opcode arguments and return type.
41395b482a8SLen Brown 			 */
41495b482a8SLen Brown 			status =
41595b482a8SLen Brown 			    acpi_gbl_op_type_dispatch[op_type] (walk_state);
41695b482a8SLen Brown 		} else {
41795b482a8SLen Brown 			/*
41895b482a8SLen Brown 			 * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the
41995b482a8SLen Brown 			 * Local is uninitialized.
42095b482a8SLen Brown 			 */
42195b482a8SLen Brown 			if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
42295b482a8SLen Brown 			    (walk_state->opcode == AML_STORE_OP) &&
42395b482a8SLen Brown 			    (walk_state->operands[0]->common.type ==
42495b482a8SLen Brown 			     ACPI_TYPE_LOCAL_REFERENCE)
42595b482a8SLen Brown 			    && (walk_state->operands[1]->common.type ==
42695b482a8SLen Brown 				ACPI_TYPE_LOCAL_REFERENCE)
42795b482a8SLen Brown 			    && (walk_state->operands[0]->reference.class ==
42895b482a8SLen Brown 				walk_state->operands[1]->reference.class)
42995b482a8SLen Brown 			    && (walk_state->operands[0]->reference.value ==
43095b482a8SLen Brown 				walk_state->operands[1]->reference.value)) {
43195b482a8SLen Brown 				status = AE_OK;
43295b482a8SLen Brown 			} else {
43395b482a8SLen Brown 				ACPI_EXCEPTION((AE_INFO, status,
43495b482a8SLen Brown 						"While resolving operands for [%s]",
43595b482a8SLen Brown 						acpi_ps_get_opcode_name
43695b482a8SLen Brown 						(walk_state->opcode)));
43795b482a8SLen Brown 			}
43895b482a8SLen Brown 		}
43995b482a8SLen Brown 
44095b482a8SLen Brown 		/* Always delete the argument objects and clear the operand stack */
44195b482a8SLen Brown 
44295b482a8SLen Brown 		acpi_ds_clear_operands(walk_state);
44395b482a8SLen Brown 
44495b482a8SLen Brown 		/*
44595b482a8SLen Brown 		 * If a result object was returned from above, push it on the
44695b482a8SLen Brown 		 * current result stack
44795b482a8SLen Brown 		 */
44895b482a8SLen Brown 		if (ACPI_SUCCESS(status) && walk_state->result_obj) {
44995b482a8SLen Brown 			status =
45095b482a8SLen Brown 			    acpi_ds_result_push(walk_state->result_obj,
45195b482a8SLen Brown 						walk_state);
45295b482a8SLen Brown 		}
45395b482a8SLen Brown 		break;
45495b482a8SLen Brown 
45595b482a8SLen Brown 	default:
45695b482a8SLen Brown 
45795b482a8SLen Brown 		switch (op_type) {
45895b482a8SLen Brown 		case AML_TYPE_CONTROL:	/* Type 1 opcode, IF/ELSE/WHILE/NOOP */
45995b482a8SLen Brown 
46095b482a8SLen Brown 			/* 1 Operand, 0 external_result, 0 internal_result */
46195b482a8SLen Brown 
46295b482a8SLen Brown 			status = acpi_ds_exec_end_control_op(walk_state, op);
46395b482a8SLen Brown 
46495b482a8SLen Brown 			break;
46595b482a8SLen Brown 
46695b482a8SLen Brown 		case AML_TYPE_METHOD_CALL:
46795b482a8SLen Brown 			/*
46895b482a8SLen Brown 			 * If the method is referenced from within a package
46995b482a8SLen Brown 			 * declaration, it is not a invocation of the method, just
47095b482a8SLen Brown 			 * a reference to it.
47195b482a8SLen Brown 			 */
47295b482a8SLen Brown 			if ((op->asl.parent) &&
47395b482a8SLen Brown 			    ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP)
47495b482a8SLen Brown 			     || (op->asl.parent->asl.aml_opcode ==
4759ff5a21aSBob Moore 				 AML_VARIABLE_PACKAGE_OP))) {
47695b482a8SLen Brown 				ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
47795b482a8SLen Brown 						  "Method Reference in a Package, Op=%p\n",
47895b482a8SLen Brown 						  op));
47995b482a8SLen Brown 
4801fad8738SBob Moore 				op->common.node = (struct acpi_namespace_node *)
4811fad8738SBob Moore 				    op->asl.value.arg->asl.node;
48295b482a8SLen Brown 				acpi_ut_add_reference(op->asl.value.arg->asl.
48395b482a8SLen Brown 						      node->object);
48495b482a8SLen Brown 				return_ACPI_STATUS(AE_OK);
48595b482a8SLen Brown 			}
48695b482a8SLen Brown 
48795b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
48895b482a8SLen Brown 					  "Method invocation, Op=%p\n", op));
48995b482a8SLen Brown 
49095b482a8SLen Brown 			/*
49195b482a8SLen Brown 			 * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
49295b482a8SLen Brown 			 * the method Node pointer
49395b482a8SLen Brown 			 */
49495b482a8SLen Brown 			/* next_op points to the op that holds the method name */
49595b482a8SLen Brown 
49695b482a8SLen Brown 			next_op = first_arg;
49795b482a8SLen Brown 
49895b482a8SLen Brown 			/* next_op points to first argument op */
49995b482a8SLen Brown 
50095b482a8SLen Brown 			next_op = next_op->common.next;
50195b482a8SLen Brown 
50295b482a8SLen Brown 			/*
50395b482a8SLen Brown 			 * Get the method's arguments and put them on the operand stack
50495b482a8SLen Brown 			 */
50595b482a8SLen Brown 			status = acpi_ds_create_operands(walk_state, next_op);
50695b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
50795b482a8SLen Brown 				break;
50895b482a8SLen Brown 			}
50995b482a8SLen Brown 
51095b482a8SLen Brown 			/*
51195b482a8SLen Brown 			 * Since the operands will be passed to another control method,
51295b482a8SLen Brown 			 * we must resolve all local references here (Local variables,
51395b482a8SLen Brown 			 * arguments to *this* method, etc.)
51495b482a8SLen Brown 			 */
51595b482a8SLen Brown 			status = acpi_ds_resolve_operands(walk_state);
51695b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
51795b482a8SLen Brown 
51895b482a8SLen Brown 				/* On error, clear all resolved operands */
51995b482a8SLen Brown 
52095b482a8SLen Brown 				acpi_ds_clear_operands(walk_state);
52195b482a8SLen Brown 				break;
52295b482a8SLen Brown 			}
52395b482a8SLen Brown 
52495b482a8SLen Brown 			/*
52595b482a8SLen Brown 			 * Tell the walk loop to preempt this running method and
52695b482a8SLen Brown 			 * execute the new method
52795b482a8SLen Brown 			 */
52895b482a8SLen Brown 			status = AE_CTRL_TRANSFER;
52995b482a8SLen Brown 
53095b482a8SLen Brown 			/*
53195b482a8SLen Brown 			 * Return now; we don't want to disturb anything,
53295b482a8SLen Brown 			 * especially the operand count!
53395b482a8SLen Brown 			 */
53495b482a8SLen Brown 			return_ACPI_STATUS(status);
53595b482a8SLen Brown 
53695b482a8SLen Brown 		case AML_TYPE_CREATE_FIELD:
53795b482a8SLen Brown 
53895b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
53995b482a8SLen Brown 					  "Executing CreateField Buffer/Index Op=%p\n",
54095b482a8SLen Brown 					  op));
54195b482a8SLen Brown 
54295b482a8SLen Brown 			status = acpi_ds_load2_end_op(walk_state);
54395b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
54495b482a8SLen Brown 				break;
54595b482a8SLen Brown 			}
54695b482a8SLen Brown 
54795b482a8SLen Brown 			status =
54895b482a8SLen Brown 			    acpi_ds_eval_buffer_field_operands(walk_state, op);
5499a1ae804SBob Moore 			if (ACPI_FAILURE(status)) {
5509a1ae804SBob Moore 				break;
5519a1ae804SBob Moore 			}
5529a1ae804SBob Moore #ifdef ACPI_EXEC_APP
5539a1ae804SBob Moore 			/*
5549a1ae804SBob Moore 			 * acpi_exec support for namespace initialization file (initialize
5559a1ae804SBob Moore 			 * buffer_fields in this code.)
5569a1ae804SBob Moore 			 */
5579a1ae804SBob Moore 			namepath =
5589a1ae804SBob Moore 			    acpi_ns_get_external_pathname(op->common.node);
5599a1ae804SBob Moore 			status = ae_lookup_init_file_entry(namepath, &obj_desc);
5609a1ae804SBob Moore 			if (ACPI_SUCCESS(status)) {
5619a1ae804SBob Moore 				status =
5629a1ae804SBob Moore 				    acpi_ex_write_data_to_field(obj_desc,
5639a1ae804SBob Moore 								op->common.
5649a1ae804SBob Moore 								node->object,
5659a1ae804SBob Moore 								NULL);
5665ecce804SBob Moore 				if (ACPI_FAILURE(status)) {
5679a1ae804SBob Moore 					ACPI_EXCEPTION((AE_INFO, status,
5689a1ae804SBob Moore 							"While writing to buffer field"));
5699a1ae804SBob Moore 				}
5709a1ae804SBob Moore 			}
5719a1ae804SBob Moore 			ACPI_FREE(namepath);
5729a1ae804SBob Moore 			status = AE_OK;
5739a1ae804SBob Moore #endif
57495b482a8SLen Brown 			break;
57595b482a8SLen Brown 
57695b482a8SLen Brown 		case AML_TYPE_CREATE_OBJECT:
57795b482a8SLen Brown 
57895b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
5795a8361f7SSchmauss, Erik 					  "Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n",
5805a8361f7SSchmauss, Erik 					  op, op->named.value.arg,
5815a8361f7SSchmauss, Erik 					  op->common.parent->common.
5825a8361f7SSchmauss, Erik 					  aml_opcode));
58395b482a8SLen Brown 
58495b482a8SLen Brown 			switch (op->common.parent->common.aml_opcode) {
58595b482a8SLen Brown 			case AML_NAME_OP:
58695b482a8SLen Brown 				/*
58795b482a8SLen Brown 				 * Put the Node on the object stack (Contains the ACPI Name
58895b482a8SLen Brown 				 * of this object)
58995b482a8SLen Brown 				 */
5901fad8738SBob Moore 				walk_state->operands[0] = (void *)
5911fad8738SBob Moore 				    op->common.parent->common.node;
59295b482a8SLen Brown 				walk_state->num_operands = 1;
59395b482a8SLen Brown 
59495b482a8SLen Brown 				status = acpi_ds_create_node(walk_state,
59595b482a8SLen Brown 							     op->common.parent->
59695b482a8SLen Brown 							     common.node,
59795b482a8SLen Brown 							     op->common.parent);
59895b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
59995b482a8SLen Brown 					break;
60095b482a8SLen Brown 				}
60195b482a8SLen Brown 
602c1a7c2ceSNick Desaulniers 				ACPI_FALLTHROUGH;
60395b482a8SLen Brown 
60495b482a8SLen Brown 			case AML_INT_EVAL_SUBTREE_OP:
60595b482a8SLen Brown 
60695b482a8SLen Brown 				status =
60795b482a8SLen Brown 				    acpi_ds_eval_data_object_operands
60895b482a8SLen Brown 				    (walk_state, op,
60995b482a8SLen Brown 				     acpi_ns_get_attached_object(op->common.
61095b482a8SLen Brown 								 parent->common.
61195b482a8SLen Brown 								 node));
61295b482a8SLen Brown 				break;
61395b482a8SLen Brown 
61495b482a8SLen Brown 			default:
61595b482a8SLen Brown 
61695b482a8SLen Brown 				status =
61795b482a8SLen Brown 				    acpi_ds_eval_data_object_operands
61895b482a8SLen Brown 				    (walk_state, op, NULL);
61995b482a8SLen Brown 				break;
62095b482a8SLen Brown 			}
62195b482a8SLen Brown 
62295b482a8SLen Brown 			/*
62395b482a8SLen Brown 			 * If a result object was returned from above, push it on the
62495b482a8SLen Brown 			 * current result stack
62595b482a8SLen Brown 			 */
62695b482a8SLen Brown 			if (walk_state->result_obj) {
62795b482a8SLen Brown 				status =
62895b482a8SLen Brown 				    acpi_ds_result_push(walk_state->result_obj,
62995b482a8SLen Brown 							walk_state);
63095b482a8SLen Brown 			}
63195b482a8SLen Brown 			break;
63295b482a8SLen Brown 
63395b482a8SLen Brown 		case AML_TYPE_NAMED_FIELD:
63495b482a8SLen Brown 		case AML_TYPE_NAMED_COMPLEX:
63595b482a8SLen Brown 		case AML_TYPE_NAMED_SIMPLE:
63695b482a8SLen Brown 		case AML_TYPE_NAMED_NO_OBJ:
63795b482a8SLen Brown 
63895b482a8SLen Brown 			status = acpi_ds_load2_end_op(walk_state);
63995b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
64095b482a8SLen Brown 				break;
64195b482a8SLen Brown 			}
64295b482a8SLen Brown 
64395b482a8SLen Brown 			if (op->common.aml_opcode == AML_REGION_OP) {
64495b482a8SLen Brown 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
64595b482a8SLen Brown 						  "Executing OpRegion Address/Length Op=%p\n",
64695b482a8SLen Brown 						  op));
64795b482a8SLen Brown 
64895b482a8SLen Brown 				status =
64995b482a8SLen Brown 				    acpi_ds_eval_region_operands(walk_state,
65095b482a8SLen Brown 								 op);
65195b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
65295b482a8SLen Brown 					break;
65395b482a8SLen Brown 				}
65495b482a8SLen Brown 			} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
65595b482a8SLen Brown 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
65695b482a8SLen Brown 						  "Executing DataTableRegion Strings Op=%p\n",
65795b482a8SLen Brown 						  op));
65895b482a8SLen Brown 
65995b482a8SLen Brown 				status =
66095b482a8SLen Brown 				    acpi_ds_eval_table_region_operands
66195b482a8SLen Brown 				    (walk_state, op);
66295b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
66395b482a8SLen Brown 					break;
66495b482a8SLen Brown 				}
66595b482a8SLen Brown 			} else if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
66695b482a8SLen Brown 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
66795b482a8SLen Brown 						  "Executing BankField Op=%p\n",
66895b482a8SLen Brown 						  op));
66995b482a8SLen Brown 
67095b482a8SLen Brown 				status =
67195b482a8SLen Brown 				    acpi_ds_eval_bank_field_operands(walk_state,
67295b482a8SLen Brown 								     op);
67395b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
67495b482a8SLen Brown 					break;
67595b482a8SLen Brown 				}
67695b482a8SLen Brown 			}
67795b482a8SLen Brown 			break;
67895b482a8SLen Brown 
67995b482a8SLen Brown 		case AML_TYPE_UNDEFINED:
68095b482a8SLen Brown 
68195b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
68295b482a8SLen Brown 				    "Undefined opcode type Op=%p", op));
68395b482a8SLen Brown 			return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
68495b482a8SLen Brown 
68595b482a8SLen Brown 		case AML_TYPE_BOGUS:
68695b482a8SLen Brown 
68795b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
68895b482a8SLen Brown 					  "Internal opcode=%X type Op=%p\n",
68995b482a8SLen Brown 					  walk_state->opcode, op));
69095b482a8SLen Brown 			break;
69195b482a8SLen Brown 
69295b482a8SLen Brown 		default:
69395b482a8SLen Brown 
69495b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
6951fad8738SBob Moore 				    "Unimplemented opcode, class=0x%X "
6961fad8738SBob Moore 				    "type=0x%X Opcode=0x%X Op=%p",
69795b482a8SLen Brown 				    op_class, op_type, op->common.aml_opcode,
69895b482a8SLen Brown 				    op));
69995b482a8SLen Brown 
70095b482a8SLen Brown 			status = AE_NOT_IMPLEMENTED;
70195b482a8SLen Brown 			break;
70295b482a8SLen Brown 		}
70395b482a8SLen Brown 	}
70495b482a8SLen Brown 
70595b482a8SLen Brown 	/*
70695b482a8SLen Brown 	 * ACPI 2.0 support for 64-bit integers: Truncate numeric
70795b482a8SLen Brown 	 * result value if we are executing from a 32-bit ACPI table
70895b482a8SLen Brown 	 */
709ef42e53fSBob Moore 	(void)acpi_ex_truncate_for32bit_table(walk_state->result_obj);
71095b482a8SLen Brown 
71195b482a8SLen Brown 	/*
71295b482a8SLen Brown 	 * Check if we just completed the evaluation of a
71395b482a8SLen Brown 	 * conditional predicate
71495b482a8SLen Brown 	 */
71595b482a8SLen Brown 	if ((ACPI_SUCCESS(status)) &&
71695b482a8SLen Brown 	    (walk_state->control_state) &&
71795b482a8SLen Brown 	    (walk_state->control_state->common.state ==
71895b482a8SLen Brown 	     ACPI_CONTROL_PREDICATE_EXECUTING) &&
71995b482a8SLen Brown 	    (walk_state->control_state->control.predicate_op == op)) {
72095b482a8SLen Brown 		status =
72195b482a8SLen Brown 		    acpi_ds_get_predicate_value(walk_state,
72295b482a8SLen Brown 						walk_state->result_obj);
72395b482a8SLen Brown 		walk_state->result_obj = NULL;
72495b482a8SLen Brown 	}
72595b482a8SLen Brown 
72695b482a8SLen Brown cleanup:
72795b482a8SLen Brown 
72895b482a8SLen Brown 	if (walk_state->result_obj) {
72995b482a8SLen Brown 
73095b482a8SLen Brown 		/* Break to debugger to display result */
73195b482a8SLen Brown 
7328a2a2501SLv Zheng 		acpi_db_display_result_object(walk_state->result_obj,
7338a2a2501SLv Zheng 					      walk_state);
73495b482a8SLen Brown 
73595b482a8SLen Brown 		/*
73695b482a8SLen Brown 		 * Delete the result op if and only if:
73795b482a8SLen Brown 		 * Parent will not use the result -- such as any
73895b482a8SLen Brown 		 * non-nested type2 op in a method (parent will be method)
73995b482a8SLen Brown 		 */
74095b482a8SLen Brown 		acpi_ds_delete_result_if_not_used(op, walk_state->result_obj,
74195b482a8SLen Brown 						  walk_state);
74295b482a8SLen Brown 	}
74395b482a8SLen Brown #ifdef _UNDER_DEVELOPMENT
74495b482a8SLen Brown 
74595b482a8SLen Brown 	if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) {
74695b482a8SLen Brown 		acpi_db_method_end(walk_state);
74795b482a8SLen Brown 	}
74895b482a8SLen Brown #endif
74995b482a8SLen Brown 
75095b482a8SLen Brown 	/* Invoke exception handler on error */
75195b482a8SLen Brown 
75295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
75395b482a8SLen Brown 		status = acpi_ds_method_error(status, walk_state);
75495b482a8SLen Brown 	}
75595b482a8SLen Brown 
75695b482a8SLen Brown 	/* Always clear the object stack */
75795b482a8SLen Brown 
75895b482a8SLen Brown 	walk_state->num_operands = 0;
75995b482a8SLen Brown 	return_ACPI_STATUS(status);
76095b482a8SLen Brown }
761