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