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