1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: dbxface - AML Debugger external interfaces
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun ******************************************************************************/
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun #include "amlcode.h"
11*4882a593Smuzhiyun #include "acdebug.h"
12*4882a593Smuzhiyun #include "acinterp.h"
13*4882a593Smuzhiyun #include "acparser.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define _COMPONENT ACPI_CA_DEBUGGER
16*4882a593Smuzhiyun ACPI_MODULE_NAME("dbxface")
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun /* Local prototypes */
19*4882a593Smuzhiyun static acpi_status
20*4882a593Smuzhiyun acpi_db_start_command(struct acpi_walk_state *walk_state,
21*4882a593Smuzhiyun union acpi_parse_object *op);
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #ifdef ACPI_OBSOLETE_FUNCTIONS
24*4882a593Smuzhiyun void acpi_db_method_end(struct acpi_walk_state *walk_state);
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #ifdef ACPI_DISASSEMBLER
28*4882a593Smuzhiyun static union acpi_parse_object *acpi_db_get_display_op(struct acpi_walk_state
29*4882a593Smuzhiyun *walk_state,
30*4882a593Smuzhiyun union acpi_parse_object
31*4882a593Smuzhiyun *op);
32*4882a593Smuzhiyun #endif
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /*******************************************************************************
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * FUNCTION: acpi_db_start_command
37*4882a593Smuzhiyun *
38*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk
39*4882a593Smuzhiyun * op - Current executing Op, from AML interpreter
40*4882a593Smuzhiyun *
41*4882a593Smuzhiyun * RETURN: Status
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun * DESCRIPTION: Enter debugger command loop
44*4882a593Smuzhiyun *
45*4882a593Smuzhiyun ******************************************************************************/
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static acpi_status
acpi_db_start_command(struct acpi_walk_state * walk_state,union acpi_parse_object * op)48*4882a593Smuzhiyun acpi_db_start_command(struct acpi_walk_state *walk_state,
49*4882a593Smuzhiyun union acpi_parse_object *op)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun acpi_status status;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun /* TBD: [Investigate] are there namespace locking issues here? */
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* Go into the command loop and await next user command */
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun acpi_gbl_method_executing = TRUE;
60*4882a593Smuzhiyun status = AE_CTRL_TRUE;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun while (status == AE_CTRL_TRUE) {
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* Notify the completion of the command */
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun status = acpi_os_notify_command_complete();
67*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
68*4882a593Smuzhiyun goto error_exit;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun /* Wait the readiness of the command */
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun status = acpi_os_wait_command_ready();
74*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
75*4882a593Smuzhiyun goto error_exit;
76*4882a593Smuzhiyun }
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun status =
79*4882a593Smuzhiyun acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state,
80*4882a593Smuzhiyun op);
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun error_exit:
86*4882a593Smuzhiyun if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) {
87*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
88*4882a593Smuzhiyun "While parsing/handling command line"));
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun return (status);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /*******************************************************************************
94*4882a593Smuzhiyun *
95*4882a593Smuzhiyun * FUNCTION: acpi_db_signal_break_point
96*4882a593Smuzhiyun *
97*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk
98*4882a593Smuzhiyun *
99*4882a593Smuzhiyun * RETURN: Status
100*4882a593Smuzhiyun *
101*4882a593Smuzhiyun * DESCRIPTION: Called for AML_BREAKPOINT_OP
102*4882a593Smuzhiyun *
103*4882a593Smuzhiyun ******************************************************************************/
104*4882a593Smuzhiyun
acpi_db_signal_break_point(struct acpi_walk_state * walk_state)105*4882a593Smuzhiyun void acpi_db_signal_break_point(struct acpi_walk_state *walk_state)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun #ifndef ACPI_APPLICATION
109*4882a593Smuzhiyun if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
110*4882a593Smuzhiyun return;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun #endif
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /*
115*4882a593Smuzhiyun * Set the single-step flag. This will cause the debugger (if present)
116*4882a593Smuzhiyun * to break to the console within the AML debugger at the start of the
117*4882a593Smuzhiyun * next AML instruction.
118*4882a593Smuzhiyun */
119*4882a593Smuzhiyun acpi_gbl_cm_single_step = TRUE;
120*4882a593Smuzhiyun acpi_os_printf("**break** Executed AML BreakPoint opcode\n");
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun #ifdef ACPI_DISASSEMBLER
124*4882a593Smuzhiyun /*******************************************************************************
125*4882a593Smuzhiyun *
126*4882a593Smuzhiyun * FUNCTION: acpi_db_get_display_op
127*4882a593Smuzhiyun *
128*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk
129*4882a593Smuzhiyun * op - Current executing op (from aml interpreter)
130*4882a593Smuzhiyun *
131*4882a593Smuzhiyun * RETURN: Opcode to display
132*4882a593Smuzhiyun *
133*4882a593Smuzhiyun * DESCRIPTION: Find the opcode to display during single stepping
134*4882a593Smuzhiyun *
135*4882a593Smuzhiyun ******************************************************************************/
136*4882a593Smuzhiyun
acpi_db_get_display_op(struct acpi_walk_state * walk_state,union acpi_parse_object * op)137*4882a593Smuzhiyun static union acpi_parse_object *acpi_db_get_display_op(struct acpi_walk_state
138*4882a593Smuzhiyun *walk_state,
139*4882a593Smuzhiyun union acpi_parse_object
140*4882a593Smuzhiyun *op)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun union acpi_parse_object *display_op;
143*4882a593Smuzhiyun union acpi_parse_object *parent_op;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun display_op = op;
146*4882a593Smuzhiyun parent_op = op->common.parent;
147*4882a593Smuzhiyun if (parent_op) {
148*4882a593Smuzhiyun if ((walk_state->control_state) &&
149*4882a593Smuzhiyun (walk_state->control_state->common.state ==
150*4882a593Smuzhiyun ACPI_CONTROL_PREDICATE_EXECUTING)) {
151*4882a593Smuzhiyun /*
152*4882a593Smuzhiyun * We are executing the predicate of an IF or WHILE statement
153*4882a593Smuzhiyun * Search upwards for the containing IF or WHILE so that the
154*4882a593Smuzhiyun * entire predicate can be displayed.
155*4882a593Smuzhiyun */
156*4882a593Smuzhiyun while (parent_op) {
157*4882a593Smuzhiyun if ((parent_op->common.aml_opcode == AML_IF_OP)
158*4882a593Smuzhiyun || (parent_op->common.aml_opcode ==
159*4882a593Smuzhiyun AML_WHILE_OP)) {
160*4882a593Smuzhiyun display_op = parent_op;
161*4882a593Smuzhiyun break;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun parent_op = parent_op->common.parent;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun } else {
166*4882a593Smuzhiyun while (parent_op) {
167*4882a593Smuzhiyun if ((parent_op->common.aml_opcode == AML_IF_OP)
168*4882a593Smuzhiyun || (parent_op->common.aml_opcode ==
169*4882a593Smuzhiyun AML_ELSE_OP)
170*4882a593Smuzhiyun || (parent_op->common.aml_opcode ==
171*4882a593Smuzhiyun AML_SCOPE_OP)
172*4882a593Smuzhiyun || (parent_op->common.aml_opcode ==
173*4882a593Smuzhiyun AML_METHOD_OP)
174*4882a593Smuzhiyun || (parent_op->common.aml_opcode ==
175*4882a593Smuzhiyun AML_WHILE_OP)) {
176*4882a593Smuzhiyun break;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun display_op = parent_op;
179*4882a593Smuzhiyun parent_op = parent_op->common.parent;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun return display_op;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun #endif
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun /*******************************************************************************
188*4882a593Smuzhiyun *
189*4882a593Smuzhiyun * FUNCTION: acpi_db_single_step
190*4882a593Smuzhiyun *
191*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk
192*4882a593Smuzhiyun * op - Current executing op (from aml interpreter)
193*4882a593Smuzhiyun * opcode_class - Class of the current AML Opcode
194*4882a593Smuzhiyun *
195*4882a593Smuzhiyun * RETURN: Status
196*4882a593Smuzhiyun *
197*4882a593Smuzhiyun * DESCRIPTION: Called just before execution of an AML opcode.
198*4882a593Smuzhiyun *
199*4882a593Smuzhiyun ******************************************************************************/
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun acpi_status
acpi_db_single_step(struct acpi_walk_state * walk_state,union acpi_parse_object * op,u32 opcode_class)202*4882a593Smuzhiyun acpi_db_single_step(struct acpi_walk_state *walk_state,
203*4882a593Smuzhiyun union acpi_parse_object *op, u32 opcode_class)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun union acpi_parse_object *next;
206*4882a593Smuzhiyun acpi_status status = AE_OK;
207*4882a593Smuzhiyun u32 original_debug_level;
208*4882a593Smuzhiyun u32 aml_offset;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun #ifndef ACPI_APPLICATION
213*4882a593Smuzhiyun if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
214*4882a593Smuzhiyun return (AE_OK);
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun #endif
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun /* Check the abort flag */
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun if (acpi_gbl_abort_method) {
221*4882a593Smuzhiyun acpi_gbl_abort_method = FALSE;
222*4882a593Smuzhiyun return (AE_ABORT_METHOD);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
226*4882a593Smuzhiyun walk_state->parser_state.aml_start);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /* Check for single-step breakpoint */
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (walk_state->method_breakpoint &&
231*4882a593Smuzhiyun (walk_state->method_breakpoint <= aml_offset)) {
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun /* Check if the breakpoint has been reached or passed */
234*4882a593Smuzhiyun /* Hit the breakpoint, resume single step, reset breakpoint */
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun acpi_os_printf("***Break*** at AML offset %X\n", aml_offset);
237*4882a593Smuzhiyun acpi_gbl_cm_single_step = TRUE;
238*4882a593Smuzhiyun acpi_gbl_step_to_next_call = FALSE;
239*4882a593Smuzhiyun walk_state->method_breakpoint = 0;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun /* Check for user breakpoint (Must be on exact Aml offset) */
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun else if (walk_state->user_breakpoint &&
245*4882a593Smuzhiyun (walk_state->user_breakpoint == aml_offset)) {
246*4882a593Smuzhiyun acpi_os_printf("***UserBreakpoint*** at AML offset %X\n",
247*4882a593Smuzhiyun aml_offset);
248*4882a593Smuzhiyun acpi_gbl_cm_single_step = TRUE;
249*4882a593Smuzhiyun acpi_gbl_step_to_next_call = FALSE;
250*4882a593Smuzhiyun walk_state->method_breakpoint = 0;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun * Check if this is an opcode that we are interested in --
255*4882a593Smuzhiyun * namely, opcodes that have arguments
256*4882a593Smuzhiyun */
257*4882a593Smuzhiyun if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
258*4882a593Smuzhiyun return (AE_OK);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun switch (opcode_class) {
262*4882a593Smuzhiyun case AML_CLASS_UNKNOWN:
263*4882a593Smuzhiyun case AML_CLASS_ARGUMENT: /* constants, literals, etc. do nothing */
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun return (AE_OK);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun default:
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun /* All other opcodes -- continue */
270*4882a593Smuzhiyun break;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun /*
274*4882a593Smuzhiyun * Under certain debug conditions, display this opcode and its operands
275*4882a593Smuzhiyun */
276*4882a593Smuzhiyun if ((acpi_gbl_db_output_to_file) ||
277*4882a593Smuzhiyun (acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) {
278*4882a593Smuzhiyun if ((acpi_gbl_db_output_to_file) ||
279*4882a593Smuzhiyun (acpi_dbg_level & ACPI_LV_PARSE)) {
280*4882a593Smuzhiyun acpi_os_printf
281*4882a593Smuzhiyun ("\nAML Debug: Next AML Opcode to execute:\n");
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun /*
285*4882a593Smuzhiyun * Display this op (and only this op - zero out the NEXT field
286*4882a593Smuzhiyun * temporarily, and disable parser trace output for the duration of
287*4882a593Smuzhiyun * the display because we don't want the extraneous debug output)
288*4882a593Smuzhiyun */
289*4882a593Smuzhiyun original_debug_level = acpi_dbg_level;
290*4882a593Smuzhiyun acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS);
291*4882a593Smuzhiyun next = op->common.next;
292*4882a593Smuzhiyun op->common.next = NULL;
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun /* Now we can disassemble and display it */
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun #ifdef ACPI_DISASSEMBLER
297*4882a593Smuzhiyun acpi_dm_disassemble(walk_state,
298*4882a593Smuzhiyun acpi_db_get_display_op(walk_state, op),
299*4882a593Smuzhiyun ACPI_UINT32_MAX);
300*4882a593Smuzhiyun #else
301*4882a593Smuzhiyun /*
302*4882a593Smuzhiyun * The AML Disassembler is not configured - at least we can
303*4882a593Smuzhiyun * display the opcode value and name
304*4882a593Smuzhiyun */
305*4882a593Smuzhiyun acpi_os_printf("AML Opcode: %4.4X %s\n", op->common.aml_opcode,
306*4882a593Smuzhiyun acpi_ps_get_opcode_name(op->common.aml_opcode));
307*4882a593Smuzhiyun #endif
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if ((op->common.aml_opcode == AML_IF_OP) ||
310*4882a593Smuzhiyun (op->common.aml_opcode == AML_WHILE_OP)) {
311*4882a593Smuzhiyun if (walk_state->control_state->common.value) {
312*4882a593Smuzhiyun acpi_os_printf
313*4882a593Smuzhiyun ("Predicate = [True], IF block was executed\n");
314*4882a593Smuzhiyun } else {
315*4882a593Smuzhiyun acpi_os_printf
316*4882a593Smuzhiyun ("Predicate = [False], Skipping IF block\n");
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun } else if (op->common.aml_opcode == AML_ELSE_OP) {
319*4882a593Smuzhiyun acpi_os_printf
320*4882a593Smuzhiyun ("Predicate = [False], ELSE block was executed\n");
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun /* Restore everything */
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun op->common.next = next;
326*4882a593Smuzhiyun acpi_os_printf("\n");
327*4882a593Smuzhiyun if ((acpi_gbl_db_output_to_file) ||
328*4882a593Smuzhiyun (acpi_dbg_level & ACPI_LV_PARSE)) {
329*4882a593Smuzhiyun acpi_os_printf("\n");
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun acpi_dbg_level = original_debug_level;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun /* If we are not single stepping, just continue executing the method */
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun if (!acpi_gbl_cm_single_step) {
337*4882a593Smuzhiyun return (AE_OK);
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun /*
341*4882a593Smuzhiyun * If we are executing a step-to-call command,
342*4882a593Smuzhiyun * Check if this is a method call.
343*4882a593Smuzhiyun */
344*4882a593Smuzhiyun if (acpi_gbl_step_to_next_call) {
345*4882a593Smuzhiyun if (op->common.aml_opcode != AML_INT_METHODCALL_OP) {
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun /* Not a method call, just keep executing */
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun return (AE_OK);
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun /* Found a method call, stop executing */
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun acpi_gbl_step_to_next_call = FALSE;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun /*
358*4882a593Smuzhiyun * If the next opcode is a method call, we will "step over" it
359*4882a593Smuzhiyun * by default.
360*4882a593Smuzhiyun */
361*4882a593Smuzhiyun if (op->common.aml_opcode == AML_INT_METHODCALL_OP) {
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun /* Force no more single stepping while executing called method */
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun acpi_gbl_cm_single_step = FALSE;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun /*
368*4882a593Smuzhiyun * Set the breakpoint on/before the call, it will stop execution
369*4882a593Smuzhiyun * as soon as we return
370*4882a593Smuzhiyun */
371*4882a593Smuzhiyun walk_state->method_breakpoint = 1; /* Must be non-zero! */
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun
374*4882a593Smuzhiyun acpi_ex_exit_interpreter();
375*4882a593Smuzhiyun status = acpi_db_start_command(walk_state, op);
376*4882a593Smuzhiyun acpi_ex_enter_interpreter();
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun /* User commands complete, continue execution of the interrupted method */
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun return (status);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun /*******************************************************************************
384*4882a593Smuzhiyun *
385*4882a593Smuzhiyun * FUNCTION: acpi_initialize_debugger
386*4882a593Smuzhiyun *
387*4882a593Smuzhiyun * PARAMETERS: None
388*4882a593Smuzhiyun *
389*4882a593Smuzhiyun * RETURN: Status
390*4882a593Smuzhiyun *
391*4882a593Smuzhiyun * DESCRIPTION: Init and start debugger
392*4882a593Smuzhiyun *
393*4882a593Smuzhiyun ******************************************************************************/
394*4882a593Smuzhiyun
acpi_initialize_debugger(void)395*4882a593Smuzhiyun acpi_status acpi_initialize_debugger(void)
396*4882a593Smuzhiyun {
397*4882a593Smuzhiyun acpi_status status;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(acpi_initialize_debugger);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun /* Init globals */
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun acpi_gbl_db_buffer = NULL;
404*4882a593Smuzhiyun acpi_gbl_db_filename = NULL;
405*4882a593Smuzhiyun acpi_gbl_db_output_to_file = FALSE;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2;
408*4882a593Smuzhiyun acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES;
409*4882a593Smuzhiyun acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun acpi_gbl_db_opt_no_ini_methods = FALSE;
412*4882a593Smuzhiyun acpi_gbl_db_opt_no_region_support = FALSE;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE);
415*4882a593Smuzhiyun if (!acpi_gbl_db_buffer) {
416*4882a593Smuzhiyun return_ACPI_STATUS(AE_NO_MEMORY);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE);
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun /* Initial scope is the root */
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX;
423*4882a593Smuzhiyun acpi_gbl_db_scope_buf[1] = 0;
424*4882a593Smuzhiyun acpi_gbl_db_scope_node = acpi_gbl_root_node;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun /* Initialize user commands loop */
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun acpi_gbl_db_terminate_loop = FALSE;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun /*
431*4882a593Smuzhiyun * If configured for multi-thread support, the debug executor runs in
432*4882a593Smuzhiyun * a separate thread so that the front end can be in another address
433*4882a593Smuzhiyun * space, environment, or even another machine.
434*4882a593Smuzhiyun */
435*4882a593Smuzhiyun if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun /* These were created with one unit, grab it */
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun status = acpi_os_initialize_debugger();
440*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
441*4882a593Smuzhiyun acpi_os_printf("Could not get debugger mutex\n");
442*4882a593Smuzhiyun return_ACPI_STATUS(status);
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun /* Create the debug execution thread to execute commands */
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun acpi_gbl_db_threads_terminated = FALSE;
448*4882a593Smuzhiyun status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD,
449*4882a593Smuzhiyun acpi_db_execute_thread, NULL);
450*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
451*4882a593Smuzhiyun ACPI_EXCEPTION((AE_INFO, status,
452*4882a593Smuzhiyun "Could not start debugger thread"));
453*4882a593Smuzhiyun acpi_gbl_db_threads_terminated = TRUE;
454*4882a593Smuzhiyun return_ACPI_STATUS(status);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun } else {
457*4882a593Smuzhiyun acpi_gbl_db_thread_id = acpi_os_get_thread_id();
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)463*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun /*******************************************************************************
466*4882a593Smuzhiyun *
467*4882a593Smuzhiyun * FUNCTION: acpi_terminate_debugger
468*4882a593Smuzhiyun *
469*4882a593Smuzhiyun * PARAMETERS: None
470*4882a593Smuzhiyun *
471*4882a593Smuzhiyun * RETURN: None
472*4882a593Smuzhiyun *
473*4882a593Smuzhiyun * DESCRIPTION: Stop debugger
474*4882a593Smuzhiyun *
475*4882a593Smuzhiyun ******************************************************************************/
476*4882a593Smuzhiyun void acpi_terminate_debugger(void)
477*4882a593Smuzhiyun {
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /* Terminate the AML Debugger */
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun acpi_gbl_db_terminate_loop = TRUE;
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun /* Wait the AML Debugger threads */
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun while (!acpi_gbl_db_threads_terminated) {
488*4882a593Smuzhiyun acpi_os_sleep(100);
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun acpi_os_terminate_debugger();
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun if (acpi_gbl_db_buffer) {
495*4882a593Smuzhiyun acpi_os_free(acpi_gbl_db_buffer);
496*4882a593Smuzhiyun acpi_gbl_db_buffer = NULL;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* Ensure that debug output is now disabled */
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)504*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun /*******************************************************************************
507*4882a593Smuzhiyun *
508*4882a593Smuzhiyun * FUNCTION: acpi_set_debugger_thread_id
509*4882a593Smuzhiyun *
510*4882a593Smuzhiyun * PARAMETERS: thread_id - Debugger thread ID
511*4882a593Smuzhiyun *
512*4882a593Smuzhiyun * RETURN: None
513*4882a593Smuzhiyun *
514*4882a593Smuzhiyun * DESCRIPTION: Set debugger thread ID
515*4882a593Smuzhiyun *
516*4882a593Smuzhiyun ******************************************************************************/
517*4882a593Smuzhiyun void acpi_set_debugger_thread_id(acpi_thread_id thread_id)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun acpi_gbl_db_thread_id = thread_id;
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id)
523