Home | History | Annotate | Line # | Download | only in disassembler
dmwalk.c revision 1.1.1.2.8.2
      1 /*******************************************************************************
      2  *
      3  * Module Name: dmwalk - AML disassembly tree walk
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2011, 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         {
    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 
    329 UINT32
    330 AcpiDmListType (
    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 
    391 static ACPI_STATUS
    392 AcpiDmDescendingOp (
    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     {
    469         return (AE_OK);
    470     }
    471 
    472     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
    473         (Op->Common.AmlOpcode == AML_RETURN_OP))
    474     {
    475         Info->Level--;
    476     }
    477 
    478     /* Start the opcode argument list if necessary */
    479 
    480     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    481 
    482     if ((OpInfo->Flags & AML_HAS_ARGS) ||
    483         (Op->Common.AmlOpcode == AML_EVENT_OP))
    484     {
    485         /* This opcode has an argument list */
    486 
    487         if (AcpiDmBlockType (Op) & BLOCK_PAREN)
    488         {
    489             AcpiOsPrintf (" (");
    490         }
    491 
    492         /* If this is a named opcode, print the associated name value */
    493 
    494         if (OpInfo->Flags & AML_NAMED)
    495         {
    496             switch (Op->Common.AmlOpcode)
    497             {
    498             case AML_ALIAS_OP:
    499 
    500                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    501                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    502                 AcpiDmNamestring (NextOp->Common.Value.Name);
    503                 AcpiOsPrintf (", ");
    504 
    505                 /*lint -fallthrough */
    506 
    507             default:
    508 
    509                 Name = AcpiPsGetName (Op);
    510                 if (Op->Named.Path)
    511                 {
    512                     AcpiDmNamestring ((char *) Op->Named.Path);
    513                 }
    514                 else
    515                 {
    516                     AcpiDmDumpName (Name);
    517                 }
    518 
    519                 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
    520                 {
    521                     if (AcpiGbl_DbOpt_verbose)
    522                     {
    523                         (void) AcpiPsDisplayObjectPathname (NULL, Op);
    524                     }
    525                 }
    526                 break;
    527             }
    528 
    529             switch (Op->Common.AmlOpcode)
    530             {
    531             case AML_METHOD_OP:
    532 
    533                 AcpiDmMethodFlags (Op);
    534                 AcpiOsPrintf (")");
    535                 break;
    536 
    537 
    538             case AML_NAME_OP:
    539 
    540                 /* Check for _HID and related EISAID() */
    541 
    542                 AcpiDmIsEisaId (Op);
    543                 AcpiOsPrintf (", ");
    544                 break;
    545 
    546 
    547             case AML_REGION_OP:
    548 
    549                 AcpiDmRegionFlags (Op);
    550                 break;
    551 
    552 
    553             case AML_POWER_RES_OP:
    554 
    555                 /* Mark the next two Ops as part of the parameter list */
    556 
    557                 AcpiOsPrintf (", ");
    558                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    559                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    560 
    561                 NextOp = NextOp->Common.Next;
    562                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    563                 return (AE_OK);
    564 
    565 
    566             case AML_PROCESSOR_OP:
    567 
    568                 /* Mark the next three Ops as part of the parameter list */
    569 
    570                 AcpiOsPrintf (", ");
    571                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    572                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    573 
    574                 NextOp = NextOp->Common.Next;
    575                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    576 
    577                 NextOp = NextOp->Common.Next;
    578                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    579                 return (AE_OK);
    580 
    581 
    582             case AML_MUTEX_OP:
    583             case AML_DATA_REGION_OP:
    584 
    585                 AcpiOsPrintf (", ");
    586                 return (AE_OK);
    587 
    588 
    589             case AML_EVENT_OP:
    590             case AML_ALIAS_OP:
    591 
    592                 return (AE_OK);
    593 
    594 
    595             case AML_SCOPE_OP:
    596             case AML_DEVICE_OP:
    597             case AML_THERMAL_ZONE_OP:
    598 
    599                 AcpiOsPrintf (")");
    600                 break;
    601 
    602 
    603             default:
    604 
    605                 AcpiOsPrintf ("*** Unhandled named opcode %X\n", Op->Common.AmlOpcode);
    606                 break;
    607             }
    608         }
    609 
    610         else switch (Op->Common.AmlOpcode)
    611         {
    612         case AML_FIELD_OP:
    613         case AML_BANK_FIELD_OP:
    614         case AML_INDEX_FIELD_OP:
    615 
    616             Info->BitOffset = 0;
    617 
    618             /* Name of the parent OperationRegion */
    619 
    620             NextOp = AcpiPsGetDepthNext (NULL, Op);
    621             AcpiDmNamestring (NextOp->Common.Value.Name);
    622             AcpiOsPrintf (", ");
    623             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    624 
    625             switch (Op->Common.AmlOpcode)
    626             {
    627             case AML_BANK_FIELD_OP:
    628 
    629                 /* Namestring - Bank Name */
    630 
    631                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
    632                 AcpiDmNamestring (NextOp->Common.Value.Name);
    633                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    634                 AcpiOsPrintf (", ");
    635 
    636                 /*
    637                  * Bank Value. This is a TermArg in the middle of the parameter
    638                  * list, must handle it here.
    639                  *
    640                  * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
    641                  * eliminates newline in the output.
    642                  */
    643                 NextOp = NextOp->Common.Next;
    644 
    645                 Info->Flags = ACPI_PARSEOP_PARAMLIST;
    646                 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp, AcpiDmAscendingOp, Info);
    647                 Info->Flags = 0;
    648                 Info->Level = Level;
    649 
    650                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    651                 AcpiOsPrintf (", ");
    652                 break;
    653 
    654             case AML_INDEX_FIELD_OP:
    655 
    656                 /* Namestring - Data Name */
    657 
    658                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
    659                 AcpiDmNamestring (NextOp->Common.Value.Name);
    660                 AcpiOsPrintf (", ");
    661                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    662                 break;
    663 
    664             default:
    665 
    666                 break;
    667             }
    668 
    669             AcpiDmFieldFlags (NextOp);
    670             break;
    671 
    672 
    673         case AML_BUFFER_OP:
    674 
    675             /* The next op is the size parameter */
    676 
    677             NextOp = AcpiPsGetDepthNext (NULL, Op);
    678             if (!NextOp)
    679             {
    680                 /* Single-step support */
    681 
    682                 return (AE_OK);
    683             }
    684 
    685             if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
    686             {
    687                 /*
    688                  * We have a resource list.  Don't need to output
    689                  * the buffer size Op.  Open up a new block
    690                  */
    691                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    692                 NextOp = NextOp->Common.Next;
    693                 AcpiOsPrintf (")\n");
    694                 AcpiDmIndent (Info->Level);
    695                 AcpiOsPrintf ("{\n");
    696                 return (AE_OK);
    697             }
    698 
    699             /* Normal Buffer, mark size as in the parameter list */
    700 
    701             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    702             return (AE_OK);
    703 
    704 
    705         case AML_VAR_PACKAGE_OP:
    706         case AML_IF_OP:
    707         case AML_WHILE_OP:
    708 
    709             /* The next op is the size or predicate parameter */
    710 
    711             NextOp = AcpiPsGetDepthNext (NULL, Op);
    712             if (NextOp)
    713             {
    714                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    715             }
    716             return (AE_OK);
    717 
    718 
    719         case AML_PACKAGE_OP:
    720 
    721             /* The next op is the size or predicate parameter */
    722 
    723             NextOp = AcpiPsGetDepthNext (NULL, Op);
    724             if (NextOp)
    725             {
    726                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    727             }
    728             return (AE_OK);
    729 
    730 
    731         case AML_MATCH_OP:
    732 
    733             AcpiDmMatchOp (Op);
    734             break;
    735 
    736 
    737         default:
    738 
    739             break;
    740         }
    741 
    742         if (AcpiDmBlockType (Op) & BLOCK_BRACE)
    743         {
    744             AcpiOsPrintf ("\n");
    745             AcpiDmIndent (Level);
    746             AcpiOsPrintf ("{\n");
    747         }
    748     }
    749 
    750     return (AE_OK);
    751 }
    752 
    753 
    754 /*******************************************************************************
    755  *
    756  * FUNCTION:    AcpiDmAscendingOp
    757  *
    758  * PARAMETERS:  ASL_WALK_CALLBACK
    759  *
    760  * RETURN:      Status
    761  *
    762  * DESCRIPTION: Second visitation of a parse object, during ascent of parse
    763  *              tree.  Close out any parameter lists and complete the opcode.
    764  *
    765  ******************************************************************************/
    766 
    767 static ACPI_STATUS
    768 AcpiDmAscendingOp (
    769     ACPI_PARSE_OBJECT       *Op,
    770     UINT32                  Level,
    771     void                    *Context)
    772 {
    773     ACPI_OP_WALK_INFO       *Info = Context;
    774 
    775 
    776     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
    777     {
    778         /* Ignore this op -- it was handled elsewhere */
    779 
    780         return (AE_OK);
    781     }
    782 
    783     if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
    784     {
    785         /* Indicates the end of the current descriptor block (table) */
    786 
    787         AcpiOsPrintf ("}\n\n");
    788         return (AE_OK);
    789     }
    790 
    791     switch (AcpiDmBlockType (Op))
    792     {
    793     case BLOCK_PAREN:
    794 
    795         /* Completed an op that has arguments, add closing paren */
    796 
    797         AcpiOsPrintf (")");
    798 
    799         /* Could be a nested operator, check if comma required */
    800 
    801         if (!AcpiDmCommaIfListMember (Op))
    802         {
    803             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    804                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
    805                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    806             {
    807                 /*
    808                  * This is a first-level element of a term list
    809                  * start a new line
    810                  */
    811                 if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST))
    812                 {
    813                     AcpiOsPrintf ("\n");
    814                 }
    815             }
    816         }
    817         break;
    818 
    819 
    820     case BLOCK_BRACE:
    821     case (BLOCK_BRACE | BLOCK_PAREN):
    822 
    823         /* Completed an op that has a term list, add closing brace */
    824 
    825         if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
    826         {
    827             AcpiOsPrintf ("}");
    828         }
    829         else
    830         {
    831             AcpiDmIndent (Level);
    832             AcpiOsPrintf ("}");
    833         }
    834 
    835         AcpiDmCommaIfListMember (Op);
    836 
    837         if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
    838         {
    839             AcpiOsPrintf ("\n");
    840             if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
    841             {
    842                 if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
    843                     (Op->Common.Next) &&
    844                     (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
    845                 {
    846                     break;
    847                 }
    848 
    849                 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    850                     (!Op->Common.Next))
    851                 {
    852                     break;
    853                 }
    854                 AcpiOsPrintf ("\n");
    855             }
    856         }
    857         break;
    858 
    859 
    860     case BLOCK_NONE:
    861     default:
    862 
    863         /* Could be a nested operator, check if comma required */
    864 
    865         if (!AcpiDmCommaIfListMember (Op))
    866         {
    867             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    868                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
    869                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    870             {
    871                 /*
    872                  * This is a first-level element of a term list
    873                  * start a new line
    874                  */
    875                 AcpiOsPrintf ("\n");
    876             }
    877         }
    878         else if (Op->Common.Parent)
    879         {
    880             switch (Op->Common.Parent->Common.AmlOpcode)
    881             {
    882             case AML_PACKAGE_OP:
    883             case AML_VAR_PACKAGE_OP:
    884 
    885                 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
    886                 {
    887                     AcpiOsPrintf ("\n");
    888                 }
    889                 break;
    890 
    891             default:
    892 
    893                 break;
    894             }
    895         }
    896         break;
    897     }
    898 
    899     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
    900     {
    901         if ((Op->Common.Next) &&
    902             (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
    903         {
    904             return (AE_OK);
    905         }
    906 
    907         /*
    908          * Just completed a parameter node for something like "Buffer (param)".
    909          * Close the paren and open up the term list block with a brace
    910          */
    911         if (Op->Common.Next)
    912         {
    913             AcpiOsPrintf (")\n");
    914             AcpiDmIndent (Level - 1);
    915             AcpiOsPrintf ("{\n");
    916         }
    917         else
    918         {
    919             Op->Common.Parent->Common.DisasmFlags |=
    920                                     ACPI_PARSEOP_EMPTY_TERMLIST;
    921             AcpiOsPrintf (") {");
    922         }
    923     }
    924 
    925     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
    926         (Op->Common.AmlOpcode == AML_RETURN_OP))
    927     {
    928         Info->Level++;
    929     }
    930     return (AE_OK);
    931 }
    932 
    933 
    934 #endif  /* ACPI_DISASSEMBLER */
    935