/******************************************************************************* * * FUNCTION: acpi_ex_opcode_3A_0T_0R * * PARAMETERS: walk_state - Current walk state * * RETURN: Status * * DESCRIPTION: Execute Triadic operator (3 operands) * ******************************************************************************/ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) { union acpi_operand_object **operand = &walk_state->operands[0]; struct acpi_signal_fatal_info *fatal; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_0T_0R", acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (u32) operand[0]->integer.value, (u32) operand[1]->integer.value, (u32) operand[2]->integer.value)); fatal = ACPI_MEM_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); if (fatal) { fatal->type = (u32) operand[0]->integer.value; fatal->code = (u32) operand[1]->integer.value; fatal->argument = (u32) operand[2]->integer.value; } /* Always signal the OS! */ status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal); /* Might return while OS is shutting down, just continue */ ACPI_MEM_FREE(fatal); break; default: ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } cleanup: return_ACPI_STATUS(status); }
acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) { union acpi_operand_object **operand = &walk_state->operands[0]; struct acpi_signal_fatal_info *fatal; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { case AML_FATAL_OP: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (u32) operand[0]->integer.value, (u32) operand[1]->integer.value, (u32) operand[2]->integer.value)); fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); if (fatal) { fatal->type = (u32) operand[0]->integer.value; fatal->code = (u32) operand[1]->integer.value; fatal->argument = (u32) operand[2]->integer.value; } status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal); ACPI_FREE(fatal); break; default: ACPI_ERROR((AE_INFO, "Unknown AML opcode %X", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } cleanup: return_ACPI_STATUS(status); }
acpi_status acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, union acpi_parse_object * op) { acpi_status status = AE_OK; union acpi_generic_state *control_state; ACPI_FUNCTION_NAME(ds_exec_end_control_op); switch (op->common.aml_opcode) { case AML_IF_OP: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); /* * Save the result of the predicate in case there is an * ELSE to come */ walk_state->last_predicate = (u8) walk_state->control_state->common.value; /* * Pop the control state that was created at the start * of the IF and free it */ control_state = acpi_ut_pop_generic_state(&walk_state->control_state); acpi_ut_delete_generic_state(control_state); break; case AML_ELSE_OP: break; case AML_WHILE_OP: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); if (walk_state->control_state->common.value) { /* Predicate was true, go back and evaluate it again! */ status = AE_CTRL_PENDING; } ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] termination! Op=%p\n", op)); /* Pop this control state and free it */ control_state = acpi_ut_pop_generic_state(&walk_state->control_state); walk_state->aml_last_while = control_state->control.aml_predicate_start; acpi_ut_delete_generic_state(control_state); break; case AML_RETURN_OP: ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[RETURN_OP] Op=%p Arg=%p\n", op, op->common.value.arg)); /* * One optional operand -- the return value * It can be either an immediate operand or a result that * has been bubbled up the tree */ if (op->common.value.arg) { /* Since we have a real Return(), delete any implicit return */ acpi_ds_clear_implicit_return(walk_state); /* Return statement has an immediate operand */ status = acpi_ds_create_operands(walk_state, op->common.value.arg); if (ACPI_FAILURE(status)) { return (status); } /* * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. */ status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); if (ACPI_FAILURE(status)) { return (status); } /* * Get the return value and save as the last result * value. This is the only place where walk_state->return_desc * is set to anything other than zero! */ walk_state->return_desc = walk_state->operands[0]; } else if ((walk_state->results) && (walk_state->results->results.num_results > 0)) { /* Since we have a real Return(), delete any implicit return */ acpi_ds_clear_implicit_return(walk_state); /* * The return value has come from a previous calculation. * * If value being returned is a Reference (such as * an arg or local), resolve it now because it may * cease to exist at the end of the method. * * Allow references created by the Index operator to return unchanged. */ if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) && (ACPI_GET_OBJECT_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_TYPE_LOCAL_REFERENCE) && ((walk_state->results->results.obj_desc[0])-> reference.opcode != AML_INDEX_OP)) { status = acpi_ex_resolve_to_value(&walk_state-> results->results. obj_desc[0], walk_state); if (ACPI_FAILURE(status)) { return (status); } } walk_state->return_desc = walk_state->results->results.obj_desc[0]; } else { /* No return operand */ if (walk_state->num_operands) { acpi_ut_remove_reference(walk_state-> operands[0]); } walk_state->operands[0] = NULL; walk_state->num_operands = 0; walk_state->return_desc = NULL; } ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Completed RETURN_OP State=%p, RetVal=%p\n", walk_state, walk_state->return_desc)); /* End the control method execution right now */ status = AE_CTRL_TERMINATE; break; case AML_NOOP_OP: /* Just do nothing! */ break; case AML_BREAK_POINT_OP: /* Call up to the OS service layer to handle this */ status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode"); /* If and when it returns, all done. */ break; case AML_BREAK_OP: case AML_CONTINUE_OP: /* ACPI 2.0 */ /* Pop and delete control states until we find a while */ while (walk_state->control_state && (walk_state->control_state->control.opcode != AML_WHILE_OP)) { control_state = acpi_ut_pop_generic_state(&walk_state-> control_state); acpi_ut_delete_generic_state(control_state); } /* No while found? */ if (!walk_state->control_state) { return (AE_AML_NO_WHILE); } /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ walk_state->aml_last_while = walk_state->control_state->control.package_end; /* Return status depending on opcode */ if (op->common.aml_opcode == AML_BREAK_OP) { status = AE_CTRL_BREAK; } else { status = AE_CTRL_CONTINUE; } break; default: ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p", op->common.aml_opcode, op)); status = AE_AML_BAD_OPCODE; break; } return (status); }
/******************************************************************************* * * FUNCTION: acpi_ex_opcode_3A_0T_0R * * PARAMETERS: walk_state - Current walk state * * RETURN: Status * * DESCRIPTION: Execute Triadic operator (3 operands) * ******************************************************************************/ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) { union acpi_operand_object **operand = &walk_state->operands[0]; struct acpi_signal_fatal_info *fatal; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R, acpi_ps_get_opcode_name(walk_state->opcode)); switch (walk_state->opcode) { case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "FatalOp: Type %X Code %X Arg %X " "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (u32)operand[0]->integer.value, (u32)operand[1]->integer.value, (u32)operand[2]->integer.value)); fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info)); if (fatal) { fatal->type = (u32) operand[0]->integer.value; fatal->code = (u32) operand[1]->integer.value; fatal->argument = (u32) operand[2]->integer.value; } /* Always signal the OS! */ status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal); /* Might return while OS is shutting down, just continue */ ACPI_FREE(fatal); goto cleanup; case AML_EXTERNAL_OP: /* * If the interpreter sees this opcode, just ignore it. The External * op is intended for use by disassemblers in order to properly * disassemble control method invocations. The opcode or group of * opcodes should be surrounded by an "if (0)" clause to ensure that * AML interpreters never see the opcode. Thus, something is * wrong if an external opcode ever gets here. */ ACPI_ERROR((AE_INFO, "Executed External Op")); status = AE_OK; goto cleanup; default: ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", walk_state->opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } cleanup: return_ACPI_STATUS(status); }