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 * 7800ba7c5SBob Moore * Copyright (C) 2000 - 2020, 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, 3395b482a8SLen Brown acpi_ex_opcode_1A_1T_0R, 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 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 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 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 39295b482a8SLen Brown * being the object_type and size_of operators. 39395b482a8SLen Brown */ 39495b482a8SLen Brown if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) { 39595b482a8SLen Brown 39695b482a8SLen Brown /* Resolve all operands */ 39795b482a8SLen Brown 39895b482a8SLen Brown status = acpi_ex_resolve_operands(walk_state->opcode, 39995b482a8SLen Brown &(walk_state-> 40095b482a8SLen Brown operands 40195b482a8SLen Brown [walk_state-> 40295b482a8SLen Brown num_operands - 1]), 40395b482a8SLen Brown walk_state); 40495b482a8SLen Brown } 40595b482a8SLen Brown 40695b482a8SLen Brown if (ACPI_SUCCESS(status)) { 40795b482a8SLen Brown /* 40895b482a8SLen Brown * Dispatch the request to the appropriate interpreter handler 40995b482a8SLen Brown * routine. There is one routine per opcode "type" based upon the 41095b482a8SLen Brown * number of opcode arguments and return type. 41195b482a8SLen Brown */ 41295b482a8SLen Brown status = 41395b482a8SLen Brown acpi_gbl_op_type_dispatch[op_type] (walk_state); 41495b482a8SLen Brown } else { 41595b482a8SLen Brown /* 41695b482a8SLen Brown * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the 41795b482a8SLen Brown * Local is uninitialized. 41895b482a8SLen Brown */ 41995b482a8SLen Brown if ((status == AE_AML_UNINITIALIZED_LOCAL) && 42095b482a8SLen Brown (walk_state->opcode == AML_STORE_OP) && 42195b482a8SLen Brown (walk_state->operands[0]->common.type == 42295b482a8SLen Brown ACPI_TYPE_LOCAL_REFERENCE) 42395b482a8SLen Brown && (walk_state->operands[1]->common.type == 42495b482a8SLen Brown ACPI_TYPE_LOCAL_REFERENCE) 42595b482a8SLen Brown && (walk_state->operands[0]->reference.class == 42695b482a8SLen Brown walk_state->operands[1]->reference.class) 42795b482a8SLen Brown && (walk_state->operands[0]->reference.value == 42895b482a8SLen Brown walk_state->operands[1]->reference.value)) { 42995b482a8SLen Brown status = AE_OK; 43095b482a8SLen Brown } else { 43195b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, 43295b482a8SLen Brown "While resolving operands for [%s]", 43395b482a8SLen Brown acpi_ps_get_opcode_name 43495b482a8SLen Brown (walk_state->opcode))); 43595b482a8SLen Brown } 43695b482a8SLen Brown } 43795b482a8SLen Brown 43895b482a8SLen Brown /* Always delete the argument objects and clear the operand stack */ 43995b482a8SLen Brown 44095b482a8SLen Brown acpi_ds_clear_operands(walk_state); 44195b482a8SLen Brown 44295b482a8SLen Brown /* 44395b482a8SLen Brown * If a result object was returned from above, push it on the 44495b482a8SLen Brown * current result stack 44595b482a8SLen Brown */ 44695b482a8SLen Brown if (ACPI_SUCCESS(status) && walk_state->result_obj) { 44795b482a8SLen Brown status = 44895b482a8SLen Brown acpi_ds_result_push(walk_state->result_obj, 44995b482a8SLen Brown walk_state); 45095b482a8SLen Brown } 45195b482a8SLen Brown break; 45295b482a8SLen Brown 45395b482a8SLen Brown default: 45495b482a8SLen Brown 45595b482a8SLen Brown switch (op_type) { 45695b482a8SLen Brown case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ 45795b482a8SLen Brown 45895b482a8SLen Brown /* 1 Operand, 0 external_result, 0 internal_result */ 45995b482a8SLen Brown 46095b482a8SLen Brown status = acpi_ds_exec_end_control_op(walk_state, op); 46195b482a8SLen Brown 46295b482a8SLen Brown break; 46395b482a8SLen Brown 46495b482a8SLen Brown case AML_TYPE_METHOD_CALL: 46595b482a8SLen Brown /* 46695b482a8SLen Brown * If the method is referenced from within a package 46795b482a8SLen Brown * declaration, it is not a invocation of the method, just 46895b482a8SLen Brown * a reference to it. 46995b482a8SLen Brown */ 47095b482a8SLen Brown if ((op->asl.parent) && 47195b482a8SLen Brown ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) 47295b482a8SLen Brown || (op->asl.parent->asl.aml_opcode == 4739ff5a21aSBob Moore AML_VARIABLE_PACKAGE_OP))) { 47495b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 47595b482a8SLen Brown "Method Reference in a Package, Op=%p\n", 47695b482a8SLen Brown op)); 47795b482a8SLen Brown 4781fad8738SBob Moore op->common.node = (struct acpi_namespace_node *) 4791fad8738SBob Moore op->asl.value.arg->asl.node; 48095b482a8SLen Brown acpi_ut_add_reference(op->asl.value.arg->asl. 48195b482a8SLen Brown node->object); 48295b482a8SLen Brown return_ACPI_STATUS(AE_OK); 48395b482a8SLen Brown } 48495b482a8SLen Brown 48595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 48695b482a8SLen Brown "Method invocation, Op=%p\n", op)); 48795b482a8SLen Brown 48895b482a8SLen Brown /* 48995b482a8SLen Brown * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains 49095b482a8SLen Brown * the method Node pointer 49195b482a8SLen Brown */ 49295b482a8SLen Brown /* next_op points to the op that holds the method name */ 49395b482a8SLen Brown 49495b482a8SLen Brown next_op = first_arg; 49595b482a8SLen Brown 49695b482a8SLen Brown /* next_op points to first argument op */ 49795b482a8SLen Brown 49895b482a8SLen Brown next_op = next_op->common.next; 49995b482a8SLen Brown 50095b482a8SLen Brown /* 50195b482a8SLen Brown * Get the method's arguments and put them on the operand stack 50295b482a8SLen Brown */ 50395b482a8SLen Brown status = acpi_ds_create_operands(walk_state, next_op); 50495b482a8SLen Brown if (ACPI_FAILURE(status)) { 50595b482a8SLen Brown break; 50695b482a8SLen Brown } 50795b482a8SLen Brown 50895b482a8SLen Brown /* 50995b482a8SLen Brown * Since the operands will be passed to another control method, 51095b482a8SLen Brown * we must resolve all local references here (Local variables, 51195b482a8SLen Brown * arguments to *this* method, etc.) 51295b482a8SLen Brown */ 51395b482a8SLen Brown status = acpi_ds_resolve_operands(walk_state); 51495b482a8SLen Brown if (ACPI_FAILURE(status)) { 51595b482a8SLen Brown 51695b482a8SLen Brown /* On error, clear all resolved operands */ 51795b482a8SLen Brown 51895b482a8SLen Brown acpi_ds_clear_operands(walk_state); 51995b482a8SLen Brown break; 52095b482a8SLen Brown } 52195b482a8SLen Brown 52295b482a8SLen Brown /* 52395b482a8SLen Brown * Tell the walk loop to preempt this running method and 52495b482a8SLen Brown * execute the new method 52595b482a8SLen Brown */ 52695b482a8SLen Brown status = AE_CTRL_TRANSFER; 52795b482a8SLen Brown 52895b482a8SLen Brown /* 52995b482a8SLen Brown * Return now; we don't want to disturb anything, 53095b482a8SLen Brown * especially the operand count! 53195b482a8SLen Brown */ 53295b482a8SLen Brown return_ACPI_STATUS(status); 53395b482a8SLen Brown 53495b482a8SLen Brown case AML_TYPE_CREATE_FIELD: 53595b482a8SLen Brown 53695b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 53795b482a8SLen Brown "Executing CreateField Buffer/Index Op=%p\n", 53895b482a8SLen Brown op)); 53995b482a8SLen Brown 54095b482a8SLen Brown status = acpi_ds_load2_end_op(walk_state); 54195b482a8SLen Brown if (ACPI_FAILURE(status)) { 54295b482a8SLen Brown break; 54395b482a8SLen Brown } 54495b482a8SLen Brown 54595b482a8SLen Brown status = 54695b482a8SLen Brown acpi_ds_eval_buffer_field_operands(walk_state, op); 5479a1ae804SBob Moore if (ACPI_FAILURE(status)) { 5489a1ae804SBob Moore break; 5499a1ae804SBob Moore } 5509a1ae804SBob Moore #ifdef ACPI_EXEC_APP 5519a1ae804SBob Moore /* 5529a1ae804SBob Moore * acpi_exec support for namespace initialization file (initialize 5539a1ae804SBob Moore * buffer_fields in this code.) 5549a1ae804SBob Moore */ 5559a1ae804SBob Moore namepath = 5569a1ae804SBob Moore acpi_ns_get_external_pathname(op->common.node); 5579a1ae804SBob Moore status = ae_lookup_init_file_entry(namepath, &obj_desc); 5589a1ae804SBob Moore if (ACPI_SUCCESS(status)) { 5599a1ae804SBob Moore status = 5609a1ae804SBob Moore acpi_ex_write_data_to_field(obj_desc, 5619a1ae804SBob Moore op->common. 5629a1ae804SBob Moore node->object, 5639a1ae804SBob Moore NULL); 5649a1ae804SBob Moore if ACPI_FAILURE 5659a1ae804SBob Moore (status) { 5669a1ae804SBob Moore ACPI_EXCEPTION((AE_INFO, status, 5679a1ae804SBob Moore "While writing to buffer field")); 5689a1ae804SBob Moore } 5699a1ae804SBob Moore } 5709a1ae804SBob Moore ACPI_FREE(namepath); 5719a1ae804SBob Moore status = AE_OK; 5729a1ae804SBob Moore #endif 57395b482a8SLen Brown break; 57495b482a8SLen Brown 57595b482a8SLen Brown case AML_TYPE_CREATE_OBJECT: 57695b482a8SLen Brown 57795b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 5785a8361f7SSchmauss, Erik "Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n", 5795a8361f7SSchmauss, Erik op, op->named.value.arg, 5805a8361f7SSchmauss, Erik op->common.parent->common. 5815a8361f7SSchmauss, Erik aml_opcode)); 58295b482a8SLen Brown 58395b482a8SLen Brown switch (op->common.parent->common.aml_opcode) { 58495b482a8SLen Brown case AML_NAME_OP: 58595b482a8SLen Brown /* 58695b482a8SLen Brown * Put the Node on the object stack (Contains the ACPI Name 58795b482a8SLen Brown * of this object) 58895b482a8SLen Brown */ 5891fad8738SBob Moore walk_state->operands[0] = (void *) 5901fad8738SBob Moore op->common.parent->common.node; 59195b482a8SLen Brown walk_state->num_operands = 1; 59295b482a8SLen Brown 59395b482a8SLen Brown status = acpi_ds_create_node(walk_state, 59495b482a8SLen Brown op->common.parent-> 59595b482a8SLen Brown common.node, 59695b482a8SLen Brown op->common.parent); 59795b482a8SLen Brown if (ACPI_FAILURE(status)) { 59895b482a8SLen Brown break; 59995b482a8SLen Brown } 60095b482a8SLen Brown 601*c1a7c2ceSNick Desaulniers ACPI_FALLTHROUGH; 60295b482a8SLen Brown 60395b482a8SLen Brown case AML_INT_EVAL_SUBTREE_OP: 60495b482a8SLen Brown 60595b482a8SLen Brown status = 60695b482a8SLen Brown acpi_ds_eval_data_object_operands 60795b482a8SLen Brown (walk_state, op, 60895b482a8SLen Brown acpi_ns_get_attached_object(op->common. 60995b482a8SLen Brown parent->common. 61095b482a8SLen Brown node)); 61195b482a8SLen Brown break; 61295b482a8SLen Brown 61395b482a8SLen Brown default: 61495b482a8SLen Brown 61595b482a8SLen Brown status = 61695b482a8SLen Brown acpi_ds_eval_data_object_operands 61795b482a8SLen Brown (walk_state, op, NULL); 61895b482a8SLen Brown break; 61995b482a8SLen Brown } 62095b482a8SLen Brown 62195b482a8SLen Brown /* 62295b482a8SLen Brown * If a result object was returned from above, push it on the 62395b482a8SLen Brown * current result stack 62495b482a8SLen Brown */ 62595b482a8SLen Brown if (walk_state->result_obj) { 62695b482a8SLen Brown status = 62795b482a8SLen Brown acpi_ds_result_push(walk_state->result_obj, 62895b482a8SLen Brown walk_state); 62995b482a8SLen Brown } 63095b482a8SLen Brown break; 63195b482a8SLen Brown 63295b482a8SLen Brown case AML_TYPE_NAMED_FIELD: 63395b482a8SLen Brown case AML_TYPE_NAMED_COMPLEX: 63495b482a8SLen Brown case AML_TYPE_NAMED_SIMPLE: 63595b482a8SLen Brown case AML_TYPE_NAMED_NO_OBJ: 63695b482a8SLen Brown 63795b482a8SLen Brown status = acpi_ds_load2_end_op(walk_state); 63895b482a8SLen Brown if (ACPI_FAILURE(status)) { 63995b482a8SLen Brown break; 64095b482a8SLen Brown } 64195b482a8SLen Brown 64295b482a8SLen Brown if (op->common.aml_opcode == AML_REGION_OP) { 64395b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 64495b482a8SLen Brown "Executing OpRegion Address/Length Op=%p\n", 64595b482a8SLen Brown op)); 64695b482a8SLen Brown 64795b482a8SLen Brown status = 64895b482a8SLen Brown acpi_ds_eval_region_operands(walk_state, 64995b482a8SLen Brown op); 65095b482a8SLen Brown if (ACPI_FAILURE(status)) { 65195b482a8SLen Brown break; 65295b482a8SLen Brown } 65395b482a8SLen Brown } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { 65495b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 65595b482a8SLen Brown "Executing DataTableRegion Strings Op=%p\n", 65695b482a8SLen Brown op)); 65795b482a8SLen Brown 65895b482a8SLen Brown status = 65995b482a8SLen Brown acpi_ds_eval_table_region_operands 66095b482a8SLen Brown (walk_state, op); 66195b482a8SLen Brown if (ACPI_FAILURE(status)) { 66295b482a8SLen Brown break; 66395b482a8SLen Brown } 66495b482a8SLen Brown } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { 66595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 66695b482a8SLen Brown "Executing BankField Op=%p\n", 66795b482a8SLen Brown op)); 66895b482a8SLen Brown 66995b482a8SLen Brown status = 67095b482a8SLen Brown acpi_ds_eval_bank_field_operands(walk_state, 67195b482a8SLen Brown op); 67295b482a8SLen Brown if (ACPI_FAILURE(status)) { 67395b482a8SLen Brown break; 67495b482a8SLen Brown } 67595b482a8SLen Brown } 67695b482a8SLen Brown break; 67795b482a8SLen Brown 67895b482a8SLen Brown case AML_TYPE_UNDEFINED: 67995b482a8SLen Brown 68095b482a8SLen Brown ACPI_ERROR((AE_INFO, 68195b482a8SLen Brown "Undefined opcode type Op=%p", op)); 68295b482a8SLen Brown return_ACPI_STATUS(AE_NOT_IMPLEMENTED); 68395b482a8SLen Brown 68495b482a8SLen Brown case AML_TYPE_BOGUS: 68595b482a8SLen Brown 68695b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 68795b482a8SLen Brown "Internal opcode=%X type Op=%p\n", 68895b482a8SLen Brown walk_state->opcode, op)); 68995b482a8SLen Brown break; 69095b482a8SLen Brown 69195b482a8SLen Brown default: 69295b482a8SLen Brown 69395b482a8SLen Brown ACPI_ERROR((AE_INFO, 6941fad8738SBob Moore "Unimplemented opcode, class=0x%X " 6951fad8738SBob Moore "type=0x%X Opcode=0x%X Op=%p", 69695b482a8SLen Brown op_class, op_type, op->common.aml_opcode, 69795b482a8SLen Brown op)); 69895b482a8SLen Brown 69995b482a8SLen Brown status = AE_NOT_IMPLEMENTED; 70095b482a8SLen Brown break; 70195b482a8SLen Brown } 70295b482a8SLen Brown } 70395b482a8SLen Brown 70495b482a8SLen Brown /* 70595b482a8SLen Brown * ACPI 2.0 support for 64-bit integers: Truncate numeric 70695b482a8SLen Brown * result value if we are executing from a 32-bit ACPI table 70795b482a8SLen Brown */ 708ef42e53fSBob Moore (void)acpi_ex_truncate_for32bit_table(walk_state->result_obj); 70995b482a8SLen Brown 71095b482a8SLen Brown /* 71195b482a8SLen Brown * Check if we just completed the evaluation of a 71295b482a8SLen Brown * conditional predicate 71395b482a8SLen Brown */ 71495b482a8SLen Brown if ((ACPI_SUCCESS(status)) && 71595b482a8SLen Brown (walk_state->control_state) && 71695b482a8SLen Brown (walk_state->control_state->common.state == 71795b482a8SLen Brown ACPI_CONTROL_PREDICATE_EXECUTING) && 71895b482a8SLen Brown (walk_state->control_state->control.predicate_op == op)) { 71995b482a8SLen Brown status = 72095b482a8SLen Brown acpi_ds_get_predicate_value(walk_state, 72195b482a8SLen Brown walk_state->result_obj); 72295b482a8SLen Brown walk_state->result_obj = NULL; 72395b482a8SLen Brown } 72495b482a8SLen Brown 72595b482a8SLen Brown cleanup: 72695b482a8SLen Brown 72795b482a8SLen Brown if (walk_state->result_obj) { 72895b482a8SLen Brown 72995b482a8SLen Brown /* Break to debugger to display result */ 73095b482a8SLen Brown 7318a2a2501SLv Zheng acpi_db_display_result_object(walk_state->result_obj, 7328a2a2501SLv Zheng walk_state); 73395b482a8SLen Brown 73495b482a8SLen Brown /* 73595b482a8SLen Brown * Delete the result op if and only if: 73695b482a8SLen Brown * Parent will not use the result -- such as any 73795b482a8SLen Brown * non-nested type2 op in a method (parent will be method) 73895b482a8SLen Brown */ 73995b482a8SLen Brown acpi_ds_delete_result_if_not_used(op, walk_state->result_obj, 74095b482a8SLen Brown walk_state); 74195b482a8SLen Brown } 74295b482a8SLen Brown #ifdef _UNDER_DEVELOPMENT 74395b482a8SLen Brown 74495b482a8SLen Brown if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) { 74595b482a8SLen Brown acpi_db_method_end(walk_state); 74695b482a8SLen Brown } 74795b482a8SLen Brown #endif 74895b482a8SLen Brown 74995b482a8SLen Brown /* Invoke exception handler on error */ 75095b482a8SLen Brown 75195b482a8SLen Brown if (ACPI_FAILURE(status)) { 75295b482a8SLen Brown status = acpi_ds_method_error(status, walk_state); 75395b482a8SLen Brown } 75495b482a8SLen Brown 75595b482a8SLen Brown /* Always clear the object stack */ 75695b482a8SLen Brown 75795b482a8SLen Brown walk_state->num_operands = 0; 75895b482a8SLen Brown return_ACPI_STATUS(status); 75995b482a8SLen Brown } 760