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