ACPICA: Debugger: Fix "quit/exit" command by cleaning up user commands termination...
[linux-2.6-microblaze.git] / drivers / acpi / acpica / dbxface.c
1 /*******************************************************************************
2  *
3  * Module Name: dbxface - AML Debugger external interfaces
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "amlcode.h"
47 #include "acdebug.h"
48
49 #define _COMPONENT          ACPI_CA_DEBUGGER
50 ACPI_MODULE_NAME("dbxface")
51
52 /* Local prototypes */
53 static acpi_status
54 acpi_db_start_command(struct acpi_walk_state *walk_state,
55                       union acpi_parse_object *op);
56
57 #ifdef ACPI_OBSOLETE_FUNCTIONS
58 void acpi_db_method_end(struct acpi_walk_state *walk_state);
59 #endif
60
61 /*******************************************************************************
62  *
63  * FUNCTION:    acpi_db_start_command
64  *
65  * PARAMETERS:  walk_state      - Current walk
66  *              op              - Current executing Op, from AML interpreter
67  *
68  * RETURN:      Status
69  *
70  * DESCRIPTION: Enter debugger command loop
71  *
72  ******************************************************************************/
73
74 static acpi_status
75 acpi_db_start_command(struct acpi_walk_state *walk_state,
76                       union acpi_parse_object *op)
77 {
78         acpi_status status;
79
80         /* TBD: [Investigate] are there namespace locking issues here? */
81
82         /* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */
83
84         /* Go into the command loop and await next user command */
85
86         acpi_gbl_method_executing = TRUE;
87         status = AE_CTRL_TRUE;
88         while (status == AE_CTRL_TRUE) {
89                 if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) {
90
91                         /* Handshake with the front-end that gets user command lines */
92
93                         acpi_os_release_mutex(acpi_gbl_db_command_complete);
94
95                         status =
96                             acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
97                                                   ACPI_WAIT_FOREVER);
98                         if (ACPI_FAILURE(status)) {
99                                 return (status);
100                         }
101                 } else {
102                         /* Single threaded, we must get a command line ourselves */
103
104                         /* Force output to console until a command is entered */
105
106                         acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
107
108                         /* Different prompt if method is executing */
109
110                         if (!acpi_gbl_method_executing) {
111                                 acpi_os_printf("%1c ",
112                                                ACPI_DEBUGGER_COMMAND_PROMPT);
113                         } else {
114                                 acpi_os_printf("%1c ",
115                                                ACPI_DEBUGGER_EXECUTE_PROMPT);
116                         }
117
118                         /* Get the user input line */
119
120                         status = acpi_os_get_line(acpi_gbl_db_line_buf,
121                                                   ACPI_DB_LINE_BUFFER_SIZE,
122                                                   NULL);
123                         if (ACPI_FAILURE(status)) {
124                                 ACPI_EXCEPTION((AE_INFO, status,
125                                                 "While parsing command line"));
126                                 return (status);
127                         }
128                 }
129
130                 status =
131                     acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state,
132                                              op);
133         }
134
135         /* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
136
137         return (status);
138 }
139
140 /*******************************************************************************
141  *
142  * FUNCTION:    acpi_db_single_step
143  *
144  * PARAMETERS:  walk_state      - Current walk
145  *              op              - Current executing op (from aml interpreter)
146  *              opcode_class    - Class of the current AML Opcode
147  *
148  * RETURN:      Status
149  *
150  * DESCRIPTION: Called just before execution of an AML opcode.
151  *
152  ******************************************************************************/
153
154 acpi_status
155 acpi_db_single_step(struct acpi_walk_state * walk_state,
156                     union acpi_parse_object * op, u32 opcode_class)
157 {
158         union acpi_parse_object *next;
159         acpi_status status = AE_OK;
160         u32 original_debug_level;
161         union acpi_parse_object *display_op;
162         union acpi_parse_object *parent_op;
163         u32 aml_offset;
164
165         ACPI_FUNCTION_ENTRY();
166
167         /* Check the abort flag */
168
169         if (acpi_gbl_abort_method) {
170                 acpi_gbl_abort_method = FALSE;
171                 return (AE_ABORT_METHOD);
172         }
173
174         aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
175                                         walk_state->parser_state.aml_start);
176
177         /* Check for single-step breakpoint */
178
179         if (walk_state->method_breakpoint &&
180             (walk_state->method_breakpoint <= aml_offset)) {
181
182                 /* Check if the breakpoint has been reached or passed */
183                 /* Hit the breakpoint, resume single step, reset breakpoint */
184
185                 acpi_os_printf("***Break*** at AML offset %X\n", aml_offset);
186                 acpi_gbl_cm_single_step = TRUE;
187                 acpi_gbl_step_to_next_call = FALSE;
188                 walk_state->method_breakpoint = 0;
189         }
190
191         /* Check for user breakpoint (Must be on exact Aml offset) */
192
193         else if (walk_state->user_breakpoint &&
194                  (walk_state->user_breakpoint == aml_offset)) {
195                 acpi_os_printf("***UserBreakpoint*** at AML offset %X\n",
196                                aml_offset);
197                 acpi_gbl_cm_single_step = TRUE;
198                 acpi_gbl_step_to_next_call = FALSE;
199                 walk_state->method_breakpoint = 0;
200         }
201
202         /*
203          * Check if this is an opcode that we are interested in --
204          * namely, opcodes that have arguments
205          */
206         if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
207                 return (AE_OK);
208         }
209
210         switch (opcode_class) {
211         case AML_CLASS_UNKNOWN:
212         case AML_CLASS_ARGUMENT:        /* constants, literals, etc. do nothing */
213
214                 return (AE_OK);
215
216         default:
217
218                 /* All other opcodes -- continue */
219                 break;
220         }
221
222         /*
223          * Under certain debug conditions, display this opcode and its operands
224          */
225         if ((acpi_gbl_db_output_to_file) ||
226             (acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) {
227                 if ((acpi_gbl_db_output_to_file) ||
228                     (acpi_dbg_level & ACPI_LV_PARSE)) {
229                         acpi_os_printf
230                             ("\n[AmlDebug] Next AML Opcode to execute:\n");
231                 }
232
233                 /*
234                  * Display this op (and only this op - zero out the NEXT field
235                  * temporarily, and disable parser trace output for the duration of
236                  * the display because we don't want the extraneous debug output)
237                  */
238                 original_debug_level = acpi_dbg_level;
239                 acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS);
240                 next = op->common.next;
241                 op->common.next = NULL;
242
243                 display_op = op;
244                 parent_op = op->common.parent;
245                 if (parent_op) {
246                         if ((walk_state->control_state) &&
247                             (walk_state->control_state->common.state ==
248                              ACPI_CONTROL_PREDICATE_EXECUTING)) {
249                                 /*
250                                  * We are executing the predicate of an IF or WHILE statement
251                                  * Search upwards for the containing IF or WHILE so that the
252                                  * entire predicate can be displayed.
253                                  */
254                                 while (parent_op) {
255                                         if ((parent_op->common.aml_opcode ==
256                                              AML_IF_OP)
257                                             || (parent_op->common.aml_opcode ==
258                                                 AML_WHILE_OP)) {
259                                                 display_op = parent_op;
260                                                 break;
261                                         }
262                                         parent_op = parent_op->common.parent;
263                                 }
264                         } else {
265                                 while (parent_op) {
266                                         if ((parent_op->common.aml_opcode ==
267                                              AML_IF_OP)
268                                             || (parent_op->common.aml_opcode ==
269                                                 AML_ELSE_OP)
270                                             || (parent_op->common.aml_opcode ==
271                                                 AML_SCOPE_OP)
272                                             || (parent_op->common.aml_opcode ==
273                                                 AML_METHOD_OP)
274                                             || (parent_op->common.aml_opcode ==
275                                                 AML_WHILE_OP)) {
276                                                 break;
277                                         }
278                                         display_op = parent_op;
279                                         parent_op = parent_op->common.parent;
280                                 }
281                         }
282                 }
283
284                 /* Now we can display it */
285
286 #ifdef ACPI_DISASSEMBLER
287                 acpi_dm_disassemble(walk_state, display_op, ACPI_UINT32_MAX);
288 #endif
289
290                 if ((op->common.aml_opcode == AML_IF_OP) ||
291                     (op->common.aml_opcode == AML_WHILE_OP)) {
292                         if (walk_state->control_state->common.value) {
293                                 acpi_os_printf
294                                     ("Predicate = [True], IF block was executed\n");
295                         } else {
296                                 acpi_os_printf
297                                     ("Predicate = [False], Skipping IF block\n");
298                         }
299                 } else if (op->common.aml_opcode == AML_ELSE_OP) {
300                         acpi_os_printf
301                             ("Predicate = [False], ELSE block was executed\n");
302                 }
303
304                 /* Restore everything */
305
306                 op->common.next = next;
307                 acpi_os_printf("\n");
308                 if ((acpi_gbl_db_output_to_file) ||
309                     (acpi_dbg_level & ACPI_LV_PARSE)) {
310                         acpi_os_printf("\n");
311                 }
312                 acpi_dbg_level = original_debug_level;
313         }
314
315         /* If we are not single stepping, just continue executing the method */
316
317         if (!acpi_gbl_cm_single_step) {
318                 return (AE_OK);
319         }
320
321         /*
322          * If we are executing a step-to-call command,
323          * Check if this is a method call.
324          */
325         if (acpi_gbl_step_to_next_call) {
326                 if (op->common.aml_opcode != AML_INT_METHODCALL_OP) {
327
328                         /* Not a method call, just keep executing */
329
330                         return (AE_OK);
331                 }
332
333                 /* Found a method call, stop executing */
334
335                 acpi_gbl_step_to_next_call = FALSE;
336         }
337
338         /*
339          * If the next opcode is a method call, we will "step over" it
340          * by default.
341          */
342         if (op->common.aml_opcode == AML_INT_METHODCALL_OP) {
343
344                 /* Force no more single stepping while executing called method */
345
346                 acpi_gbl_cm_single_step = FALSE;
347
348                 /*
349                  * Set the breakpoint on/before the call, it will stop execution
350                  * as soon as we return
351                  */
352                 walk_state->method_breakpoint = 1;      /* Must be non-zero! */
353         }
354
355         status = acpi_db_start_command(walk_state, op);
356
357         /* User commands complete, continue execution of the interrupted method */
358
359         return (status);
360 }
361
362 /*******************************************************************************
363  *
364  * FUNCTION:    acpi_initialize_debugger
365  *
366  * PARAMETERS:  None
367  *
368  * RETURN:      Status
369  *
370  * DESCRIPTION: Init and start debugger
371  *
372  ******************************************************************************/
373
374 acpi_status acpi_initialize_debugger(void)
375 {
376         acpi_status status;
377
378         ACPI_FUNCTION_TRACE(acpi_initialize_debugger);
379
380         /* Init globals */
381
382         acpi_gbl_db_buffer = NULL;
383         acpi_gbl_db_filename = NULL;
384         acpi_gbl_db_output_to_file = FALSE;
385
386         acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2;
387         acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES;
388         acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
389
390         acpi_gbl_db_opt_no_ini_methods = FALSE;
391
392         acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE);
393         if (!acpi_gbl_db_buffer) {
394                 return_ACPI_STATUS(AE_NO_MEMORY);
395         }
396         memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE);
397
398         /* Initial scope is the root */
399
400         acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX;
401         acpi_gbl_db_scope_buf[1] = 0;
402         acpi_gbl_db_scope_node = acpi_gbl_root_node;
403
404         /* Initialize user commands loop */
405
406         acpi_gbl_db_terminate_loop = FALSE;
407
408         /*
409          * If configured for multi-thread support, the debug executor runs in
410          * a separate thread so that the front end can be in another address
411          * space, environment, or even another machine.
412          */
413         if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
414
415                 /* These were created with one unit, grab it */
416
417                 status = acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
418                                                ACPI_WAIT_FOREVER);
419                 if (ACPI_FAILURE(status)) {
420                         acpi_os_printf("Could not get debugger mutex\n");
421                         return_ACPI_STATUS(status);
422                 }
423
424                 status = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
425                                                ACPI_WAIT_FOREVER);
426                 if (ACPI_FAILURE(status)) {
427                         acpi_os_printf("Could not get debugger mutex\n");
428                         return_ACPI_STATUS(status);
429                 }
430
431                 /* Create the debug execution thread to execute commands */
432
433                 acpi_gbl_db_threads_terminated = FALSE;
434                 status = acpi_os_execute(OSL_DEBUGGER_THREAD,
435                                          acpi_db_execute_thread, NULL);
436                 if (ACPI_FAILURE(status)) {
437                         ACPI_EXCEPTION((AE_INFO, status,
438                                         "Could not start debugger thread"));
439                         acpi_gbl_db_threads_terminated = TRUE;
440                         return_ACPI_STATUS(status);
441                 }
442         }
443
444         return_ACPI_STATUS(AE_OK);
445 }
446
447 ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)
448
449 /*******************************************************************************
450  *
451  * FUNCTION:    acpi_terminate_debugger
452  *
453  * PARAMETERS:  None
454  *
455  * RETURN:      None
456  *
457  * DESCRIPTION: Stop debugger
458  *
459  ******************************************************************************/
460 void acpi_terminate_debugger(void)
461 {
462
463         /* Terminate the AML Debugger */
464
465         acpi_gbl_db_terminate_loop = TRUE;
466
467         if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
468                 acpi_os_release_mutex(acpi_gbl_db_command_ready);
469
470                 /* Wait the AML Debugger threads */
471
472                 while (!acpi_gbl_db_threads_terminated) {
473                         acpi_os_sleep(100);
474                 }
475         }
476
477         if (acpi_gbl_db_buffer) {
478                 acpi_os_free(acpi_gbl_db_buffer);
479                 acpi_gbl_db_buffer = NULL;
480         }
481
482         /* Ensure that debug output is now disabled */
483
484         acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT;
485 }
486
487 ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)