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