162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/******************************************************************************* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: dbxface - AML Debugger external interfaces 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci ******************************************************************************/ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <acpi/acpi.h> 962306a36Sopenharmony_ci#include "accommon.h" 1062306a36Sopenharmony_ci#include "amlcode.h" 1162306a36Sopenharmony_ci#include "acdebug.h" 1262306a36Sopenharmony_ci#include "acinterp.h" 1362306a36Sopenharmony_ci#include "acparser.h" 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#define _COMPONENT ACPI_CA_DEBUGGER 1662306a36Sopenharmony_ciACPI_MODULE_NAME("dbxface") 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/* Local prototypes */ 1962306a36Sopenharmony_cistatic acpi_status 2062306a36Sopenharmony_ciacpi_db_start_command(struct acpi_walk_state *walk_state, 2162306a36Sopenharmony_ci union acpi_parse_object *op); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#ifdef ACPI_OBSOLETE_FUNCTIONS 2462306a36Sopenharmony_civoid acpi_db_method_end(struct acpi_walk_state *walk_state); 2562306a36Sopenharmony_ci#endif 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#ifdef ACPI_DISASSEMBLER 2862306a36Sopenharmony_cistatic union acpi_parse_object *acpi_db_get_display_op(struct acpi_walk_state 2962306a36Sopenharmony_ci *walk_state, 3062306a36Sopenharmony_ci union acpi_parse_object 3162306a36Sopenharmony_ci *op); 3262306a36Sopenharmony_ci#endif 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/******************************************************************************* 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * FUNCTION: acpi_db_start_command 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * PARAMETERS: walk_state - Current walk 3962306a36Sopenharmony_ci * op - Current executing Op, from AML interpreter 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * RETURN: Status 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * DESCRIPTION: Enter debugger command loop 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci ******************************************************************************/ 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic acpi_status 4862306a36Sopenharmony_ciacpi_db_start_command(struct acpi_walk_state *walk_state, 4962306a36Sopenharmony_ci union acpi_parse_object *op) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci acpi_status status; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* TBD: [Investigate] are there namespace locking issues here? */ 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* Go into the command loop and await next user command */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci acpi_gbl_method_executing = TRUE; 6062306a36Sopenharmony_ci status = AE_CTRL_TRUE; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci while (status == AE_CTRL_TRUE) { 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* Notify the completion of the command */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci status = acpi_os_notify_command_complete(); 6762306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 6862306a36Sopenharmony_ci goto error_exit; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* Wait the readiness of the command */ 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci status = acpi_os_wait_command_ready(); 7462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 7562306a36Sopenharmony_ci goto error_exit; 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci status = 7962306a36Sopenharmony_ci acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state, 8062306a36Sopenharmony_ci op); 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */ 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cierror_exit: 8662306a36Sopenharmony_ci if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) { 8762306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 8862306a36Sopenharmony_ci "While parsing/handling command line")); 8962306a36Sopenharmony_ci } 9062306a36Sopenharmony_ci return (status); 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/******************************************************************************* 9462306a36Sopenharmony_ci * 9562306a36Sopenharmony_ci * FUNCTION: acpi_db_signal_break_point 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * PARAMETERS: walk_state - Current walk 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * RETURN: Status 10062306a36Sopenharmony_ci * 10162306a36Sopenharmony_ci * DESCRIPTION: Called for AML_BREAKPOINT_OP 10262306a36Sopenharmony_ci * 10362306a36Sopenharmony_ci ******************************************************************************/ 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_civoid acpi_db_signal_break_point(struct acpi_walk_state *walk_state) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci#ifndef ACPI_APPLICATION 10962306a36Sopenharmony_ci if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) { 11062306a36Sopenharmony_ci return; 11162306a36Sopenharmony_ci } 11262306a36Sopenharmony_ci#endif 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* 11562306a36Sopenharmony_ci * Set the single-step flag. This will cause the debugger (if present) 11662306a36Sopenharmony_ci * to break to the console within the AML debugger at the start of the 11762306a36Sopenharmony_ci * next AML instruction. 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ci acpi_gbl_cm_single_step = TRUE; 12062306a36Sopenharmony_ci acpi_os_printf("**break** Executed AML BreakPoint opcode\n"); 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#ifdef ACPI_DISASSEMBLER 12462306a36Sopenharmony_ci/******************************************************************************* 12562306a36Sopenharmony_ci * 12662306a36Sopenharmony_ci * FUNCTION: acpi_db_get_display_op 12762306a36Sopenharmony_ci * 12862306a36Sopenharmony_ci * PARAMETERS: walk_state - Current walk 12962306a36Sopenharmony_ci * op - Current executing op (from aml interpreter) 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * RETURN: Opcode to display 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci * DESCRIPTION: Find the opcode to display during single stepping 13462306a36Sopenharmony_ci * 13562306a36Sopenharmony_ci ******************************************************************************/ 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic union acpi_parse_object *acpi_db_get_display_op(struct acpi_walk_state 13862306a36Sopenharmony_ci *walk_state, 13962306a36Sopenharmony_ci union acpi_parse_object 14062306a36Sopenharmony_ci *op) 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci union acpi_parse_object *display_op; 14362306a36Sopenharmony_ci union acpi_parse_object *parent_op; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci display_op = op; 14662306a36Sopenharmony_ci parent_op = op->common.parent; 14762306a36Sopenharmony_ci if (parent_op) { 14862306a36Sopenharmony_ci if ((walk_state->control_state) && 14962306a36Sopenharmony_ci (walk_state->control_state->common.state == 15062306a36Sopenharmony_ci ACPI_CONTROL_PREDICATE_EXECUTING)) { 15162306a36Sopenharmony_ci /* 15262306a36Sopenharmony_ci * We are executing the predicate of an IF or WHILE statement 15362306a36Sopenharmony_ci * Search upwards for the containing IF or WHILE so that the 15462306a36Sopenharmony_ci * entire predicate can be displayed. 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ci while (parent_op) { 15762306a36Sopenharmony_ci if ((parent_op->common.aml_opcode == AML_IF_OP) 15862306a36Sopenharmony_ci || (parent_op->common.aml_opcode == 15962306a36Sopenharmony_ci AML_WHILE_OP)) { 16062306a36Sopenharmony_ci display_op = parent_op; 16162306a36Sopenharmony_ci break; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci parent_op = parent_op->common.parent; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci } else { 16662306a36Sopenharmony_ci while (parent_op) { 16762306a36Sopenharmony_ci if ((parent_op->common.aml_opcode == AML_IF_OP) 16862306a36Sopenharmony_ci || (parent_op->common.aml_opcode == 16962306a36Sopenharmony_ci AML_ELSE_OP) 17062306a36Sopenharmony_ci || (parent_op->common.aml_opcode == 17162306a36Sopenharmony_ci AML_SCOPE_OP) 17262306a36Sopenharmony_ci || (parent_op->common.aml_opcode == 17362306a36Sopenharmony_ci AML_METHOD_OP) 17462306a36Sopenharmony_ci || (parent_op->common.aml_opcode == 17562306a36Sopenharmony_ci AML_WHILE_OP)) { 17662306a36Sopenharmony_ci break; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci display_op = parent_op; 17962306a36Sopenharmony_ci parent_op = parent_op->common.parent; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci return display_op; 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci#endif 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/******************************************************************************* 18862306a36Sopenharmony_ci * 18962306a36Sopenharmony_ci * FUNCTION: acpi_db_single_step 19062306a36Sopenharmony_ci * 19162306a36Sopenharmony_ci * PARAMETERS: walk_state - Current walk 19262306a36Sopenharmony_ci * op - Current executing op (from aml interpreter) 19362306a36Sopenharmony_ci * opcode_class - Class of the current AML Opcode 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * RETURN: Status 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * DESCRIPTION: Called just before execution of an AML opcode. 19862306a36Sopenharmony_ci * 19962306a36Sopenharmony_ci ******************************************************************************/ 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ciacpi_status 20262306a36Sopenharmony_ciacpi_db_single_step(struct acpi_walk_state *walk_state, 20362306a36Sopenharmony_ci union acpi_parse_object *op, u32 opcode_class) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci union acpi_parse_object *next; 20662306a36Sopenharmony_ci acpi_status status = AE_OK; 20762306a36Sopenharmony_ci u32 original_debug_level; 20862306a36Sopenharmony_ci u32 aml_offset; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci ACPI_FUNCTION_ENTRY(); 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci#ifndef ACPI_APPLICATION 21362306a36Sopenharmony_ci if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) { 21462306a36Sopenharmony_ci return (AE_OK); 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci#endif 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci /* Check the abort flag */ 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci if (acpi_gbl_abort_method) { 22162306a36Sopenharmony_ci acpi_gbl_abort_method = FALSE; 22262306a36Sopenharmony_ci return (AE_ABORT_METHOD); 22362306a36Sopenharmony_ci } 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml, 22662306a36Sopenharmony_ci walk_state->parser_state.aml_start); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci /* Check for single-step breakpoint */ 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci if (walk_state->method_breakpoint && 23162306a36Sopenharmony_ci (walk_state->method_breakpoint <= aml_offset)) { 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci /* Check if the breakpoint has been reached or passed */ 23462306a36Sopenharmony_ci /* Hit the breakpoint, resume single step, reset breakpoint */ 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci acpi_os_printf("***Break*** at AML offset %X\n", aml_offset); 23762306a36Sopenharmony_ci acpi_gbl_cm_single_step = TRUE; 23862306a36Sopenharmony_ci acpi_gbl_step_to_next_call = FALSE; 23962306a36Sopenharmony_ci walk_state->method_breakpoint = 0; 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* Check for user breakpoint (Must be on exact Aml offset) */ 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci else if (walk_state->user_breakpoint && 24562306a36Sopenharmony_ci (walk_state->user_breakpoint == aml_offset)) { 24662306a36Sopenharmony_ci acpi_os_printf("***UserBreakpoint*** at AML offset %X\n", 24762306a36Sopenharmony_ci aml_offset); 24862306a36Sopenharmony_ci acpi_gbl_cm_single_step = TRUE; 24962306a36Sopenharmony_ci acpi_gbl_step_to_next_call = FALSE; 25062306a36Sopenharmony_ci walk_state->method_breakpoint = 0; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci /* 25462306a36Sopenharmony_ci * Check if this is an opcode that we are interested in -- 25562306a36Sopenharmony_ci * namely, opcodes that have arguments 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { 25862306a36Sopenharmony_ci return (AE_OK); 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci switch (opcode_class) { 26262306a36Sopenharmony_ci case AML_CLASS_UNKNOWN: 26362306a36Sopenharmony_ci case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */ 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci return (AE_OK); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci default: 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci /* All other opcodes -- continue */ 27062306a36Sopenharmony_ci break; 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* 27462306a36Sopenharmony_ci * Under certain debug conditions, display this opcode and its operands 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_ci if ((acpi_gbl_db_output_to_file) || 27762306a36Sopenharmony_ci (acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) { 27862306a36Sopenharmony_ci if ((acpi_gbl_db_output_to_file) || 27962306a36Sopenharmony_ci (acpi_dbg_level & ACPI_LV_PARSE)) { 28062306a36Sopenharmony_ci acpi_os_printf 28162306a36Sopenharmony_ci ("\nAML Debug: Next AML Opcode to execute:\n"); 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* 28562306a36Sopenharmony_ci * Display this op (and only this op - zero out the NEXT field 28662306a36Sopenharmony_ci * temporarily, and disable parser trace output for the duration of 28762306a36Sopenharmony_ci * the display because we don't want the extraneous debug output) 28862306a36Sopenharmony_ci */ 28962306a36Sopenharmony_ci original_debug_level = acpi_dbg_level; 29062306a36Sopenharmony_ci acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS); 29162306a36Sopenharmony_ci next = op->common.next; 29262306a36Sopenharmony_ci op->common.next = NULL; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* Now we can disassemble and display it */ 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci#ifdef ACPI_DISASSEMBLER 29762306a36Sopenharmony_ci acpi_dm_disassemble(walk_state, 29862306a36Sopenharmony_ci acpi_db_get_display_op(walk_state, op), 29962306a36Sopenharmony_ci ACPI_UINT32_MAX); 30062306a36Sopenharmony_ci#else 30162306a36Sopenharmony_ci /* 30262306a36Sopenharmony_ci * The AML Disassembler is not configured - at least we can 30362306a36Sopenharmony_ci * display the opcode value and name 30462306a36Sopenharmony_ci */ 30562306a36Sopenharmony_ci acpi_os_printf("AML Opcode: %4.4X %s\n", op->common.aml_opcode, 30662306a36Sopenharmony_ci acpi_ps_get_opcode_name(op->common.aml_opcode)); 30762306a36Sopenharmony_ci#endif 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if ((op->common.aml_opcode == AML_IF_OP) || 31062306a36Sopenharmony_ci (op->common.aml_opcode == AML_WHILE_OP)) { 31162306a36Sopenharmony_ci if (walk_state->control_state->common.value) { 31262306a36Sopenharmony_ci acpi_os_printf 31362306a36Sopenharmony_ci ("Predicate = [True], IF block was executed\n"); 31462306a36Sopenharmony_ci } else { 31562306a36Sopenharmony_ci acpi_os_printf 31662306a36Sopenharmony_ci ("Predicate = [False], Skipping IF block\n"); 31762306a36Sopenharmony_ci } 31862306a36Sopenharmony_ci } else if (op->common.aml_opcode == AML_ELSE_OP) { 31962306a36Sopenharmony_ci acpi_os_printf 32062306a36Sopenharmony_ci ("Predicate = [False], ELSE block was executed\n"); 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* Restore everything */ 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci op->common.next = next; 32662306a36Sopenharmony_ci acpi_os_printf("\n"); 32762306a36Sopenharmony_ci if ((acpi_gbl_db_output_to_file) || 32862306a36Sopenharmony_ci (acpi_dbg_level & ACPI_LV_PARSE)) { 32962306a36Sopenharmony_ci acpi_os_printf("\n"); 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci acpi_dbg_level = original_debug_level; 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci /* If we are not single stepping, just continue executing the method */ 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (!acpi_gbl_cm_single_step) { 33762306a36Sopenharmony_ci return (AE_OK); 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* 34162306a36Sopenharmony_ci * If we are executing a step-to-call command, 34262306a36Sopenharmony_ci * Check if this is a method call. 34362306a36Sopenharmony_ci */ 34462306a36Sopenharmony_ci if (acpi_gbl_step_to_next_call) { 34562306a36Sopenharmony_ci if (op->common.aml_opcode != AML_INT_METHODCALL_OP) { 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* Not a method call, just keep executing */ 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci return (AE_OK); 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* Found a method call, stop executing */ 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci acpi_gbl_step_to_next_call = FALSE; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* 35862306a36Sopenharmony_ci * If the next opcode is a method call, we will "step over" it 35962306a36Sopenharmony_ci * by default. 36062306a36Sopenharmony_ci */ 36162306a36Sopenharmony_ci if (op->common.aml_opcode == AML_INT_METHODCALL_OP) { 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci /* Force no more single stepping while executing called method */ 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci acpi_gbl_cm_single_step = FALSE; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci /* 36862306a36Sopenharmony_ci * Set the breakpoint on/before the call, it will stop execution 36962306a36Sopenharmony_ci * as soon as we return 37062306a36Sopenharmony_ci */ 37162306a36Sopenharmony_ci walk_state->method_breakpoint = 1; /* Must be non-zero! */ 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci acpi_ex_exit_interpreter(); 37562306a36Sopenharmony_ci status = acpi_db_start_command(walk_state, op); 37662306a36Sopenharmony_ci acpi_ex_enter_interpreter(); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci /* User commands complete, continue execution of the interrupted method */ 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci return (status); 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci/******************************************************************************* 38462306a36Sopenharmony_ci * 38562306a36Sopenharmony_ci * FUNCTION: acpi_initialize_debugger 38662306a36Sopenharmony_ci * 38762306a36Sopenharmony_ci * PARAMETERS: None 38862306a36Sopenharmony_ci * 38962306a36Sopenharmony_ci * RETURN: Status 39062306a36Sopenharmony_ci * 39162306a36Sopenharmony_ci * DESCRIPTION: Init and start debugger 39262306a36Sopenharmony_ci * 39362306a36Sopenharmony_ci ******************************************************************************/ 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ciacpi_status acpi_initialize_debugger(void) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci acpi_status status; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(acpi_initialize_debugger); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* Init globals */ 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci acpi_gbl_db_buffer = NULL; 40462306a36Sopenharmony_ci acpi_gbl_db_filename = NULL; 40562306a36Sopenharmony_ci acpi_gbl_db_output_to_file = FALSE; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2; 40862306a36Sopenharmony_ci acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES; 40962306a36Sopenharmony_ci acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci acpi_gbl_db_opt_no_ini_methods = FALSE; 41262306a36Sopenharmony_ci acpi_gbl_db_opt_no_region_support = FALSE; 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE); 41562306a36Sopenharmony_ci if (!acpi_gbl_db_buffer) { 41662306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci /* Initial scope is the root */ 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX; 42362306a36Sopenharmony_ci acpi_gbl_db_scope_buf[1] = 0; 42462306a36Sopenharmony_ci acpi_gbl_db_scope_node = acpi_gbl_root_node; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci /* Initialize user commands loop */ 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci acpi_gbl_db_terminate_loop = FALSE; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci /* 43162306a36Sopenharmony_ci * If configured for multi-thread support, the debug executor runs in 43262306a36Sopenharmony_ci * a separate thread so that the front end can be in another address 43362306a36Sopenharmony_ci * space, environment, or even another machine. 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_ci if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) { 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* These were created with one unit, grab it */ 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci status = acpi_os_initialize_debugger(); 44062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 44162306a36Sopenharmony_ci acpi_os_printf("Could not get debugger mutex\n"); 44262306a36Sopenharmony_ci return_ACPI_STATUS(status); 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci /* Create the debug execution thread to execute commands */ 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci acpi_gbl_db_threads_terminated = FALSE; 44862306a36Sopenharmony_ci status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD, 44962306a36Sopenharmony_ci acpi_db_execute_thread, NULL); 45062306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 45162306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 45262306a36Sopenharmony_ci "Could not start debugger thread")); 45362306a36Sopenharmony_ci acpi_gbl_db_threads_terminated = TRUE; 45462306a36Sopenharmony_ci return_ACPI_STATUS(status); 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci } else { 45762306a36Sopenharmony_ci acpi_gbl_db_thread_id = acpi_os_get_thread_id(); 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 46162306a36Sopenharmony_ci} 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_initialize_debugger) 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci/******************************************************************************* 46662306a36Sopenharmony_ci * 46762306a36Sopenharmony_ci * FUNCTION: acpi_terminate_debugger 46862306a36Sopenharmony_ci * 46962306a36Sopenharmony_ci * PARAMETERS: None 47062306a36Sopenharmony_ci * 47162306a36Sopenharmony_ci * RETURN: None 47262306a36Sopenharmony_ci * 47362306a36Sopenharmony_ci * DESCRIPTION: Stop debugger 47462306a36Sopenharmony_ci * 47562306a36Sopenharmony_ci ******************************************************************************/ 47662306a36Sopenharmony_civoid acpi_terminate_debugger(void) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci /* Terminate the AML Debugger */ 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci acpi_gbl_db_terminate_loop = TRUE; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) { 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci /* Wait the AML Debugger threads */ 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci while (!acpi_gbl_db_threads_terminated) { 48862306a36Sopenharmony_ci acpi_os_sleep(100); 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci acpi_os_terminate_debugger(); 49262306a36Sopenharmony_ci } 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci if (acpi_gbl_db_buffer) { 49562306a36Sopenharmony_ci acpi_os_free(acpi_gbl_db_buffer); 49662306a36Sopenharmony_ci acpi_gbl_db_buffer = NULL; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci /* Ensure that debug output is now disabled */ 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT; 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_terminate_debugger) 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci/******************************************************************************* 50762306a36Sopenharmony_ci * 50862306a36Sopenharmony_ci * FUNCTION: acpi_set_debugger_thread_id 50962306a36Sopenharmony_ci * 51062306a36Sopenharmony_ci * PARAMETERS: thread_id - Debugger thread ID 51162306a36Sopenharmony_ci * 51262306a36Sopenharmony_ci * RETURN: None 51362306a36Sopenharmony_ci * 51462306a36Sopenharmony_ci * DESCRIPTION: Set debugger thread ID 51562306a36Sopenharmony_ci * 51662306a36Sopenharmony_ci ******************************************************************************/ 51762306a36Sopenharmony_civoid acpi_set_debugger_thread_id(acpi_thread_id thread_id) 51862306a36Sopenharmony_ci{ 51962306a36Sopenharmony_ci acpi_gbl_db_thread_id = thread_id; 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ciACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id) 523