1 /*******************************************************************************
2  *
3  * Module Name: dbinput - user front-end to the AML debugger
4  *
5  ******************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151 
152 #include "acpi.h"
153 #include "accommon.h"
154 #include "acdebug.h"
155 
156 #ifdef ACPI_APPLICATION
157 #include "acapps.h"
158 #endif
159 
160 #ifdef ACPI_DEBUGGER
161 
162 #define _COMPONENT          ACPI_CA_DEBUGGER
163         ACPI_MODULE_NAME    ("dbinput")
164 
165 
166 /* Local prototypes */
167 
168 static UINT32
169 AcpiDbGetLine (
170     char                    *InputBuffer);
171 
172 static UINT32
173 AcpiDbMatchCommand (
174     char                    *UserCommand);
175 
176 static void
177 AcpiDbDisplayCommandInfo (
178     const char              *Command,
179     BOOLEAN                 DisplayAll);
180 
181 static void
182 AcpiDbDisplayHelp (
183     char                    *Command);
184 
185 static BOOLEAN
186 AcpiDbMatchCommandHelp (
187     const char                  *Command,
188     const ACPI_DB_COMMAND_HELP  *Help);
189 
190 
191 /*
192  * Top-level debugger commands.
193  *
194  * This list of commands must match the string table below it
195  */
196 enum AcpiExDebuggerCommands
197 {
198     CMD_NOT_FOUND = 0,
199     CMD_NULL,
200     CMD_ALLOCATIONS,
201     CMD_ARGS,
202     CMD_ARGUMENTS,
203     CMD_BREAKPOINT,
204     CMD_BUSINFO,
205     CMD_CALL,
206     CMD_DEBUG,
207     CMD_DISASSEMBLE,
208     CMD_DISASM,
209     CMD_DUMP,
210     CMD_EVALUATE,
211     CMD_EXECUTE,
212     CMD_EXIT,
213     CMD_FIND,
214     CMD_GO,
215     CMD_HANDLERS,
216     CMD_HELP,
217     CMD_HELP2,
218     CMD_HISTORY,
219     CMD_HISTORY_EXE,
220     CMD_HISTORY_LAST,
221     CMD_INFORMATION,
222     CMD_INTEGRITY,
223     CMD_INTO,
224     CMD_LEVEL,
225     CMD_LIST,
226     CMD_LOCALS,
227     CMD_LOCKS,
228     CMD_METHODS,
229     CMD_NAMESPACE,
230     CMD_NOTIFY,
231     CMD_OBJECTS,
232     CMD_OSI,
233     CMD_OWNER,
234     CMD_PATHS,
235     CMD_PREDEFINED,
236     CMD_PREFIX,
237     CMD_QUIT,
238     CMD_REFERENCES,
239     CMD_RESOURCES,
240     CMD_RESULTS,
241     CMD_SET,
242     CMD_STATS,
243     CMD_STOP,
244     CMD_TABLES,
245     CMD_TEMPLATE,
246     CMD_TRACE,
247     CMD_TREE,
248     CMD_TYPE,
249 #ifdef ACPI_APPLICATION
250     CMD_ENABLEACPI,
251     CMD_EVENT,
252     CMD_GPE,
253     CMD_GPES,
254     CMD_SCI,
255     CMD_SLEEP,
256 
257     CMD_CLOSE,
258     CMD_LOAD,
259     CMD_OPEN,
260     CMD_UNLOAD,
261 
262     CMD_TERMINATE,
263     CMD_THREADS,
264 
265     CMD_TEST,
266 #endif
267 };
268 
269 #define CMD_FIRST_VALID     2
270 
271 
272 /* Second parameter is the required argument count */
273 
274 static const ACPI_DB_COMMAND_INFO   AcpiGbl_DbCommands[] =
275 {
276     {"<NOT FOUND>",  0},
277     {"<NULL>",       0},
278     {"ALLOCATIONS",  0},
279     {"ARGS",         0},
280     {"ARGUMENTS",    0},
281     {"BREAKPOINT",   1},
282     {"BUSINFO",      0},
283     {"CALL",         0},
284     {"DEBUG",        1},
285     {"DISASSEMBLE",  1},
286     {"DISASM",       1},
287     {"DUMP",         1},
288     {"EVALUATE",     1},
289     {"EXECUTE",      1},
290     {"EXIT",         0},
291     {"FIND",         1},
292     {"GO",           0},
293     {"HANDLERS",     0},
294     {"HELP",         0},
295     {"?",            0},
296     {"HISTORY",      0},
297     {"!",            1},
298     {"!!",           0},
299     {"INFORMATION",  0},
300     {"INTEGRITY",    0},
301     {"INTO",         0},
302     {"LEVEL",        0},
303     {"LIST",         0},
304     {"LOCALS",       0},
305     {"LOCKS",        0},
306     {"METHODS",      0},
307     {"NAMESPACE",    0},
308     {"NOTIFY",       2},
309     {"OBJECTS",      0},
310     {"OSI",          0},
311     {"OWNER",        1},
312     {"PATHS",        0},
313     {"PREDEFINED",   0},
314     {"PREFIX",       0},
315     {"QUIT",         0},
316     {"REFERENCES",   1},
317     {"RESOURCES",    0},
318     {"RESULTS",      0},
319     {"SET",          3},
320     {"STATS",        1},
321     {"STOP",         0},
322     {"TABLES",       0},
323     {"TEMPLATE",     1},
324     {"TRACE",        1},
325     {"TREE",         0},
326     {"TYPE",         1},
327 #ifdef ACPI_APPLICATION
328     {"ENABLEACPI",   0},
329     {"EVENT",        1},
330     {"GPE",          1},
331     {"GPES",         0},
332     {"SCI",          0},
333     {"SLEEP",        0},
334 
335     {"CLOSE",        0},
336     {"LOAD",         1},
337     {"OPEN",         1},
338     {"UNLOAD",       1},
339 
340     {"TERMINATE",    0},
341     {"THREADS",      3},
342 
343     {"TEST",         1},
344 #endif
345     {NULL,           0}
346 };
347 
348 /*
349  * Help for all debugger commands. First argument is the number of lines
350  * of help to output for the command.
351  */
352 static const ACPI_DB_COMMAND_HELP   AcpiGbl_DbCommandHelp[] =
353 {
354     {0, "\nGeneral-Purpose Commands:",         "\n"},
355     {1, "  Allocations",                       "Display list of current memory allocations\n"},
356     {2, "  Dump <Address>|<Namepath>",         "\n"},
357     {0, "       [Byte|Word|Dword|Qword]",      "Display ACPI objects or memory\n"},
358     {1, "  Handlers",                          "Info about global handlers\n"},
359     {1, "  Help [Command]",                    "This help screen or individual command\n"},
360     {1, "  History",                           "Display command history buffer\n"},
361     {1, "  Level <DebugLevel>] [console]",     "Get/Set debug level for file or console\n"},
362     {1, "  Locks",                             "Current status of internal mutexes\n"},
363     {1, "  Osi [Install|Remove <name>]",       "Display or modify global _OSI list\n"},
364     {1, "  Quit or Exit",                      "Exit this command\n"},
365     {8, "  Stats <SubCommand>",                "Display namespace and memory statistics\n"},
366     {1, "     Allocations",                    "Display list of current memory allocations\n"},
367     {1, "     Memory",                         "Dump internal memory lists\n"},
368     {1, "     Misc",                           "Namespace search and mutex stats\n"},
369     {1, "     Objects",                        "Summary of namespace objects\n"},
370     {1, "     Sizes",                          "Sizes for each of the internal objects\n"},
371     {1, "     Stack",                          "Display CPU stack usage\n"},
372     {1, "     Tables",                         "Info about current ACPI table(s)\n"},
373     {1, "  Tables",                            "Display info about loaded ACPI tables\n"},
374     {1, "  ! <CommandNumber>",                 "Execute command from history buffer\n"},
375     {1, "  !!",                                "Execute last command again\n"},
376 
377     {0, "\nNamespace Access Commands:",        "\n"},
378     {1, "  Businfo",                           "Display system bus info\n"},
379     {1, "  Disassemble <Method>",              "Disassemble a control method\n"},
380     {1, "  Find <AcpiName> (? is wildcard)",   "Find ACPI name(s) with wildcards\n"},
381     {1, "  Integrity",                         "Validate namespace integrity\n"},
382     {1, "  Methods",                           "Display list of loaded control methods\n"},
383     {1, "  Namespace [Object] [Depth]",        "Display loaded namespace tree/subtree\n"},
384     {1, "  Notify <Object> <Value>",           "Send a notification on Object\n"},
385     {1, "  Objects [ObjectType]",              "Display summary of all objects or just given type\n"},
386     {1, "  Owner <OwnerId> [Depth]",           "Display loaded namespace by object owner\n"},
387     {1, "  Paths",                             "Display full pathnames of namespace objects\n"},
388     {1, "  Predefined",                        "Check all predefined names\n"},
389     {1, "  Prefix [<Namepath>]",               "Set or Get current execution prefix\n"},
390     {1, "  References <Addr>",                 "Find all references to object at addr\n"},
391     {1, "  Resources [DeviceName]",            "Display Device resources (no arg = all devices)\n"},
392     {1, "  Set N <NamedObject> <Value>",       "Set value for named integer\n"},
393     {1, "  Template <Object>",                 "Format/dump a Buffer/ResourceTemplate\n"},
394     {1, "  Type <Object>",                     "Display object type\n"},
395 
396     {0, "\nControl Method Execution Commands:","\n"},
397     {1, "  Arguments (or Args)",               "Display method arguments\n"},
398     {1, "  Breakpoint <AmlOffset>",            "Set an AML execution breakpoint\n"},
399     {1, "  Call",                              "Run to next control method invocation\n"},
400     {1, "  Debug <Namepath> [Arguments]",      "Single Step a control method\n"},
401     {6, "  Evaluate",                          "Synonym for Execute\n"},
402     {5, "  Execute <Namepath> [Arguments]",    "Execute control method\n"},
403     {1, "     Hex Integer",                    "Integer method argument\n"},
404     {1, "     \"Ascii String\"",               "String method argument\n"},
405     {1, "     (Hex Byte List)",                "Buffer method argument\n"},
406     {1, "     [Package Element List]",         "Package method argument\n"},
407     {5, "  Execute predefined",                "Execute all predefined (public) methods\n"},
408     {1, "  Go",                                "Allow method to run to completion\n"},
409     {1, "  Information",                       "Display info about the current method\n"},
410     {1, "  Into",                              "Step into (not over) a method call\n"},
411     {1, "  List [# of Aml Opcodes]",           "Display method ASL statements\n"},
412     {1, "  Locals",                            "Display method local variables\n"},
413     {1, "  Results",                           "Display method result stack\n"},
414     {1, "  Set <A|L> <#> <Value>",             "Set method data (Arguments/Locals)\n"},
415     {1, "  Stop",                              "Terminate control method\n"},
416     {5, "  Trace <State> [<Namepath>] [Once]", "Trace control method execution\n"},
417     {1, "     Enable",                         "Enable all messages\n"},
418     {1, "     Disable",                        "Disable tracing\n"},
419     {1, "     Method",                         "Enable method execution messages\n"},
420     {1, "     Opcode",                         "Enable opcode execution messages\n"},
421     {1, "  Tree",                              "Display control method calling tree\n"},
422     {1, "  <Enter>",                           "Single step next AML opcode (over calls)\n"},
423 
424 #ifdef ACPI_APPLICATION
425     {0, "\nHardware Simulation Commands:",         "\n"},
426     {1, "  EnableAcpi",                        "Enable ACPI (hardware) mode\n"},
427     {1, "  Event <F|G> <Value>",               "Generate AcpiEvent (Fixed/GPE)\n"},
428     {1, "  Gpe <GpeNum> [GpeBlockDevice]",     "Simulate a GPE\n"},
429     {1, "  Gpes",                              "Display info on all GPE devices\n"},
430     {1, "  Sci",                               "Generate an SCI\n"},
431     {1, "  Sleep [SleepState]",                "Simulate sleep/wake sequence(s) (0-5)\n"},
432 
433     {0, "\nFile I/O Commands:",                "\n"},
434     {1, "  Close",                             "Close debug output file\n"},
435     {1, "  Load <Input Filename>",             "Load ACPI table from a file\n"},
436     {1, "  Open <Output Filename>",            "Open a file for debug output\n"},
437     {1, "  Unload <Namepath>",                 "Unload an ACPI table via namespace object\n"},
438 
439     {0, "\nUser Space Commands:",              "\n"},
440     {1, "  Terminate",                         "Delete namespace and all internal objects\n"},
441     {1, "  Thread <Threads><Loops><NamePath>", "Spawn threads to execute method(s)\n"},
442 
443     {0, "\nDebug Test Commands:",              "\n"},
444     {3, "  Test <TestName>",                   "Invoke a debug test\n"},
445     {1, "     Objects",                        "Read/write/compare all namespace data objects\n"},
446     {1, "     Predefined",                     "Execute all ACPI predefined names (_STA, etc.)\n"},
447 #endif
448     {0, NULL, NULL}
449 };
450 
451 
452 /*******************************************************************************
453  *
454  * FUNCTION:    AcpiDbMatchCommandHelp
455  *
456  * PARAMETERS:  Command             - Command string to match
457  *              Help                - Help table entry to attempt match
458  *
459  * RETURN:      TRUE if command matched, FALSE otherwise
460  *
461  * DESCRIPTION: Attempt to match a command in the help table in order to
462  *              print help information for a single command.
463  *
464  ******************************************************************************/
465 
466 static BOOLEAN
467 AcpiDbMatchCommandHelp (
468     const char                  *Command,
469     const ACPI_DB_COMMAND_HELP  *Help)
470 {
471     char                    *Invocation = Help->Invocation;
472     UINT32                  LineCount;
473 
474 
475     /* Valid commands in the help table begin with a couple of spaces */
476 
477     if (*Invocation != ' ')
478     {
479         return (FALSE);
480     }
481 
482     while (*Invocation == ' ')
483     {
484         Invocation++;
485     }
486 
487     /* Match command name (full command or substring) */
488 
489     while ((*Command) && (*Invocation) && (*Invocation != ' '))
490     {
491         if (tolower ((int) *Command) != tolower ((int) *Invocation))
492         {
493             return (FALSE);
494         }
495 
496         Invocation++;
497         Command++;
498     }
499 
500     /* Print the appropriate number of help lines */
501 
502     LineCount = Help->LineCount;
503     while (LineCount)
504     {
505         AcpiOsPrintf ("%-38s : %s", Help->Invocation, Help->Description);
506         Help++;
507         LineCount--;
508     }
509 
510     return (TRUE);
511 }
512 
513 
514 /*******************************************************************************
515  *
516  * FUNCTION:    AcpiDbDisplayCommandInfo
517  *
518  * PARAMETERS:  Command             - Command string to match
519  *              DisplayAll          - Display all matching commands, or just
520  *                                    the first one (substring match)
521  *
522  * RETURN:      None
523  *
524  * DESCRIPTION: Display help information for a Debugger command.
525  *
526  ******************************************************************************/
527 
528 static void
529 AcpiDbDisplayCommandInfo (
530     const char              *Command,
531     BOOLEAN                 DisplayAll)
532 {
533     const ACPI_DB_COMMAND_HELP  *Next;
534     BOOLEAN                     Matched;
535 
536 
537     Next = AcpiGbl_DbCommandHelp;
538     while (Next->Invocation)
539     {
540         Matched = AcpiDbMatchCommandHelp (Command, Next);
541         if (!DisplayAll && Matched)
542         {
543             return;
544         }
545 
546         Next++;
547     }
548 }
549 
550 
551 /*******************************************************************************
552  *
553  * FUNCTION:    AcpiDbDisplayHelp
554  *
555  * PARAMETERS:  Command             - Optional command string to display help.
556  *                                    if not specified, all debugger command
557  *                                    help strings are displayed
558  *
559  * RETURN:      None
560  *
561  * DESCRIPTION: Display help for a single debugger command, or all of them.
562  *
563  ******************************************************************************/
564 
565 static void
566 AcpiDbDisplayHelp (
567     char                    *Command)
568 {
569     const ACPI_DB_COMMAND_HELP  *Next = AcpiGbl_DbCommandHelp;
570 
571 
572     if (!Command)
573     {
574         /* No argument to help, display help for all commands */
575 
576         while (Next->Invocation)
577         {
578             AcpiOsPrintf ("%-38s%s", Next->Invocation, Next->Description);
579             Next++;
580         }
581     }
582     else
583     {
584         /* Display help for all commands that match the subtring */
585 
586         AcpiDbDisplayCommandInfo (Command, TRUE);
587     }
588 }
589 
590 
591 /*******************************************************************************
592  *
593  * FUNCTION:    AcpiDbGetNextToken
594  *
595  * PARAMETERS:  String          - Command buffer
596  *              Next            - Return value, end of next token
597  *
598  * RETURN:      Pointer to the start of the next token.
599  *
600  * DESCRIPTION: Command line parsing. Get the next token on the command line
601  *
602  ******************************************************************************/
603 
604 char *
605 AcpiDbGetNextToken (
606     char                    *String,
607     char                    **Next,
608     ACPI_OBJECT_TYPE        *ReturnType)
609 {
610     char                    *Start;
611     UINT32                  Depth;
612     ACPI_OBJECT_TYPE        Type = ACPI_TYPE_INTEGER;
613 
614 
615     /* At end of buffer? */
616 
617     if (!String || !(*String))
618     {
619         return (NULL);
620     }
621 
622     /* Remove any spaces at the beginning */
623 
624     if (*String == ' ')
625     {
626         while (*String && (*String == ' '))
627         {
628             String++;
629         }
630 
631         if (!(*String))
632         {
633             return (NULL);
634         }
635     }
636 
637     switch (*String)
638     {
639     case '"':
640 
641         /* This is a quoted string, scan until closing quote */
642 
643         String++;
644         Start = String;
645         Type = ACPI_TYPE_STRING;
646 
647         /* Find end of string */
648 
649         while (*String && (*String != '"'))
650         {
651             String++;
652         }
653         break;
654 
655     case '(':
656 
657         /* This is the start of a buffer, scan until closing paren */
658 
659         String++;
660         Start = String;
661         Type = ACPI_TYPE_BUFFER;
662 
663         /* Find end of buffer */
664 
665         while (*String && (*String != ')'))
666         {
667             String++;
668         }
669         break;
670 
671     case '[':
672 
673         /* This is the start of a package, scan until closing bracket */
674 
675         String++;
676         Depth = 1;
677         Start = String;
678         Type = ACPI_TYPE_PACKAGE;
679 
680         /* Find end of package (closing bracket) */
681 
682         while (*String)
683         {
684             /* Handle String package elements */
685 
686             if (*String == '"')
687             {
688                 /* Find end of string */
689 
690                 String++;
691                 while (*String && (*String != '"'))
692                 {
693                     String++;
694                 }
695                 if (!(*String))
696                 {
697                     break;
698                 }
699             }
700             else if (*String == '[')
701             {
702                 Depth++;         /* A nested package declaration */
703             }
704             else if (*String == ']')
705             {
706                 Depth--;
707                 if (Depth == 0) /* Found final package closing bracket */
708                 {
709                     break;
710                 }
711             }
712 
713             String++;
714         }
715         break;
716 
717     default:
718 
719         Start = String;
720 
721         /* Find end of token */
722 
723         while (*String && (*String != ' '))
724         {
725             String++;
726         }
727         break;
728     }
729 
730     if (!(*String))
731     {
732         *Next = NULL;
733     }
734     else
735     {
736         *String = 0;
737         *Next = String + 1;
738     }
739 
740     *ReturnType = Type;
741     return (Start);
742 }
743 
744 
745 /*******************************************************************************
746  *
747  * FUNCTION:    AcpiDbGetLine
748  *
749  * PARAMETERS:  InputBuffer         - Command line buffer
750  *
751  * RETURN:      Count of arguments to the command
752  *
753  * DESCRIPTION: Get the next command line from the user. Gets entire line
754  *              up to the next newline
755  *
756  ******************************************************************************/
757 
758 static UINT32
759 AcpiDbGetLine (
760     char                    *InputBuffer)
761 {
762     UINT32                  i;
763     UINT32                  Count;
764     char                    *Next;
765     char                    *This;
766 
767 
768     if (AcpiUtSafeStrcpy (AcpiGbl_DbParsedBuf, sizeof (AcpiGbl_DbParsedBuf),
769         InputBuffer))
770     {
771         AcpiOsPrintf (
772             "Buffer overflow while parsing input line (max %u characters)\n",
773             sizeof (AcpiGbl_DbParsedBuf));
774         return (0);
775     }
776 
777     This = AcpiGbl_DbParsedBuf;
778     for (i = 0; i < ACPI_DEBUGGER_MAX_ARGS; i++)
779     {
780         AcpiGbl_DbArgs[i] = AcpiDbGetNextToken (This, &Next,
781             &AcpiGbl_DbArgTypes[i]);
782         if (!AcpiGbl_DbArgs[i])
783         {
784             break;
785         }
786 
787         This = Next;
788     }
789 
790     /* Uppercase the actual command */
791 
792     AcpiUtStrupr (AcpiGbl_DbArgs[0]);
793 
794     Count = i;
795     if (Count)
796     {
797         Count--;  /* Number of args only */
798     }
799 
800     return (Count);
801 }
802 
803 
804 /*******************************************************************************
805  *
806  * FUNCTION:    AcpiDbMatchCommand
807  *
808  * PARAMETERS:  UserCommand             - User command line
809  *
810  * RETURN:      Index into command array, -1 if not found
811  *
812  * DESCRIPTION: Search command array for a command match
813  *
814  ******************************************************************************/
815 
816 static UINT32
817 AcpiDbMatchCommand (
818     char                    *UserCommand)
819 {
820     UINT32                  i;
821 
822 
823     if (!UserCommand || UserCommand[0] == 0)
824     {
825         return (CMD_NULL);
826     }
827 
828     for (i = CMD_FIRST_VALID; AcpiGbl_DbCommands[i].Name; i++)
829     {
830         if (strstr (
831             ACPI_CAST_PTR (char, AcpiGbl_DbCommands[i].Name), UserCommand) ==
832             AcpiGbl_DbCommands[i].Name)
833         {
834             return (i);
835         }
836     }
837 
838     /* Command not recognized */
839 
840     return (CMD_NOT_FOUND);
841 }
842 
843 
844 /*******************************************************************************
845  *
846  * FUNCTION:    AcpiDbCommandDispatch
847  *
848  * PARAMETERS:  InputBuffer         - Command line buffer
849  *              WalkState           - Current walk
850  *              Op                  - Current (executing) parse op
851  *
852  * RETURN:      Status
853  *
854  * DESCRIPTION: Command dispatcher.
855  *
856  ******************************************************************************/
857 
858 ACPI_STATUS
859 AcpiDbCommandDispatch (
860     char                    *InputBuffer,
861     ACPI_WALK_STATE         *WalkState,
862     ACPI_PARSE_OBJECT       *Op)
863 {
864     UINT32                  Temp;
865     UINT32                  CommandIndex;
866     UINT32                  ParamCount;
867     char                    *CommandLine;
868     ACPI_STATUS             Status = AE_CTRL_TRUE;
869 
870 
871     /* If AcpiTerminate has been called, terminate this thread */
872 
873     if (AcpiGbl_DbTerminateLoop)
874     {
875         return (AE_CTRL_TERMINATE);
876     }
877 
878     /* Find command and add to the history buffer */
879 
880     ParamCount = AcpiDbGetLine (InputBuffer);
881     CommandIndex = AcpiDbMatchCommand (AcpiGbl_DbArgs[0]);
882     Temp = 0;
883 
884     /*
885      * We don't want to add the !! command to the history buffer. It
886      * would cause an infinite loop because it would always be the
887      * previous command.
888      */
889     if (CommandIndex != CMD_HISTORY_LAST)
890     {
891         AcpiDbAddToHistory (InputBuffer);
892     }
893 
894     /* Verify that we have the minimum number of params */
895 
896     if (ParamCount < AcpiGbl_DbCommands[CommandIndex].MinArgs)
897     {
898         AcpiOsPrintf ("%u parameters entered, [%s] requires %u parameters\n",
899             ParamCount, AcpiGbl_DbCommands[CommandIndex].Name,
900             AcpiGbl_DbCommands[CommandIndex].MinArgs);
901 
902         AcpiDbDisplayCommandInfo (
903             AcpiGbl_DbCommands[CommandIndex].Name, FALSE);
904         return (AE_CTRL_TRUE);
905     }
906 
907     /* Decode and dispatch the command */
908 
909     switch (CommandIndex)
910     {
911     case CMD_NULL:
912 
913         if (Op)
914         {
915             return (AE_OK);
916         }
917         break;
918 
919     case CMD_ALLOCATIONS:
920 
921 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
922         AcpiUtDumpAllocations ((UINT32) -1, NULL);
923 #endif
924         break;
925 
926     case CMD_ARGS:
927     case CMD_ARGUMENTS:
928 
929         AcpiDbDisplayArguments ();
930         break;
931 
932     case CMD_BREAKPOINT:
933 
934         AcpiDbSetMethodBreakpoint (AcpiGbl_DbArgs[1], WalkState, Op);
935         break;
936 
937     case CMD_BUSINFO:
938 
939         AcpiDbGetBusInfo ();
940         break;
941 
942     case CMD_CALL:
943 
944         AcpiDbSetMethodCallBreakpoint (Op);
945         Status = AE_OK;
946         break;
947 
948     case CMD_DEBUG:
949 
950         AcpiDbExecute (AcpiGbl_DbArgs[1],
951             &AcpiGbl_DbArgs[2], &AcpiGbl_DbArgTypes[2], EX_SINGLE_STEP);
952         break;
953 
954     case CMD_DISASSEMBLE:
955     case CMD_DISASM:
956 
957         (void) AcpiDbDisassembleMethod (AcpiGbl_DbArgs[1]);
958         break;
959 
960     case CMD_DUMP:
961 
962         AcpiDbDecodeAndDisplayObject (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
963         break;
964 
965     case CMD_EVALUATE:
966     case CMD_EXECUTE:
967 
968         AcpiDbExecute (AcpiGbl_DbArgs[1],
969             &AcpiGbl_DbArgs[2], &AcpiGbl_DbArgTypes[2], EX_NO_SINGLE_STEP);
970         break;
971 
972     case CMD_FIND:
973 
974         Status = AcpiDbFindNameInNamespace (AcpiGbl_DbArgs[1]);
975         break;
976 
977     case CMD_GO:
978 
979         AcpiGbl_CmSingleStep = FALSE;
980         return (AE_OK);
981 
982     case CMD_HANDLERS:
983 
984         AcpiDbDisplayHandlers ();
985         break;
986 
987     case CMD_HELP:
988     case CMD_HELP2:
989 
990         AcpiDbDisplayHelp (AcpiGbl_DbArgs[1]);
991         break;
992 
993     case CMD_HISTORY:
994 
995         AcpiDbDisplayHistory ();
996         break;
997 
998     case CMD_HISTORY_EXE: /* ! command */
999 
1000         CommandLine = AcpiDbGetFromHistory (AcpiGbl_DbArgs[1]);
1001         if (!CommandLine)
1002         {
1003             return (AE_CTRL_TRUE);
1004         }
1005 
1006         Status = AcpiDbCommandDispatch (CommandLine, WalkState, Op);
1007         return (Status);
1008 
1009     case CMD_HISTORY_LAST: /* !! command */
1010 
1011         CommandLine = AcpiDbGetFromHistory (NULL);
1012         if (!CommandLine)
1013         {
1014             return (AE_CTRL_TRUE);
1015         }
1016 
1017         Status = AcpiDbCommandDispatch (CommandLine, WalkState, Op);
1018         return (Status);
1019 
1020     case CMD_INFORMATION:
1021 
1022         AcpiDbDisplayMethodInfo (Op);
1023         break;
1024 
1025     case CMD_INTEGRITY:
1026 
1027         AcpiDbCheckIntegrity ();
1028         break;
1029 
1030     case CMD_INTO:
1031 
1032         if (Op)
1033         {
1034             AcpiGbl_CmSingleStep = TRUE;
1035             return (AE_OK);
1036         }
1037         break;
1038 
1039     case CMD_LEVEL:
1040 
1041         if (ParamCount == 0)
1042         {
1043             AcpiOsPrintf (
1044                 "Current debug level for file output is:    %8.8lX\n",
1045                 AcpiGbl_DbDebugLevel);
1046             AcpiOsPrintf (
1047                 "Current debug level for console output is: %8.8lX\n",
1048                 AcpiGbl_DbConsoleDebugLevel);
1049         }
1050         else if (ParamCount == 2)
1051         {
1052             Temp = AcpiGbl_DbConsoleDebugLevel;
1053             AcpiGbl_DbConsoleDebugLevel =
1054                 strtoul (AcpiGbl_DbArgs[1], NULL, 16);
1055             AcpiOsPrintf (
1056                 "Debug Level for console output was %8.8lX, now %8.8lX\n",
1057                 Temp, AcpiGbl_DbConsoleDebugLevel);
1058         }
1059         else
1060         {
1061             Temp = AcpiGbl_DbDebugLevel;
1062             AcpiGbl_DbDebugLevel = strtoul (AcpiGbl_DbArgs[1], NULL, 16);
1063             AcpiOsPrintf (
1064                 "Debug Level for file output was %8.8lX, now %8.8lX\n",
1065                 Temp, AcpiGbl_DbDebugLevel);
1066         }
1067         break;
1068 
1069     case CMD_LIST:
1070 
1071         AcpiDbDisassembleAml (AcpiGbl_DbArgs[1], Op);
1072         break;
1073 
1074     case CMD_LOCKS:
1075 
1076         AcpiDbDisplayLocks ();
1077         break;
1078 
1079     case CMD_LOCALS:
1080 
1081         AcpiDbDisplayLocals ();
1082         break;
1083 
1084     case CMD_METHODS:
1085 
1086         Status = AcpiDbDisplayObjects ("METHOD", AcpiGbl_DbArgs[1]);
1087         break;
1088 
1089     case CMD_NAMESPACE:
1090 
1091         AcpiDbDumpNamespace (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
1092         break;
1093 
1094     case CMD_NOTIFY:
1095 
1096         Temp = strtoul (AcpiGbl_DbArgs[2], NULL, 0);
1097         AcpiDbSendNotify (AcpiGbl_DbArgs[1], Temp);
1098         break;
1099 
1100     case CMD_OBJECTS:
1101 
1102         AcpiUtStrupr (AcpiGbl_DbArgs[1]);
1103         Status = AcpiDbDisplayObjects (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
1104         break;
1105 
1106     case CMD_OSI:
1107 
1108         AcpiDbDisplayInterfaces (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
1109         break;
1110 
1111     case CMD_OWNER:
1112 
1113         AcpiDbDumpNamespaceByOwner (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
1114         break;
1115 
1116     case CMD_PATHS:
1117 
1118         AcpiDbDumpNamespacePaths ();
1119         break;
1120 
1121     case CMD_PREFIX:
1122 
1123         AcpiDbSetScope (AcpiGbl_DbArgs[1]);
1124         break;
1125 
1126     case CMD_REFERENCES:
1127 
1128         AcpiDbFindReferences (AcpiGbl_DbArgs[1]);
1129         break;
1130 
1131     case CMD_RESOURCES:
1132 
1133         AcpiDbDisplayResources (AcpiGbl_DbArgs[1]);
1134         break;
1135 
1136     case CMD_RESULTS:
1137 
1138         AcpiDbDisplayResults ();
1139         break;
1140 
1141     case CMD_SET:
1142 
1143         AcpiDbSetMethodData (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2],
1144             AcpiGbl_DbArgs[3]);
1145         break;
1146 
1147     case CMD_STATS:
1148 
1149         Status = AcpiDbDisplayStatistics (AcpiGbl_DbArgs[1]);
1150         break;
1151 
1152     case CMD_STOP:
1153 
1154         return (AE_NOT_IMPLEMENTED);
1155 
1156     case CMD_TABLES:
1157 
1158         AcpiDbDisplayTableInfo (AcpiGbl_DbArgs[1]);
1159         break;
1160 
1161     case CMD_TEMPLATE:
1162 
1163         AcpiDbDisplayTemplate (AcpiGbl_DbArgs[1]);
1164         break;
1165 
1166     case CMD_TRACE:
1167 
1168         AcpiDbTrace (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2], AcpiGbl_DbArgs[3]);
1169         break;
1170 
1171     case CMD_TREE:
1172 
1173         AcpiDbDisplayCallingTree ();
1174         break;
1175 
1176     case CMD_TYPE:
1177 
1178         AcpiDbDisplayObjectType (AcpiGbl_DbArgs[1]);
1179         break;
1180 
1181 #ifdef ACPI_APPLICATION
1182 
1183     /* Hardware simulation commands. */
1184 
1185     case CMD_ENABLEACPI:
1186 #if (!ACPI_REDUCED_HARDWARE)
1187 
1188         Status = AcpiEnable();
1189         if (ACPI_FAILURE(Status))
1190         {
1191             AcpiOsPrintf("AcpiEnable failed (Status=%X)\n", Status);
1192             return (Status);
1193         }
1194 #endif /* !ACPI_REDUCED_HARDWARE */
1195         break;
1196 
1197     case CMD_EVENT:
1198 
1199         AcpiOsPrintf ("Event command not implemented\n");
1200         break;
1201 
1202     case CMD_GPE:
1203 
1204         AcpiDbGenerateGpe (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2]);
1205         break;
1206 
1207     case CMD_GPES:
1208 
1209         AcpiDbDisplayGpes ();
1210         break;
1211 
1212     case CMD_SCI:
1213 
1214         AcpiDbGenerateSci ();
1215         break;
1216 
1217     case CMD_SLEEP:
1218 
1219         Status = AcpiDbSleep (AcpiGbl_DbArgs[1]);
1220         break;
1221 
1222     /* File I/O commands. */
1223 
1224     case CMD_CLOSE:
1225 
1226         AcpiDbCloseDebugFile ();
1227         break;
1228 
1229     case CMD_LOAD:
1230         {
1231             ACPI_NEW_TABLE_DESC     *ListHead = NULL;
1232 
1233             Status = AcGetAllTablesFromFile (AcpiGbl_DbArgs[1],
1234                 ACPI_GET_ALL_TABLES, &ListHead);
1235             if (ACPI_SUCCESS (Status))
1236             {
1237                 AcpiDbLoadTables (ListHead);
1238             }
1239         }
1240         break;
1241 
1242     case CMD_OPEN:
1243 
1244         AcpiDbOpenDebugFile (AcpiGbl_DbArgs[1]);
1245         break;
1246 
1247     /* User space commands. */
1248 
1249     case CMD_TERMINATE:
1250 
1251         AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
1252         AcpiUtSubsystemShutdown ();
1253 
1254         /*
1255          * TBD: [Restructure] Need some way to re-initialize without
1256          * re-creating the semaphores!
1257          */
1258 
1259         AcpiGbl_DbTerminateLoop = TRUE;
1260         /*  AcpiInitialize (NULL);  */
1261         break;
1262 
1263     case CMD_THREADS:
1264 
1265         AcpiDbCreateExecutionThreads (AcpiGbl_DbArgs[1], AcpiGbl_DbArgs[2],
1266             AcpiGbl_DbArgs[3]);
1267         break;
1268 
1269     /* Debug test commands. */
1270 
1271     case CMD_PREDEFINED:
1272 
1273         AcpiDbCheckPredefinedNames ();
1274         break;
1275 
1276     case CMD_TEST:
1277 
1278         AcpiDbExecuteTest (AcpiGbl_DbArgs[1]);
1279         break;
1280 
1281     case CMD_UNLOAD:
1282 
1283         AcpiDbUnloadAcpiTable (AcpiGbl_DbArgs[1]);
1284         break;
1285 #endif
1286 
1287     case CMD_EXIT:
1288     case CMD_QUIT:
1289 
1290         if (Op)
1291         {
1292             AcpiOsPrintf ("Method execution terminated\n");
1293             return (AE_CTRL_TERMINATE);
1294         }
1295 
1296         if (!AcpiGbl_DbOutputToFile)
1297         {
1298             AcpiDbgLevel = ACPI_DEBUG_DEFAULT;
1299         }
1300 
1301 #ifdef ACPI_APPLICATION
1302         AcpiDbCloseDebugFile ();
1303 #endif
1304         AcpiGbl_DbTerminateLoop = TRUE;
1305         return (AE_CTRL_TERMINATE);
1306 
1307     case CMD_NOT_FOUND:
1308     default:
1309 
1310         AcpiOsPrintf ("%s: unknown command\n", AcpiGbl_DbArgs[0]);
1311         return (AE_CTRL_TRUE);
1312     }
1313 
1314     if (ACPI_SUCCESS (Status))
1315     {
1316         Status = AE_CTRL_TRUE;
1317     }
1318 
1319     return (Status);
1320 }
1321 
1322 
1323 /*******************************************************************************
1324  *
1325  * FUNCTION:    AcpiDbExecuteThread
1326  *
1327  * PARAMETERS:  Context         - Not used
1328  *
1329  * RETURN:      None
1330  *
1331  * DESCRIPTION: Debugger execute thread. Waits for a command line, then
1332  *              simply dispatches it.
1333  *
1334  ******************************************************************************/
1335 
1336 void ACPI_SYSTEM_XFACE
1337 AcpiDbExecuteThread (
1338     void                    *Context)
1339 {
1340 
1341     (void) AcpiDbUserCommands ();
1342     AcpiGbl_DbThreadsTerminated = TRUE;
1343 }
1344 
1345 
1346 /*******************************************************************************
1347  *
1348  * FUNCTION:    AcpiDbUserCommands
1349  *
1350  * PARAMETERS:  None
1351  *
1352  * RETURN:      None
1353  *
1354  * DESCRIPTION: Command line execution for the AML debugger. Commands are
1355  *              matched and dispatched here.
1356  *
1357  ******************************************************************************/
1358 
1359 ACPI_STATUS
1360 AcpiDbUserCommands (
1361     void)
1362 {
1363     ACPI_STATUS             Status = AE_OK;
1364 
1365 
1366     AcpiOsPrintf ("\n");
1367 
1368     /* TBD: [Restructure] Need a separate command line buffer for step mode */
1369 
1370     while (!AcpiGbl_DbTerminateLoop)
1371     {
1372         /* Wait the readiness of the command */
1373 
1374         Status = AcpiOsWaitCommandReady ();
1375         if (ACPI_FAILURE (Status))
1376         {
1377             break;
1378         }
1379 
1380         /* Just call to the command line interpreter */
1381 
1382         AcpiGbl_MethodExecuting = FALSE;
1383         AcpiGbl_StepToNextCall = FALSE;
1384 
1385         (void) AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, NULL, NULL);
1386 
1387         /* Notify the completion of the command */
1388 
1389         Status = AcpiOsNotifyCommandComplete ();
1390         if (ACPI_FAILURE (Status))
1391         {
1392             break;
1393         }
1394     }
1395 
1396     if (ACPI_FAILURE (Status) && Status != AE_CTRL_TERMINATE)
1397     {
1398         ACPI_EXCEPTION ((AE_INFO, Status, "While parsing command line"));
1399     }
1400     return (Status);
1401 }
1402 
1403 #endif  /* ACPI_DEBUGGER */
1404