xref: /freebsd/sys/contrib/dev/acpica/components/debugger/dbinput.c (revision 7d99ab9fd0cc2c1ce2ecef0ed6d0672c2a50b0cb)
1 /*******************************************************************************
2  *
3  * Module Name: dbinput - user front-end to the AML debugger
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2013, 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 <contrib/dev/acpica/include/acpi.h>
46 #include <contrib/dev/acpica/include/accommon.h>
47 #include <contrib/dev/acpica/include/acdebug.h>
48 
49 
50 #ifdef ACPI_DEBUGGER
51 
52 #define _COMPONENT          ACPI_CA_DEBUGGER
53         ACPI_MODULE_NAME    ("dbinput")
54 
55 /* Local prototypes */
56 
57 static UINT32
58 AcpiDbGetLine (
59     char                    *InputBuffer);
60 
61 static UINT32
62 AcpiDbMatchCommand (
63     char                    *UserCommand);
64 
65 static void
66 AcpiDbSingleThread (
67     void);
68 
69 static void
70 AcpiDbDisplayCommandInfo (
71     char                    *Command,
72     BOOLEAN                 DisplayAll);
73 
74 static void
75 AcpiDbDisplayHelp (
76     char                    *Command);
77 
78 static BOOLEAN
79 AcpiDbMatchCommandHelp (
80     char                        *Command,
81     const ACPI_DB_COMMAND_HELP  *Help);
82 
83 
84 /*
85  * Top-level debugger commands.
86  *
87  * This list of commands must match the string table below it
88  */
89 enum AcpiExDebuggerCommands
90 {
91     CMD_NOT_FOUND = 0,
92     CMD_NULL,
93     CMD_ALLOCATIONS,
94     CMD_ARGS,
95     CMD_ARGUMENTS,
96     CMD_BATCH,
97     CMD_BREAKPOINT,
98     CMD_BUSINFO,
99     CMD_CALL,
100     CMD_CLOSE,
101     CMD_DEBUG,
102     CMD_DISASSEMBLE,
103     CMD_DISASM,
104     CMD_DUMP,
105     CMD_ENABLEACPI,
106     CMD_EVALUATE,
107     CMD_EVENT,
108     CMD_EXECUTE,
109     CMD_EXIT,
110     CMD_FIND,
111     CMD_GO,
112     CMD_GPE,
113     CMD_GPES,
114     CMD_HANDLERS,
115     CMD_HELP,
116     CMD_HELP2,
117     CMD_HISTORY,
118     CMD_HISTORY_EXE,
119     CMD_HISTORY_LAST,
120     CMD_INFORMATION,
121     CMD_INTEGRITY,
122     CMD_INTO,
123     CMD_LEVEL,
124     CMD_LIST,
125     CMD_LOAD,
126     CMD_LOCALS,
127     CMD_LOCKS,
128     CMD_METHODS,
129     CMD_NAMESPACE,
130     CMD_NOTIFY,
131     CMD_OBJECT,
132     CMD_OPEN,
133     CMD_OSI,
134     CMD_OWNER,
135     CMD_PREDEFINED,
136     CMD_PREFIX,
137     CMD_QUIT,
138     CMD_REFERENCES,
139     CMD_RESOURCES,
140     CMD_RESULTS,
141     CMD_SET,
142     CMD_SLEEP,
143     CMD_STATS,
144     CMD_STOP,
145     CMD_TABLES,
146     CMD_TEMPLATE,
147     CMD_TERMINATE,
148     CMD_THREADS,
149     CMD_TRACE,
150     CMD_TREE,
151     CMD_TYPE,
152     CMD_UNLOAD
153 };
154 
155 #define CMD_FIRST_VALID     2
156 
157 
158 /* Second parameter is the required argument count */
159 
160 static const ACPI_DB_COMMAND_INFO   AcpiGbl_DbCommands[] =
161 {
162     {"<NOT FOUND>",  0},
163     {"<NULL>",       0},
164     {"ALLOCATIONS",  0},
165     {"ARGS",         0},
166     {"ARGUMENTS",    0},
167     {"BATCH",        0},
168     {"BREAKPOINT",   1},
169     {"BUSINFO",      0},
170     {"CALL",         0},
171     {"CLOSE",        0},
172     {"DEBUG",        1},
173     {"DISASSEMBLE",  1},
174     {"DISASM",       1},
175     {"DUMP",         1},
176     {"ENABLEACPI",   0},
177     {"EVALUATE",     1},
178     {"EVENT",        1},
179     {"EXECUTE",      1},
180     {"EXIT",         0},
181     {"FIND",         1},
182     {"GO",           0},
183     {"GPE",          2},
184     {"GPES",         0},
185     {"HANDLERS",     0},
186     {"HELP",         0},
187     {"?",            0},
188     {"HISTORY",      0},
189     {"!",            1},
190     {"!!",           0},
191     {"INFORMATION",  0},
192     {"INTEGRITY",    0},
193     {"INTO",         0},
194     {"LEVEL",        0},
195     {"LIST",         0},
196     {"LOAD",         1},
197     {"LOCALS",       0},
198     {"LOCKS",        0},
199     {"METHODS",      0},
200     {"NAMESPACE",    0},
201     {"NOTIFY",       2},
202     {"OBJECT",       1},
203     {"OPEN",         1},
204     {"OSI",          0},
205     {"OWNER",        1},
206     {"PREDEFINED",   0},
207     {"PREFIX",       0},
208     {"QUIT",         0},
209     {"REFERENCES",   1},
210     {"RESOURCES",    0},
211     {"RESULTS",      0},
212     {"SET",          3},
213     {"SLEEP",        0},
214     {"STATS",        1},
215     {"STOP",         0},
216     {"TABLES",       0},
217     {"TEMPLATE",     1},
218     {"TERMINATE",    0},
219     {"THREADS",      3},
220     {"TRACE",        1},
221     {"TREE",         0},
222     {"TYPE",         1},
223     {"UNLOAD",       1},
224     {NULL,           0}
225 };
226 
227 /*
228  * Help for all debugger commands. First argument is the number of lines
229  * of help to output for the command.
230  */
231 static const ACPI_DB_COMMAND_HELP   AcpiGbl_DbCommandHelp[] =
232 {
233     {0, "\nGeneral-Purpose Commands:",         "\n"},
234     {1, "  Allocations",                       "Display list of current memory allocations\n"},
235     {2, "  Dump <Address>|<Namepath>",         "\n"},
236     {0, "       [Byte|Word|Dword|Qword]",      "Display ACPI objects or memory\n"},
237     {1, "  EnableAcpi",                        "Enable ACPI (hardware) mode\n"},
238     {1, "  Handlers",                          "Info about global handlers\n"},
239     {1, "  Help [Command]",                    "This help screen or individual command\n"},
240     {1, "  History",                           "Display command history buffer\n"},
241     {1, "  Level <DebugLevel>] [console]",     "Get/Set debug level for file or console\n"},
242     {1, "  Locks",                             "Current status of internal mutexes\n"},
243     {1, "  Osi [Install|Remove <name>]",       "Display or modify global _OSI list\n"},
244     {1, "  Quit or Exit",                      "Exit this command\n"},
245     {9, "  Stats [Allocations|Memory|Misc|",   "\n"},
246     {1, "      Objects|Sizes|Stack|Tables]",   "Display namespace and memory statistics\n"},
247     {1, "     Allocations",                    "Display list of current memory allocations\n"},
248     {1, "     Memory",                         "Dump internal memory lists\n"},
249     {1, "     Misc",                           "Namespace search and mutex stats\n"},
250     {1, "     Objects",                        "Summary of namespace objects\n"},
251     {1, "     Sizes",                          "Sizes for each of the internal objects\n"},
252     {1, "     Stack",                          "Display CPU stack usage\n"},
253     {1, "     Tables",                         "Info about current ACPI table(s)\n"},
254     {1, "  Tables",                            "Display info about loaded ACPI tables\n"},
255     {1, "  Unload <Namepath>",                 "Unload an ACPI table via namespace object\n"},
256     {1, "  ! <CommandNumber>",                 "Execute command from history buffer\n"},
257     {1, "  !!",                                "Execute last command again\n"},
258 
259     {0, "\nNamespace Access Commands:",        "\n"},
260     {1, "  Businfo",                           "Display system bus info\n"},
261     {1, "  Disassemble <Method>",              "Disassemble a control method\n"},
262     {1, "  Event <F|G> <Value>",               "Generate AcpiEvent (Fixed/GPE)\n"},
263     {1, "  Find <AcpiName> (? is wildcard)",   "Find ACPI name(s) with wildcards\n"},
264     {1, "  Gpe <GpeNum> <GpeBlock>",           "Simulate a GPE\n"},
265     {1, "  Gpes",                              "Display info on all GPEs\n"},
266     {1, "  Integrity",                         "Validate namespace integrity\n"},
267     {1, "  Methods",                           "Display list of loaded control methods\n"},
268     {1, "  Namespace [Object] [Depth]",        "Display loaded namespace tree/subtree\n"},
269     {1, "  Notify <Object> <Value>",           "Send a notification on Object\n"},
270     {1, "  Objects <ObjectType>",              "Display all objects of the given type\n"},
271     {1, "  Owner <OwnerId> [Depth]",           "Display loaded namespace by object owner\n"},
272     {1, "  Predefined",                        "Check all predefined names\n"},
273     {1, "  Prefix [<NamePath>]",               "Set or Get current execution prefix\n"},
274     {1, "  References <Addr>",                 "Find all references to object at addr\n"},
275     {1, "  Resources [DeviceName]",            "Display Device resources (no arg = all devices)\n"},
276     {1, "  Set N <NamedObject> <Value>",       "Set value for named integer\n"},
277     {1, "  Sleep [SleepState]",                "Simulate sleep/wake sequence(s) (0-5)\n"},
278     {1, "  Template <Object>",                 "Format/dump a Buffer/ResourceTemplate\n"},
279     {1, "  Terminate",                         "Delete namespace and all internal objects\n"},
280     {1, "  Type <Object>",                     "Display object type\n"},
281 
282     {0, "\nControl Method Execution Commands:","\n"},
283     {1, "  Arguments (or Args)",               "Display method arguments\n"},
284     {1, "  Breakpoint <AmlOffset>",            "Set an AML execution breakpoint\n"},
285     {1, "  Call",                              "Run to next control method invocation\n"},
286     {1, "  Debug <Namepath> [Arguments]",      "Single Step a control method\n"},
287     {6, "  Evaluate",                          "Synonym for Execute\n"},
288     {5, "  Execute <Namepath> [Arguments]",    "Execute control method\n"},
289     {1, "     Hex Integer",                    "Integer method argument\n"},
290     {1, "     \"Ascii String\"",               "String method argument\n"},
291     {1, "     (Byte List)",                    "Buffer method argument\n"},
292     {1, "     [Package Element List]",         "Package method argument\n"},
293     {1, "  Go",                                "Allow method to run to completion\n"},
294     {1, "  Information",                       "Display info about the current method\n"},
295     {1, "  Into",                              "Step into (not over) a method call\n"},
296     {1, "  List [# of Aml Opcodes]",           "Display method ASL statements\n"},
297     {1, "  Locals",                            "Display method local variables\n"},
298     {1, "  Results",                           "Display method result stack\n"},
299     {1, "  Set <A|L> <#> <Value>",             "Set method data (Arguments/Locals)\n"},
300     {1, "  Stop",                              "Terminate control method\n"},
301     {1, "  Thread <Threads><Loops><NamePath>", "Spawn threads to execute method(s)\n"},
302     {1, "  Trace <method name>",               "Trace method execution\n"},
303     {1, "  Tree",                              "Display control method calling tree\n"},
304     {1, "  <Enter>",                           "Single step next AML opcode (over calls)\n"},
305 
306     {0, "\nFile I/O Commands:",                "\n"},
307     {1, "  Close",                             "Close debug output file\n"},
308     {1, "  Load <Input Filename>",             "Load ACPI table from a file\n"},
309     {1, "  Open <Output Filename>",            "Open a file for debug output\n"},
310     {0, NULL, NULL}
311 };
312 
313 
314 /*******************************************************************************
315  *
316  * FUNCTION:    AcpiDbMatchCommandHelp
317  *
318  * PARAMETERS:  Command             - Command string to match
319  *              Help                - Help table entry to attempt match
320  *
321  * RETURN:      TRUE if command matched, FALSE otherwise
322  *
323  * DESCRIPTION: Attempt to match a command in the help table in order to
324  *              print help information for a single command.
325  *
326  ******************************************************************************/
327 
328 static BOOLEAN
329 AcpiDbMatchCommandHelp (
330     char                        *Command,
331     const ACPI_DB_COMMAND_HELP  *Help)
332 {
333     char                    *Invocation = Help->Invocation;
334     UINT32                  LineCount;
335 
336 
337     /* Valid commands in the help table begin with a couple of spaces */
338 
339     if (*Invocation != ' ')
340     {
341         return (FALSE);
342     }
343 
344     while (*Invocation == ' ')
345     {
346         Invocation++;
347     }
348 
349     /* Match command name (full command or substring) */
350 
351     while ((*Command) && (*Invocation) && (*Invocation != ' '))
352     {
353         if (ACPI_TOLOWER (*Command) != ACPI_TOLOWER (*Invocation))
354         {
355             return (FALSE);
356         }
357 
358         Invocation++;
359         Command++;
360     }
361 
362     /* Print the appropriate number of help lines */
363 
364     LineCount = Help->LineCount;
365     while (LineCount)
366     {
367         AcpiOsPrintf ("%-38s : %s", Help->Invocation, Help->Description);
368         Help++;
369         LineCount--;
370     }
371 
372     return (TRUE);
373 }
374 
375 
376 /*******************************************************************************
377  *
378  * FUNCTION:    AcpiDbDisplayCommandInfo
379  *
380  * PARAMETERS:  Command             - Command string to match
381  *              DisplayAll          - Display all matching commands, or just
382  *                                    the first one (substring match)
383  *
384  * RETURN:      None
385  *
386  * DESCRIPTION: Display help information for a Debugger command.
387  *
388  ******************************************************************************/
389 
390 static void
391 AcpiDbDisplayCommandInfo (
392     char                    *Command,
393     BOOLEAN                 DisplayAll)
394 {
395     const ACPI_DB_COMMAND_HELP  *Next;
396     BOOLEAN                     Matched;
397 
398 
399     Next = AcpiGbl_DbCommandHelp;
400     while (Next->Invocation)
401     {
402         Matched = AcpiDbMatchCommandHelp (Command, Next);
403         if (!DisplayAll && Matched)
404         {
405             return;
406         }
407 
408         Next++;
409     }
410 }
411 
412 
413 /*******************************************************************************
414  *
415  * FUNCTION:    AcpiDbDisplayHelp
416  *
417  * PARAMETERS:  Command             - Optional command string to display help.
418  *                                    if not specified, all debugger command
419  *                                    help strings are displayed
420  *
421  * RETURN:      None
422  *
423  * DESCRIPTION: Display help for a single debugger command, or all of them.
424  *
425  ******************************************************************************/
426 
427 static void
428 AcpiDbDisplayHelp (
429     char                    *Command)
430 {
431     const ACPI_DB_COMMAND_HELP  *Next = AcpiGbl_DbCommandHelp;
432 
433 
434     if (!Command)
435     {
436         /* No argument to help, display help for all commands */
437 
438         while (Next->Invocation)
439         {
440             AcpiOsPrintf ("%-38s%s", Next->Invocation, Next->Description);
441             Next++;
442         }
443     }
444     else
445     {
446         /* Display help for all commands that match the subtring */
447 
448         AcpiDbDisplayCommandInfo (Command, TRUE);
449     }
450 }
451 
452 
453 /*******************************************************************************
454  *
455  * FUNCTION:    AcpiDbGetNextToken
456  *
457  * PARAMETERS:  String          - Command buffer
458  *              Next            - Return value, end of next token
459  *
460  * RETURN:      Pointer to the start of the next token.
461  *
462  * DESCRIPTION: Command line parsing. Get the next token on the command line
463  *
464  ******************************************************************************/
465 
466 char *
467 AcpiDbGetNextToken (
468     char                    *String,
469     char                    **Next,
470     ACPI_OBJECT_TYPE        *ReturnType)
471 {
472     char                    *Start;
473     UINT32                  Depth;
474     ACPI_OBJECT_TYPE        Type = ACPI_TYPE_INTEGER;
475 
476 
477     /* At end of buffer? */
478 
479     if (!String || !(*String))
480     {
481         return (NULL);
482     }
483 
484     /* Remove any spaces at the beginning */
485 
486     if (*String == ' ')
487     {
488         while (*String && (*String == ' '))
489         {
490             String++;
491         }
492 
493         if (!(*String))
494         {
495             return (NULL);
496         }
497     }
498 
499     switch (*String)
500     {
501     case '"':
502 
503         /* This is a quoted string, scan until closing quote */
504 
505         String++;
506         Start = String;
507         Type = ACPI_TYPE_STRING;
508 
509         /* Find end of string */
510 
511         while (*String && (*String != '"'))
512         {
513             String++;
514         }
515         break;
516 
517     case '(':
518 
519         /* This is the start of a buffer, scan until closing paren */
520 
521         String++;
522         Start = String;
523         Type = ACPI_TYPE_BUFFER;
524 
525         /* Find end of buffer */
526 
527         while (*String && (*String != ')'))
528         {
529             String++;
530         }
531         break;
532 
533     case '[':
534 
535         /* This is the start of a package, scan until closing bracket */
536 
537         String++;
538         Depth = 1;
539         Start = String;
540         Type = ACPI_TYPE_PACKAGE;
541 
542         /* Find end of package (closing bracket) */
543 
544         while (*String)
545         {
546             /* Handle String package elements */
547 
548             if (*String == '"')
549             {
550                 /* Find end of string */
551 
552                 String++;
553                 while (*String && (*String != '"'))
554                 {
555                     String++;
556                 }
557                 if (!(*String))
558                 {
559                     break;
560                 }
561             }
562             else if (*String == '[')
563             {
564                 Depth++;         /* A nested package declaration */
565             }
566             else if (*String == ']')
567             {
568                 Depth--;
569                 if (Depth == 0) /* Found final package closing bracket */
570                 {
571                     break;
572                 }
573             }
574 
575             String++;
576         }
577         break;
578 
579     default:
580 
581         Start = String;
582 
583         /* Find end of token */
584 
585         while (*String && (*String != ' '))
586         {
587             String++;
588         }
589         break;
590     }
591 
592     if (!(*String))
593     {
594         *Next = NULL;
595     }
596     else
597     {
598         *String = 0;
599         *Next = String + 1;
600     }
601 
602     *ReturnType = Type;
603     return (Start);
604 }
605 
606 
607 /*******************************************************************************
608  *
609  * FUNCTION:    AcpiDbGetLine
610  *
611  * PARAMETERS:  InputBuffer         - Command line buffer
612  *
613  * RETURN:      Count of arguments to the command
614  *
615  * DESCRIPTION: Get the next command line from the user. Gets entire line
616  *              up to the next newline
617  *
618  ******************************************************************************/
619 
620 static UINT32
621 AcpiDbGetLine (
622     char                    *InputBuffer)
623 {
624     UINT32                  i;
625     UINT32                  Count;
626     char                    *Next;
627     char                    *This;
628 
629 
630     ACPI_STRCPY (AcpiGbl_DbParsedBuf, InputBuffer);
631 
632     This = AcpiGbl_DbParsedBuf;
633     for (i = 0; i < ACPI_DEBUGGER_MAX_ARGS; i++)
634     {
635         AcpiGbl_DbArgs[i] = AcpiDbGetNextToken (This, &Next,
636             &AcpiGbl_DbArgTypes[i]);
637         if (!AcpiGbl_DbArgs[i])
638         {
639             break;
640         }
641 
642         This = Next;
643     }
644 
645     /* Uppercase the actual command */
646 
647     if (AcpiGbl_DbArgs[0])
648     {
649         AcpiUtStrupr (AcpiGbl_DbArgs[0]);
650     }
651 
652     Count = i;
653     if (Count)
654     {
655         Count--;  /* Number of args only */
656     }
657 
658     return (Count);
659 }
660 
661 
662 /*******************************************************************************
663  *
664  * FUNCTION:    AcpiDbMatchCommand
665  *
666  * PARAMETERS:  UserCommand             - User command line
667  *
668  * RETURN:      Index into command array, -1 if not found
669  *
670  * DESCRIPTION: Search command array for a command match
671  *
672  ******************************************************************************/
673 
674 static UINT32
675 AcpiDbMatchCommand (
676     char                    *UserCommand)
677 {
678     UINT32                  i;
679 
680 
681     if (!UserCommand || UserCommand[0] == 0)
682     {
683         return (CMD_NULL);
684     }
685 
686     for (i = CMD_FIRST_VALID; AcpiGbl_DbCommands[i].Name; i++)
687     {
688         if (ACPI_STRSTR (AcpiGbl_DbCommands[i].Name, UserCommand) ==
689                          AcpiGbl_DbCommands[i].Name)
690         {
691             return (i);
692         }
693     }
694 
695     /* Command not recognized */
696 
697     return (CMD_NOT_FOUND);
698 }
699 
700 
701 /*******************************************************************************
702  *
703  * FUNCTION:    AcpiDbCommandDispatch
704  *
705  * PARAMETERS:  InputBuffer         - Command line buffer
706  *              WalkState           - Current walk
707  *              Op                  - Current (executing) parse op
708  *
709  * RETURN:      Status
710  *
711  * DESCRIPTION: Command dispatcher.
712  *
713  ******************************************************************************/
714 
715 ACPI_STATUS
716 AcpiDbCommandDispatch (
717     char                    *InputBuffer,
718     ACPI_WALK_STATE         *WalkState,
719     ACPI_PARSE_OBJECT       *Op)
720 {
721     UINT32                  Temp;
722     UINT32                  CommandIndex;
723     UINT32                  ParamCount;
724     char                    *CommandLine;
725     ACPI_STATUS             Status = AE_CTRL_TRUE;
726 
727 
728     /* If AcpiTerminate has been called, terminate this thread */
729 
730     if (AcpiGbl_DbTerminateThreads)
731     {
732         return (AE_CTRL_TERMINATE);
733     }
734 
735     ParamCount = AcpiDbGetLine (InputBuffer);
736     CommandIndex = AcpiDbMatchCommand (AcpiGbl_DbArgs[0]);
737     Temp = 0;
738 
739     /* Verify that we have the minimum number of params */
740 
741     if (ParamCount < AcpiGbl_DbCommands[CommandIndex].MinArgs)
742     {
743         AcpiOsPrintf ("%u parameters entered, [%s] requires %u parameters\n",
744             ParamCount, AcpiGbl_DbCommands[CommandIndex].Name,
745             AcpiGbl_DbCommands[CommandIndex].MinArgs);
746 
747         AcpiDbDisplayCommandInfo (AcpiGbl_DbCommands[CommandIndex].Name, FALSE);
748         return (AE_CTRL_TRUE);
749     }
750 
751     /* Decode and dispatch the command */
752 
753     switch (CommandIndex)
754     {
755     case CMD_NULL:
756 
757         if (Op)
758         {
759             return (AE_OK);
760         }
761         break;
762 
763     case CMD_ALLOCATIONS:
764 
765 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
766         AcpiUtDumpAllocations ((UINT32) -1, NULL);
767 #endif
768         break;
769 
770     case CMD_ARGS:
771     case CMD_ARGUMENTS:
772 
773         AcpiDbDisplayArguments ();
774         break;
775 
776     case CMD_BATCH:
777 
778         AcpiDbBatchExecute (AcpiGbl_DbArgs[1]);
779         break;
780 
781     case CMD_BREAKPOINT:
782 
783         AcpiDbSetMethodBreakpoint (AcpiGbl_DbArgs[1], WalkState, Op);
784         break;
785 
786     case CMD_BUSINFO:
787 
788         AcpiDbGetBusInfo ();
789         break;
790 
791     case CMD_CALL:
792 
793         AcpiDbSetMethodCallBreakpoint (Op);
794         Status = AE_OK;
795         break;
796 
797     case CMD_CLOSE:
798 
799         AcpiDbCloseDebugFile ();
800         break;
801 
802     case CMD_DEBUG:
803 
804         AcpiDbExecute (AcpiGbl_DbArgs[1],
805             &AcpiGbl_DbArgs[2], &AcpiGbl_DbArgTypes[2], EX_SINGLE_STEP);
806         break;
807 
808     case CMD_DISASSEMBLE:
809     case CMD_DISASM:
810 
811         (void) AcpiDbDisassembleMethod (AcpiGbl_DbArgs[1]);
812         break;
813 
814     case CMD_DUMP:
815 
816         AcpiDbDecodeAndDisplayObject (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
817         break;
818 
819     case CMD_ENABLEACPI:
820 #if (!ACPI_REDUCED_HARDWARE)
821 
822         Status = AcpiEnable();
823         if (ACPI_FAILURE(Status))
824         {
825             AcpiOsPrintf("AcpiEnable failed (Status=%X)\n", Status);
826             return (Status);
827         }
828 #endif /* !ACPI_REDUCED_HARDWARE */
829         break;
830 
831     case CMD_EVENT:
832 
833         AcpiOsPrintf ("Event command not implemented\n");
834         break;
835 
836     case CMD_EVALUATE:
837     case CMD_EXECUTE:
838 
839         AcpiDbExecute (AcpiGbl_DbArgs[1],
840             &AcpiGbl_DbArgs[2], &AcpiGbl_DbArgTypes[2], EX_NO_SINGLE_STEP);
841         break;
842 
843     case CMD_FIND:
844 
845         Status = AcpiDbFindNameInNamespace (AcpiGbl_DbArgs[1]);
846         break;
847 
848     case CMD_GO:
849 
850         AcpiGbl_CmSingleStep = FALSE;
851         return (AE_OK);
852 
853     case CMD_GPE:
854 
855         AcpiDbGenerateGpe (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
856         break;
857 
858     case CMD_GPES:
859 
860         AcpiDbDisplayGpes ();
861         break;
862 
863     case CMD_HANDLERS:
864 
865         AcpiDbDisplayHandlers ();
866         break;
867 
868     case CMD_HELP:
869     case CMD_HELP2:
870 
871         AcpiDbDisplayHelp (AcpiGbl_DbArgs[1]);
872         break;
873 
874     case CMD_HISTORY:
875 
876         AcpiDbDisplayHistory ();
877         break;
878 
879     case CMD_HISTORY_EXE: /* ! command */
880 
881         CommandLine = AcpiDbGetFromHistory (AcpiGbl_DbArgs[1]);
882         if (!CommandLine)
883         {
884             return (AE_CTRL_TRUE);
885         }
886 
887         Status = AcpiDbCommandDispatch (CommandLine, WalkState, Op);
888         return (Status);
889 
890     case CMD_HISTORY_LAST: /* !! command */
891 
892         CommandLine = AcpiDbGetFromHistory (NULL);
893         if (!CommandLine)
894         {
895             return (AE_CTRL_TRUE);
896         }
897 
898         Status = AcpiDbCommandDispatch (CommandLine, WalkState, Op);
899         return (Status);
900 
901     case CMD_INFORMATION:
902 
903         AcpiDbDisplayMethodInfo (Op);
904         break;
905 
906     case CMD_INTEGRITY:
907 
908         AcpiDbCheckIntegrity ();
909         break;
910 
911     case CMD_INTO:
912 
913         if (Op)
914         {
915             AcpiGbl_CmSingleStep = TRUE;
916             return (AE_OK);
917         }
918         break;
919 
920     case CMD_LEVEL:
921 
922         if (ParamCount == 0)
923         {
924             AcpiOsPrintf ("Current debug level for file output is:    %8.8lX\n",
925                 AcpiGbl_DbDebugLevel);
926             AcpiOsPrintf ("Current debug level for console output is: %8.8lX\n",
927                 AcpiGbl_DbConsoleDebugLevel);
928         }
929         else if (ParamCount == 2)
930         {
931             Temp = AcpiGbl_DbConsoleDebugLevel;
932             AcpiGbl_DbConsoleDebugLevel = ACPI_STRTOUL (AcpiGbl_DbArgs[1],
933                                             NULL, 16);
934             AcpiOsPrintf (
935                 "Debug Level for console output was %8.8lX, now %8.8lX\n",
936                 Temp, AcpiGbl_DbConsoleDebugLevel);
937         }
938         else
939         {
940             Temp = AcpiGbl_DbDebugLevel;
941             AcpiGbl_DbDebugLevel = ACPI_STRTOUL (AcpiGbl_DbArgs[1], NULL, 16);
942             AcpiOsPrintf (
943                 "Debug Level for file output was %8.8lX, now %8.8lX\n",
944                 Temp, AcpiGbl_DbDebugLevel);
945         }
946         break;
947 
948     case CMD_LIST:
949 
950         AcpiDbDisassembleAml (AcpiGbl_DbArgs[1], Op);
951         break;
952 
953     case CMD_LOAD:
954 
955         Status = AcpiDbGetTableFromFile (AcpiGbl_DbArgs[1], NULL);
956         break;
957 
958     case CMD_LOCKS:
959 
960         AcpiDbDisplayLocks ();
961         break;
962 
963     case CMD_LOCALS:
964 
965         AcpiDbDisplayLocals ();
966         break;
967 
968     case CMD_METHODS:
969 
970         Status = AcpiDbDisplayObjects ("METHOD", AcpiGbl_DbArgs[1]);
971         break;
972 
973     case CMD_NAMESPACE:
974 
975         AcpiDbDumpNamespace (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
976         break;
977 
978     case CMD_NOTIFY:
979 
980         Temp = ACPI_STRTOUL (AcpiGbl_DbArgs[2], NULL, 0);
981         AcpiDbSendNotify (AcpiGbl_DbArgs[1], Temp);
982         break;
983 
984     case CMD_OBJECT:
985 
986         AcpiUtStrupr (AcpiGbl_DbArgs[1]);
987         Status = AcpiDbDisplayObjects (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
988         break;
989 
990     case CMD_OPEN:
991 
992         AcpiDbOpenDebugFile (AcpiGbl_DbArgs[1]);
993         break;
994 
995     case CMD_OSI:
996 
997         AcpiDbDisplayInterfaces (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
998         break;
999 
1000     case CMD_OWNER:
1001 
1002         AcpiDbDumpNamespaceByOwner (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
1003         break;
1004 
1005     case CMD_PREDEFINED:
1006 
1007         AcpiDbCheckPredefinedNames ();
1008         break;
1009 
1010     case CMD_PREFIX:
1011 
1012         AcpiDbSetScope (AcpiGbl_DbArgs[1]);
1013         break;
1014 
1015     case CMD_REFERENCES:
1016 
1017         AcpiDbFindReferences (AcpiGbl_DbArgs[1]);
1018         break;
1019 
1020     case CMD_RESOURCES:
1021 
1022         AcpiDbDisplayResources (AcpiGbl_DbArgs[1]);
1023         break;
1024 
1025     case CMD_RESULTS:
1026 
1027         AcpiDbDisplayResults ();
1028         break;
1029 
1030     case CMD_SET:
1031 
1032         AcpiDbSetMethodData (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2],
1033             AcpiGbl_DbArgs[3]);
1034         break;
1035 
1036     case CMD_SLEEP:
1037 
1038         Status = AcpiDbSleep (AcpiGbl_DbArgs[1]);
1039         break;
1040 
1041     case CMD_STATS:
1042 
1043         Status = AcpiDbDisplayStatistics (AcpiGbl_DbArgs[1]);
1044         break;
1045 
1046     case CMD_STOP:
1047 
1048         return (AE_NOT_IMPLEMENTED);
1049 
1050     case CMD_TABLES:
1051 
1052         AcpiDbDisplayTableInfo (AcpiGbl_DbArgs[1]);
1053         break;
1054 
1055     case CMD_TEMPLATE:
1056 
1057         AcpiDbDisplayTemplate (AcpiGbl_DbArgs[1]);
1058         break;
1059 
1060     case CMD_TERMINATE:
1061 
1062         AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
1063         AcpiUtSubsystemShutdown ();
1064 
1065         /*
1066          * TBD: [Restructure] Need some way to re-initialize without
1067          * re-creating the semaphores!
1068          */
1069 
1070         /*  AcpiInitialize (NULL);  */
1071         break;
1072 
1073     case CMD_THREADS:
1074 
1075         AcpiDbCreateExecutionThreads (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2],
1076             AcpiGbl_DbArgs[3]);
1077         break;
1078 
1079     case CMD_TRACE:
1080 
1081         (void) AcpiDebugTrace (AcpiGbl_DbArgs[1],0,0,1);
1082         break;
1083 
1084     case CMD_TREE:
1085 
1086         AcpiDbDisplayCallingTree ();
1087         break;
1088 
1089     case CMD_TYPE:
1090 
1091         AcpiDbDisplayObjectType (AcpiGbl_DbArgs[1]);
1092         break;
1093 
1094     case CMD_UNLOAD:
1095 
1096         AcpiDbUnloadAcpiTable (AcpiGbl_DbArgs[1]);
1097         break;
1098 
1099     case CMD_EXIT:
1100     case CMD_QUIT:
1101 
1102         if (Op)
1103         {
1104             AcpiOsPrintf ("Method execution terminated\n");
1105             return (AE_CTRL_TERMINATE);
1106         }
1107 
1108         if (!AcpiGbl_DbOutputToFile)
1109         {
1110             AcpiDbgLevel = ACPI_DEBUG_DEFAULT;
1111         }
1112 
1113         AcpiDbCloseDebugFile ();
1114         AcpiGbl_DbTerminateThreads = TRUE;
1115         return (AE_CTRL_TERMINATE);
1116 
1117     case CMD_NOT_FOUND:
1118     default:
1119 
1120         AcpiOsPrintf ("Unknown Command\n");
1121         return (AE_CTRL_TRUE);
1122     }
1123 
1124     if (ACPI_SUCCESS (Status))
1125     {
1126         Status = AE_CTRL_TRUE;
1127     }
1128 
1129     /* Add all commands that come here to the history buffer */
1130 
1131     AcpiDbAddToHistory (InputBuffer);
1132     return (Status);
1133 }
1134 
1135 
1136 /*******************************************************************************
1137  *
1138  * FUNCTION:    AcpiDbExecuteThread
1139  *
1140  * PARAMETERS:  Context         - Not used
1141  *
1142  * RETURN:      None
1143  *
1144  * DESCRIPTION: Debugger execute thread. Waits for a command line, then
1145  *              simply dispatches it.
1146  *
1147  ******************************************************************************/
1148 
1149 void ACPI_SYSTEM_XFACE
1150 AcpiDbExecuteThread (
1151     void                    *Context)
1152 {
1153     ACPI_STATUS             Status = AE_OK;
1154     ACPI_STATUS             MStatus;
1155 
1156 
1157     while (Status != AE_CTRL_TERMINATE)
1158     {
1159         AcpiGbl_MethodExecuting = FALSE;
1160         AcpiGbl_StepToNextCall = FALSE;
1161 
1162         MStatus = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_READY);
1163         if (ACPI_FAILURE (MStatus))
1164         {
1165             return;
1166         }
1167 
1168         Status = AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, NULL, NULL);
1169 
1170         MStatus = AcpiUtReleaseMutex (ACPI_MTX_DEBUG_CMD_COMPLETE);
1171         if (ACPI_FAILURE (MStatus))
1172         {
1173             return;
1174         }
1175     }
1176 }
1177 
1178 
1179 /*******************************************************************************
1180  *
1181  * FUNCTION:    AcpiDbSingleThread
1182  *
1183  * PARAMETERS:  None
1184  *
1185  * RETURN:      None
1186  *
1187  * DESCRIPTION: Debugger execute thread. Waits for a command line, then
1188  *              simply dispatches it.
1189  *
1190  ******************************************************************************/
1191 
1192 static void
1193 AcpiDbSingleThread (
1194     void)
1195 {
1196 
1197     AcpiGbl_MethodExecuting = FALSE;
1198     AcpiGbl_StepToNextCall = FALSE;
1199 
1200     (void) AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, NULL, NULL);
1201 }
1202 
1203 
1204 /*******************************************************************************
1205  *
1206  * FUNCTION:    AcpiDbUserCommands
1207  *
1208  * PARAMETERS:  Prompt              - User prompt (depends on mode)
1209  *              Op                  - Current executing parse op
1210  *
1211  * RETURN:      None
1212  *
1213  * DESCRIPTION: Command line execution for the AML debugger. Commands are
1214  *              matched and dispatched here.
1215  *
1216  ******************************************************************************/
1217 
1218 ACPI_STATUS
1219 AcpiDbUserCommands (
1220     char                    Prompt,
1221     ACPI_PARSE_OBJECT       *Op)
1222 {
1223     ACPI_STATUS             Status = AE_OK;
1224 
1225 
1226     AcpiOsPrintf ("\n");
1227 
1228     /* TBD: [Restructure] Need a separate command line buffer for step mode */
1229 
1230     while (!AcpiGbl_DbTerminateThreads)
1231     {
1232         /* Force output to console until a command is entered */
1233 
1234         AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
1235 
1236         /* Different prompt if method is executing */
1237 
1238         if (!AcpiGbl_MethodExecuting)
1239         {
1240             AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
1241         }
1242         else
1243         {
1244             AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
1245         }
1246 
1247         /* Get the user input line */
1248 
1249         Status = AcpiOsGetLine (AcpiGbl_DbLineBuf,
1250             ACPI_DB_LINE_BUFFER_SIZE, NULL);
1251         if (ACPI_FAILURE (Status))
1252         {
1253             ACPI_EXCEPTION ((AE_INFO, Status, "While parsing command line"));
1254             return (Status);
1255         }
1256 
1257         /* Check for single or multithreaded debug */
1258 
1259         if (AcpiGbl_DebuggerConfiguration & DEBUGGER_MULTI_THREADED)
1260         {
1261             /*
1262              * Signal the debug thread that we have a command to execute,
1263              * and wait for the command to complete.
1264              */
1265             Status = AcpiUtReleaseMutex (ACPI_MTX_DEBUG_CMD_READY);
1266             if (ACPI_FAILURE (Status))
1267             {
1268                 return (Status);
1269             }
1270 
1271             Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_COMPLETE);
1272             if (ACPI_FAILURE (Status))
1273             {
1274                 return (Status);
1275             }
1276         }
1277         else
1278         {
1279             /* Just call to the command line interpreter */
1280 
1281             AcpiDbSingleThread ();
1282         }
1283     }
1284 
1285     /*
1286      * Only this thread (the original thread) should actually terminate the
1287      * subsystem, because all the semaphores are deleted during termination
1288      */
1289     Status = AcpiTerminate ();
1290     return (Status);
1291 }
1292 
1293 #endif  /* ACPI_DEBUGGER */
1294