Home | History | Annotate | Line # | Download | only in disassembler
dmwalk.c revision 1.2
      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 
    416 
    417     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
    418     {
    419         /* Ignore this op -- it was handled elsewhere */
    420 
    421         return (AE_CTRL_DEPTH);
    422     }
    423 
    424     /* Level 0 is at the Definition Block level */
    425 
    426     if (Level == 0)
    427     {
    428         /* In verbose mode, print the AML offset, opcode and depth count */
    429 
    430         if (Info->WalkState)
    431         {
    432             VERBOSE_PRINT ((DB_FULL_OP_INFO,
    433                 (Info->WalkState->MethodNode ?
    434                     Info->WalkState->MethodNode->Name.Ascii : "   "),
    435                 Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode));
    436         }
    437 
    438         if (Op->Common.AmlOpcode == AML_SCOPE_OP)
    439         {
    440             /* This is the beginning of the Definition Block */
    441 
    442             AcpiOsPrintf ("{\n");
    443 
    444             /* Emit all External() declarations here */
    445 
    446             AcpiDmEmitExternals ();
    447             return (AE_OK);
    448         }
    449     }
    450     else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    451              (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
    452              (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    453     {
    454             /*
    455              * This is a first-level element of a term list,
    456              * indent a new line
    457              */
    458             switch (Op->Common.AmlOpcode)
    459             {
    460             case AML_NOOP_OP:
    461                 /*
    462                  * Optionally just ignore this opcode. Some tables use
    463                  * NoOp opcodes for "padding" out packages that the BIOS
    464                  * changes dynamically. This can leave hundreds or
    465                  * thousands of NoOp opcodes that if disassembled,
    466                  * cannot be compiled because they are syntactically
    467                  * incorrect.
    468                  */
    469                 if (AcpiGbl_IgnoreNoopOperator)
    470                 {
    471                     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    472                     return (AE_OK);
    473                 }
    474 
    475                 /* Fallthrough */
    476 
    477             default:
    478 
    479                 AcpiDmIndent (Level);
    480                 break;
    481             }
    482 
    483             Info->LastLevel = Level;
    484             Info->Count = 0;
    485     }
    486 
    487     /*
    488      * This is an inexpensive mechanism to try and keep lines from getting
    489      * too long. When the limit is hit, start a new line at the previous
    490      * indent plus one. A better but more expensive mechanism would be to
    491      * keep track of the current column.
    492      */
    493     Info->Count++;
    494     if (Info->Count /* +Info->LastLevel */ > 12)
    495     {
    496         Info->Count = 0;
    497         AcpiOsPrintf ("\n");
    498         AcpiDmIndent (Info->LastLevel + 1);
    499     }
    500 
    501     /* If ASL+ is enabled, check for a C-style operator */
    502 
    503     if (AcpiDmCheckForSymbolicOpcode (Op, Info))
    504     {
    505         return (AE_OK);
    506     }
    507 
    508     /* Print the opcode name */
    509 
    510     AcpiDmDisassembleOneOp (NULL, Info, Op);
    511 
    512     if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
    513         (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
    514     {
    515         return (AE_OK);
    516     }
    517 
    518     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
    519         (Op->Common.AmlOpcode == AML_RETURN_OP))
    520     {
    521         Info->Level--;
    522     }
    523 
    524     /* Start the opcode argument list if necessary */
    525 
    526     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    527 
    528     if ((OpInfo->Flags & AML_HAS_ARGS) ||
    529         (Op->Common.AmlOpcode == AML_EVENT_OP))
    530     {
    531         /* This opcode has an argument list */
    532 
    533         if (AcpiDmBlockType (Op) & BLOCK_PAREN)
    534         {
    535             AcpiOsPrintf (" (");
    536         }
    537 
    538         /* If this is a named opcode, print the associated name value */
    539 
    540         if (OpInfo->Flags & AML_NAMED)
    541         {
    542             switch (Op->Common.AmlOpcode)
    543             {
    544             case AML_ALIAS_OP:
    545 
    546                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    547                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    548                 AcpiDmNamestring (NextOp->Common.Value.Name);
    549                 AcpiOsPrintf (", ");
    550 
    551                 /*lint -fallthrough */
    552 
    553             default:
    554 
    555                 Name = AcpiPsGetName (Op);
    556                 if (Op->Named.Path)
    557                 {
    558                     AcpiDmNamestring ((char *) Op->Named.Path);
    559                 }
    560                 else
    561                 {
    562                     AcpiDmDumpName (Name);
    563                 }
    564 
    565                 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
    566                 {
    567                     if (AcpiGbl_DbOpt_Verbose)
    568                     {
    569                         (void) AcpiPsDisplayObjectPathname (NULL, Op);
    570                     }
    571                 }
    572                 break;
    573             }
    574 
    575             switch (Op->Common.AmlOpcode)
    576             {
    577             case AML_METHOD_OP:
    578 
    579                 AcpiDmMethodFlags (Op);
    580                 AcpiOsPrintf (")");
    581 
    582                 /* Emit description comment for Method() with a predefined ACPI name */
    583 
    584                 AcpiDmPredefinedDescription (Op);
    585                 break;
    586 
    587             case AML_NAME_OP:
    588 
    589                 /* Check for _HID and related EISAID() */
    590 
    591                 AcpiDmCheckForHardwareId (Op);
    592                 AcpiOsPrintf (", ");
    593                 break;
    594 
    595             case AML_REGION_OP:
    596 
    597                 AcpiDmRegionFlags (Op);
    598                 break;
    599 
    600             case AML_POWER_RES_OP:
    601 
    602                 /* Mark the next two Ops as part of the parameter list */
    603 
    604                 AcpiOsPrintf (", ");
    605                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    606                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    607 
    608                 NextOp = NextOp->Common.Next;
    609                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    610                 return (AE_OK);
    611 
    612             case AML_PROCESSOR_OP:
    613 
    614                 /* Mark the next three Ops as part of the parameter list */
    615 
    616                 AcpiOsPrintf (", ");
    617                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    618                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    619 
    620                 NextOp = NextOp->Common.Next;
    621                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    622 
    623                 NextOp = NextOp->Common.Next;
    624                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    625                 return (AE_OK);
    626 
    627             case AML_MUTEX_OP:
    628             case AML_DATA_REGION_OP:
    629 
    630                 AcpiOsPrintf (", ");
    631                 return (AE_OK);
    632 
    633             case AML_EVENT_OP:
    634             case AML_ALIAS_OP:
    635 
    636                 return (AE_OK);
    637 
    638             case AML_SCOPE_OP:
    639             case AML_DEVICE_OP:
    640             case AML_THERMAL_ZONE_OP:
    641 
    642                 AcpiOsPrintf (")");
    643                 break;
    644 
    645             default:
    646 
    647                 AcpiOsPrintf ("*** Unhandled named opcode %X\n",
    648                     Op->Common.AmlOpcode);
    649                 break;
    650             }
    651         }
    652 
    653         else switch (Op->Common.AmlOpcode)
    654         {
    655         case AML_FIELD_OP:
    656         case AML_BANK_FIELD_OP:
    657         case AML_INDEX_FIELD_OP:
    658 
    659             Info->BitOffset = 0;
    660 
    661             /* Name of the parent OperationRegion */
    662 
    663             NextOp = AcpiPsGetDepthNext (NULL, Op);
    664             AcpiDmNamestring (NextOp->Common.Value.Name);
    665             AcpiOsPrintf (", ");
    666             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    667 
    668             switch (Op->Common.AmlOpcode)
    669             {
    670             case AML_BANK_FIELD_OP:
    671 
    672                 /* Namestring - Bank Name */
    673 
    674                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
    675                 AcpiDmNamestring (NextOp->Common.Value.Name);
    676                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    677                 AcpiOsPrintf (", ");
    678 
    679                 /*
    680                  * Bank Value. This is a TermArg in the middle of the parameter
    681                  * list, must handle it here.
    682                  *
    683                  * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
    684                  * eliminates newline in the output.
    685                  */
    686                 NextOp = NextOp->Common.Next;
    687 
    688                 Info->Flags = ACPI_PARSEOP_PARAMLIST;
    689                 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
    690                     AcpiDmAscendingOp, Info);
    691                 Info->Flags = 0;
    692                 Info->Level = Level;
    693 
    694                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    695                 AcpiOsPrintf (", ");
    696                 break;
    697 
    698             case AML_INDEX_FIELD_OP:
    699 
    700                 /* Namestring - Data Name */
    701 
    702                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
    703                 AcpiDmNamestring (NextOp->Common.Value.Name);
    704                 AcpiOsPrintf (", ");
    705                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    706                 break;
    707 
    708             default:
    709 
    710                 break;
    711             }
    712 
    713             AcpiDmFieldFlags (NextOp);
    714             break;
    715 
    716         case AML_BUFFER_OP:
    717 
    718             /* The next op is the size parameter */
    719 
    720             NextOp = AcpiPsGetDepthNext (NULL, Op);
    721             if (!NextOp)
    722             {
    723                 /* Single-step support */
    724 
    725                 return (AE_OK);
    726             }
    727 
    728             if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
    729             {
    730                 /*
    731                  * We have a resource list. Don't need to output
    732                  * the buffer size Op. Open up a new block
    733                  */
    734                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    735                 NextOp = NextOp->Common.Next;
    736                 AcpiOsPrintf (")");
    737 
    738                 /* Emit description comment for Name() with a predefined ACPI name */
    739 
    740                 AcpiDmPredefinedDescription (Op->Asl.Parent);
    741 
    742                 AcpiOsPrintf ("\n");
    743                 AcpiDmIndent (Info->Level);
    744                 AcpiOsPrintf ("{\n");
    745                 return (AE_OK);
    746             }
    747 
    748             /* Normal Buffer, mark size as in the parameter list */
    749 
    750             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    751             return (AE_OK);
    752 
    753         case AML_VAR_PACKAGE_OP:
    754         case AML_IF_OP:
    755         case AML_WHILE_OP:
    756 
    757             /* The next op is the size or predicate parameter */
    758 
    759             NextOp = AcpiPsGetDepthNext (NULL, Op);
    760             if (NextOp)
    761             {
    762                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    763             }
    764             return (AE_OK);
    765 
    766         case AML_PACKAGE_OP:
    767 
    768             /* The next op is the size parameter */
    769 
    770             NextOp = AcpiPsGetDepthNext (NULL, Op);
    771             if (NextOp)
    772             {
    773                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    774             }
    775             return (AE_OK);
    776 
    777         case AML_MATCH_OP:
    778 
    779             AcpiDmMatchOp (Op);
    780             break;
    781 
    782         default:
    783 
    784             break;
    785         }
    786 
    787         if (AcpiDmBlockType (Op) & BLOCK_BRACE)
    788         {
    789             AcpiOsPrintf ("\n");
    790             AcpiDmIndent (Level);
    791             AcpiOsPrintf ("{\n");
    792         }
    793     }
    794 
    795     return (AE_OK);
    796 }
    797 
    798 
    799 /*******************************************************************************
    800  *
    801  * FUNCTION:    AcpiDmAscendingOp
    802  *
    803  * PARAMETERS:  ASL_WALK_CALLBACK
    804  *
    805  * RETURN:      Status
    806  *
    807  * DESCRIPTION: Second visitation of a parse object, during ascent of parse
    808  *              tree. Close out any parameter lists and complete the opcode.
    809  *
    810  ******************************************************************************/
    811 
    812 static ACPI_STATUS
    813 AcpiDmAscendingOp (
    814     ACPI_PARSE_OBJECT       *Op,
    815     UINT32                  Level,
    816     void                    *Context)
    817 {
    818     ACPI_OP_WALK_INFO       *Info = Context;
    819     ACPI_PARSE_OBJECT       *ParentOp;
    820 
    821 
    822     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
    823     {
    824         /* Ignore this op -- it was handled elsewhere */
    825 
    826         return (AE_OK);
    827     }
    828 
    829     if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
    830     {
    831         /* Indicates the end of the current descriptor block (table) */
    832 
    833         AcpiOsPrintf ("}\n\n");
    834         return (AE_OK);
    835     }
    836 
    837     switch (AcpiDmBlockType (Op))
    838     {
    839     case BLOCK_PAREN:
    840 
    841         /* Completed an op that has arguments, add closing paren if needed */
    842 
    843         AcpiDmCloseOperator (Op);
    844 
    845         if (Op->Common.AmlOpcode == AML_NAME_OP)
    846         {
    847             /* Emit description comment for Name() with a predefined ACPI name */
    848 
    849             AcpiDmPredefinedDescription (Op);
    850         }
    851         else
    852         {
    853             /* For Create* operators, attempt to emit resource tag description */
    854 
    855             AcpiDmFieldPredefinedDescription (Op);
    856         }
    857 
    858         /* Decode Notify() values */
    859 
    860         if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
    861         {
    862             AcpiDmNotifyDescription (Op);
    863         }
    864 
    865         AcpiDmDisplayTargetPathname (Op);
    866 
    867         /* Could be a nested operator, check if comma required */
    868 
    869         if (!AcpiDmCommaIfListMember (Op))
    870         {
    871             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    872                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
    873                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    874             {
    875                 /*
    876                  * This is a first-level element of a term list
    877                  * start a new line
    878                  */
    879                 if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST))
    880                 {
    881                     AcpiOsPrintf ("\n");
    882                 }
    883             }
    884         }
    885         break;
    886 
    887     case BLOCK_BRACE:
    888     case (BLOCK_BRACE | BLOCK_PAREN):
    889 
    890         /* Completed an op that has a term list, add closing brace */
    891 
    892         if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
    893         {
    894             AcpiOsPrintf ("}");
    895         }
    896         else
    897         {
    898             AcpiDmIndent (Level);
    899             AcpiOsPrintf ("}");
    900         }
    901 
    902         AcpiDmCommaIfListMember (Op);
    903 
    904         if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
    905         {
    906             AcpiOsPrintf ("\n");
    907             if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
    908             {
    909                 if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
    910                     (Op->Common.Next) &&
    911                     (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
    912                 {
    913                     break;
    914                 }
    915 
    916                 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    917                     (!Op->Common.Next))
    918                 {
    919                     break;
    920                 }
    921                 AcpiOsPrintf ("\n");
    922             }
    923         }
    924         break;
    925 
    926     case BLOCK_NONE:
    927     default:
    928 
    929         /* Could be a nested operator, check if comma required */
    930 
    931         if (!AcpiDmCommaIfListMember (Op))
    932         {
    933             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    934                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
    935                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    936             {
    937                 /*
    938                  * This is a first-level element of a term list
    939                  * start a new line
    940                  */
    941                 AcpiOsPrintf ("\n");
    942             }
    943         }
    944         else if (Op->Common.Parent)
    945         {
    946             switch (Op->Common.Parent->Common.AmlOpcode)
    947             {
    948             case AML_PACKAGE_OP:
    949             case AML_VAR_PACKAGE_OP:
    950 
    951                 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
    952                 {
    953                     AcpiOsPrintf ("\n");
    954                 }
    955                 break;
    956 
    957             default:
    958 
    959                 break;
    960             }
    961         }
    962         break;
    963     }
    964 
    965     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
    966     {
    967         if ((Op->Common.Next) &&
    968             (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
    969         {
    970             return (AE_OK);
    971         }
    972 
    973         /*
    974          * The parent Op is guaranteed to be valid because of the flag
    975          * ACPI_PARSEOP_PARAMLIST -- which means that this op is part of
    976          * a parameter list and thus has a valid parent.
    977          */
    978         ParentOp = Op->Common.Parent;
    979 
    980         /*
    981          * Just completed a parameter node for something like "Buffer (param)".
    982          * Close the paren and open up the term list block with a brace
    983          */
    984         if (Op->Common.Next)
    985         {
    986             AcpiOsPrintf (")");
    987 
    988             /*
    989              * Emit a description comment for a Name() operator that is a
    990              * predefined ACPI name. Must check the grandparent.
    991              */
    992             ParentOp = ParentOp->Common.Parent;
    993             if (ParentOp &&
    994                 (ParentOp->Asl.AmlOpcode == AML_NAME_OP))
    995             {
    996                 AcpiDmPredefinedDescription (ParentOp);
    997             }
    998 
    999             AcpiOsPrintf ("\n");
   1000             AcpiDmIndent (Level - 1);
   1001             AcpiOsPrintf ("{\n");
   1002         }
   1003         else
   1004         {
   1005             ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
   1006             AcpiOsPrintf (") {");
   1007         }
   1008     }
   1009 
   1010     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
   1011         (Op->Common.AmlOpcode == AML_RETURN_OP))
   1012     {
   1013         Info->Level++;
   1014     }
   1015 
   1016     /*
   1017      * For ASL+, check for and emit a C-style symbol. If valid, the
   1018      * symbol string has been deferred until after the first operand
   1019      */
   1020     if (AcpiGbl_CstyleDisassembly)
   1021     {
   1022         if (Op->Asl.OperatorSymbol)
   1023         {
   1024             AcpiOsPrintf ("%s", Op->Asl.OperatorSymbol);
   1025             Op->Asl.OperatorSymbol = NULL;
   1026         }
   1027     }
   1028 
   1029     return (AE_OK);
   1030 }
   1031 
   1032 #endif  /* ACPI_DISASSEMBLER */
   1033