Home | History | Annotate | Line # | Download | only in disassembler
dmwalk.c revision 1.1.1.4
      1 /*******************************************************************************
      2  *
      3  * Module Name: dmwalk - AML disassembly tree walk
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2014, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #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         {
    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             switch (Op->Common.AmlOpcode)
    445             {
    446             case AML_NOOP_OP:
    447                 /*
    448                  * Optionally just ignore this opcode. Some tables use
    449                  * NoOp opcodes for "padding" out packages that the BIOS
    450                  * changes dynamically. This can leave hundreds or
    451                  * thousands of NoOp opcodes that if disassembled,
    452                  * cannot be compiled because they are syntactically
    453                  * incorrect.
    454                  */
    455                 if (AcpiGbl_IgnoreNoopOperator)
    456                 {
    457                     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    458                     return (AE_OK);
    459                 }
    460 
    461                 /* Fallthrough */
    462 
    463             default:
    464 
    465                 AcpiDmIndent (Level);
    466                 break;
    467             }
    468 
    469             Info->LastLevel = Level;
    470             Info->Count = 0;
    471     }
    472 
    473     /*
    474      * This is an inexpensive mechanism to try and keep lines from getting
    475      * too long. When the limit is hit, start a new line at the previous
    476      * indent plus one. A better but more expensive mechanism would be to
    477      * keep track of the current column.
    478      */
    479     Info->Count++;
    480     if (Info->Count /* +Info->LastLevel */ > 10)
    481     {
    482         Info->Count = 0;
    483         AcpiOsPrintf ("\n");
    484         AcpiDmIndent (Info->LastLevel + 1);
    485     }
    486 
    487     /* Print the opcode name */
    488 
    489     AcpiDmDisassembleOneOp (NULL, Info, Op);
    490 
    491     if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
    492         (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
    493     {
    494         return (AE_OK);
    495     }
    496 
    497     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
    498         (Op->Common.AmlOpcode == AML_RETURN_OP))
    499     {
    500         Info->Level--;
    501     }
    502 
    503     /* Start the opcode argument list if necessary */
    504 
    505     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    506 
    507     if ((OpInfo->Flags & AML_HAS_ARGS) ||
    508         (Op->Common.AmlOpcode == AML_EVENT_OP))
    509     {
    510         /* This opcode has an argument list */
    511 
    512         if (AcpiDmBlockType (Op) & BLOCK_PAREN)
    513         {
    514             AcpiOsPrintf (" (");
    515         }
    516 
    517         /* If this is a named opcode, print the associated name value */
    518 
    519         if (OpInfo->Flags & AML_NAMED)
    520         {
    521             switch (Op->Common.AmlOpcode)
    522             {
    523             case AML_ALIAS_OP:
    524 
    525                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    526                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    527                 AcpiDmNamestring (NextOp->Common.Value.Name);
    528                 AcpiOsPrintf (", ");
    529 
    530                 /*lint -fallthrough */
    531 
    532             default:
    533 
    534                 Name = AcpiPsGetName (Op);
    535                 if (Op->Named.Path)
    536                 {
    537                     AcpiDmNamestring ((char *) Op->Named.Path);
    538                 }
    539                 else
    540                 {
    541                     AcpiDmDumpName (Name);
    542                 }
    543 
    544                 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
    545                 {
    546                     if (AcpiGbl_DbOpt_verbose)
    547                     {
    548                         (void) AcpiPsDisplayObjectPathname (NULL, Op);
    549                     }
    550                 }
    551                 break;
    552             }
    553 
    554             switch (Op->Common.AmlOpcode)
    555             {
    556             case AML_METHOD_OP:
    557 
    558                 AcpiDmMethodFlags (Op);
    559                 AcpiOsPrintf (")");
    560 
    561                 /* Emit description comment for Method() with a predefined ACPI name */
    562 
    563                 AcpiDmPredefinedDescription (Op);
    564                 break;
    565 
    566 
    567             case AML_NAME_OP:
    568 
    569                 /* Check for _HID and related EISAID() */
    570 
    571                 AcpiDmCheckForHardwareId (Op);
    572                 AcpiOsPrintf (", ");
    573                 break;
    574 
    575 
    576             case AML_REGION_OP:
    577 
    578                 AcpiDmRegionFlags (Op);
    579                 break;
    580 
    581 
    582             case AML_POWER_RES_OP:
    583 
    584                 /* Mark the next two Ops as part of the parameter list */
    585 
    586                 AcpiOsPrintf (", ");
    587                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    588                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    589 
    590                 NextOp = NextOp->Common.Next;
    591                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    592                 return (AE_OK);
    593 
    594 
    595             case AML_PROCESSOR_OP:
    596 
    597                 /* Mark the next three Ops as part of the parameter list */
    598 
    599                 AcpiOsPrintf (", ");
    600                 NextOp = AcpiPsGetDepthNext (NULL, Op);
    601                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    602 
    603                 NextOp = NextOp->Common.Next;
    604                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    605 
    606                 NextOp = NextOp->Common.Next;
    607                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    608                 return (AE_OK);
    609 
    610 
    611             case AML_MUTEX_OP:
    612             case AML_DATA_REGION_OP:
    613 
    614                 AcpiOsPrintf (", ");
    615                 return (AE_OK);
    616 
    617 
    618             case AML_EVENT_OP:
    619             case AML_ALIAS_OP:
    620 
    621                 return (AE_OK);
    622 
    623 
    624             case AML_SCOPE_OP:
    625             case AML_DEVICE_OP:
    626             case AML_THERMAL_ZONE_OP:
    627 
    628                 AcpiOsPrintf (")");
    629                 break;
    630 
    631 
    632             default:
    633 
    634                 AcpiOsPrintf ("*** Unhandled named opcode %X\n",
    635                     Op->Common.AmlOpcode);
    636                 break;
    637             }
    638         }
    639 
    640         else switch (Op->Common.AmlOpcode)
    641         {
    642         case AML_FIELD_OP:
    643         case AML_BANK_FIELD_OP:
    644         case AML_INDEX_FIELD_OP:
    645 
    646             Info->BitOffset = 0;
    647 
    648             /* Name of the parent OperationRegion */
    649 
    650             NextOp = AcpiPsGetDepthNext (NULL, Op);
    651             AcpiDmNamestring (NextOp->Common.Value.Name);
    652             AcpiOsPrintf (", ");
    653             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    654 
    655             switch (Op->Common.AmlOpcode)
    656             {
    657             case AML_BANK_FIELD_OP:
    658 
    659                 /* Namestring - Bank Name */
    660 
    661                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
    662                 AcpiDmNamestring (NextOp->Common.Value.Name);
    663                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    664                 AcpiOsPrintf (", ");
    665 
    666                 /*
    667                  * Bank Value. This is a TermArg in the middle of the parameter
    668                  * list, must handle it here.
    669                  *
    670                  * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
    671                  * eliminates newline in the output.
    672                  */
    673                 NextOp = NextOp->Common.Next;
    674 
    675                 Info->Flags = ACPI_PARSEOP_PARAMLIST;
    676                 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
    677                     AcpiDmAscendingOp, Info);
    678                 Info->Flags = 0;
    679                 Info->Level = Level;
    680 
    681                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    682                 AcpiOsPrintf (", ");
    683                 break;
    684 
    685             case AML_INDEX_FIELD_OP:
    686 
    687                 /* Namestring - Data Name */
    688 
    689                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
    690                 AcpiDmNamestring (NextOp->Common.Value.Name);
    691                 AcpiOsPrintf (", ");
    692                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    693                 break;
    694 
    695             default:
    696 
    697                 break;
    698             }
    699 
    700             AcpiDmFieldFlags (NextOp);
    701             break;
    702 
    703         case AML_BUFFER_OP:
    704 
    705             /* The next op is the size parameter */
    706 
    707             NextOp = AcpiPsGetDepthNext (NULL, Op);
    708             if (!NextOp)
    709             {
    710                 /* Single-step support */
    711 
    712                 return (AE_OK);
    713             }
    714 
    715             if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
    716             {
    717                 /*
    718                  * We have a resource list. Don't need to output
    719                  * the buffer size Op. Open up a new block
    720                  */
    721                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    722                 NextOp = NextOp->Common.Next;
    723                 AcpiOsPrintf (")");
    724 
    725                 /* Emit description comment for Name() with a predefined ACPI name */
    726 
    727                 AcpiDmPredefinedDescription (Op->Asl.Parent);
    728 
    729                 AcpiOsPrintf ("\n");
    730                 AcpiDmIndent (Info->Level);
    731                 AcpiOsPrintf ("{\n");
    732                 return (AE_OK);
    733             }
    734 
    735             /* Normal Buffer, mark size as in the parameter list */
    736 
    737             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    738             return (AE_OK);
    739 
    740         case AML_VAR_PACKAGE_OP:
    741         case AML_IF_OP:
    742         case AML_WHILE_OP:
    743 
    744             /* The next op is the size or predicate parameter */
    745 
    746             NextOp = AcpiPsGetDepthNext (NULL, Op);
    747             if (NextOp)
    748             {
    749                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    750             }
    751             return (AE_OK);
    752 
    753         case AML_PACKAGE_OP:
    754 
    755             /* The next op is the size parameter */
    756 
    757             NextOp = AcpiPsGetDepthNext (NULL, Op);
    758             if (NextOp)
    759             {
    760                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
    761             }
    762             return (AE_OK);
    763 
    764         case AML_MATCH_OP:
    765 
    766             AcpiDmMatchOp (Op);
    767             break;
    768 
    769         default:
    770 
    771             break;
    772         }
    773 
    774         if (AcpiDmBlockType (Op) & BLOCK_BRACE)
    775         {
    776             AcpiOsPrintf ("\n");
    777             AcpiDmIndent (Level);
    778             AcpiOsPrintf ("{\n");
    779         }
    780     }
    781 
    782     return (AE_OK);
    783 }
    784 
    785 
    786 /*******************************************************************************
    787  *
    788  * FUNCTION:    AcpiDmAscendingOp
    789  *
    790  * PARAMETERS:  ASL_WALK_CALLBACK
    791  *
    792  * RETURN:      Status
    793  *
    794  * DESCRIPTION: Second visitation of a parse object, during ascent of parse
    795  *              tree. Close out any parameter lists and complete the opcode.
    796  *
    797  ******************************************************************************/
    798 
    799 static ACPI_STATUS
    800 AcpiDmAscendingOp (
    801     ACPI_PARSE_OBJECT       *Op,
    802     UINT32                  Level,
    803     void                    *Context)
    804 {
    805     ACPI_OP_WALK_INFO       *Info = Context;
    806     ACPI_PARSE_OBJECT       *ParentOp;
    807 
    808 
    809     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
    810     {
    811         /* Ignore this op -- it was handled elsewhere */
    812 
    813         return (AE_OK);
    814     }
    815 
    816     if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
    817     {
    818         /* Indicates the end of the current descriptor block (table) */
    819 
    820         AcpiOsPrintf ("}\n\n");
    821         return (AE_OK);
    822     }
    823 
    824     switch (AcpiDmBlockType (Op))
    825     {
    826     case BLOCK_PAREN:
    827 
    828         /* Completed an op that has arguments, add closing paren */
    829 
    830         AcpiOsPrintf (")");
    831 
    832         if (Op->Common.AmlOpcode == AML_NAME_OP)
    833         {
    834             /* Emit description comment for Name() with a predefined ACPI name */
    835 
    836             AcpiDmPredefinedDescription (Op);
    837         }
    838         else
    839         {
    840             /* For Create* operators, attempt to emit resource tag description */
    841 
    842             AcpiDmFieldPredefinedDescription (Op);
    843         }
    844 
    845         /* Decode Notify() values */
    846 
    847         if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
    848         {
    849             AcpiDmNotifyDescription (Op);
    850         }
    851 
    852         AcpiDmDisplayTargetPathname (Op);
    853 
    854         /* Could be a nested operator, check if comma required */
    855 
    856         if (!AcpiDmCommaIfListMember (Op))
    857         {
    858             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    859                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
    860                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    861             {
    862                 /*
    863                  * This is a first-level element of a term list
    864                  * start a new line
    865                  */
    866                 if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST))
    867                 {
    868                     AcpiOsPrintf ("\n");
    869                 }
    870             }
    871         }
    872         break;
    873 
    874     case BLOCK_BRACE:
    875     case (BLOCK_BRACE | BLOCK_PAREN):
    876 
    877         /* Completed an op that has a term list, add closing brace */
    878 
    879         if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
    880         {
    881             AcpiOsPrintf ("}");
    882         }
    883         else
    884         {
    885             AcpiDmIndent (Level);
    886             AcpiOsPrintf ("}");
    887         }
    888 
    889         AcpiDmCommaIfListMember (Op);
    890 
    891         if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
    892         {
    893             AcpiOsPrintf ("\n");
    894             if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
    895             {
    896                 if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
    897                     (Op->Common.Next) &&
    898                     (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
    899                 {
    900                     break;
    901                 }
    902 
    903                 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    904                     (!Op->Common.Next))
    905                 {
    906                     break;
    907                 }
    908                 AcpiOsPrintf ("\n");
    909             }
    910         }
    911         break;
    912 
    913     case BLOCK_NONE:
    914     default:
    915 
    916         /* Could be a nested operator, check if comma required */
    917 
    918         if (!AcpiDmCommaIfListMember (Op))
    919         {
    920             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
    921                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
    922                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    923             {
    924                 /*
    925                  * This is a first-level element of a term list
    926                  * start a new line
    927                  */
    928                 AcpiOsPrintf ("\n");
    929             }
    930         }
    931         else if (Op->Common.Parent)
    932         {
    933             switch (Op->Common.Parent->Common.AmlOpcode)
    934             {
    935             case AML_PACKAGE_OP:
    936             case AML_VAR_PACKAGE_OP:
    937 
    938                 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
    939                 {
    940                     AcpiOsPrintf ("\n");
    941                 }
    942                 break;
    943 
    944             default:
    945 
    946                 break;
    947             }
    948         }
    949         break;
    950     }
    951 
    952     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
    953     {
    954         if ((Op->Common.Next) &&
    955             (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
    956         {
    957             return (AE_OK);
    958         }
    959 
    960         /*
    961          * The parent Op is guaranteed to be valid because of the flag
    962          * ACPI_PARSEOP_PARAMLIST -- which means that this op is part of
    963          * a parameter list and thus has a valid parent.
    964          */
    965         ParentOp = Op->Common.Parent;
    966 
    967         /*
    968          * Just completed a parameter node for something like "Buffer (param)".
    969          * Close the paren and open up the term list block with a brace
    970          */
    971         if (Op->Common.Next)
    972         {
    973             AcpiOsPrintf (")");
    974 
    975             /*
    976              * Emit a description comment for a Name() operator that is a
    977              * predefined ACPI name. Must check the grandparent.
    978              */
    979             ParentOp = ParentOp->Common.Parent;
    980             if (ParentOp &&
    981                 (ParentOp->Asl.AmlOpcode == AML_NAME_OP))
    982             {
    983                 AcpiDmPredefinedDescription (ParentOp);
    984             }
    985 
    986             AcpiOsPrintf ("\n");
    987             AcpiDmIndent (Level - 1);
    988             AcpiOsPrintf ("{\n");
    989         }
    990         else
    991         {
    992             ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
    993             AcpiOsPrintf (") {");
    994         }
    995     }
    996 
    997     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
    998         (Op->Common.AmlOpcode == AML_RETURN_OP))
    999     {
   1000         Info->Level++;
   1001     }
   1002     return (AE_OK);
   1003 }
   1004 
   1005 
   1006 #endif  /* ACPI_DISASSEMBLER */
   1007