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