Home | History | Annotate | Line # | Download | only in disassembler
dmopcode.c revision 1.1.1.13.2.1
      1 /*******************************************************************************
      2  *
      3  * Module Name: dmopcode - AML disassembler, specific AML opcodes
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2018, 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 "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_STATUS             Status;
    693     UINT8                   *Aml;
    694     const AH_DEVICE_ID      *IdInfo;
    695 
    696 
    697     if (!Op)
    698     {
    699         AcpiOsPrintf ("<NULL OP PTR>");
    700         return;
    701     }
    702 
    703     if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
    704     {
    705         return; /* ElseIf macro was already emitted */
    706     }
    707 
    708     switch (Op->Common.DisasmOpcode)
    709     {
    710     case ACPI_DASM_MATCHOP:
    711 
    712         AcpiDmMatchKeyword (Op);
    713         return;
    714 
    715     case ACPI_DASM_LNOT_SUFFIX:
    716 
    717         if (!AcpiGbl_CstyleDisassembly)
    718         {
    719             switch (Op->Common.AmlOpcode)
    720             {
    721             case AML_LOGICAL_EQUAL_OP:
    722                 AcpiOsPrintf ("LNotEqual");
    723                 break;
    724 
    725             case AML_LOGICAL_GREATER_OP:
    726                 AcpiOsPrintf ("LLessEqual");
    727                 break;
    728 
    729             case AML_LOGICAL_LESS_OP:
    730                 AcpiOsPrintf ("LGreaterEqual");
    731                 break;
    732 
    733             default:
    734                 break;
    735             }
    736         }
    737 
    738         Op->Common.DisasmOpcode = 0;
    739         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    740         return;
    741 
    742     default:
    743         break;
    744     }
    745 
    746     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    747 
    748     /* The op and arguments */
    749 
    750     switch (Op->Common.AmlOpcode)
    751     {
    752     case AML_LOGICAL_NOT_OP:
    753 
    754         Child = Op->Common.Value.Arg;
    755         if ((Child->Common.AmlOpcode == AML_LOGICAL_EQUAL_OP) ||
    756             (Child->Common.AmlOpcode == AML_LOGICAL_GREATER_OP) ||
    757             (Child->Common.AmlOpcode == AML_LOGICAL_LESS_OP))
    758         {
    759             Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
    760             Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
    761         }
    762         else
    763         {
    764             AcpiOsPrintf ("%s", OpInfo->Name);
    765         }
    766         break;
    767 
    768     case AML_BYTE_OP:
    769 
    770         AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
    771         break;
    772 
    773     case AML_WORD_OP:
    774 
    775         if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
    776         {
    777             AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
    778         }
    779         else
    780         {
    781             AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
    782         }
    783         break;
    784 
    785     case AML_DWORD_OP:
    786 
    787         if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
    788         {
    789             AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
    790         }
    791         else
    792         {
    793             AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
    794         }
    795         break;
    796 
    797     case AML_QWORD_OP:
    798 
    799         AcpiOsPrintf ("0x%8.8X%8.8X",
    800             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
    801         break;
    802 
    803     case AML_STRING_OP:
    804 
    805         AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
    806 
    807         /* For _HID/_CID strings, attempt to output a descriptive comment */
    808 
    809         if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
    810         {
    811             /* If we know about the ID, emit the description */
    812 
    813             IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
    814             if (IdInfo)
    815             {
    816                 AcpiOsPrintf (" /* %s */", IdInfo->Description);
    817             }
    818         }
    819         break;
    820 
    821     case AML_BUFFER_OP:
    822         /*
    823          * Determine the type of buffer. We can have one of the following:
    824          *
    825          * 1) ResourceTemplate containing Resource Descriptors.
    826          * 2) Unicode String buffer
    827          * 3) ASCII String buffer
    828          * 4) Raw data buffer (if none of the above)
    829          *
    830          * Since there are no special AML opcodes to differentiate these
    831          * types of buffers, we have to closely look at the data in the
    832          * buffer to determine the type.
    833          */
    834         if (!AcpiGbl_NoResourceDisassembly)
    835         {
    836             Status = AcpiDmIsResourceTemplate (WalkState, Op);
    837             if (ACPI_SUCCESS (Status))
    838             {
    839                 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
    840                 AcpiOsPrintf ("ResourceTemplate");
    841                 break;
    842             }
    843             else if (Status == AE_AML_NO_RESOURCE_END_TAG)
    844             {
    845                 AcpiOsPrintf (
    846                     "/**** Is ResourceTemplate, "
    847                     "but EndTag not at buffer end ****/ ");
    848             }
    849         }
    850 
    851         if (AcpiDmIsUuidBuffer (Op))
    852         {
    853             Op->Common.DisasmOpcode = ACPI_DASM_UUID;
    854             AcpiOsPrintf ("ToUUID (");
    855         }
    856         else if (AcpiDmIsUnicodeBuffer (Op))
    857         {
    858             Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
    859             AcpiOsPrintf ("Unicode (");
    860         }
    861         else if (AcpiDmIsStringBuffer (Op))
    862         {
    863             Op->Common.DisasmOpcode = ACPI_DASM_STRING;
    864             AcpiOsPrintf ("Buffer");
    865         }
    866         else if (AcpiDmIsPldBuffer (Op))
    867         {
    868             Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
    869             AcpiOsPrintf ("ToPLD (");
    870         }
    871         else
    872         {
    873             Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
    874             AcpiOsPrintf ("Buffer");
    875         }
    876         break;
    877 
    878     case AML_INT_NAMEPATH_OP:
    879 
    880         AcpiDmNamestring (Op->Common.Value.Name);
    881         break;
    882 
    883     case AML_INT_NAMEDFIELD_OP:
    884 
    885         Length = AcpiDmDumpName (Op->Named.Name);
    886 
    887         AcpiOsPrintf (",");
    888         ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
    889         AcpiOsPrintf ("%*.s  %u", (unsigned) (5 - Length), " ",
    890             (UINT32) Op->Common.Value.Integer);
    891 
    892         AcpiDmCommaIfFieldMember (Op);
    893 
    894         Info->BitOffset += (UINT32) Op->Common.Value.Integer;
    895         break;
    896 
    897     case AML_INT_RESERVEDFIELD_OP:
    898 
    899         /* Offset() -- Must account for previous offsets */
    900 
    901         Offset = (UINT32) Op->Common.Value.Integer;
    902         Info->BitOffset += Offset;
    903 
    904         if (Info->BitOffset % 8 == 0)
    905         {
    906             AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
    907         }
    908         else
    909         {
    910             AcpiOsPrintf ("    ,   %u", Offset);
    911         }
    912 
    913         AcpiDmCommaIfFieldMember (Op);
    914         break;
    915 
    916     case AML_INT_ACCESSFIELD_OP:
    917     case AML_INT_EXTACCESSFIELD_OP:
    918 
    919         AcpiOsPrintf ("AccessAs (%s, ",
    920             AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
    921 
    922         AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
    923 
    924         if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
    925         {
    926             AcpiOsPrintf (" (0x%2.2X)", (unsigned)
    927                 ((Op->Common.Value.Integer >> 16) & 0xFF));
    928         }
    929 
    930         AcpiOsPrintf (")");
    931         AcpiDmCommaIfFieldMember (Op);
    932         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
    933         break;
    934 
    935     case AML_INT_CONNECTION_OP:
    936         /*
    937          * Two types of Connection() - one with a buffer object, the
    938          * other with a namestring that points to a buffer object.
    939          */
    940         AcpiOsPrintf ("Connection (");
    941         Child = Op->Common.Value.Arg;
    942 
    943         if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
    944         {
    945             AcpiOsPrintf ("\n");
    946 
    947             Aml = Child->Named.Data;
    948             Length = (UINT32) Child->Common.Value.Integer;
    949 
    950             Info->Level += 1;
    951             Info->MappingOp = Op;
    952             Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
    953 
    954             AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
    955 
    956             Info->Level -= 1;
    957             AcpiDmIndent (Info->Level);
    958         }
    959         else
    960         {
    961             AcpiDmNamestring (Child->Common.Value.Name);
    962         }
    963 
    964         AcpiOsPrintf (")");
    965         AcpiDmCommaIfFieldMember (Op);
    966         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
    967         ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, NULL, 0);
    968         AcpiOsPrintf ("\n");
    969 
    970         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
    971         Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    972         break;
    973 
    974     case AML_INT_BYTELIST_OP:
    975 
    976         AcpiDmByteList (Info, Op);
    977         break;
    978 
    979     case AML_INT_METHODCALL_OP:
    980 
    981         Op = AcpiPsGetDepthNext (NULL, Op);
    982         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    983 
    984         AcpiDmNamestring (Op->Common.Value.Name);
    985         break;
    986 
    987     case AML_WHILE_OP:
    988 
    989         if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH)
    990         {
    991             AcpiOsPrintf ("%s", "Switch");
    992             break;
    993         }
    994 
    995         AcpiOsPrintf ("%s", OpInfo->Name);
    996         break;
    997 
    998     case AML_IF_OP:
    999 
   1000         if (Op->Common.DisasmOpcode == ACPI_DASM_CASE)
   1001         {
   1002             AcpiOsPrintf ("%s", "Case");
   1003             break;
   1004         }
   1005 
   1006         AcpiOsPrintf ("%s", OpInfo->Name);
   1007         break;
   1008 
   1009     case AML_ELSE_OP:
   1010 
   1011         AcpiDmConvertToElseIf (Op);
   1012         break;
   1013 
   1014     case AML_EXTERNAL_OP:
   1015 
   1016         if (AcpiGbl_DmEmitExternalOpcodes)
   1017         {
   1018             AcpiDmEmitExternal (Op, AcpiPsGetArg(Op, 0));
   1019         }
   1020 
   1021         break;
   1022 
   1023     default:
   1024 
   1025         /* Just get the opcode name and print it */
   1026 
   1027         AcpiOsPrintf ("%s", OpInfo->Name);
   1028 
   1029 
   1030 #ifdef ACPI_DEBUGGER
   1031 
   1032         if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
   1033             (WalkState) &&
   1034             (WalkState->Results) &&
   1035             (WalkState->ResultCount))
   1036         {
   1037             AcpiDbDecodeInternalObject (
   1038                 WalkState->Results->Results.ObjDesc [
   1039                     (WalkState->ResultCount - 1) %
   1040                         ACPI_RESULTS_FRAME_OBJ_NUM]);
   1041         }
   1042 #endif
   1043 
   1044         break;
   1045     }
   1046 }
   1047 
   1048 
   1049 /*******************************************************************************
   1050  *
   1051  * FUNCTION:    AcpiDmConvertToElseIf
   1052  *
   1053  * PARAMETERS:  OriginalElseOp          - ELSE Object to be examined
   1054  *
   1055  * RETURN:      None. Emits either an "Else" or an "ElseIf" ASL operator.
   1056  *
   1057  * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
   1058  *
   1059  * EXAMPLE:
   1060  *
   1061  * This If..Else..If nested sequence:
   1062  *
   1063  *        If (Arg0 == 1)
   1064  *        {
   1065  *            Local0 = 4
   1066  *        }
   1067  *        Else
   1068  *        {
   1069  *            If (Arg0 == 2)
   1070  *            {
   1071  *                Local0 = 5
   1072  *            }
   1073  *        }
   1074  *
   1075  * Is converted to this simpler If..ElseIf sequence:
   1076  *
   1077  *        If (Arg0 == 1)
   1078  *        {
   1079  *            Local0 = 4
   1080  *        }
   1081  *        ElseIf (Arg0 == 2)
   1082  *        {
   1083  *            Local0 = 5
   1084  *        }
   1085  *
   1086  * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
   1087  * macro that emits an Else opcode followed by an If opcode. This function
   1088  * reverses these AML sequences back to an ElseIf macro where possible. This
   1089  * can make the disassembled ASL code simpler and more like the original code.
   1090  *
   1091  ******************************************************************************/
   1092 
   1093 static void
   1094 AcpiDmConvertToElseIf (
   1095     ACPI_PARSE_OBJECT       *OriginalElseOp)
   1096 {
   1097     ACPI_PARSE_OBJECT       *IfOp;
   1098     ACPI_PARSE_OBJECT       *ElseOp;
   1099 
   1100 
   1101     /*
   1102      * To be able to perform the conversion, two conditions must be satisfied:
   1103      * 1) The first child of the Else must be an If statement.
   1104      * 2) The If block can only be followed by an Else block and these must
   1105      *    be the only blocks under the original Else.
   1106      */
   1107     IfOp = OriginalElseOp->Common.Value.Arg;
   1108 
   1109     if (!IfOp ||
   1110         (IfOp->Common.AmlOpcode != AML_IF_OP) ||
   1111         (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
   1112     {
   1113         /* Not a proper Else..If sequence, cannot convert to ElseIf */
   1114 
   1115         if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1116         {
   1117             AcpiOsPrintf ("%s", "Default");
   1118             return;
   1119         }
   1120 
   1121         AcpiOsPrintf ("%s", "Else");
   1122         return;
   1123     }
   1124 
   1125     /* Cannot have anything following the If...Else block */
   1126 
   1127     ElseOp = IfOp->Common.Next;
   1128     if (ElseOp && ElseOp->Common.Next)
   1129     {
   1130         if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1131         {
   1132             AcpiOsPrintf ("%s", "Default");
   1133             return;
   1134         }
   1135 
   1136         AcpiOsPrintf ("%s", "Else");
   1137         return;
   1138     }
   1139 
   1140     if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1141     {
   1142         /*
   1143          * There is an ElseIf but in this case the Else is actually
   1144          * a Default block for a Switch/Case statement. No conversion.
   1145          */
   1146         AcpiOsPrintf ("%s", "Default");
   1147         return;
   1148     }
   1149 
   1150     if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE)
   1151     {
   1152         /*
   1153          * This ElseIf is actually a Case block for a Switch/Case
   1154          * statement. Print Case but do not return so that we can
   1155          * promote the subtree and keep the indentation level.
   1156          */
   1157         AcpiOsPrintf ("%s", "Case");
   1158     }
   1159     else
   1160     {
   1161        /* Emit ElseIf, mark the IF as now an ELSEIF */
   1162 
   1163         AcpiOsPrintf ("%s", "ElseIf");
   1164     }
   1165 
   1166     IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
   1167 
   1168     /* The IF parent will now be the same as the original ELSE parent */
   1169 
   1170     IfOp->Common.Parent = OriginalElseOp->Common.Parent;
   1171 
   1172     /*
   1173      * Update the NEXT pointers to restructure the parse tree, essentially
   1174      * promoting an If..Else block up to the same level as the original
   1175      * Else.
   1176      *
   1177      * Check if the IF has a corresponding ELSE peer
   1178      */
   1179     ElseOp = IfOp->Common.Next;
   1180     if (ElseOp &&
   1181         (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
   1182     {
   1183         /* If an ELSE matches the IF, promote it also */
   1184 
   1185         ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
   1186 
   1187         /* Promote the entire block under the ElseIf (All Next OPs) */
   1188 
   1189         AcpiDmPromoteSubtree (OriginalElseOp);
   1190     }
   1191     else
   1192     {
   1193         /* Otherwise, set the IF NEXT to the original ELSE NEXT */
   1194 
   1195         IfOp->Common.Next = OriginalElseOp->Common.Next;
   1196     }
   1197 
   1198     /* Detach the child IF block from the original ELSE */
   1199 
   1200     OriginalElseOp->Common.Value.Arg = NULL;
   1201 
   1202     /* Ignore the original ELSE from now on */
   1203 
   1204     OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
   1205     OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
   1206 
   1207     /* Insert IF (now ELSEIF) as next peer of the original ELSE */
   1208 
   1209     OriginalElseOp->Common.Next = IfOp;
   1210 }
   1211 
   1212 
   1213 /*******************************************************************************
   1214  *
   1215  * FUNCTION:    AcpiDmPromoteSubtree
   1216  *
   1217  * PARAMETERS:  StartOpOp           - Original parent of the entire subtree
   1218  *
   1219  * RETURN:      None
   1220  *
   1221  * DESCRIPTION: Promote an entire parse subtree up one level.
   1222  *
   1223  ******************************************************************************/
   1224 
   1225 static void
   1226 AcpiDmPromoteSubtree (
   1227     ACPI_PARSE_OBJECT       *StartOp)
   1228 {
   1229     ACPI_PARSE_OBJECT       *Op;
   1230     ACPI_PARSE_OBJECT       *ParentOp;
   1231 
   1232 
   1233     /* New parent for subtree elements */
   1234 
   1235     ParentOp = StartOp->Common.Parent;
   1236 
   1237     /* First child starts the subtree */
   1238 
   1239     Op = StartOp->Common.Value.Arg;
   1240 
   1241     /* Walk the top-level elements of the subtree */
   1242 
   1243     while (Op)
   1244     {
   1245         Op->Common.Parent = ParentOp;
   1246         if (!Op->Common.Next)
   1247         {
   1248             /* Last Op in list, update its next field */
   1249 
   1250             Op->Common.Next = StartOp->Common.Next;
   1251             break;
   1252         }
   1253         Op = Op->Common.Next;
   1254     }
   1255 }
   1256