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