1 /******************************************************************************* 2 * 3 * Module Name: dmwalk - AML disassembly tree walk 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 45 #include "acpi.h" 46 #include "accommon.h" 47 #include "acparser.h" 48 #include "amlcode.h" 49 #include "acdisasm.h" 50 #include "acdebug.h" 51 52 53 #ifdef ACPI_DISASSEMBLER 54 55 #define _COMPONENT ACPI_CA_DEBUGGER 56 ACPI_MODULE_NAME ("dmwalk") 57 58 59 #define DB_FULL_OP_INFO "[%4.4s] @%5.5X #%4.4X: " 60 61 /* Stub for non-compiler code */ 62 63 #ifndef ACPI_ASL_COMPILER 64 void 65 AcpiDmEmitExternals ( 66 void) 67 { 68 return; 69 } 70 #endif 71 72 /* Local prototypes */ 73 74 static ACPI_STATUS 75 AcpiDmDescendingOp ( 76 ACPI_PARSE_OBJECT *Op, 77 UINT32 Level, 78 void *Context); 79 80 static ACPI_STATUS 81 AcpiDmAscendingOp ( 82 ACPI_PARSE_OBJECT *Op, 83 UINT32 Level, 84 void *Context); 85 86 static UINT32 87 AcpiDmBlockType ( 88 ACPI_PARSE_OBJECT *Op); 89 90 91 /******************************************************************************* 92 * 93 * FUNCTION: AcpiDmDisassemble 94 * 95 * PARAMETERS: WalkState - Current state 96 * Origin - Starting object 97 * NumOpcodes - Max number of opcodes to be displayed 98 * 99 * RETURN: None 100 * 101 * DESCRIPTION: Disassemble parser object and its children. This is the 102 * main entry point of the disassembler. 103 * 104 ******************************************************************************/ 105 106 void 107 AcpiDmDisassemble ( 108 ACPI_WALK_STATE *WalkState, 109 ACPI_PARSE_OBJECT *Origin, 110 UINT32 NumOpcodes) 111 { 112 ACPI_PARSE_OBJECT *Op = Origin; 113 ACPI_OP_WALK_INFO Info; 114 115 116 if (!Op) 117 { 118 return; 119 } 120 121 Info.Flags = 0; 122 Info.Level = 0; 123 Info.Count = 0; 124 Info.WalkState = WalkState; 125 AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info); 126 return; 127 } 128 129 130 /******************************************************************************* 131 * 132 * FUNCTION: AcpiDmWalkParseTree 133 * 134 * PARAMETERS: Op - Root Op object 135 * DescendingCallback - Called during tree descent 136 * AscendingCallback - Called during tree ascent 137 * Context - To be passed to the callbacks 138 * 139 * RETURN: Status from callback(s) 140 * 141 * DESCRIPTION: Walk the entire parse tree. 142 * 143 ******************************************************************************/ 144 145 void 146 AcpiDmWalkParseTree ( 147 ACPI_PARSE_OBJECT *Op, 148 ASL_WALK_CALLBACK DescendingCallback, 149 ASL_WALK_CALLBACK AscendingCallback, 150 void *Context) 151 { 152 BOOLEAN NodePreviouslyVisited; 153 ACPI_PARSE_OBJECT *StartOp = Op; 154 ACPI_STATUS Status; 155 ACPI_PARSE_OBJECT *Next; 156 ACPI_OP_WALK_INFO *Info = Context; 157 158 159 Info->Level = 0; 160 NodePreviouslyVisited = FALSE; 161 162 while (Op) 163 { 164 if (NodePreviouslyVisited) 165 { 166 if (AscendingCallback) 167 { 168 Status = AscendingCallback (Op, Info->Level, Context); 169 if (ACPI_FAILURE (Status)) 170 { 171 return; 172 } 173 } 174 } 175 else 176 { 177 /* Let the callback process the node */ 178 179 Status = DescendingCallback (Op, Info->Level, Context); 180 if (ACPI_SUCCESS (Status)) 181 { 182 /* Visit children first, once */ 183 184 Next = AcpiPsGetArg (Op, 0); 185 if (Next) 186 { 187 Info->Level++; 188 Op = Next; 189 continue; 190 } 191 } 192 else if (Status != AE_CTRL_DEPTH) 193 { 194 /* Exit immediately on any error */ 195 196 return; 197 } 198 } 199 200 /* Terminate walk at start op */ 201 202 if (Op == StartOp) 203 { 204 break; 205 } 206 207 /* No more children, re-visit this node */ 208 209 if (!NodePreviouslyVisited) 210 { 211 NodePreviouslyVisited = TRUE; 212 continue; 213 } 214 215 /* No more children, visit peers */ 216 217 if (Op->Common.Next) 218 { 219 Op = Op->Common.Next; 220 NodePreviouslyVisited = FALSE; 221 } 222 else 223 { 224 /* No peers, re-visit parent */ 225 226 if (Info->Level != 0 ) 227 { 228 Info->Level--; 229 } 230 231 Op = Op->Common.Parent; 232 NodePreviouslyVisited = TRUE; 233 } 234 } 235 236 /* If we get here, the walk completed with no errors */ 237 238 return; 239 } 240 241 242 /******************************************************************************* 243 * 244 * FUNCTION: AcpiDmBlockType 245 * 246 * PARAMETERS: Op - Object to be examined 247 * 248 * RETURN: BlockType - not a block, parens, braces, or even both. 249 * 250 * DESCRIPTION: Type of block for this op (parens or braces) 251 * 252 ******************************************************************************/ 253 254 static UINT32 255 AcpiDmBlockType ( 256 ACPI_PARSE_OBJECT *Op) 257 { 258 const ACPI_OPCODE_INFO *OpInfo; 259 260 261 if (!Op) 262 { 263 return (BLOCK_NONE); 264 } 265 266 switch (Op->Common.AmlOpcode) 267 { 268 case AML_ELSE_OP: 269 270 return (BLOCK_BRACE); 271 272 case AML_METHOD_OP: 273 case AML_DEVICE_OP: 274 case AML_SCOPE_OP: 275 case AML_PROCESSOR_OP: 276 case AML_POWER_RES_OP: 277 case AML_THERMAL_ZONE_OP: 278 case AML_IF_OP: 279 case AML_WHILE_OP: 280 case AML_FIELD_OP: 281 case AML_INDEX_FIELD_OP: 282 case AML_BANK_FIELD_OP: 283 284 return (BLOCK_PAREN | BLOCK_BRACE); 285 286 case AML_BUFFER_OP: 287 288 if ((Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) || 289 (Op->Common.DisasmOpcode == ACPI_DASM_UUID)) 290 { 291 return (BLOCK_NONE); 292 } 293 294 /*lint -fallthrough */ 295 296 case AML_PACKAGE_OP: 297 case AML_VAR_PACKAGE_OP: 298 299 return (BLOCK_PAREN | BLOCK_BRACE); 300 301 case AML_EVENT_OP: 302 303 return (BLOCK_PAREN); 304 305 default: 306 307 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 308 if (OpInfo->Flags & AML_HAS_ARGS) 309 { 310 return (BLOCK_PAREN); 311 } 312 313 return (BLOCK_NONE); 314 } 315 } 316 317 318 /******************************************************************************* 319 * 320 * FUNCTION: AcpiDmListType 321 * 322 * PARAMETERS: Op - Object to be examined 323 * 324 * RETURN: ListType - has commas or not. 325 * 326 * DESCRIPTION: Type of block for this op (parens or braces) 327 * 328 ******************************************************************************/ 329 330 UINT32 331 AcpiDmListType ( 332 ACPI_PARSE_OBJECT *Op) 333 { 334 const ACPI_OPCODE_INFO *OpInfo; 335 336 337 if (!Op) 338 { 339 return (BLOCK_NONE); 340 } 341 342 switch (Op->Common.AmlOpcode) 343 { 344 345 case AML_ELSE_OP: 346 case AML_METHOD_OP: 347 case AML_DEVICE_OP: 348 case AML_SCOPE_OP: 349 case AML_POWER_RES_OP: 350 case AML_PROCESSOR_OP: 351 case AML_THERMAL_ZONE_OP: 352 case AML_IF_OP: 353 case AML_WHILE_OP: 354 case AML_FIELD_OP: 355 case AML_INDEX_FIELD_OP: 356 case AML_BANK_FIELD_OP: 357 358 return (BLOCK_NONE); 359 360 case AML_BUFFER_OP: 361 case AML_PACKAGE_OP: 362 case AML_VAR_PACKAGE_OP: 363 364 return (BLOCK_COMMA_LIST); 365 366 default: 367 368 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 369 if (OpInfo->Flags & AML_HAS_ARGS) 370 { 371 return (BLOCK_COMMA_LIST); 372 } 373 374 return (BLOCK_NONE); 375 } 376 } 377 378 379 /******************************************************************************* 380 * 381 * FUNCTION: AcpiDmDescendingOp 382 * 383 * PARAMETERS: ASL_WALK_CALLBACK 384 * 385 * RETURN: Status 386 * 387 * DESCRIPTION: First visitation of a parse object during tree descent. 388 * Decode opcode name and begin parameter list(s), if any. 389 * 390 ******************************************************************************/ 391 392 static ACPI_STATUS 393 AcpiDmDescendingOp ( 394 ACPI_PARSE_OBJECT *Op, 395 UINT32 Level, 396 void *Context) 397 { 398 ACPI_OP_WALK_INFO *Info = Context; 399 const ACPI_OPCODE_INFO *OpInfo; 400 UINT32 Name; 401 ACPI_PARSE_OBJECT *NextOp; 402 403 404 if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) 405 { 406 /* Ignore this op -- it was handled elsewhere */ 407 408 return (AE_CTRL_DEPTH); 409 } 410 411 /* Level 0 is at the Definition Block level */ 412 413 if (Level == 0) 414 { 415 /* In verbose mode, print the AML offset, opcode and depth count */ 416 417 if (Info->WalkState) 418 { 419 VERBOSE_PRINT ((DB_FULL_OP_INFO, 420 (Info->WalkState->MethodNode ? 421 Info->WalkState->MethodNode->Name.Ascii : " "), 422 Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode)); 423 } 424 425 if (Op->Common.AmlOpcode == AML_SCOPE_OP) 426 { 427 /* This is the beginning of the Definition Block */ 428 429 AcpiOsPrintf ("{\n"); 430 431 /* Emit all External() declarations here */ 432 433 AcpiDmEmitExternals (); 434 return (AE_OK); 435 } 436 } 437 else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 438 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 439 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 440 { 441 /* 442 * This is a first-level element of a term list, 443 * indent a new line 444 */ 445 switch (Op->Common.AmlOpcode) 446 { 447 case AML_NOOP_OP: 448 /* 449 * Optionally just ignore this opcode. Some tables use 450 * NoOp opcodes for "padding" out packages that the BIOS 451 * changes dynamically. This can leave hundreds or 452 * thousands of NoOp opcodes that if disassembled, 453 * cannot be compiled because they are syntactically 454 * incorrect. 455 */ 456 if (AcpiGbl_IgnoreNoopOperator) 457 { 458 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 459 return (AE_OK); 460 } 461 462 /* Fallthrough */ 463 464 default: 465 466 AcpiDmIndent (Level); 467 break; 468 } 469 470 Info->LastLevel = Level; 471 Info->Count = 0; 472 } 473 474 /* 475 * This is an inexpensive mechanism to try and keep lines from getting 476 * too long. When the limit is hit, start a new line at the previous 477 * indent plus one. A better but more expensive mechanism would be to 478 * keep track of the current column. 479 */ 480 Info->Count++; 481 if (Info->Count /* +Info->LastLevel */ > 10) 482 { 483 Info->Count = 0; 484 AcpiOsPrintf ("\n"); 485 AcpiDmIndent (Info->LastLevel + 1); 486 } 487 488 /* Print the opcode name */ 489 490 AcpiDmDisassembleOneOp (NULL, Info, Op); 491 492 if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) || 493 (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP)) 494 { 495 return (AE_OK); 496 } 497 498 if ((Op->Common.AmlOpcode == AML_NAME_OP) || 499 (Op->Common.AmlOpcode == AML_RETURN_OP)) 500 { 501 Info->Level--; 502 } 503 504 /* Start the opcode argument list if necessary */ 505 506 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 507 508 if ((OpInfo->Flags & AML_HAS_ARGS) || 509 (Op->Common.AmlOpcode == AML_EVENT_OP)) 510 { 511 /* This opcode has an argument list */ 512 513 if (AcpiDmBlockType (Op) & BLOCK_PAREN) 514 { 515 AcpiOsPrintf (" ("); 516 } 517 518 /* If this is a named opcode, print the associated name value */ 519 520 if (OpInfo->Flags & AML_NAMED) 521 { 522 switch (Op->Common.AmlOpcode) 523 { 524 case AML_ALIAS_OP: 525 526 NextOp = AcpiPsGetDepthNext (NULL, Op); 527 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 528 AcpiDmNamestring (NextOp->Common.Value.Name); 529 AcpiOsPrintf (", "); 530 531 /*lint -fallthrough */ 532 533 default: 534 535 Name = AcpiPsGetName (Op); 536 if (Op->Named.Path) 537 { 538 AcpiDmNamestring ((char *) Op->Named.Path); 539 } 540 else 541 { 542 AcpiDmDumpName (Name); 543 } 544 545 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP) 546 { 547 if (AcpiGbl_DbOpt_verbose) 548 { 549 (void) AcpiPsDisplayObjectPathname (NULL, Op); 550 } 551 } 552 break; 553 } 554 555 switch (Op->Common.AmlOpcode) 556 { 557 case AML_METHOD_OP: 558 559 AcpiDmMethodFlags (Op); 560 AcpiOsPrintf (")"); 561 562 /* Emit description comment for Method() with a predefined ACPI name */ 563 564 AcpiDmPredefinedDescription (Op); 565 break; 566 567 568 case AML_NAME_OP: 569 570 /* Check for _HID and related EISAID() */ 571 572 AcpiDmCheckForHardwareId (Op); 573 AcpiOsPrintf (", "); 574 break; 575 576 577 case AML_REGION_OP: 578 579 AcpiDmRegionFlags (Op); 580 break; 581 582 583 case AML_POWER_RES_OP: 584 585 /* Mark the next two Ops as part of the parameter list */ 586 587 AcpiOsPrintf (", "); 588 NextOp = AcpiPsGetDepthNext (NULL, Op); 589 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 590 591 NextOp = NextOp->Common.Next; 592 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 593 return (AE_OK); 594 595 596 case AML_PROCESSOR_OP: 597 598 /* Mark the next three Ops as part of the parameter list */ 599 600 AcpiOsPrintf (", "); 601 NextOp = AcpiPsGetDepthNext (NULL, Op); 602 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 603 604 NextOp = NextOp->Common.Next; 605 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 606 607 NextOp = NextOp->Common.Next; 608 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 609 return (AE_OK); 610 611 612 case AML_MUTEX_OP: 613 case AML_DATA_REGION_OP: 614 615 AcpiOsPrintf (", "); 616 return (AE_OK); 617 618 619 case AML_EVENT_OP: 620 case AML_ALIAS_OP: 621 622 return (AE_OK); 623 624 625 case AML_SCOPE_OP: 626 case AML_DEVICE_OP: 627 case AML_THERMAL_ZONE_OP: 628 629 AcpiOsPrintf (")"); 630 break; 631 632 633 default: 634 635 AcpiOsPrintf ("*** Unhandled named opcode %X\n", 636 Op->Common.AmlOpcode); 637 break; 638 } 639 } 640 641 else switch (Op->Common.AmlOpcode) 642 { 643 case AML_FIELD_OP: 644 case AML_BANK_FIELD_OP: 645 case AML_INDEX_FIELD_OP: 646 647 Info->BitOffset = 0; 648 649 /* Name of the parent OperationRegion */ 650 651 NextOp = AcpiPsGetDepthNext (NULL, Op); 652 AcpiDmNamestring (NextOp->Common.Value.Name); 653 AcpiOsPrintf (", "); 654 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 655 656 switch (Op->Common.AmlOpcode) 657 { 658 case AML_BANK_FIELD_OP: 659 660 /* Namestring - Bank Name */ 661 662 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 663 AcpiDmNamestring (NextOp->Common.Value.Name); 664 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 665 AcpiOsPrintf (", "); 666 667 /* 668 * Bank Value. This is a TermArg in the middle of the parameter 669 * list, must handle it here. 670 * 671 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST 672 * eliminates newline in the output. 673 */ 674 NextOp = NextOp->Common.Next; 675 676 Info->Flags = ACPI_PARSEOP_PARAMLIST; 677 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp, 678 AcpiDmAscendingOp, Info); 679 Info->Flags = 0; 680 Info->Level = Level; 681 682 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 683 AcpiOsPrintf (", "); 684 break; 685 686 case AML_INDEX_FIELD_OP: 687 688 /* Namestring - Data Name */ 689 690 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 691 AcpiDmNamestring (NextOp->Common.Value.Name); 692 AcpiOsPrintf (", "); 693 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 694 break; 695 696 default: 697 698 break; 699 } 700 701 AcpiDmFieldFlags (NextOp); 702 break; 703 704 case AML_BUFFER_OP: 705 706 /* The next op is the size parameter */ 707 708 NextOp = AcpiPsGetDepthNext (NULL, Op); 709 if (!NextOp) 710 { 711 /* Single-step support */ 712 713 return (AE_OK); 714 } 715 716 if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE) 717 { 718 /* 719 * We have a resource list. Don't need to output 720 * the buffer size Op. Open up a new block 721 */ 722 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 723 NextOp = NextOp->Common.Next; 724 AcpiOsPrintf (")"); 725 726 /* Emit description comment for Name() with a predefined ACPI name */ 727 728 AcpiDmPredefinedDescription (Op->Asl.Parent); 729 730 AcpiOsPrintf ("\n"); 731 AcpiDmIndent (Info->Level); 732 AcpiOsPrintf ("{\n"); 733 return (AE_OK); 734 } 735 736 /* Normal Buffer, mark size as in the parameter list */ 737 738 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 739 return (AE_OK); 740 741 case AML_VAR_PACKAGE_OP: 742 case AML_IF_OP: 743 case AML_WHILE_OP: 744 745 /* The next op is the size or predicate parameter */ 746 747 NextOp = AcpiPsGetDepthNext (NULL, Op); 748 if (NextOp) 749 { 750 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 751 } 752 return (AE_OK); 753 754 case AML_PACKAGE_OP: 755 756 /* The next op is the size parameter */ 757 758 NextOp = AcpiPsGetDepthNext (NULL, Op); 759 if (NextOp) 760 { 761 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 762 } 763 return (AE_OK); 764 765 case AML_MATCH_OP: 766 767 AcpiDmMatchOp (Op); 768 break; 769 770 default: 771 772 break; 773 } 774 775 if (AcpiDmBlockType (Op) & BLOCK_BRACE) 776 { 777 AcpiOsPrintf ("\n"); 778 AcpiDmIndent (Level); 779 AcpiOsPrintf ("{\n"); 780 } 781 } 782 783 return (AE_OK); 784 } 785 786 787 /******************************************************************************* 788 * 789 * FUNCTION: AcpiDmAscendingOp 790 * 791 * PARAMETERS: ASL_WALK_CALLBACK 792 * 793 * RETURN: Status 794 * 795 * DESCRIPTION: Second visitation of a parse object, during ascent of parse 796 * tree. Close out any parameter lists and complete the opcode. 797 * 798 ******************************************************************************/ 799 800 static ACPI_STATUS 801 AcpiDmAscendingOp ( 802 ACPI_PARSE_OBJECT *Op, 803 UINT32 Level, 804 void *Context) 805 { 806 ACPI_OP_WALK_INFO *Info = Context; 807 ACPI_PARSE_OBJECT *ParentOp; 808 809 810 if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) 811 { 812 /* Ignore this op -- it was handled elsewhere */ 813 814 return (AE_OK); 815 } 816 817 if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP)) 818 { 819 /* Indicates the end of the current descriptor block (table) */ 820 821 AcpiOsPrintf ("}\n\n"); 822 return (AE_OK); 823 } 824 825 switch (AcpiDmBlockType (Op)) 826 { 827 case BLOCK_PAREN: 828 829 /* Completed an op that has arguments, add closing paren */ 830 831 AcpiOsPrintf (")"); 832 833 if (Op->Common.AmlOpcode == AML_NAME_OP) 834 { 835 /* Emit description comment for Name() with a predefined ACPI name */ 836 837 AcpiDmPredefinedDescription (Op); 838 } 839 else 840 { 841 /* For Create* operators, attempt to emit resource tag description */ 842 843 AcpiDmFieldPredefinedDescription (Op); 844 } 845 846 /* Decode Notify() values */ 847 848 if (Op->Common.AmlOpcode == AML_NOTIFY_OP) 849 { 850 AcpiDmNotifyDescription (Op); 851 } 852 853 AcpiDmDisplayTargetPathname (Op); 854 855 /* Could be a nested operator, check if comma required */ 856 857 if (!AcpiDmCommaIfListMember (Op)) 858 { 859 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 860 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 861 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 862 { 863 /* 864 * This is a first-level element of a term list 865 * start a new line 866 */ 867 if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST)) 868 { 869 AcpiOsPrintf ("\n"); 870 } 871 } 872 } 873 break; 874 875 case BLOCK_BRACE: 876 case (BLOCK_BRACE | BLOCK_PAREN): 877 878 /* Completed an op that has a term list, add closing brace */ 879 880 if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST) 881 { 882 AcpiOsPrintf ("}"); 883 } 884 else 885 { 886 AcpiDmIndent (Level); 887 AcpiOsPrintf ("}"); 888 } 889 890 AcpiDmCommaIfListMember (Op); 891 892 if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN) 893 { 894 AcpiOsPrintf ("\n"); 895 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)) 896 { 897 if ((Op->Common.AmlOpcode == AML_IF_OP) && 898 (Op->Common.Next) && 899 (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP)) 900 { 901 break; 902 } 903 904 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 905 (!Op->Common.Next)) 906 { 907 break; 908 } 909 AcpiOsPrintf ("\n"); 910 } 911 } 912 break; 913 914 case BLOCK_NONE: 915 default: 916 917 /* Could be a nested operator, check if comma required */ 918 919 if (!AcpiDmCommaIfListMember (Op)) 920 { 921 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 922 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 923 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 924 { 925 /* 926 * This is a first-level element of a term list 927 * start a new line 928 */ 929 AcpiOsPrintf ("\n"); 930 } 931 } 932 else if (Op->Common.Parent) 933 { 934 switch (Op->Common.Parent->Common.AmlOpcode) 935 { 936 case AML_PACKAGE_OP: 937 case AML_VAR_PACKAGE_OP: 938 939 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) 940 { 941 AcpiOsPrintf ("\n"); 942 } 943 break; 944 945 default: 946 947 break; 948 } 949 } 950 break; 951 } 952 953 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST) 954 { 955 if ((Op->Common.Next) && 956 (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) 957 { 958 return (AE_OK); 959 } 960 961 /* 962 * The parent Op is guaranteed to be valid because of the flag 963 * ACPI_PARSEOP_PARAMLIST -- which means that this op is part of 964 * a parameter list and thus has a valid parent. 965 */ 966 ParentOp = Op->Common.Parent; 967 968 /* 969 * Just completed a parameter node for something like "Buffer (param)". 970 * Close the paren and open up the term list block with a brace 971 */ 972 if (Op->Common.Next) 973 { 974 AcpiOsPrintf (")"); 975 976 /* 977 * Emit a description comment for a Name() operator that is a 978 * predefined ACPI name. Must check the grandparent. 979 */ 980 ParentOp = ParentOp->Common.Parent; 981 if (ParentOp && 982 (ParentOp->Asl.AmlOpcode == AML_NAME_OP)) 983 { 984 AcpiDmPredefinedDescription (ParentOp); 985 } 986 987 AcpiOsPrintf ("\n"); 988 AcpiDmIndent (Level - 1); 989 AcpiOsPrintf ("{\n"); 990 } 991 else 992 { 993 ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST; 994 AcpiOsPrintf (") {"); 995 } 996 } 997 998 if ((Op->Common.AmlOpcode == AML_NAME_OP) || 999 (Op->Common.AmlOpcode == AML_RETURN_OP)) 1000 { 1001 Info->Level++; 1002 } 1003 return (AE_OK); 1004 } 1005 1006 1007 #endif /* ACPI_DISASSEMBLER */ 1008