Merge branch 'vendor/WPA_SUPPLICANT'
[dragonfly.git] / sys / contrib / dev / acpica / source / components / debugger / dbxface.c
1 /*******************************************************************************
2  *
3  * Module Name: dbxface - AML Debugger external interfaces
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, 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
45 #include "acpi.h"
46 #include "accommon.h"
47 #include "amlcode.h"
48 #include "acdebug.h"
49 #include "acdisasm.h"
50
51
52 #ifdef ACPI_DEBUGGER
53
54 #define _COMPONENT          ACPI_CA_DEBUGGER
55         ACPI_MODULE_NAME    ("dbxface")
56
57
58 /* Local prototypes */
59
60 static ACPI_STATUS
61 AcpiDbStartCommand (
62     ACPI_WALK_STATE         *WalkState,
63     ACPI_PARSE_OBJECT       *Op);
64
65 #ifdef ACPI_OBSOLETE_FUNCTIONS
66 void
67 AcpiDbMethodEnd (
68     ACPI_WALK_STATE         *WalkState);
69 #endif
70
71
72 /*******************************************************************************
73  *
74  * FUNCTION:    AcpiDbStartCommand
75  *
76  * PARAMETERS:  WalkState       - Current walk
77  *              Op              - Current executing Op, from AML interpreter
78  *
79  * RETURN:      Status
80  *
81  * DESCRIPTION: Enter debugger command loop
82  *
83  ******************************************************************************/
84
85 static ACPI_STATUS
86 AcpiDbStartCommand (
87     ACPI_WALK_STATE         *WalkState,
88     ACPI_PARSE_OBJECT       *Op)
89 {
90     ACPI_STATUS             Status;
91
92
93     /* TBD: [Investigate] are there namespace locking issues here? */
94
95     /* AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); */
96
97     /* Go into the command loop and await next user command */
98
99
100     AcpiGbl_MethodExecuting = TRUE;
101     Status = AE_CTRL_TRUE;
102     while (Status == AE_CTRL_TRUE)
103     {
104         if (AcpiGbl_DebuggerConfiguration == DEBUGGER_MULTI_THREADED)
105         {
106             /* Handshake with the front-end that gets user command lines */
107
108             Status = AcpiUtReleaseMutex (ACPI_MTX_DEBUG_CMD_COMPLETE);
109             if (ACPI_FAILURE (Status))
110             {
111                 return (Status);
112             }
113             Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_READY);
114             if (ACPI_FAILURE (Status))
115             {
116                 return (Status);
117             }
118         }
119         else
120         {
121             /* Single threaded, we must get a command line ourselves */
122
123             /* Force output to console until a command is entered */
124
125             AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
126
127             /* Different prompt if method is executing */
128
129             if (!AcpiGbl_MethodExecuting)
130             {
131                 AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
132             }
133             else
134             {
135                 AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
136             }
137
138             /* Get the user input line */
139
140             Status = AcpiOsGetLine (AcpiGbl_DbLineBuf,
141                 ACPI_DB_LINE_BUFFER_SIZE, NULL);
142             if (ACPI_FAILURE (Status))
143             {
144                 ACPI_EXCEPTION ((AE_INFO, Status, "While parsing command line"));
145                 return (Status);
146             }
147         }
148
149         Status = AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, WalkState, Op);
150     }
151
152     /* AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); */
153
154     return (Status);
155 }
156
157
158 /*******************************************************************************
159  *
160  * FUNCTION:    AcpiDbSingleStep
161  *
162  * PARAMETERS:  WalkState       - Current walk
163  *              Op              - Current executing op (from aml interpreter)
164  *              OpcodeClass     - Class of the current AML Opcode
165  *
166  * RETURN:      Status
167  *
168  * DESCRIPTION: Called just before execution of an AML opcode.
169  *
170  ******************************************************************************/
171
172 ACPI_STATUS
173 AcpiDbSingleStep (
174     ACPI_WALK_STATE         *WalkState,
175     ACPI_PARSE_OBJECT       *Op,
176     UINT32                  OpcodeClass)
177 {
178     ACPI_PARSE_OBJECT       *Next;
179     ACPI_STATUS             Status = AE_OK;
180     UINT32                  OriginalDebugLevel;
181     ACPI_PARSE_OBJECT       *DisplayOp;
182     ACPI_PARSE_OBJECT       *ParentOp;
183
184
185     ACPI_FUNCTION_ENTRY ();
186
187
188     /* Check the abort flag */
189
190     if (AcpiGbl_AbortMethod)
191     {
192         AcpiGbl_AbortMethod = FALSE;
193         return (AE_ABORT_METHOD);
194     }
195
196     /* Check for single-step breakpoint */
197
198     if (WalkState->MethodBreakpoint &&
199        (WalkState->MethodBreakpoint <= Op->Common.AmlOffset))
200     {
201         /* Check if the breakpoint has been reached or passed */
202         /* Hit the breakpoint, resume single step, reset breakpoint */
203
204         AcpiOsPrintf ("***Break*** at AML offset %X\n", Op->Common.AmlOffset);
205         AcpiGbl_CmSingleStep = TRUE;
206         AcpiGbl_StepToNextCall = FALSE;
207         WalkState->MethodBreakpoint = 0;
208     }
209
210     /* Check for user breakpoint (Must be on exact Aml offset) */
211
212     else if (WalkState->UserBreakpoint &&
213             (WalkState->UserBreakpoint == Op->Common.AmlOffset))
214     {
215         AcpiOsPrintf ("***UserBreakpoint*** at AML offset %X\n",
216             Op->Common.AmlOffset);
217         AcpiGbl_CmSingleStep = TRUE;
218         AcpiGbl_StepToNextCall = FALSE;
219         WalkState->MethodBreakpoint = 0;
220     }
221
222     /*
223      * Check if this is an opcode that we are interested in --
224      * namely, opcodes that have arguments
225      */
226     if (Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP)
227     {
228         return (AE_OK);
229     }
230
231     switch (OpcodeClass)
232     {
233     case AML_CLASS_UNKNOWN:
234     case AML_CLASS_ARGUMENT:    /* constants, literals, etc. do nothing */
235
236         return (AE_OK);
237
238     default:
239
240         /* All other opcodes -- continue */
241         break;
242     }
243
244     /*
245      * Under certain debug conditions, display this opcode and its operands
246      */
247     if ((AcpiGbl_DbOutputToFile)            ||
248         (AcpiGbl_CmSingleStep)              ||
249         (AcpiDbgLevel & ACPI_LV_PARSE))
250     {
251         if ((AcpiGbl_DbOutputToFile)        ||
252             (AcpiDbgLevel & ACPI_LV_PARSE))
253         {
254             AcpiOsPrintf ("\n[AmlDebug] Next AML Opcode to execute:\n");
255         }
256
257         /*
258          * Display this op (and only this op - zero out the NEXT field
259          * temporarily, and disable parser trace output for the duration of
260          * the display because we don't want the extraneous debug output)
261          */
262         OriginalDebugLevel = AcpiDbgLevel;
263         AcpiDbgLevel &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS);
264         Next = Op->Common.Next;
265         Op->Common.Next = NULL;
266
267
268         DisplayOp = Op;
269         ParentOp = Op->Common.Parent;
270         if (ParentOp)
271         {
272             if ((WalkState->ControlState) &&
273                 (WalkState->ControlState->Common.State ==
274                     ACPI_CONTROL_PREDICATE_EXECUTING))
275             {
276                 /*
277                  * We are executing the predicate of an IF or WHILE statement
278                  * Search upwards for the containing IF or WHILE so that the
279                  * entire predicate can be displayed.
280                  */
281                 while (ParentOp)
282                 {
283                     if ((ParentOp->Common.AmlOpcode == AML_IF_OP) ||
284                         (ParentOp->Common.AmlOpcode == AML_WHILE_OP))
285                     {
286                         DisplayOp = ParentOp;
287                         break;
288                     }
289                     ParentOp = ParentOp->Common.Parent;
290                 }
291             }
292             else
293             {
294                 while (ParentOp)
295                 {
296                     if ((ParentOp->Common.AmlOpcode == AML_IF_OP)     ||
297                         (ParentOp->Common.AmlOpcode == AML_ELSE_OP)   ||
298                         (ParentOp->Common.AmlOpcode == AML_SCOPE_OP)  ||
299                         (ParentOp->Common.AmlOpcode == AML_METHOD_OP) ||
300                         (ParentOp->Common.AmlOpcode == AML_WHILE_OP))
301                     {
302                         break;
303                     }
304                     DisplayOp = ParentOp;
305                     ParentOp = ParentOp->Common.Parent;
306                 }
307             }
308         }
309
310         /* Now we can display it */
311
312         AcpiDmDisassemble (WalkState, DisplayOp, ACPI_UINT32_MAX);
313
314         if ((Op->Common.AmlOpcode == AML_IF_OP) ||
315             (Op->Common.AmlOpcode == AML_WHILE_OP))
316         {
317             if (WalkState->ControlState->Common.Value)
318             {
319                 AcpiOsPrintf ("Predicate = [True], IF block was executed\n");
320             }
321             else
322             {
323                 AcpiOsPrintf ("Predicate = [False], Skipping IF block\n");
324             }
325         }
326         else if (Op->Common.AmlOpcode == AML_ELSE_OP)
327         {
328             AcpiOsPrintf ("Predicate = [False], ELSE block was executed\n");
329         }
330
331         /* Restore everything */
332
333         Op->Common.Next = Next;
334         AcpiOsPrintf ("\n");
335         if ((AcpiGbl_DbOutputToFile)        ||
336             (AcpiDbgLevel & ACPI_LV_PARSE))
337         {
338             AcpiOsPrintf ("\n");
339         }
340         AcpiDbgLevel = OriginalDebugLevel;
341     }
342
343     /* If we are not single stepping, just continue executing the method */
344
345     if (!AcpiGbl_CmSingleStep)
346     {
347         return (AE_OK);
348     }
349
350     /*
351      * If we are executing a step-to-call command,
352      * Check if this is a method call.
353      */
354     if (AcpiGbl_StepToNextCall)
355     {
356         if (Op->Common.AmlOpcode != AML_INT_METHODCALL_OP)
357         {
358             /* Not a method call, just keep executing */
359
360             return (AE_OK);
361         }
362
363         /* Found a method call, stop executing */
364
365         AcpiGbl_StepToNextCall = FALSE;
366     }
367
368     /*
369      * If the next opcode is a method call, we will "step over" it
370      * by default.
371      */
372     if (Op->Common.AmlOpcode == AML_INT_METHODCALL_OP)
373     {
374         /* Force no more single stepping while executing called method */
375
376         AcpiGbl_CmSingleStep = FALSE;
377
378         /*
379          * Set the breakpoint on/before the call, it will stop execution
380          * as soon as we return
381          */
382         WalkState->MethodBreakpoint = 1;  /* Must be non-zero! */
383     }
384
385
386     Status = AcpiDbStartCommand (WalkState, Op);
387
388     /* User commands complete, continue execution of the interrupted method */
389
390     return (Status);
391 }
392
393
394 /*******************************************************************************
395  *
396  * FUNCTION:    AcpiDbInitialize
397  *
398  * PARAMETERS:  None
399  *
400  * RETURN:      Status
401  *
402  * DESCRIPTION: Init and start debugger
403  *
404  ******************************************************************************/
405
406 ACPI_STATUS
407 AcpiDbInitialize (
408     void)
409 {
410     ACPI_STATUS             Status;
411
412
413     ACPI_FUNCTION_TRACE (DbInitialize);
414
415
416     /* Init globals */
417
418     AcpiGbl_DbBuffer            = NULL;
419     AcpiGbl_DbFilename          = NULL;
420     AcpiGbl_DbOutputToFile      = FALSE;
421
422     AcpiGbl_DbDebugLevel        = ACPI_LV_VERBOSITY2;
423     AcpiGbl_DbConsoleDebugLevel = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES;
424     AcpiGbl_DbOutputFlags       = ACPI_DB_CONSOLE_OUTPUT;
425
426     AcpiGbl_DbOpt_tables        = FALSE;
427     AcpiGbl_DbOpt_disasm        = FALSE;
428     AcpiGbl_DbOpt_stats         = FALSE;
429     AcpiGbl_DbOpt_verbose       = TRUE;
430     AcpiGbl_DbOpt_ini_methods   = TRUE;
431
432     AcpiGbl_DbBuffer = AcpiOsAllocate (ACPI_DEBUG_BUFFER_SIZE);
433     if (!AcpiGbl_DbBuffer)
434     {
435         return_ACPI_STATUS (AE_NO_MEMORY);
436     }
437     ACPI_MEMSET (AcpiGbl_DbBuffer, 0, ACPI_DEBUG_BUFFER_SIZE);
438
439     /* Initial scope is the root */
440
441     AcpiGbl_DbScopeBuf [0] = AML_ROOT_PREFIX;
442     AcpiGbl_DbScopeBuf [1] =  0;
443     AcpiGbl_DbScopeNode = AcpiGbl_RootNode;
444
445     /*
446      * If configured for multi-thread support, the debug executor runs in
447      * a separate thread so that the front end can be in another address
448      * space, environment, or even another machine.
449      */
450     if (AcpiGbl_DebuggerConfiguration & DEBUGGER_MULTI_THREADED)
451     {
452         /* These were created with one unit, grab it */
453
454         Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_COMPLETE);
455         if (ACPI_FAILURE (Status))
456         {
457             AcpiOsPrintf ("Could not get debugger mutex\n");
458             return_ACPI_STATUS (Status);
459         }
460
461         Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_READY);
462         if (ACPI_FAILURE (Status))
463         {
464             AcpiOsPrintf ("Could not get debugger mutex\n");
465             return_ACPI_STATUS (Status);
466         }
467
468         /* Create the debug execution thread to execute commands */
469
470         Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbExecuteThread, NULL);
471         if (ACPI_FAILURE (Status))
472         {
473             ACPI_EXCEPTION ((AE_INFO, Status, "Could not start debugger thread"));
474             return_ACPI_STATUS (Status);
475         }
476     }
477
478     if (!AcpiGbl_DbOpt_verbose)
479     {
480         AcpiGbl_DbOpt_disasm = TRUE;
481         AcpiGbl_DbOpt_stats = FALSE;
482     }
483
484     return_ACPI_STATUS (AE_OK);
485 }
486
487
488 /*******************************************************************************
489  *
490  * FUNCTION:    AcpiDbTerminate
491  *
492  * PARAMETERS:  None
493  *
494  * RETURN:      None
495  *
496  * DESCRIPTION: Stop debugger
497  *
498  ******************************************************************************/
499
500 void
501 AcpiDbTerminate (
502     void)
503 {
504
505     if (AcpiGbl_DbBuffer)
506     {
507         AcpiOsFree (AcpiGbl_DbBuffer);
508         AcpiGbl_DbBuffer = NULL;
509     }
510
511     /* Ensure that debug output is now disabled */
512
513     AcpiGbl_DbOutputFlags = ACPI_DB_DISABLE_OUTPUT;
514 }
515
516
517 #ifdef ACPI_OBSOLETE_FUNCTIONS
518 /*******************************************************************************
519  *
520  * FUNCTION:    AcpiDbMethodEnd
521  *
522  * PARAMETERS:  WalkState       - Current walk
523  *
524  * RETURN:      Status
525  *
526  * DESCRIPTION: Called at method termination
527  *
528  ******************************************************************************/
529
530 void
531 AcpiDbMethodEnd (
532     ACPI_WALK_STATE         *WalkState)
533 {
534
535     if (!AcpiGbl_CmSingleStep)
536     {
537         return;
538     }
539
540     AcpiOsPrintf ("<Method Terminating>\n");
541
542     AcpiDbStartCommand (WalkState, NULL);
543 }
544 #endif
545
546 #endif /* ACPI_DEBUGGER */