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