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