Home | History | Annotate | Line # | Download | only in disassembler
      1 /*******************************************************************************
      2  *
      3  * Module Name: dmopcode - AML disassembler, specific AML opcodes
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2026, 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 "acinterp.h"
     49 #include "acnamesp.h"
     50 #include "acdebug.h"
     51 #include "acconvert.h"
     52 
     53 
     54 #define _COMPONENT          ACPI_CA_DEBUGGER
     55         ACPI_MODULE_NAME    ("dmopcode")
     56 
     57 
     58 /* Local prototypes */
     59 
     60 static void
     61 AcpiDmMatchKeyword (
     62     ACPI_PARSE_OBJECT       *Op);
     63 
     64 static void
     65 AcpiDmConvertToElseIf (
     66     ACPI_PARSE_OBJECT       *Op);
     67 
     68 static void
     69 AcpiDmPromoteSubtree (
     70     ACPI_PARSE_OBJECT       *StartOp);
     71 
     72 /*******************************************************************************
     73  *
     74  * FUNCTION:    AcpiDmDisplayTargetPathname
     75  *
     76  * PARAMETERS:  Op              - Parse object
     77  *
     78  * RETURN:      None
     79  *
     80  * DESCRIPTION: For AML opcodes that have a target operand, display the full
     81  *              pathname for the target, in a comment field. Handles Return()
     82  *              statements also.
     83  *
     84  ******************************************************************************/
     85 
     86 void
     87 AcpiDmDisplayTargetPathname (
     88     ACPI_PARSE_OBJECT       *Op)
     89 {
     90     ACPI_PARSE_OBJECT       *NextOp;
     91     ACPI_PARSE_OBJECT       *PrevOp = NULL;
     92     char                    *Pathname;
     93     const ACPI_OPCODE_INFO  *OpInfo;
     94 
     95 
     96     if (Op->Common.AmlOpcode == AML_RETURN_OP)
     97     {
     98         PrevOp = Op->Asl.Value.Arg;
     99     }
    100     else
    101     {
    102         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    103         if (!(OpInfo->Flags & AML_HAS_TARGET))
    104         {
    105             return;
    106         }
    107 
    108         /* Target is the last Op in the arg list */
    109 
    110         NextOp = Op->Asl.Value.Arg;
    111         while (NextOp)
    112         {
    113             PrevOp = NextOp;
    114             NextOp = PrevOp->Asl.Next;
    115         }
    116     }
    117 
    118     if (!PrevOp)
    119     {
    120         return;
    121     }
    122 
    123     /* We must have a namepath AML opcode */
    124 
    125     if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
    126     {
    127         return;
    128     }
    129 
    130     /* A null string is the "no target specified" case */
    131 
    132     if (!PrevOp->Asl.Value.String)
    133     {
    134         return;
    135     }
    136 
    137     /* No node means "unresolved external reference" */
    138 
    139     if (!PrevOp->Asl.Node)
    140     {
    141         AcpiOsPrintf (" /* External reference */");
    142         return;
    143     }
    144 
    145     /* Ignore if path is already from the root */
    146 
    147     if (*PrevOp->Asl.Value.String == '\\')
    148     {
    149         return;
    150     }
    151 
    152     /* Now: we can get the full pathname */
    153 
    154     Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
    155     if (!Pathname)
    156     {
    157         return;
    158     }
    159 
    160     AcpiOsPrintf (" /* %s */", Pathname);
    161     ACPI_FREE (Pathname);
    162 }
    163 
    164 
    165 /*******************************************************************************
    166  *
    167  * FUNCTION:    AcpiDmNotifyDescription
    168  *
    169  * PARAMETERS:  Op              - Name() parse object
    170  *
    171  * RETURN:      None
    172  *
    173  * DESCRIPTION: Emit a description comment for the value associated with a
    174  *              Notify() operator.
    175  *
    176  ******************************************************************************/
    177 
    178 void
    179 AcpiDmNotifyDescription (
    180     ACPI_PARSE_OBJECT       *Op)
    181 {
    182     ACPI_PARSE_OBJECT       *NextOp;
    183     ACPI_NAMESPACE_NODE     *Node;
    184     UINT8                   NotifyValue;
    185     UINT8                   Type = ACPI_TYPE_ANY;
    186 
    187 
    188     /* The notify value is the second argument */
    189 
    190     NextOp = Op->Asl.Value.Arg;
    191     NextOp = NextOp->Asl.Next;
    192 
    193     switch (NextOp->Common.AmlOpcode)
    194     {
    195     case AML_ZERO_OP:
    196     case AML_ONE_OP:
    197 
    198         NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
    199         break;
    200 
    201     case AML_BYTE_OP:
    202 
    203         NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
    204         break;
    205 
    206     default:
    207         return;
    208     }
    209 
    210     /*
    211      * Attempt to get the namespace node so we can determine the object type.
    212      * Some notify values are dependent on the object type (Device, Thermal,
    213      * or Processor).
    214      */
    215     Node = Op->Asl.Node;
    216     if (Node)
    217     {
    218         Type = Node->Type;
    219     }
    220 
    221     AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
    222 }
    223 
    224 
    225 /*******************************************************************************
    226  *
    227  * FUNCTION:    AcpiDmPredefinedDescription
    228  *
    229  * PARAMETERS:  Op              - Name() parse object
    230  *
    231  * RETURN:      None
    232  *
    233  * DESCRIPTION: Emit a description comment for a predefined ACPI name.
    234  *              Used for iASL compiler only.
    235  *
    236  ******************************************************************************/
    237 
    238 void
    239 AcpiDmPredefinedDescription (
    240     ACPI_PARSE_OBJECT       *Op)
    241 {
    242 #ifdef ACPI_ASL_COMPILER
    243     const AH_PREDEFINED_NAME    *Info;
    244     char                        *NameString;
    245     int                         LastCharIsDigit;
    246     int                         LastCharsAreHex;
    247 
    248 
    249     if (!Op)
    250     {
    251         return;
    252     }
    253 
    254     /* Ensure that the comment field is emitted only once */
    255 
    256     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
    257     {
    258         return;
    259     }
    260     Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
    261 
    262     /* Predefined name must start with an underscore */
    263 
    264     NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
    265     if (NameString[0] != '_')
    266     {
    267         return;
    268     }
    269 
    270     /*
    271      * Check for the special ACPI names:
    272      * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
    273      * (where d=decimal_digit, x=hex_digit, a=anything)
    274      *
    275      * Convert these to the generic name for table lookup.
    276      * Note: NameString is guaranteed to be upper case here.
    277      */
    278     LastCharIsDigit =
    279         (isdigit ((int) NameString[3]));    /* d */
    280     LastCharsAreHex =
    281         (isxdigit ((int) NameString[2]) &&  /* xx */
    282          isxdigit ((int) NameString[3]));
    283 
    284     switch (NameString[1])
    285     {
    286     case 'A':
    287 
    288         if ((NameString[2] == 'C') && (LastCharIsDigit))
    289         {
    290             NameString = "_ACx";
    291         }
    292         else if ((NameString[2] == 'L') && (LastCharIsDigit))
    293         {
    294             NameString = "_ALx";
    295         }
    296         break;
    297 
    298     case 'E':
    299 
    300         if ((NameString[2] == 'J') && (LastCharIsDigit))
    301         {
    302             NameString = "_EJx";
    303         }
    304         else if (LastCharsAreHex)
    305         {
    306             NameString = "_Exx";
    307         }
    308         break;
    309 
    310     case 'L':
    311 
    312         if (LastCharsAreHex)
    313         {
    314             NameString = "_Lxx";
    315         }
    316         break;
    317 
    318     case 'Q':
    319 
    320         if (LastCharsAreHex)
    321         {
    322             NameString = "_Qxx";
    323         }
    324         break;
    325 
    326     case 'T':
    327 
    328         if (NameString[2] == '_')
    329         {
    330             NameString = "_T_x";
    331         }
    332         break;
    333 
    334     case 'W':
    335 
    336         if (LastCharsAreHex)
    337         {
    338             NameString = "_Wxx";
    339         }
    340         break;
    341 
    342     default:
    343 
    344         break;
    345     }
    346 
    347     /* Match the name in the info table */
    348 
    349     Info = AcpiAhMatchPredefinedName (NameString);
    350     if (Info)
    351     {
    352         AcpiOsPrintf ("  // %4.4s: %s",
    353             NameString, ACPI_CAST_PTR (char, Info->Description));
    354     }
    355 
    356 #endif
    357     return;
    358 }
    359 
    360 
    361 /*******************************************************************************
    362  *
    363  * FUNCTION:    AcpiDmFieldPredefinedDescription
    364  *
    365  * PARAMETERS:  Op              - Parse object
    366  *
    367  * RETURN:      None
    368  *
    369  * DESCRIPTION: Emit a description comment for a resource descriptor tag
    370  *              (which is a predefined ACPI name.) Used for iASL compiler only.
    371  *
    372  ******************************************************************************/
    373 
    374 void
    375 AcpiDmFieldPredefinedDescription (
    376     ACPI_PARSE_OBJECT       *Op)
    377 {
    378 #ifdef ACPI_ASL_COMPILER
    379     ACPI_PARSE_OBJECT       *IndexOp;
    380     char                    *Tag;
    381     const ACPI_OPCODE_INFO  *OpInfo;
    382     const AH_PREDEFINED_NAME *Info;
    383 
    384 
    385     if (!Op)
    386     {
    387         return;
    388     }
    389 
    390     /* Ensure that the comment field is emitted only once */
    391 
    392     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
    393     {
    394         return;
    395     }
    396     Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
    397 
    398     /*
    399      * Op must be one of the Create* operators: CreateField, CreateBitField,
    400      * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
    401      */
    402     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    403     if (!(OpInfo->Flags & AML_CREATE))
    404     {
    405         return;
    406     }
    407 
    408     /* Second argument is the Index argument */
    409 
    410     IndexOp = Op->Common.Value.Arg;
    411     IndexOp = IndexOp->Common.Next;
    412 
    413     /* Index argument must be a namepath */
    414 
    415     if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
    416     {
    417         return;
    418     }
    419 
    420     /* Major cheat: We previously put the Tag ptr in the Node field */
    421 
    422     Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
    423     if (!Tag || (*Tag == 0))
    424     {
    425         return;
    426     }
    427 
    428     /* Is the tag a predefined name? */
    429 
    430     Info = AcpiAhMatchPredefinedName (Tag);
    431     if (!Info)
    432     {
    433         /* Not a predefined name (does not start with underscore) */
    434 
    435         return;
    436     }
    437 
    438     AcpiOsPrintf ("  // %4.4s: %s", Tag,
    439         ACPI_CAST_PTR (char, Info->Description));
    440 
    441     /* String contains the prefix path, free it */
    442 
    443     ACPI_FREE (IndexOp->Common.Value.String);
    444     IndexOp->Common.Value.String = NULL;
    445 #endif
    446 
    447     return;
    448 }
    449 
    450 
    451 /*******************************************************************************
    452  *
    453  * FUNCTION:    AcpiDmMethodFlags
    454  *
    455  * PARAMETERS:  Op              - Method Object to be examined
    456  *
    457  * RETURN:      None
    458  *
    459  * DESCRIPTION: Decode control method flags
    460  *
    461  ******************************************************************************/
    462 
    463 void
    464 AcpiDmMethodFlags (
    465     ACPI_PARSE_OBJECT       *Op)
    466 {
    467     UINT32                  Flags;
    468     UINT32                  Args;
    469 
    470 
    471     /* The next Op contains the flags */
    472 
    473     Op = AcpiPsGetDepthNext (NULL, Op);
    474     Flags = (UINT8) Op->Common.Value.Integer;
    475     Args = Flags & 0x07;
    476 
    477     /* Mark the Op as completed */
    478 
    479     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    480 
    481     /* 1) Method argument count */
    482 
    483     AcpiOsPrintf (", %u, ", Args);
    484 
    485     /* 2) Serialize rule */
    486 
    487     if (!(Flags & 0x08))
    488     {
    489         AcpiOsPrintf ("Not");
    490     }
    491 
    492     AcpiOsPrintf ("Serialized");
    493 
    494     /* 3) SyncLevel */
    495 
    496     if (Flags & 0xF0)
    497     {
    498         AcpiOsPrintf (", %u", Flags >> 4);
    499     }
    500 }
    501 
    502 
    503 /*******************************************************************************
    504  *
    505  * FUNCTION:    AcpiDmFieldFlags
    506  *
    507  * PARAMETERS:  Op              - Field Object to be examined
    508  *
    509  * RETURN:      None
    510  *
    511  * DESCRIPTION: Decode Field definition flags
    512  *
    513  ******************************************************************************/
    514 
    515 void
    516 AcpiDmFieldFlags (
    517     ACPI_PARSE_OBJECT       *Op)
    518 {
    519     UINT32                  Flags;
    520 
    521 
    522     Op = Op->Common.Next;
    523     Flags = (UINT8) Op->Common.Value.Integer;
    524 
    525     /* Mark the Op as completed */
    526 
    527     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    528 
    529     AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
    530     AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
    531     AcpiOsPrintf ("%s)",  AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
    532 }
    533 
    534 
    535 /*******************************************************************************
    536  *
    537  * FUNCTION:    AcpiDmAddressSpace
    538  *
    539  * PARAMETERS:  SpaceId         - ID to be translated
    540  *
    541  * RETURN:      None
    542  *
    543  * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
    544  *
    545  ******************************************************************************/
    546 
    547 void
    548 AcpiDmAddressSpace (
    549     UINT8                   SpaceId)
    550 {
    551 
    552     if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
    553     {
    554         if (SpaceId == 0x7F)
    555         {
    556             AcpiOsPrintf ("FFixedHW, ");
    557         }
    558         else
    559         {
    560             AcpiOsPrintf ("0x%.2X, ", SpaceId);
    561         }
    562     }
    563     else
    564     {
    565         AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
    566     }
    567 }
    568 
    569 
    570 /*******************************************************************************
    571  *
    572  * FUNCTION:    AcpiDmRegionFlags
    573  *
    574  * PARAMETERS:  Op              - Object to be examined
    575  *
    576  * RETURN:      None
    577  *
    578  * DESCRIPTION: Decode OperationRegion flags
    579  *
    580  ******************************************************************************/
    581 
    582 void
    583 AcpiDmRegionFlags (
    584     ACPI_PARSE_OBJECT       *Op)
    585 {
    586 
    587     /* The next Op contains the SpaceId */
    588 
    589     Op = AcpiPsGetDepthNext (NULL, Op);
    590 
    591     /* Mark the Op as completed */
    592 
    593     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    594 
    595     AcpiOsPrintf (", ");
    596     AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
    597 }
    598 
    599 
    600 /*******************************************************************************
    601  *
    602  * FUNCTION:    AcpiDmMatchOp
    603  *
    604  * PARAMETERS:  Op              - Match Object to be examined
    605  *
    606  * RETURN:      None
    607  *
    608  * DESCRIPTION: Decode Match opcode operands
    609  *
    610  ******************************************************************************/
    611 
    612 void
    613 AcpiDmMatchOp (
    614     ACPI_PARSE_OBJECT       *Op)
    615 {
    616     ACPI_PARSE_OBJECT       *NextOp;
    617 
    618 
    619     NextOp = AcpiPsGetDepthNext (NULL, Op);
    620     NextOp = NextOp->Common.Next;
    621 
    622     if (!NextOp)
    623     {
    624         /* Handle partial tree during single-step */
    625 
    626         return;
    627     }
    628 
    629     /* Mark the two nodes that contain the encoding for the match keywords */
    630 
    631     NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
    632 
    633     NextOp = NextOp->Common.Next;
    634     NextOp = NextOp->Common.Next;
    635     NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
    636 }
    637 
    638 
    639 /*******************************************************************************
    640  *
    641  * FUNCTION:    AcpiDmMatchKeyword
    642  *
    643  * PARAMETERS:  Op              - Match Object to be examined
    644  *
    645  * RETURN:      None
    646  *
    647  * DESCRIPTION: Decode Match opcode operands
    648  *
    649  ******************************************************************************/
    650 
    651 static void
    652 AcpiDmMatchKeyword (
    653     ACPI_PARSE_OBJECT       *Op)
    654 {
    655 
    656     if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
    657     {
    658         AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
    659     }
    660     else
    661     {
    662         AcpiOsPrintf ("%s",
    663             AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]);
    664     }
    665 }
    666 
    667 
    668 /*******************************************************************************
    669  *
    670  * FUNCTION:    AcpiDmDisassembleOneOp
    671  *
    672  * PARAMETERS:  WalkState           - Current walk info
    673  *              Info                - Parse tree walk info
    674  *              Op                  - Op that is to be printed
    675  *
    676  * RETURN:      None
    677  *
    678  * DESCRIPTION: Disassemble a single AML opcode
    679  *
    680  ******************************************************************************/
    681 
    682 void
    683 AcpiDmDisassembleOneOp (
    684     ACPI_WALK_STATE         *WalkState,
    685     ACPI_OP_WALK_INFO       *Info,
    686     ACPI_PARSE_OBJECT       *Op)
    687 {
    688     const ACPI_OPCODE_INFO  *OpInfo = NULL;
    689     UINT32                  Offset;
    690     UINT32                  Length;
    691     ACPI_PARSE_OBJECT       *Child;
    692     ACPI_PARSE_OBJECT       *MethodCallOp;
    693     ACPI_STATUS             Status;
    694     UINT8                   *Aml;
    695     const AH_DEVICE_ID      *IdInfo;
    696 
    697 
    698     if (!Op)
    699     {
    700         AcpiOsPrintf ("<NULL OP PTR>");
    701         return;
    702     }
    703 
    704     if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
    705     {
    706         return; /* ElseIf macro was already emitted */
    707     }
    708 
    709     switch (Op->Common.DisasmOpcode)
    710     {
    711     case ACPI_DASM_MATCHOP:
    712 
    713         AcpiDmMatchKeyword (Op);
    714         return;
    715 
    716     case ACPI_DASM_LNOT_SUFFIX:
    717 
    718         if (!AcpiGbl_CstyleDisassembly)
    719         {
    720             switch (Op->Common.AmlOpcode)
    721             {
    722             case AML_LOGICAL_EQUAL_OP:
    723                 AcpiOsPrintf ("LNotEqual");
    724                 break;
    725 
    726             case AML_LOGICAL_GREATER_OP:
    727                 AcpiOsPrintf ("LLessEqual");
    728                 break;
    729 
    730             case AML_LOGICAL_LESS_OP:
    731                 AcpiOsPrintf ("LGreaterEqual");
    732                 break;
    733 
    734             default:
    735                 break;
    736             }
    737         }
    738 
    739         Op->Common.DisasmOpcode = 0;
    740         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    741         return;
    742 
    743     default:
    744         break;
    745     }
    746 
    747     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    748 
    749     /* The op and arguments */
    750 
    751     switch (Op->Common.AmlOpcode)
    752     {
    753     case AML_LOGICAL_NOT_OP:
    754 
    755         Child = Op->Common.Value.Arg;
    756         if ((Child->Common.AmlOpcode == AML_LOGICAL_EQUAL_OP) ||
    757             (Child->Common.AmlOpcode == AML_LOGICAL_GREATER_OP) ||
    758             (Child->Common.AmlOpcode == AML_LOGICAL_LESS_OP))
    759         {
    760             Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
    761             Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
    762         }
    763         else
    764         {
    765             AcpiOsPrintf ("%s", OpInfo->Name);
    766         }
    767         break;
    768 
    769     case AML_BYTE_OP:
    770 
    771         AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
    772         break;
    773 
    774     case AML_WORD_OP:
    775 
    776         if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
    777         {
    778             AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
    779         }
    780         else
    781         {
    782             AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
    783         }
    784         break;
    785 
    786     case AML_DWORD_OP:
    787 
    788         if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
    789         {
    790             AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
    791         }
    792         else
    793         {
    794             AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
    795         }
    796         break;
    797 
    798     case AML_QWORD_OP:
    799 
    800         AcpiOsPrintf ("0x%8.8X%8.8X",
    801             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
    802         break;
    803 
    804     case AML_STRING_OP:
    805 
    806         AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
    807 
    808         /* For _HID/_CID strings, attempt to output a descriptive comment */
    809 
    810         if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
    811         {
    812             /* If we know about the ID, emit the description */
    813 
    814             IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
    815             if (IdInfo)
    816             {
    817                 AcpiOsPrintf (" /* %s */", IdInfo->Description);
    818             }
    819         }
    820         break;
    821 
    822     case AML_BUFFER_OP:
    823         /*
    824          * Determine the type of buffer. We can have one of the following:
    825          *
    826          * 1) ResourceTemplate containing Resource Descriptors.
    827          * 2) Unicode String buffer
    828          * 3) ASCII String buffer
    829          * 4) Raw data buffer (if none of the above)
    830          *
    831          * Since there are no special AML opcodes to differentiate these
    832          * types of buffers, we have to closely look at the data in the
    833          * buffer to determine the type.
    834          */
    835         if (!AcpiGbl_NoResourceDisassembly)
    836         {
    837             Status = AcpiDmIsResourceTemplate (WalkState, Op);
    838             if (ACPI_SUCCESS (Status))
    839             {
    840                 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
    841                 AcpiOsPrintf ("ResourceTemplate");
    842                 break;
    843             }
    844             else if (Status == AE_AML_NO_RESOURCE_END_TAG)
    845             {
    846                 AcpiOsPrintf (
    847                     "/**** Is ResourceTemplate, "
    848                     "but EndTag not at buffer end ****/ ");
    849             }
    850         }
    851 
    852         if (AcpiDmIsUuidBuffer (Op))
    853         {
    854             Op->Common.DisasmOpcode = ACPI_DASM_UUID;
    855             AcpiOsPrintf ("ToUUID (");
    856         }
    857         else if (AcpiDmIsUnicodeBuffer (Op))
    858         {
    859             Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
    860             AcpiOsPrintf ("Unicode (");
    861         }
    862         else if (AcpiDmIsStringBuffer (Op))
    863         {
    864             Op->Common.DisasmOpcode = ACPI_DASM_STRING;
    865             AcpiOsPrintf ("Buffer");
    866         }
    867         else if (AcpiDmIsPldBuffer (Op))
    868         {
    869             Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
    870             AcpiOsPrintf ("ToPLD (");
    871         }
    872         else
    873         {
    874             Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
    875             AcpiOsPrintf ("Buffer");
    876         }
    877         break;
    878 
    879     case AML_INT_NAMEPATH_OP:
    880 
    881         AcpiDmNamestring (Op->Common.Value.Name);
    882         /* If this namepath is a Package element, emit a separating comma */
    883         if ((Op->Common.Parent) &&
    884             ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
    885              (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
    886         {
    887             AcpiOsPrintf (", ");
    888         }
    889         break;
    890 
    891     case AML_INT_NAMEDFIELD_OP:
    892 
    893         Length = AcpiDmDumpName (Op->Named.Name);
    894 
    895         AcpiOsPrintf (",");
    896         ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
    897         AcpiOsPrintf ("%*.s  %u", (unsigned) (5 - Length), " ",
    898             (UINT32) Op->Common.Value.Integer);
    899 
    900         AcpiDmCommaIfFieldMember (Op);
    901 
    902         Info->BitOffset += (UINT32) Op->Common.Value.Integer;
    903         break;
    904 
    905     case AML_INT_RESERVEDFIELD_OP:
    906 
    907         /* Offset() -- Must account for previous offsets */
    908 
    909         Offset = (UINT32) Op->Common.Value.Integer;
    910         Info->BitOffset += Offset;
    911 
    912         if (Info->BitOffset % 8 == 0)
    913         {
    914             AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
    915         }
    916         else
    917         {
    918             AcpiOsPrintf ("    ,   %u", Offset);
    919         }
    920 
    921         AcpiDmCommaIfFieldMember (Op);
    922         break;
    923 
    924     case AML_INT_ACCESSFIELD_OP:
    925     case AML_INT_EXTACCESSFIELD_OP:
    926 
    927         AcpiOsPrintf ("AccessAs (%s, ",
    928             AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
    929 
    930         AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
    931 
    932         if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
    933         {
    934             AcpiOsPrintf (" (0x%2.2X)", (unsigned)
    935                 ((Op->Common.Value.Integer >> 16) & 0xFF));
    936         }
    937 
    938         AcpiOsPrintf (")");
    939         AcpiDmCommaIfFieldMember (Op);
    940         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
    941         break;
    942 
    943     case AML_INT_CONNECTION_OP:
    944         /*
    945          * Two types of Connection() - one with a buffer object, the
    946          * other with a namestring that points to a buffer object.
    947          */
    948         AcpiOsPrintf ("Connection (");
    949         Child = Op->Common.Value.Arg;
    950 
    951         if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
    952         {
    953             AcpiOsPrintf ("\n");
    954 
    955             Aml = Child->Named.Data;
    956             Length = (UINT32) Child->Common.Value.Integer;
    957 
    958             Info->Level += 1;
    959             Info->MappingOp = Op;
    960             Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
    961 
    962             AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
    963 
    964             Info->Level -= 1;
    965             AcpiDmIndent (Info->Level);
    966         }
    967         else
    968         {
    969             AcpiDmNamestring (Child->Common.Value.Name);
    970         }
    971 
    972         AcpiOsPrintf (")");
    973         AcpiDmCommaIfFieldMember (Op);
    974         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
    975         ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, NULL, 0);
    976         AcpiOsPrintf ("\n");
    977 
    978         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
    979         Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    980         break;
    981 
    982     case AML_INT_BYTELIST_OP:
    983 
    984         AcpiDmByteList (Info, Op);
    985         break;
    986 
    987     case AML_INT_METHODCALL_OP:
    988 
    989         MethodCallOp = Op;
    990         Op = AcpiPsGetDepthNext (NULL, Op);
    991         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    992 
    993         AcpiDmNamestring (Op->Common.Value.Name);
    994 
    995         /* If the method name is a Package element, emit a separating comma */
    996         if ((MethodCallOp->Common.Parent) &&
    997             ((MethodCallOp->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
    998              (MethodCallOp->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
    999         {
   1000             AcpiOsPrintf (", ");
   1001         }
   1002         break;
   1003 
   1004     case AML_WHILE_OP:
   1005 
   1006         if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH)
   1007         {
   1008             AcpiOsPrintf ("%s", "Switch");
   1009             break;
   1010         }
   1011 
   1012         AcpiOsPrintf ("%s", OpInfo->Name);
   1013         break;
   1014 
   1015     case AML_IF_OP:
   1016 
   1017         if (Op->Common.DisasmOpcode == ACPI_DASM_CASE)
   1018         {
   1019             AcpiOsPrintf ("%s", "Case");
   1020             break;
   1021         }
   1022 
   1023         AcpiOsPrintf ("%s", OpInfo->Name);
   1024         break;
   1025 
   1026     case AML_ELSE_OP:
   1027 
   1028         AcpiDmConvertToElseIf (Op);
   1029         break;
   1030 
   1031     case AML_EXTERNAL_OP:
   1032 
   1033         if (AcpiGbl_DmEmitExternalOpcodes)
   1034         {
   1035             AcpiDmEmitExternal (Op, AcpiPsGetArg(Op, 0));
   1036         }
   1037 
   1038         break;
   1039 
   1040     default:
   1041 
   1042         /* Just get the opcode name and print it */
   1043 
   1044         AcpiOsPrintf ("%s", OpInfo->Name);
   1045 
   1046 
   1047 #ifdef ACPI_DEBUGGER
   1048 
   1049         if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
   1050             (WalkState) &&
   1051             (WalkState->Results) &&
   1052             (WalkState->ResultCount))
   1053         {
   1054             AcpiDbDecodeInternalObject (
   1055                 WalkState->Results->Results.ObjDesc [
   1056                     (WalkState->ResultCount - 1) %
   1057                         ACPI_RESULTS_FRAME_OBJ_NUM]);
   1058         }
   1059 #endif
   1060 
   1061         break;
   1062     }
   1063 }
   1064 
   1065 
   1066 /*******************************************************************************
   1067  *
   1068  * FUNCTION:    AcpiDmConvertToElseIf
   1069  *
   1070  * PARAMETERS:  OriginalElseOp          - ELSE Object to be examined
   1071  *
   1072  * RETURN:      None. Emits either an "Else" or an "ElseIf" ASL operator.
   1073  *
   1074  * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
   1075  *
   1076  * EXAMPLE:
   1077  *
   1078  * This If..Else..If nested sequence:
   1079  *
   1080  *        If (Arg0 == 1)
   1081  *        {
   1082  *            Local0 = 4
   1083  *        }
   1084  *        Else
   1085  *        {
   1086  *            If (Arg0 == 2)
   1087  *            {
   1088  *                Local0 = 5
   1089  *            }
   1090  *        }
   1091  *
   1092  * Is converted to this simpler If..ElseIf sequence:
   1093  *
   1094  *        If (Arg0 == 1)
   1095  *        {
   1096  *            Local0 = 4
   1097  *        }
   1098  *        ElseIf (Arg0 == 2)
   1099  *        {
   1100  *            Local0 = 5
   1101  *        }
   1102  *
   1103  * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
   1104  * macro that emits an Else opcode followed by an If opcode. This function
   1105  * reverses these AML sequences back to an ElseIf macro where possible. This
   1106  * can make the disassembled ASL code simpler and more like the original code.
   1107  *
   1108  ******************************************************************************/
   1109 
   1110 static void
   1111 AcpiDmConvertToElseIf (
   1112     ACPI_PARSE_OBJECT       *OriginalElseOp)
   1113 {
   1114     ACPI_PARSE_OBJECT       *IfOp;
   1115     ACPI_PARSE_OBJECT       *ElseOp;
   1116 
   1117 
   1118     /*
   1119      * To be able to perform the conversion, two conditions must be satisfied:
   1120      * 1) The first child of the Else must be an If statement.
   1121      * 2) The If block can only be followed by an Else block and these must
   1122      *    be the only blocks under the original Else.
   1123      */
   1124     IfOp = OriginalElseOp->Common.Value.Arg;
   1125 
   1126     if (!IfOp ||
   1127         (IfOp->Common.AmlOpcode != AML_IF_OP) ||
   1128         (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
   1129     {
   1130         /* Not a proper Else..If sequence, cannot convert to ElseIf */
   1131 
   1132         if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1133         {
   1134             AcpiOsPrintf ("%s", "Default");
   1135             return;
   1136         }
   1137 
   1138         AcpiOsPrintf ("%s", "Else");
   1139         return;
   1140     }
   1141 
   1142     /* Cannot have anything following the If...Else block */
   1143 
   1144     ElseOp = IfOp->Common.Next;
   1145     if (ElseOp && ElseOp->Common.Next)
   1146     {
   1147         if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1148         {
   1149             AcpiOsPrintf ("%s", "Default");
   1150             return;
   1151         }
   1152 
   1153         AcpiOsPrintf ("%s", "Else");
   1154         return;
   1155     }
   1156 
   1157     if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1158     {
   1159         /*
   1160          * There is an ElseIf but in this case the Else is actually
   1161          * a Default block for a Switch/Case statement. No conversion.
   1162          */
   1163         AcpiOsPrintf ("%s", "Default");
   1164         return;
   1165     }
   1166 
   1167     if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE)
   1168     {
   1169         /*
   1170          * This ElseIf is actually a Case block for a Switch/Case
   1171          * statement. Print Case but do not return so that we can
   1172          * promote the subtree and keep the indentation level.
   1173          */
   1174         AcpiOsPrintf ("%s", "Case");
   1175     }
   1176     else
   1177     {
   1178        /* Emit ElseIf, mark the IF as now an ELSEIF */
   1179 
   1180         AcpiOsPrintf ("%s", "ElseIf");
   1181     }
   1182 
   1183     IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
   1184 
   1185     /* The IF parent will now be the same as the original ELSE parent */
   1186 
   1187     IfOp->Common.Parent = OriginalElseOp->Common.Parent;
   1188 
   1189     /*
   1190      * Update the NEXT pointers to restructure the parse tree, essentially
   1191      * promoting an If..Else block up to the same level as the original
   1192      * Else.
   1193      *
   1194      * Check if the IF has a corresponding ELSE peer
   1195      */
   1196     ElseOp = IfOp->Common.Next;
   1197     if (ElseOp &&
   1198         (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
   1199     {
   1200         /* If an ELSE matches the IF, promote it also */
   1201 
   1202         ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
   1203 
   1204         /* Promote the entire block under the ElseIf (All Next OPs) */
   1205 
   1206         AcpiDmPromoteSubtree (OriginalElseOp);
   1207     }
   1208     else
   1209     {
   1210         /* Otherwise, set the IF NEXT to the original ELSE NEXT */
   1211 
   1212         IfOp->Common.Next = OriginalElseOp->Common.Next;
   1213     }
   1214 
   1215     /* Detach the child IF block from the original ELSE */
   1216 
   1217     OriginalElseOp->Common.Value.Arg = NULL;
   1218 
   1219     /* Ignore the original ELSE from now on */
   1220 
   1221     OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
   1222     OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
   1223 
   1224     /* Insert IF (now ELSEIF) as next peer of the original ELSE */
   1225 
   1226     OriginalElseOp->Common.Next = IfOp;
   1227 }
   1228 
   1229 
   1230 /*******************************************************************************
   1231  *
   1232  * FUNCTION:    AcpiDmPromoteSubtree
   1233  *
   1234  * PARAMETERS:  StartOpOp           - Original parent of the entire subtree
   1235  *
   1236  * RETURN:      None
   1237  *
   1238  * DESCRIPTION: Promote an entire parse subtree up one level.
   1239  *
   1240  ******************************************************************************/
   1241 
   1242 static void
   1243 AcpiDmPromoteSubtree (
   1244     ACPI_PARSE_OBJECT       *StartOp)
   1245 {
   1246     ACPI_PARSE_OBJECT       *Op;
   1247     ACPI_PARSE_OBJECT       *ParentOp;
   1248 
   1249 
   1250     /* New parent for subtree elements */
   1251 
   1252     ParentOp = StartOp->Common.Parent;
   1253 
   1254     /* First child starts the subtree */
   1255 
   1256     Op = StartOp->Common.Value.Arg;
   1257 
   1258     /* Walk the top-level elements of the subtree */
   1259 
   1260     while (Op)
   1261     {
   1262         Op->Common.Parent = ParentOp;
   1263         if (!Op->Common.Next)
   1264         {
   1265             /* Last Op in list, update its next field */
   1266 
   1267             Op->Common.Next = StartOp->Common.Next;
   1268             break;
   1269         }
   1270         Op = Op->Common.Next;
   1271     }
   1272 }
   1273