dmwalk.c revision 228110
12786Ssos/******************************************************************************* 22786Ssos * 32786Ssos * Module Name: dmwalk - AML disassembly tree walk 42786Ssos * 52786Ssos ******************************************************************************/ 62786Ssos 72786Ssos/* 82786Ssos * Copyright (C) 2000 - 2011, Intel Corp. 92786Ssos * All rights reserved. 102786Ssos * 112786Ssos * Redistribution and use in source and binary forms, with or without 122786Ssos * modification, are permitted provided that the following conditions 132786Ssos * are met: 142786Ssos * 1. Redistributions of source code must retain the above copyright 152786Ssos * notice, this list of conditions, and the following disclaimer, 162786Ssos * without modification. 172786Ssos * 2. Redistributions in binary form must reproduce at minimum a disclaimer 182786Ssos * substantially similar to the "NO WARRANTY" disclaimer below 192786Ssos * ("Disclaimer") and any redistribution must be conditioned upon 202786Ssos * including a substantially similar Disclaimer requirement for further 212786Ssos * binary redistribution. 222786Ssos * 3. Neither the names of the above-listed copyright holders nor the names 232786Ssos * of any contributors may be used to endorse or promote products derived 242786Ssos * from this software without specific prior written permission. 252786Ssos * 262786Ssos * Alternatively, this software may be distributed under the terms of the 272786Ssos * GNU General Public License ("GPL") version 2 as published by the Free 282786Ssos * Software Foundation. 292786Ssos * 302786Ssos * NO WARRANTY 312786Ssos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 322786Ssos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 332786Ssos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 342786Ssos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 352786Ssos * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 362786Ssos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 372786Ssos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 382786Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 392786Ssos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 402786Ssos * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 412786Ssos * POSSIBILITY OF SUCH DAMAGES. 422786Ssos */ 432786Ssos 442786Ssos 452786Ssos#include <contrib/dev/acpica/include/acpi.h> 462786Ssos#include <contrib/dev/acpica/include/accommon.h> 472786Ssos#include <contrib/dev/acpica/include/acparser.h> 482786Ssos#include <contrib/dev/acpica/include/amlcode.h> 492786Ssos#include <contrib/dev/acpica/include/acdisasm.h> 502786Ssos#include <contrib/dev/acpica/include/acdebug.h> 512786Ssos 522786Ssos 532786Ssos#ifdef ACPI_DISASSEMBLER 542786Ssos 552786Ssos#define _COMPONENT ACPI_CA_DEBUGGER 562786Ssos ACPI_MODULE_NAME ("dmwalk") 572786Ssos 582786Ssos 592786Ssos#define DB_FULL_OP_INFO "[%4.4s] @%5.5X #%4.4X: " 602786Ssos 612786Ssos/* Stub for non-compiler code */ 622786Ssos 632786Ssos#ifndef ACPI_ASL_COMPILER 642786Ssosvoid 652786SsosAcpiDmEmitExternals ( 662786Ssos void) 672786Ssos{ 682786Ssos return; 692786Ssos} 702786Ssos#endif 712786Ssos 722786Ssos/* Local prototypes */ 732786Ssos 742786Ssosstatic ACPI_STATUS 752786SsosAcpiDmDescendingOp ( 762786Ssos ACPI_PARSE_OBJECT *Op, 772786Ssos UINT32 Level, 782786Ssos void *Context); 792786Ssos 802786Ssosstatic ACPI_STATUS 812786SsosAcpiDmAscendingOp ( 822786Ssos ACPI_PARSE_OBJECT *Op, 832786Ssos UINT32 Level, 842786Ssos void *Context); 852786Ssos 862786Ssosstatic UINT32 872786SsosAcpiDmBlockType ( 882786Ssos ACPI_PARSE_OBJECT *Op); 892786Ssos 902786Ssos 912786Ssos/******************************************************************************* 922786Ssos * 932786Ssos * FUNCTION: AcpiDmDisassemble 942786Ssos * 952786Ssos * PARAMETERS: WalkState - Current state 962786Ssos * Origin - Starting object 972786Ssos * NumOpcodes - Max number of opcodes to be displayed 982786Ssos * 992786Ssos * RETURN: None 1002786Ssos * 1012786Ssos * DESCRIPTION: Disassemble parser object and its children. This is the 1022786Ssos * main entry point of the disassembler. 1032786Ssos * 1042786Ssos ******************************************************************************/ 1052786Ssos 1062786Ssosvoid 1072786SsosAcpiDmDisassemble ( 1082786Ssos ACPI_WALK_STATE *WalkState, 1092786Ssos 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 145void 146AcpiDmWalkParseTree ( 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 254static UINT32 255AcpiDmBlockType ( 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 { 290 return (BLOCK_NONE); 291 } 292 293 /*lint -fallthrough */ 294 295 case AML_PACKAGE_OP: 296 case AML_VAR_PACKAGE_OP: 297 298 return (BLOCK_PAREN | BLOCK_BRACE); 299 300 case AML_EVENT_OP: 301 302 return (BLOCK_PAREN); 303 304 default: 305 306 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 307 if (OpInfo->Flags & AML_HAS_ARGS) 308 { 309 return (BLOCK_PAREN); 310 } 311 312 return (BLOCK_NONE); 313 } 314} 315 316 317/******************************************************************************* 318 * 319 * FUNCTION: AcpiDmListType 320 * 321 * PARAMETERS: Op - Object to be examined 322 * 323 * RETURN: ListType - has commas or not. 324 * 325 * DESCRIPTION: Type of block for this op (parens or braces) 326 * 327 ******************************************************************************/ 328 329UINT32 330AcpiDmListType ( 331 ACPI_PARSE_OBJECT *Op) 332{ 333 const ACPI_OPCODE_INFO *OpInfo; 334 335 336 if (!Op) 337 { 338 return (BLOCK_NONE); 339 } 340 341 switch (Op->Common.AmlOpcode) 342 { 343 344 case AML_ELSE_OP: 345 case AML_METHOD_OP: 346 case AML_DEVICE_OP: 347 case AML_SCOPE_OP: 348 case AML_POWER_RES_OP: 349 case AML_PROCESSOR_OP: 350 case AML_THERMAL_ZONE_OP: 351 case AML_IF_OP: 352 case AML_WHILE_OP: 353 case AML_FIELD_OP: 354 case AML_INDEX_FIELD_OP: 355 case AML_BANK_FIELD_OP: 356 357 return (BLOCK_NONE); 358 359 case AML_BUFFER_OP: 360 case AML_PACKAGE_OP: 361 case AML_VAR_PACKAGE_OP: 362 363 return (BLOCK_COMMA_LIST); 364 365 default: 366 367 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 368 if (OpInfo->Flags & AML_HAS_ARGS) 369 { 370 return (BLOCK_COMMA_LIST); 371 } 372 373 return (BLOCK_NONE); 374 } 375} 376 377 378/******************************************************************************* 379 * 380 * FUNCTION: AcpiDmDescendingOp 381 * 382 * PARAMETERS: ASL_WALK_CALLBACK 383 * 384 * RETURN: Status 385 * 386 * DESCRIPTION: First visitation of a parse object during tree descent. 387 * Decode opcode name and begin parameter list(s), if any. 388 * 389 ******************************************************************************/ 390 391static ACPI_STATUS 392AcpiDmDescendingOp ( 393 ACPI_PARSE_OBJECT *Op, 394 UINT32 Level, 395 void *Context) 396{ 397 ACPI_OP_WALK_INFO *Info = Context; 398 const ACPI_OPCODE_INFO *OpInfo; 399 UINT32 Name; 400 ACPI_PARSE_OBJECT *NextOp; 401 402 403 if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) 404 { 405 /* Ignore this op -- it was handled elsewhere */ 406 407 return (AE_CTRL_DEPTH); 408 } 409 410 /* Level 0 is at the Definition Block level */ 411 412 if (Level == 0) 413 { 414 /* In verbose mode, print the AML offset, opcode and depth count */ 415 416 if (Info->WalkState) 417 { 418 VERBOSE_PRINT ((DB_FULL_OP_INFO, 419 (Info->WalkState->MethodNode ? 420 Info->WalkState->MethodNode->Name.Ascii : " "), 421 Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode)); 422 } 423 424 if (Op->Common.AmlOpcode == AML_SCOPE_OP) 425 { 426 /* This is the beginning of the Definition Block */ 427 428 AcpiOsPrintf ("{\n"); 429 430 /* Emit all External() declarations here */ 431 432 AcpiDmEmitExternals (); 433 return (AE_OK); 434 } 435 } 436 else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 437 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 438 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 439 { 440 /* 441 * This is a first-level element of a term list, 442 * indent a new line 443 */ 444 AcpiDmIndent (Level); 445 Info->LastLevel = Level; 446 Info->Count = 0; 447 } 448 449 /* 450 * This is an inexpensive mechanism to try and keep lines from getting 451 * too long. When the limit is hit, start a new line at the previous 452 * indent plus one. A better but more expensive mechanism would be to 453 * keep track of the current column. 454 */ 455 Info->Count++; 456 if (Info->Count /*+Info->LastLevel*/ > 10) 457 { 458 Info->Count = 0; 459 AcpiOsPrintf ("\n"); 460 AcpiDmIndent (Info->LastLevel + 1); 461 } 462 463 /* Print the opcode name */ 464 465 AcpiDmDisassembleOneOp (NULL, Info, Op); 466 467 if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) || 468 (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP)) 469 { 470 return (AE_OK); 471 } 472 473 if ((Op->Common.AmlOpcode == AML_NAME_OP) || 474 (Op->Common.AmlOpcode == AML_RETURN_OP)) 475 { 476 Info->Level--; 477 } 478 479 /* Start the opcode argument list if necessary */ 480 481 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 482 483 if ((OpInfo->Flags & AML_HAS_ARGS) || 484 (Op->Common.AmlOpcode == AML_EVENT_OP)) 485 { 486 /* This opcode has an argument list */ 487 488 if (AcpiDmBlockType (Op) & BLOCK_PAREN) 489 { 490 AcpiOsPrintf (" ("); 491 } 492 493 /* If this is a named opcode, print the associated name value */ 494 495 if (OpInfo->Flags & AML_NAMED) 496 { 497 switch (Op->Common.AmlOpcode) 498 { 499 case AML_ALIAS_OP: 500 501 NextOp = AcpiPsGetDepthNext (NULL, Op); 502 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 503 AcpiDmNamestring (NextOp->Common.Value.Name); 504 AcpiOsPrintf (", "); 505 506 /*lint -fallthrough */ 507 508 default: 509 510 Name = AcpiPsGetName (Op); 511 if (Op->Named.Path) 512 { 513 AcpiDmNamestring ((char *) Op->Named.Path); 514 } 515 else 516 { 517 AcpiDmDumpName (Name); 518 } 519 520 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP) 521 { 522 if (AcpiGbl_DbOpt_verbose) 523 { 524 (void) AcpiPsDisplayObjectPathname (NULL, Op); 525 } 526 } 527 break; 528 } 529 530 switch (Op->Common.AmlOpcode) 531 { 532 case AML_METHOD_OP: 533 534 AcpiDmMethodFlags (Op); 535 AcpiOsPrintf (")"); 536 break; 537 538 539 case AML_NAME_OP: 540 541 /* Check for _HID and related EISAID() */ 542 543 AcpiDmIsEisaId (Op); 544 AcpiOsPrintf (", "); 545 break; 546 547 548 case AML_REGION_OP: 549 550 AcpiDmRegionFlags (Op); 551 break; 552 553 554 case AML_POWER_RES_OP: 555 556 /* Mark the next two Ops as part of the parameter list */ 557 558 AcpiOsPrintf (", "); 559 NextOp = AcpiPsGetDepthNext (NULL, Op); 560 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 561 562 NextOp = NextOp->Common.Next; 563 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 564 return (AE_OK); 565 566 567 case AML_PROCESSOR_OP: 568 569 /* Mark the next three Ops as part of the parameter list */ 570 571 AcpiOsPrintf (", "); 572 NextOp = AcpiPsGetDepthNext (NULL, Op); 573 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 574 575 NextOp = NextOp->Common.Next; 576 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 577 578 NextOp = NextOp->Common.Next; 579 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 580 return (AE_OK); 581 582 583 case AML_MUTEX_OP: 584 case AML_DATA_REGION_OP: 585 586 AcpiOsPrintf (", "); 587 return (AE_OK); 588 589 590 case AML_EVENT_OP: 591 case AML_ALIAS_OP: 592 593 return (AE_OK); 594 595 596 case AML_SCOPE_OP: 597 case AML_DEVICE_OP: 598 case AML_THERMAL_ZONE_OP: 599 600 AcpiOsPrintf (")"); 601 break; 602 603 604 default: 605 606 AcpiOsPrintf ("*** Unhandled named opcode %X\n", Op->Common.AmlOpcode); 607 break; 608 } 609 } 610 611 else switch (Op->Common.AmlOpcode) 612 { 613 case AML_FIELD_OP: 614 case AML_BANK_FIELD_OP: 615 case AML_INDEX_FIELD_OP: 616 617 Info->BitOffset = 0; 618 619 /* Name of the parent OperationRegion */ 620 621 NextOp = AcpiPsGetDepthNext (NULL, Op); 622 AcpiDmNamestring (NextOp->Common.Value.Name); 623 AcpiOsPrintf (", "); 624 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 625 626 switch (Op->Common.AmlOpcode) 627 { 628 case AML_BANK_FIELD_OP: 629 630 /* Namestring - Bank Name */ 631 632 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 633 AcpiDmNamestring (NextOp->Common.Value.Name); 634 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 635 AcpiOsPrintf (", "); 636 637 /* 638 * Bank Value. This is a TermArg in the middle of the parameter 639 * list, must handle it here. 640 * 641 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST 642 * eliminates newline in the output. 643 */ 644 NextOp = NextOp->Common.Next; 645 646 Info->Flags = ACPI_PARSEOP_PARAMLIST; 647 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp, AcpiDmAscendingOp, Info); 648 Info->Flags = 0; 649 Info->Level = Level; 650 651 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 652 AcpiOsPrintf (", "); 653 break; 654 655 case AML_INDEX_FIELD_OP: 656 657 /* Namestring - Data Name */ 658 659 NextOp = AcpiPsGetDepthNext (NULL, NextOp); 660 AcpiDmNamestring (NextOp->Common.Value.Name); 661 AcpiOsPrintf (", "); 662 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 663 break; 664 665 default: 666 667 break; 668 } 669 670 AcpiDmFieldFlags (NextOp); 671 break; 672 673 674 case AML_BUFFER_OP: 675 676 /* The next op is the size parameter */ 677 678 NextOp = AcpiPsGetDepthNext (NULL, Op); 679 if (!NextOp) 680 { 681 /* Single-step support */ 682 683 return (AE_OK); 684 } 685 686 if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE) 687 { 688 /* 689 * We have a resource list. Don't need to output 690 * the buffer size Op. Open up a new block 691 */ 692 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; 693 NextOp = NextOp->Common.Next; 694 AcpiOsPrintf (")\n"); 695 AcpiDmIndent (Info->Level); 696 AcpiOsPrintf ("{\n"); 697 return (AE_OK); 698 } 699 700 /* Normal Buffer, mark size as in the parameter list */ 701 702 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 703 return (AE_OK); 704 705 706 case AML_VAR_PACKAGE_OP: 707 case AML_IF_OP: 708 case AML_WHILE_OP: 709 710 /* The next op is the size or predicate parameter */ 711 712 NextOp = AcpiPsGetDepthNext (NULL, Op); 713 if (NextOp) 714 { 715 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 716 } 717 return (AE_OK); 718 719 720 case AML_PACKAGE_OP: 721 722 /* The next op is the size or predicate parameter */ 723 724 NextOp = AcpiPsGetDepthNext (NULL, Op); 725 if (NextOp) 726 { 727 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST; 728 } 729 return (AE_OK); 730 731 732 case AML_MATCH_OP: 733 734 AcpiDmMatchOp (Op); 735 break; 736 737 738 default: 739 740 break; 741 } 742 743 if (AcpiDmBlockType (Op) & BLOCK_BRACE) 744 { 745 AcpiOsPrintf ("\n"); 746 AcpiDmIndent (Level); 747 AcpiOsPrintf ("{\n"); 748 } 749 } 750 751 return (AE_OK); 752} 753 754 755/******************************************************************************* 756 * 757 * FUNCTION: AcpiDmAscendingOp 758 * 759 * PARAMETERS: ASL_WALK_CALLBACK 760 * 761 * RETURN: Status 762 * 763 * DESCRIPTION: Second visitation of a parse object, during ascent of parse 764 * tree. Close out any parameter lists and complete the opcode. 765 * 766 ******************************************************************************/ 767 768static ACPI_STATUS 769AcpiDmAscendingOp ( 770 ACPI_PARSE_OBJECT *Op, 771 UINT32 Level, 772 void *Context) 773{ 774 ACPI_OP_WALK_INFO *Info = Context; 775 776 777 if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE) 778 { 779 /* Ignore this op -- it was handled elsewhere */ 780 781 return (AE_OK); 782 } 783 784 if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP)) 785 { 786 /* Indicates the end of the current descriptor block (table) */ 787 788 AcpiOsPrintf ("}\n\n"); 789 return (AE_OK); 790 } 791 792 switch (AcpiDmBlockType (Op)) 793 { 794 case BLOCK_PAREN: 795 796 /* Completed an op that has arguments, add closing paren */ 797 798 AcpiOsPrintf (")"); 799 800 /* Could be a nested operator, check if comma required */ 801 802 if (!AcpiDmCommaIfListMember (Op)) 803 { 804 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 805 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 806 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 807 { 808 /* 809 * This is a first-level element of a term list 810 * start a new line 811 */ 812 if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST)) 813 { 814 AcpiOsPrintf ("\n"); 815 } 816 } 817 } 818 break; 819 820 821 case BLOCK_BRACE: 822 case (BLOCK_BRACE | BLOCK_PAREN): 823 824 /* Completed an op that has a term list, add closing brace */ 825 826 if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST) 827 { 828 AcpiOsPrintf ("}"); 829 } 830 else 831 { 832 AcpiDmIndent (Level); 833 AcpiOsPrintf ("}"); 834 } 835 836 AcpiDmCommaIfListMember (Op); 837 838 if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN) 839 { 840 AcpiOsPrintf ("\n"); 841 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)) 842 { 843 if ((Op->Common.AmlOpcode == AML_IF_OP) && 844 (Op->Common.Next) && 845 (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP)) 846 { 847 break; 848 } 849 850 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 851 (!Op->Common.Next)) 852 { 853 break; 854 } 855 AcpiOsPrintf ("\n"); 856 } 857 } 858 break; 859 860 861 case BLOCK_NONE: 862 default: 863 864 /* Could be a nested operator, check if comma required */ 865 866 if (!AcpiDmCommaIfListMember (Op)) 867 { 868 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) && 869 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) && 870 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP)) 871 { 872 /* 873 * This is a first-level element of a term list 874 * start a new line 875 */ 876 AcpiOsPrintf ("\n"); 877 } 878 } 879 else if (Op->Common.Parent) 880 { 881 switch (Op->Common.Parent->Common.AmlOpcode) 882 { 883 case AML_PACKAGE_OP: 884 case AML_VAR_PACKAGE_OP: 885 886 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) 887 { 888 AcpiOsPrintf ("\n"); 889 } 890 break; 891 892 default: 893 894 break; 895 } 896 } 897 break; 898 } 899 900 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST) 901 { 902 if ((Op->Common.Next) && 903 (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) 904 { 905 return (AE_OK); 906 } 907 908 /* 909 * Just completed a parameter node for something like "Buffer (param)". 910 * Close the paren and open up the term list block with a brace 911 */ 912 if (Op->Common.Next) 913 { 914 AcpiOsPrintf (")\n"); 915 AcpiDmIndent (Level - 1); 916 AcpiOsPrintf ("{\n"); 917 } 918 else 919 { 920 Op->Common.Parent->Common.DisasmFlags |= 921 ACPI_PARSEOP_EMPTY_TERMLIST; 922 AcpiOsPrintf (") {"); 923 } 924 } 925 926 if ((Op->Common.AmlOpcode == AML_NAME_OP) || 927 (Op->Common.AmlOpcode == AML_RETURN_OP)) 928 { 929 Info->Level++; 930 } 931 return (AE_OK); 932} 933 934 935#endif /* ACPI_DISASSEMBLER */ 936