^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Module Name: dscontrol - Support for execution control opcodes -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * if/else/while/return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2000 - 2020, Intel Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *****************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <acpi/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "accommon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "amlcode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "acdispat.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "acinterp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "acdebug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define _COMPONENT ACPI_DISPATCHER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) ACPI_MODULE_NAME("dscontrol")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * FUNCTION: acpi_ds_exec_begin_control_op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * PARAMETERS: walk_list - The list that owns the walk stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * op - The control Op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * RETURN: Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * DESCRIPTION: Handles all control ops encountered during control method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * execution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) union acpi_parse_object *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) acpi_status status = AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) union acpi_generic_state *control_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) op, op->common.aml_opcode, walk_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) switch (op->common.aml_opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case AML_WHILE_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * If this is an additional iteration of a while loop, continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * There is no need to allocate a new control state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (walk_state->control_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (walk_state->control_state->control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) aml_predicate_start ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) (walk_state->parser_state.aml - 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) /* Reset the state to start-of-loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) walk_state->control_state->common.state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ACPI_CONTROL_CONDITIONAL_EXECUTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /*lint -fallthrough */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) case AML_IF_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * IF/WHILE: Create a new control state to manage these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * constructs. We need to manage these as a stack, in order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * to handle nesting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) control_state = acpi_ut_create_control_state();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (!control_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) status = AE_NO_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Save a pointer to the predicate for multiple executions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * of a loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) control_state->control.aml_predicate_start =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) walk_state->parser_state.aml - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) control_state->control.package_end =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) walk_state->parser_state.pkg_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) control_state->control.opcode = op->common.aml_opcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) control_state->control.loop_timeout = acpi_os_get_timer() +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ((u64)acpi_gbl_max_loop_iterations * ACPI_100NSEC_PER_SEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Push the control state on this walk's control stack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) acpi_ut_push_generic_state(&walk_state->control_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) control_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) case AML_ELSE_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* Predicate is in the state object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* If predicate is true, the IF was executed, ignore ELSE part */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (walk_state->last_predicate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) status = AE_CTRL_TRUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) case AML_RETURN_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /*******************************************************************************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * FUNCTION: acpi_ds_exec_end_control_op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * PARAMETERS: walk_list - The list that owns the walk stack
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * op - The control Op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * RETURN: Status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * DESCRIPTION: Handles all control ops encountered during control method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * execution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ******************************************************************************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) acpi_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) union acpi_parse_object *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) acpi_status status = AE_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) union acpi_generic_state *control_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ACPI_FUNCTION_NAME(ds_exec_end_control_op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) switch (op->common.aml_opcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case AML_IF_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * Save the result of the predicate in case there is an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * ELSE to come
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) walk_state->last_predicate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) (u8)walk_state->control_state->common.value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * Pop the control state that was created at the start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * of the IF and free it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) control_state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) acpi_ut_pop_generic_state(&walk_state->control_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) acpi_ut_delete_generic_state(control_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case AML_ELSE_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) case AML_WHILE_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) control_state = walk_state->control_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (control_state->common.value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* Predicate was true, the body of the loop was just executed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * This infinite loop detection mechanism allows the interpreter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * to escape possibly infinite loops. This can occur in poorly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * written AML when the hardware does not respond within a while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * loop and the loop does not implement a timeout.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (ACPI_TIME_AFTER(acpi_os_get_timer(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) control_state->control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) loop_timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) status = AE_AML_LOOP_TIMEOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) * Go back and evaluate the predicate and maybe execute the loop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * another time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) status = AE_CTRL_PENDING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) walk_state->aml_last_while =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) control_state->control.aml_predicate_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /* Predicate was false, terminate this while loop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) "[WHILE_OP] termination! Op=%p\n", op));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* Pop this control state and free it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) control_state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) acpi_ut_pop_generic_state(&walk_state->control_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) acpi_ut_delete_generic_state(control_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) case AML_RETURN_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) "[RETURN_OP] Op=%p Arg=%p\n", op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) op->common.value.arg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * One optional operand -- the return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * It can be either an immediate operand or a result that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * has been bubbled up the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (op->common.value.arg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Since we have a real Return(), delete any implicit return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) acpi_ds_clear_implicit_return(walk_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* Return statement has an immediate operand */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) acpi_ds_create_operands(walk_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) op->common.value.arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * If value being returned is a Reference (such as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * an arg or local), resolve it now because it may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * cease to exist at the end of the method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) acpi_ex_resolve_to_value(&walk_state->operands[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) walk_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Get the return value and save as the last result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * value. This is the only place where walk_state->return_desc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * is set to anything other than zero!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) walk_state->return_desc = walk_state->operands[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) } else if (walk_state->result_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /* Since we have a real Return(), delete any implicit return */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) acpi_ds_clear_implicit_return(walk_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * The return value has come from a previous calculation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * If value being returned is a Reference (such as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * an arg or local), resolve it now because it may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * cease to exist at the end of the method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * Allow references created by the Index operator to return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * unchanged.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if ((ACPI_GET_DESCRIPTOR_TYPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) (walk_state->results->results.obj_desc[0]) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) ACPI_DESC_TYPE_OPERAND)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) && ((walk_state->results->results.obj_desc[0])->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) common.type == ACPI_TYPE_LOCAL_REFERENCE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) && ((walk_state->results->results.obj_desc[0])->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) reference.class != ACPI_REFCLASS_INDEX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) acpi_ex_resolve_to_value(&walk_state->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) results->results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) obj_desc[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) walk_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (ACPI_FAILURE(status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) walk_state->return_desc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) walk_state->results->results.obj_desc[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* No return operand */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (walk_state->num_operands) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) acpi_ut_remove_reference(walk_state->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) operands[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) walk_state->operands[0] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) walk_state->num_operands = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) walk_state->return_desc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) "Completed RETURN_OP State=%p, RetVal=%p\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) walk_state, walk_state->return_desc));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* End the control method execution right now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) status = AE_CTRL_TERMINATE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case AML_NOOP_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Just do nothing! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case AML_BREAKPOINT_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) acpi_db_signal_break_point(walk_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /* Call to the OSL in case OS wants a piece of the action */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) "Executed AML Breakpoint opcode");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) case AML_BREAK_OP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) case AML_CONTINUE_OP: /* ACPI 2.0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* Pop and delete control states until we find a while */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) while (walk_state->control_state &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) (walk_state->control_state->control.opcode !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) AML_WHILE_OP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) control_state =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) acpi_ut_pop_generic_state(&walk_state->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) control_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) acpi_ut_delete_generic_state(control_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) /* No while found? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (!walk_state->control_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return (AE_AML_NO_WHILE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) walk_state->aml_last_while =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) walk_state->control_state->control.package_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* Return status depending on opcode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (op->common.aml_opcode == AML_BREAK_OP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) status = AE_CTRL_BREAK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) status = AE_CTRL_CONTINUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) op->common.aml_opcode, op));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) status = AE_AML_BAD_OPCODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) return (status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }