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