Home | History | Annotate | Line # | Download | only in disassembler
dmopcode.c revision 1.1.1.10.2.1
      1 /*******************************************************************************
      2  *
      3  * Module Name: dmopcode - AML disassembler, specific AML opcodes
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "acpi.h"
     45 #include "accommon.h"
     46 #include "acparser.h"
     47 #include "amlcode.h"
     48 #include "acinterp.h"
     49 #include "acnamesp.h"
     50 #include "acdebug.h"
     51 
     52 
     53 #define _COMPONENT          ACPI_CA_DEBUGGER
     54         ACPI_MODULE_NAME    ("dmopcode")
     55 
     56 
     57 /* Local prototypes */
     58 
     59 static void
     60 AcpiDmMatchKeyword (
     61     ACPI_PARSE_OBJECT       *Op);
     62 
     63 static void
     64 AcpiDmConvertToElseIf (
     65     ACPI_PARSE_OBJECT       *Op);
     66 
     67 static void
     68 AcpiDmPromoteSubtree (
     69     ACPI_PARSE_OBJECT       *StartOp);
     70 
     71 static BOOLEAN
     72 AcpiDmIsSwitchBlock (
     73     ACPI_PARSE_OBJECT       *Op);
     74 
     75 static BOOLEAN
     76 AcpiDmIsCaseBlock (
     77     ACPI_PARSE_OBJECT       *Op);
     78 
     79 /*******************************************************************************
     80  *
     81  * FUNCTION:    AcpiDmDisplayTargetPathname
     82  *
     83  * PARAMETERS:  Op              - Parse object
     84  *
     85  * RETURN:      None
     86  *
     87  * DESCRIPTION: For AML opcodes that have a target operand, display the full
     88  *              pathname for the target, in a comment field. Handles Return()
     89  *              statements also.
     90  *
     91  ******************************************************************************/
     92 
     93 void
     94 AcpiDmDisplayTargetPathname (
     95     ACPI_PARSE_OBJECT       *Op)
     96 {
     97     ACPI_PARSE_OBJECT       *NextOp;
     98     ACPI_PARSE_OBJECT       *PrevOp = NULL;
     99     char                    *Pathname;
    100     const ACPI_OPCODE_INFO  *OpInfo;
    101 
    102 
    103     if (Op->Common.AmlOpcode == AML_RETURN_OP)
    104     {
    105         PrevOp = Op->Asl.Value.Arg;
    106     }
    107     else
    108     {
    109         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    110         if (!(OpInfo->Flags & AML_HAS_TARGET))
    111         {
    112             return;
    113         }
    114 
    115         /* Target is the last Op in the arg list */
    116 
    117         NextOp = Op->Asl.Value.Arg;
    118         while (NextOp)
    119         {
    120             PrevOp = NextOp;
    121             NextOp = PrevOp->Asl.Next;
    122         }
    123     }
    124 
    125     if (!PrevOp)
    126     {
    127         return;
    128     }
    129 
    130     /* We must have a namepath AML opcode */
    131 
    132     if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
    133     {
    134         return;
    135     }
    136 
    137     /* A null string is the "no target specified" case */
    138 
    139     if (!PrevOp->Asl.Value.String)
    140     {
    141         return;
    142     }
    143 
    144     /* No node means "unresolved external reference" */
    145 
    146     if (!PrevOp->Asl.Node)
    147     {
    148         AcpiOsPrintf (" /* External reference */");
    149         return;
    150     }
    151 
    152     /* Ignore if path is already from the root */
    153 
    154     if (*PrevOp->Asl.Value.String == '\\')
    155     {
    156         return;
    157     }
    158 
    159     /* Now: we can get the full pathname */
    160 
    161     Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
    162     if (!Pathname)
    163     {
    164         return;
    165     }
    166 
    167     AcpiOsPrintf (" /* %s */", Pathname);
    168     ACPI_FREE (Pathname);
    169 }
    170 
    171 
    172 /*******************************************************************************
    173  *
    174  * FUNCTION:    AcpiDmNotifyDescription
    175  *
    176  * PARAMETERS:  Op              - Name() parse object
    177  *
    178  * RETURN:      None
    179  *
    180  * DESCRIPTION: Emit a description comment for the value associated with a
    181  *              Notify() operator.
    182  *
    183  ******************************************************************************/
    184 
    185 void
    186 AcpiDmNotifyDescription (
    187     ACPI_PARSE_OBJECT       *Op)
    188 {
    189     ACPI_PARSE_OBJECT       *NextOp;
    190     ACPI_NAMESPACE_NODE     *Node;
    191     UINT8                   NotifyValue;
    192     UINT8                   Type = ACPI_TYPE_ANY;
    193 
    194 
    195     /* The notify value is the second argument */
    196 
    197     NextOp = Op->Asl.Value.Arg;
    198     NextOp = NextOp->Asl.Next;
    199 
    200     switch (NextOp->Common.AmlOpcode)
    201     {
    202     case AML_ZERO_OP:
    203     case AML_ONE_OP:
    204 
    205         NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
    206         break;
    207 
    208     case AML_BYTE_OP:
    209 
    210         NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
    211         break;
    212 
    213     default:
    214         return;
    215     }
    216 
    217     /*
    218      * Attempt to get the namespace node so we can determine the object type.
    219      * Some notify values are dependent on the object type (Device, Thermal,
    220      * or Processor).
    221      */
    222     Node = Op->Asl.Node;
    223     if (Node)
    224     {
    225         Type = Node->Type;
    226     }
    227 
    228     AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
    229 }
    230 
    231 
    232 /*******************************************************************************
    233  *
    234  * FUNCTION:    AcpiDmPredefinedDescription
    235  *
    236  * PARAMETERS:  Op              - Name() parse object
    237  *
    238  * RETURN:      None
    239  *
    240  * DESCRIPTION: Emit a description comment for a predefined ACPI name.
    241  *              Used for iASL compiler only.
    242  *
    243  ******************************************************************************/
    244 
    245 void
    246 AcpiDmPredefinedDescription (
    247     ACPI_PARSE_OBJECT       *Op)
    248 {
    249 #ifdef ACPI_ASL_COMPILER
    250     const AH_PREDEFINED_NAME    *Info;
    251     char                        *NameString;
    252     int                         LastCharIsDigit;
    253     int                         LastCharsAreHex;
    254 
    255 
    256     if (!Op)
    257     {
    258         return;
    259     }
    260 
    261     /* Ensure that the comment field is emitted only once */
    262 
    263     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
    264     {
    265         return;
    266     }
    267     Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
    268 
    269     /* Predefined name must start with an underscore */
    270 
    271     NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
    272     if (NameString[0] != '_')
    273     {
    274         return;
    275     }
    276 
    277     /*
    278      * Check for the special ACPI names:
    279      * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
    280      * (where d=decimal_digit, x=hex_digit, a=anything)
    281      *
    282      * Convert these to the generic name for table lookup.
    283      * Note: NameString is guaranteed to be upper case here.
    284      */
    285     LastCharIsDigit =
    286         (isdigit ((int) NameString[3]));    /* d */
    287     LastCharsAreHex =
    288         (isxdigit ((int) NameString[2]) &&  /* xx */
    289          isxdigit ((int) NameString[3]));
    290 
    291     switch (NameString[1])
    292     {
    293     case 'A':
    294 
    295         if ((NameString[2] == 'C') && (LastCharIsDigit))
    296         {
    297             NameString = "_ACx";
    298         }
    299         else if ((NameString[2] == 'L') && (LastCharIsDigit))
    300         {
    301             NameString = "_ALx";
    302         }
    303         break;
    304 
    305     case 'E':
    306 
    307         if ((NameString[2] == 'J') && (LastCharIsDigit))
    308         {
    309             NameString = "_EJx";
    310         }
    311         else if (LastCharsAreHex)
    312         {
    313             NameString = "_Exx";
    314         }
    315         break;
    316 
    317     case 'L':
    318 
    319         if (LastCharsAreHex)
    320         {
    321             NameString = "_Lxx";
    322         }
    323         break;
    324 
    325     case 'Q':
    326 
    327         if (LastCharsAreHex)
    328         {
    329             NameString = "_Qxx";
    330         }
    331         break;
    332 
    333     case 'T':
    334 
    335         if (NameString[2] == '_')
    336         {
    337             NameString = "_T_x";
    338         }
    339         break;
    340 
    341     case 'W':
    342 
    343         if (LastCharsAreHex)
    344         {
    345             NameString = "_Wxx";
    346         }
    347         break;
    348 
    349     default:
    350 
    351         break;
    352     }
    353 
    354     /* Match the name in the info table */
    355 
    356     Info = AcpiAhMatchPredefinedName (NameString);
    357     if (Info)
    358     {
    359         AcpiOsPrintf ("  // %4.4s: %s",
    360             NameString, ACPI_CAST_PTR (char, Info->Description));
    361     }
    362 
    363 #endif
    364     return;
    365 }
    366 
    367 
    368 /*******************************************************************************
    369  *
    370  * FUNCTION:    AcpiDmFieldPredefinedDescription
    371  *
    372  * PARAMETERS:  Op              - Parse object
    373  *
    374  * RETURN:      None
    375  *
    376  * DESCRIPTION: Emit a description comment for a resource descriptor tag
    377  *              (which is a predefined ACPI name.) Used for iASL compiler only.
    378  *
    379  ******************************************************************************/
    380 
    381 void
    382 AcpiDmFieldPredefinedDescription (
    383     ACPI_PARSE_OBJECT       *Op)
    384 {
    385 #ifdef ACPI_ASL_COMPILER
    386     ACPI_PARSE_OBJECT       *IndexOp;
    387     char                    *Tag;
    388     const ACPI_OPCODE_INFO  *OpInfo;
    389     const AH_PREDEFINED_NAME *Info;
    390 
    391 
    392     if (!Op)
    393     {
    394         return;
    395     }
    396 
    397     /* Ensure that the comment field is emitted only once */
    398 
    399     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
    400     {
    401         return;
    402     }
    403     Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
    404 
    405     /*
    406      * Op must be one of the Create* operators: CreateField, CreateBitField,
    407      * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
    408      */
    409     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    410     if (!(OpInfo->Flags & AML_CREATE))
    411     {
    412         return;
    413     }
    414 
    415     /* Second argument is the Index argument */
    416 
    417     IndexOp = Op->Common.Value.Arg;
    418     IndexOp = IndexOp->Common.Next;
    419 
    420     /* Index argument must be a namepath */
    421 
    422     if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
    423     {
    424         return;
    425     }
    426 
    427     /* Major cheat: We previously put the Tag ptr in the Node field */
    428 
    429     Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
    430     if (!Tag)
    431     {
    432         return;
    433     }
    434 
    435     /* Match the name in the info table */
    436 
    437     Info = AcpiAhMatchPredefinedName (Tag);
    438     if (Info)
    439     {
    440         AcpiOsPrintf ("  // %4.4s: %s", Tag,
    441             ACPI_CAST_PTR (char, Info->Description));
    442     }
    443 
    444 #endif
    445     return;
    446 }
    447 
    448 
    449 /*******************************************************************************
    450  *
    451  * FUNCTION:    AcpiDmMethodFlags
    452  *
    453  * PARAMETERS:  Op              - Method Object to be examined
    454  *
    455  * RETURN:      None
    456  *
    457  * DESCRIPTION: Decode control method flags
    458  *
    459  ******************************************************************************/
    460 
    461 void
    462 AcpiDmMethodFlags (
    463     ACPI_PARSE_OBJECT       *Op)
    464 {
    465     UINT32                  Flags;
    466     UINT32                  Args;
    467 
    468 
    469     /* The next Op contains the flags */
    470 
    471     Op = AcpiPsGetDepthNext (NULL, Op);
    472     Flags = (UINT8) Op->Common.Value.Integer;
    473     Args = Flags & 0x07;
    474 
    475     /* Mark the Op as completed */
    476 
    477     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    478 
    479     /* 1) Method argument count */
    480 
    481     AcpiOsPrintf (", %u, ", Args);
    482 
    483     /* 2) Serialize rule */
    484 
    485     if (!(Flags & 0x08))
    486     {
    487         AcpiOsPrintf ("Not");
    488     }
    489 
    490     AcpiOsPrintf ("Serialized");
    491 
    492     /* 3) SyncLevel */
    493 
    494     if (Flags & 0xF0)
    495     {
    496         AcpiOsPrintf (", %u", Flags >> 4);
    497     }
    498 }
    499 
    500 
    501 /*******************************************************************************
    502  *
    503  * FUNCTION:    AcpiDmFieldFlags
    504  *
    505  * PARAMETERS:  Op              - Field Object to be examined
    506  *
    507  * RETURN:      None
    508  *
    509  * DESCRIPTION: Decode Field definition flags
    510  *
    511  ******************************************************************************/
    512 
    513 void
    514 AcpiDmFieldFlags (
    515     ACPI_PARSE_OBJECT       *Op)
    516 {
    517     UINT32                  Flags;
    518 
    519 
    520     Op = Op->Common.Next;
    521     Flags = (UINT8) Op->Common.Value.Integer;
    522 
    523     /* Mark the Op as completed */
    524 
    525     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    526 
    527     AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
    528     AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
    529     AcpiOsPrintf ("%s)",  AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
    530 }
    531 
    532 
    533 /*******************************************************************************
    534  *
    535  * FUNCTION:    AcpiDmAddressSpace
    536  *
    537  * PARAMETERS:  SpaceId         - ID to be translated
    538  *
    539  * RETURN:      None
    540  *
    541  * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
    542  *
    543  ******************************************************************************/
    544 
    545 void
    546 AcpiDmAddressSpace (
    547     UINT8                   SpaceId)
    548 {
    549 
    550     if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
    551     {
    552         if (SpaceId == 0x7F)
    553         {
    554             AcpiOsPrintf ("FFixedHW, ");
    555         }
    556         else
    557         {
    558             AcpiOsPrintf ("0x%.2X, ", SpaceId);
    559         }
    560     }
    561     else
    562     {
    563         AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
    564     }
    565 }
    566 
    567 
    568 /*******************************************************************************
    569  *
    570  * FUNCTION:    AcpiDmRegionFlags
    571  *
    572  * PARAMETERS:  Op              - Object to be examined
    573  *
    574  * RETURN:      None
    575  *
    576  * DESCRIPTION: Decode OperationRegion flags
    577  *
    578  ******************************************************************************/
    579 
    580 void
    581 AcpiDmRegionFlags (
    582     ACPI_PARSE_OBJECT       *Op)
    583 {
    584 
    585     /* The next Op contains the SpaceId */
    586 
    587     Op = AcpiPsGetDepthNext (NULL, Op);
    588 
    589     /* Mark the Op as completed */
    590 
    591     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    592 
    593     AcpiOsPrintf (", ");
    594     AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
    595 }
    596 
    597 
    598 /*******************************************************************************
    599  *
    600  * FUNCTION:    AcpiDmMatchOp
    601  *
    602  * PARAMETERS:  Op              - Match Object to be examined
    603  *
    604  * RETURN:      None
    605  *
    606  * DESCRIPTION: Decode Match opcode operands
    607  *
    608  ******************************************************************************/
    609 
    610 void
    611 AcpiDmMatchOp (
    612     ACPI_PARSE_OBJECT       *Op)
    613 {
    614     ACPI_PARSE_OBJECT       *NextOp;
    615 
    616 
    617     NextOp = AcpiPsGetDepthNext (NULL, Op);
    618     NextOp = NextOp->Common.Next;
    619 
    620     if (!NextOp)
    621     {
    622         /* Handle partial tree during single-step */
    623 
    624         return;
    625     }
    626 
    627     /* Mark the two nodes that contain the encoding for the match keywords */
    628 
    629     NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
    630 
    631     NextOp = NextOp->Common.Next;
    632     NextOp = NextOp->Common.Next;
    633     NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
    634 }
    635 
    636 
    637 /*******************************************************************************
    638  *
    639  * FUNCTION:    AcpiDmMatchKeyword
    640  *
    641  * PARAMETERS:  Op              - Match Object to be examined
    642  *
    643  * RETURN:      None
    644  *
    645  * DESCRIPTION: Decode Match opcode operands
    646  *
    647  ******************************************************************************/
    648 
    649 static void
    650 AcpiDmMatchKeyword (
    651     ACPI_PARSE_OBJECT       *Op)
    652 {
    653 
    654     if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
    655     {
    656         AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
    657     }
    658     else
    659     {
    660         AcpiOsPrintf ("%s",
    661             AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]);
    662     }
    663 }
    664 
    665 
    666 /*******************************************************************************
    667  *
    668  * FUNCTION:    AcpiDmDisassembleOneOp
    669  *
    670  * PARAMETERS:  WalkState           - Current walk info
    671  *              Info                - Parse tree walk info
    672  *              Op                  - Op that is to be printed
    673  *
    674  * RETURN:      None
    675  *
    676  * DESCRIPTION: Disassemble a single AML opcode
    677  *
    678  ******************************************************************************/
    679 
    680 void
    681 AcpiDmDisassembleOneOp (
    682     ACPI_WALK_STATE         *WalkState,
    683     ACPI_OP_WALK_INFO       *Info,
    684     ACPI_PARSE_OBJECT       *Op)
    685 {
    686     const ACPI_OPCODE_INFO  *OpInfo = NULL;
    687     UINT32                  Offset;
    688     UINT32                  Length;
    689     ACPI_PARSE_OBJECT       *Child;
    690     ACPI_STATUS             Status;
    691     UINT8                   *Aml;
    692     const AH_DEVICE_ID      *IdInfo;
    693 
    694 
    695     if (!Op)
    696     {
    697         AcpiOsPrintf ("<NULL OP PTR>");
    698         return;
    699     }
    700 
    701     if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
    702     {
    703         return; /* ElseIf macro was already emitted */
    704     }
    705 
    706     switch (Op->Common.DisasmOpcode)
    707     {
    708     case ACPI_DASM_MATCHOP:
    709 
    710         AcpiDmMatchKeyword (Op);
    711         return;
    712 
    713     case ACPI_DASM_LNOT_SUFFIX:
    714 
    715         if (!AcpiGbl_CstyleDisassembly)
    716         {
    717             switch (Op->Common.AmlOpcode)
    718             {
    719             case AML_LEQUAL_OP:
    720                 AcpiOsPrintf ("LNotEqual");
    721                 break;
    722 
    723             case AML_LGREATER_OP:
    724                 AcpiOsPrintf ("LLessEqual");
    725                 break;
    726 
    727             case AML_LLESS_OP:
    728                 AcpiOsPrintf ("LGreaterEqual");
    729                 break;
    730 
    731             default:
    732                 break;
    733             }
    734         }
    735 
    736         Op->Common.DisasmOpcode = 0;
    737         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    738         return;
    739 
    740     default:
    741         break;
    742     }
    743 
    744     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    745 
    746     /* The op and arguments */
    747 
    748     switch (Op->Common.AmlOpcode)
    749     {
    750     case AML_LNOT_OP:
    751 
    752         Child = Op->Common.Value.Arg;
    753         if ((Child->Common.AmlOpcode == AML_LEQUAL_OP) ||
    754             (Child->Common.AmlOpcode == AML_LGREATER_OP) ||
    755             (Child->Common.AmlOpcode == AML_LLESS_OP))
    756         {
    757             Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
    758             Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
    759         }
    760         else
    761         {
    762             AcpiOsPrintf ("%s", OpInfo->Name);
    763         }
    764         break;
    765 
    766     case AML_BYTE_OP:
    767 
    768         AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
    769         break;
    770 
    771     case AML_WORD_OP:
    772 
    773         if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
    774         {
    775             AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
    776         }
    777         else
    778         {
    779             AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
    780         }
    781         break;
    782 
    783     case AML_DWORD_OP:
    784 
    785         if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
    786         {
    787             AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
    788         }
    789         else
    790         {
    791             AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
    792         }
    793         break;
    794 
    795     case AML_QWORD_OP:
    796 
    797         AcpiOsPrintf ("0x%8.8X%8.8X",
    798             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
    799         break;
    800 
    801     case AML_STRING_OP:
    802 
    803         AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
    804 
    805         /* For _HID/_CID strings, attempt to output a descriptive comment */
    806 
    807         if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
    808         {
    809             /* If we know about the ID, emit the description */
    810 
    811             IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
    812             if (IdInfo)
    813             {
    814                 AcpiOsPrintf (" /* %s */", IdInfo->Description);
    815             }
    816         }
    817         break;
    818 
    819     case AML_BUFFER_OP:
    820         /*
    821          * Determine the type of buffer. We can have one of the following:
    822          *
    823          * 1) ResourceTemplate containing Resource Descriptors.
    824          * 2) Unicode String buffer
    825          * 3) ASCII String buffer
    826          * 4) Raw data buffer (if none of the above)
    827          *
    828          * Since there are no special AML opcodes to differentiate these
    829          * types of buffers, we have to closely look at the data in the
    830          * buffer to determine the type.
    831          */
    832         if (!AcpiGbl_NoResourceDisassembly)
    833         {
    834             Status = AcpiDmIsResourceTemplate (WalkState, Op);
    835             if (ACPI_SUCCESS (Status))
    836             {
    837                 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
    838                 AcpiOsPrintf ("ResourceTemplate");
    839                 break;
    840             }
    841             else if (Status == AE_AML_NO_RESOURCE_END_TAG)
    842             {
    843                 AcpiOsPrintf (
    844                     "/**** Is ResourceTemplate, "
    845                     "but EndTag not at buffer end ****/ ");
    846             }
    847         }
    848 
    849         if (AcpiDmIsUuidBuffer (Op))
    850         {
    851             Op->Common.DisasmOpcode = ACPI_DASM_UUID;
    852             AcpiOsPrintf ("ToUUID (");
    853         }
    854         else if (AcpiDmIsUnicodeBuffer (Op))
    855         {
    856             Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
    857             AcpiOsPrintf ("Unicode (");
    858         }
    859         else if (AcpiDmIsStringBuffer (Op))
    860         {
    861             Op->Common.DisasmOpcode = ACPI_DASM_STRING;
    862             AcpiOsPrintf ("Buffer");
    863         }
    864         else if (AcpiDmIsPldBuffer (Op))
    865         {
    866             Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
    867             AcpiOsPrintf ("ToPLD (");
    868         }
    869         else
    870         {
    871             Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
    872             AcpiOsPrintf ("Buffer");
    873         }
    874         break;
    875 
    876     case AML_INT_NAMEPATH_OP:
    877 
    878         AcpiDmNamestring (Op->Common.Value.Name);
    879         break;
    880 
    881     case AML_INT_NAMEDFIELD_OP:
    882 
    883         Length = AcpiDmDumpName (Op->Named.Name);
    884         AcpiOsPrintf (",%*.s  %u", (unsigned) (5 - Length), " ",
    885             (UINT32) Op->Common.Value.Integer);
    886         AcpiDmCommaIfFieldMember (Op);
    887 
    888         Info->BitOffset += (UINT32) Op->Common.Value.Integer;
    889         break;
    890 
    891     case AML_INT_RESERVEDFIELD_OP:
    892 
    893         /* Offset() -- Must account for previous offsets */
    894 
    895         Offset = (UINT32) Op->Common.Value.Integer;
    896         Info->BitOffset += Offset;
    897 
    898         if (Info->BitOffset % 8 == 0)
    899         {
    900             AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
    901         }
    902         else
    903         {
    904             AcpiOsPrintf ("    ,   %u", Offset);
    905         }
    906 
    907         AcpiDmCommaIfFieldMember (Op);
    908         break;
    909 
    910     case AML_INT_ACCESSFIELD_OP:
    911     case AML_INT_EXTACCESSFIELD_OP:
    912 
    913         AcpiOsPrintf ("AccessAs (%s, ",
    914             AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
    915 
    916         AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
    917 
    918         if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
    919         {
    920             AcpiOsPrintf (" (0x%2.2X)", (unsigned)
    921                 ((Op->Common.Value.Integer >> 16) & 0xFF));
    922         }
    923 
    924         AcpiOsPrintf (")");
    925         AcpiDmCommaIfFieldMember (Op);
    926         break;
    927 
    928     case AML_INT_CONNECTION_OP:
    929         /*
    930          * Two types of Connection() - one with a buffer object, the
    931          * other with a namestring that points to a buffer object.
    932          */
    933         AcpiOsPrintf ("Connection (");
    934         Child = Op->Common.Value.Arg;
    935 
    936         if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
    937         {
    938             AcpiOsPrintf ("\n");
    939 
    940             Aml = Child->Named.Data;
    941             Length = (UINT32) Child->Common.Value.Integer;
    942 
    943             Info->Level += 1;
    944             Info->MappingOp = Op;
    945             Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
    946 
    947             AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
    948 
    949             Info->Level -= 1;
    950             AcpiDmIndent (Info->Level);
    951         }
    952         else
    953         {
    954             AcpiDmNamestring (Child->Common.Value.Name);
    955         }
    956 
    957         AcpiOsPrintf (")");
    958         AcpiDmCommaIfFieldMember (Op);
    959         AcpiOsPrintf ("\n");
    960 
    961         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
    962         Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    963         break;
    964 
    965     case AML_INT_BYTELIST_OP:
    966 
    967         AcpiDmByteList (Info, Op);
    968         break;
    969 
    970     case AML_INT_METHODCALL_OP:
    971 
    972         Op = AcpiPsGetDepthNext (NULL, Op);
    973         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
    974 
    975         AcpiDmNamestring (Op->Common.Value.Name);
    976         break;
    977 
    978     case AML_WHILE_OP:
    979 
    980         if (AcpiDmIsSwitchBlock(Op))
    981         {
    982             AcpiOsPrintf ("%s", "Switch");
    983             break;
    984         }
    985 
    986         AcpiOsPrintf ("%s", OpInfo->Name);
    987         break;
    988 
    989     case AML_IF_OP:
    990 
    991         if (Op->Common.DisasmOpcode == ACPI_DASM_CASE)
    992         {
    993             AcpiOsPrintf ("%s", "Case");
    994             break;
    995         }
    996 
    997         AcpiOsPrintf ("%s", OpInfo->Name);
    998         break;
    999 
   1000     case AML_ELSE_OP:
   1001 
   1002         AcpiDmConvertToElseIf (Op);
   1003         break;
   1004 
   1005     case AML_EXTERNAL_OP:
   1006 
   1007         if (AcpiGbl_DmEmitExternalOpcodes)
   1008         {
   1009             AcpiOsPrintf ("/* Opcode 0x15 */ ");
   1010 
   1011             /* Fallthrough */
   1012         }
   1013         else
   1014         {
   1015             break;
   1016         }
   1017 
   1018     default:
   1019 
   1020         /* Just get the opcode name and print it */
   1021 
   1022         AcpiOsPrintf ("%s", OpInfo->Name);
   1023 
   1024 
   1025 #ifdef ACPI_DEBUGGER
   1026 
   1027         if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
   1028             (WalkState) &&
   1029             (WalkState->Results) &&
   1030             (WalkState->ResultCount))
   1031         {
   1032             AcpiDbDecodeInternalObject (
   1033                 WalkState->Results->Results.ObjDesc [
   1034                     (WalkState->ResultCount - 1) %
   1035                         ACPI_RESULTS_FRAME_OBJ_NUM]);
   1036         }
   1037 #endif
   1038 
   1039         break;
   1040     }
   1041 }
   1042 
   1043 
   1044 /*******************************************************************************
   1045  *
   1046  * FUNCTION:    AcpiDmConvertToElseIf
   1047  *
   1048  * PARAMETERS:  OriginalElseOp          - ELSE Object to be examined
   1049  *
   1050  * RETURN:      None. Emits either an "Else" or an "ElseIf" ASL operator.
   1051  *
   1052  * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
   1053  *
   1054  * EXAMPLE:
   1055  *
   1056  * This If..Else..If nested sequence:
   1057  *
   1058  *        If (Arg0 == 1)
   1059  *        {
   1060  *            Local0 = 4
   1061  *        }
   1062  *        Else
   1063  *        {
   1064  *            If (Arg0 == 2)
   1065  *            {
   1066  *                Local0 = 5
   1067  *            }
   1068  *        }
   1069  *
   1070  * Is converted to this simpler If..ElseIf sequence:
   1071  *
   1072  *        If (Arg0 == 1)
   1073  *        {
   1074  *            Local0 = 4
   1075  *        }
   1076  *        ElseIf (Arg0 == 2)
   1077  *        {
   1078  *            Local0 = 5
   1079  *        }
   1080  *
   1081  * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
   1082  * macro that emits an Else opcode followed by an If opcode. This function
   1083  * reverses these AML sequences back to an ElseIf macro where possible. This
   1084  * can make the disassembled ASL code simpler and more like the original code.
   1085  *
   1086  ******************************************************************************/
   1087 
   1088 static void
   1089 AcpiDmConvertToElseIf (
   1090     ACPI_PARSE_OBJECT       *OriginalElseOp)
   1091 {
   1092     ACPI_PARSE_OBJECT       *IfOp;
   1093     ACPI_PARSE_OBJECT       *ElseOp;
   1094 
   1095 
   1096     /*
   1097      * To be able to perform the conversion, two conditions must be satisfied:
   1098      * 1) The first child of the Else must be an If statement.
   1099      * 2) The If block can only be followed by an Else block and these must
   1100      *    be the only blocks under the original Else.
   1101      */
   1102     IfOp = OriginalElseOp->Common.Value.Arg;
   1103 
   1104     if (!IfOp ||
   1105         (IfOp->Common.AmlOpcode != AML_IF_OP) ||
   1106         (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
   1107     {
   1108         /* Not a proper Else..If sequence, cannot convert to ElseIf */
   1109 
   1110         if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1111         {
   1112             AcpiOsPrintf ("%s", "Default");
   1113             return;
   1114         }
   1115 
   1116         AcpiOsPrintf ("%s", "Else");
   1117         return;
   1118     }
   1119 
   1120     /* Cannot have anything following the If...Else block */
   1121 
   1122     ElseOp = IfOp->Common.Next;
   1123     if (ElseOp && ElseOp->Common.Next)
   1124     {
   1125         if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1126         {
   1127             AcpiOsPrintf ("%s", "Default");
   1128             return;
   1129         }
   1130 
   1131         AcpiOsPrintf ("%s", "Else");
   1132         return;
   1133     }
   1134 
   1135     if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
   1136     {
   1137         /*
   1138          * There is an ElseIf but in this case the Else is actually
   1139          * a Default block for a Switch/Case statement. No conversion.
   1140          */
   1141         AcpiOsPrintf ("%s", "Default");
   1142         return;
   1143     }
   1144 
   1145     if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE)
   1146     {
   1147         /*
   1148          * This ElseIf is actually a Case block for a Switch/Case
   1149          * statement. Print Case but do not return so that we can
   1150          * promote the subtree and keep the indentation level.
   1151          */
   1152         AcpiOsPrintf ("%s", "Case");
   1153     }
   1154     else
   1155     {
   1156        /* Emit ElseIf, mark the IF as now an ELSEIF */
   1157 
   1158         AcpiOsPrintf ("%s", "ElseIf");
   1159     }
   1160 
   1161     IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
   1162 
   1163     /* The IF parent will now be the same as the original ELSE parent */
   1164 
   1165     IfOp->Common.Parent = OriginalElseOp->Common.Parent;
   1166 
   1167     /*
   1168      * Update the NEXT pointers to restructure the parse tree, essentially
   1169      * promoting an If..Else block up to the same level as the original
   1170      * Else.
   1171      *
   1172      * Check if the IF has a corresponding ELSE peer
   1173      */
   1174     ElseOp = IfOp->Common.Next;
   1175     if (ElseOp &&
   1176         (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
   1177     {
   1178         /* If an ELSE matches the IF, promote it also */
   1179 
   1180         ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
   1181 
   1182         /* Promote the entire block under the ElseIf (All Next OPs) */
   1183 
   1184         AcpiDmPromoteSubtree (OriginalElseOp);
   1185     }
   1186     else
   1187     {
   1188         /* Otherwise, set the IF NEXT to the original ELSE NEXT */
   1189 
   1190         IfOp->Common.Next = OriginalElseOp->Common.Next;
   1191     }
   1192 
   1193     /* Detach the child IF block from the original ELSE */
   1194 
   1195     OriginalElseOp->Common.Value.Arg = NULL;
   1196 
   1197     /* Ignore the original ELSE from now on */
   1198 
   1199     OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
   1200     OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
   1201 
   1202     /* Insert IF (now ELSEIF) as next peer of the original ELSE */
   1203 
   1204     OriginalElseOp->Common.Next = IfOp;
   1205 }
   1206 
   1207 
   1208 /*******************************************************************************
   1209  *
   1210  * FUNCTION:    AcpiDmPromoteSubtree
   1211  *
   1212  * PARAMETERS:  StartOpOp           - Original parent of the entire subtree
   1213  *
   1214  * RETURN:      None
   1215  *
   1216  * DESCRIPTION: Promote an entire parse subtree up one level.
   1217  *
   1218  ******************************************************************************/
   1219 
   1220 static void
   1221 AcpiDmPromoteSubtree (
   1222     ACPI_PARSE_OBJECT       *StartOp)
   1223 {
   1224     ACPI_PARSE_OBJECT       *Op;
   1225     ACPI_PARSE_OBJECT       *ParentOp;
   1226 
   1227 
   1228     /* New parent for subtree elements */
   1229 
   1230     ParentOp = StartOp->Common.Parent;
   1231 
   1232     /* First child starts the subtree */
   1233 
   1234     Op = StartOp->Common.Value.Arg;
   1235 
   1236     /* Walk the top-level elements of the subtree */
   1237 
   1238     while (Op)
   1239     {
   1240         Op->Common.Parent = ParentOp;
   1241         if (!Op->Common.Next)
   1242         {
   1243             /* Last Op in list, update its next field */
   1244 
   1245             Op->Common.Next = StartOp->Common.Next;
   1246             break;
   1247         }
   1248         Op = Op->Common.Next;
   1249     }
   1250 }
   1251 
   1252 /*******************************************************************************
   1253  *
   1254  * FUNCTION:    AcpiDmIsTempName
   1255  *
   1256  * PARAMETERS:  Op              - Object to be examined
   1257  *
   1258  * RETURN:      TRUE if object is a temporary (_T_x) name
   1259  *
   1260  * DESCRIPTION: Determine if an object is a temporary name and ignore it.
   1261  *              Temporary names are only used for Switch statements. This
   1262  *              function depends on this restriced usage.
   1263  *
   1264  ******************************************************************************/
   1265 
   1266 BOOLEAN
   1267 AcpiDmIsTempName (
   1268     ACPI_PARSE_OBJECT       *Op)
   1269 {
   1270     char                    *Temp;
   1271 
   1272     if (Op->Common.AmlOpcode != AML_NAME_OP)
   1273     {
   1274         return (FALSE);
   1275     }
   1276 
   1277     Temp = (char *)(Op->Common.Aml);
   1278     ++Temp;
   1279 
   1280     if (strncmp(Temp, "_T_", 3))
   1281     {
   1282         return (FALSE);
   1283     }
   1284 
   1285     /* Ignore Op */
   1286 
   1287     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
   1288 
   1289     return (TRUE);
   1290 }
   1291 
   1292 /*******************************************************************************
   1293  *
   1294  * FUNCTION:    AcpiDmIsSwitchBlock
   1295  *
   1296  * PARAMETERS:  Op              - While Object
   1297  *
   1298  * RETURN:      TRUE if While block can be converted to a Switch/Case block
   1299  *
   1300  * DESCRIPTION: Determines if While block is a Switch/Case statement. Modifies
   1301  *              parse tree to allow for Switch/Case disassembly during walk.
   1302  *
   1303  * EXAMPLE: Example of parse tree to be converted
   1304  *
   1305  *    While
   1306  *        One
   1307  *        Store
   1308  *            ByteConst
   1309  *             -NamePath-
   1310  *        If
   1311  *            LEqual
   1312  *                -NamePath-
   1313  *                Zero
   1314  *            Return
   1315  *                One
   1316  *        Else
   1317  *            Return
   1318  *                WordConst
   1319  *        Break
   1320  *
   1321  ******************************************************************************/
   1322 
   1323 static BOOLEAN
   1324 AcpiDmIsSwitchBlock (
   1325     ACPI_PARSE_OBJECT       *Op)
   1326 {
   1327     ACPI_PARSE_OBJECT       *OneOp;
   1328     ACPI_PARSE_OBJECT       *StoreOp;
   1329     ACPI_PARSE_OBJECT       *NamePathOp;
   1330     ACPI_PARSE_OBJECT       *PredicateOp;
   1331     ACPI_PARSE_OBJECT       *CurrentOp;
   1332     ACPI_PARSE_OBJECT       *TempOp;
   1333 
   1334     /* Check for One Op Predicate */
   1335 
   1336     OneOp = AcpiPsGetArg (Op, 0);
   1337     if (!OneOp || (OneOp->Common.AmlOpcode != AML_ONE_OP))
   1338     {
   1339         return (FALSE);
   1340     }
   1341 
   1342     /* Check for Store Op */
   1343 
   1344     StoreOp = OneOp->Common.Next;
   1345     if (!StoreOp || (StoreOp->Common.AmlOpcode != AML_STORE_OP))
   1346     {
   1347         return (FALSE);
   1348     }
   1349 
   1350     /* Check for Name Op with _T_ string */
   1351 
   1352     NamePathOp = AcpiPsGetArg (StoreOp, 1);
   1353     if (!NamePathOp || (NamePathOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
   1354     {
   1355         return (FALSE);
   1356     }
   1357 
   1358     if (strncmp((char *)(NamePathOp->Common.Aml), "_T_", 3))
   1359     {
   1360         return (FALSE);
   1361     }
   1362 
   1363     /* This is a Switch/Case control block */
   1364 
   1365     /* Ignore the One Op Predicate */
   1366 
   1367     OneOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
   1368 
   1369     /* Ignore the Store Op, but not the children */
   1370 
   1371     StoreOp->Common.DisasmOpcode = ACPI_DASM_IGNORE_SINGLE;
   1372 
   1373     /*
   1374      * First arg of Store Op is the Switch condition.
   1375      * Mark it as a Switch predicate and as a parameter list for paren
   1376      * closing and correct indentation.
   1377      */
   1378     PredicateOp = AcpiPsGetArg (StoreOp, 0);
   1379     PredicateOp->Common.DisasmOpcode = ACPI_DASM_SWITCH_PREDICATE;
   1380     PredicateOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
   1381 
   1382     /* Ignore the Name Op */
   1383 
   1384     NamePathOp->Common.DisasmFlags = ACPI_PARSEOP_IGNORE;
   1385 
   1386     /* Remaining opcodes are the Case statements (If/ElseIf's) */
   1387 
   1388     CurrentOp = StoreOp->Common.Next;
   1389     while (AcpiDmIsCaseBlock (CurrentOp))
   1390     {
   1391         /* Block is a Case structure */
   1392 
   1393         if (CurrentOp->Common.AmlOpcode == AML_ELSE_OP)
   1394         {
   1395             /* ElseIf */
   1396 
   1397             CurrentOp->Common.DisasmOpcode = ACPI_DASM_CASE;
   1398             CurrentOp = AcpiPsGetArg (CurrentOp, 0);
   1399         }
   1400 
   1401         /* If */
   1402 
   1403         CurrentOp->Common.DisasmOpcode = ACPI_DASM_CASE;
   1404 
   1405         /*
   1406          * Mark the parse tree for Case disassembly. There are two
   1407          * types of Case statements. The first type of statement begins with
   1408          * an LEqual. The second starts with an LNot and uses a Match statement
   1409          * on a Package of constants.
   1410          */
   1411         TempOp = AcpiPsGetArg (CurrentOp, 0);
   1412         switch (TempOp->Common.AmlOpcode)
   1413         {
   1414             case (AML_LEQUAL_OP):
   1415 
   1416                 /* Ignore just the LEqual Op */
   1417 
   1418                 TempOp->Common.DisasmOpcode = ACPI_DASM_IGNORE_SINGLE;
   1419 
   1420                 /* Ignore the NamePath Op */
   1421 
   1422                 TempOp = AcpiPsGetArg (TempOp, 0);
   1423                 TempOp->Common.DisasmFlags = ACPI_PARSEOP_IGNORE;
   1424 
   1425                 /*
   1426                  * Second arg of LEqual will be the Case predicate.
   1427                  * Mark it as a predicate and also as a parameter list for paren
   1428                  * closing and correct indentation.
   1429                  */
   1430                 PredicateOp = TempOp->Common.Next;
   1431                 PredicateOp->Common.DisasmOpcode = ACPI_DASM_SWITCH_PREDICATE;
   1432                 PredicateOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
   1433 
   1434                 break;
   1435 
   1436             case (AML_LNOT_OP):
   1437 
   1438                 /*
   1439                  * The Package will be the predicate of the Case statement.
   1440                  * It's under:
   1441                  *            LNOT
   1442                  *                LEQUAL
   1443                  *                    MATCH
   1444                  *                        PACKAGE
   1445                  */
   1446 
   1447                 /* Get the LEqual Op from LNot */
   1448 
   1449                 TempOp = AcpiPsGetArg (TempOp, 0);
   1450 
   1451                 /* Get the Match Op from LEqual */
   1452 
   1453                 TempOp = AcpiPsGetArg (TempOp, 0);
   1454 
   1455                 /* Get the Package Op from Match */
   1456 
   1457                 PredicateOp = AcpiPsGetArg (TempOp, 0);
   1458 
   1459                 /* Mark as parameter list for paren closing */
   1460 
   1461                 PredicateOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
   1462 
   1463                 /*
   1464                  * The Package list would be too deeply indented if we
   1465                  * chose to simply ignore the all the parent opcodes, so
   1466                  * we rearrange the parse tree instead.
   1467                  */
   1468 
   1469                 /*
   1470                  * Save the second arg of the If/Else Op which is the
   1471                  * block code of code for this Case statement.
   1472                  */
   1473                 TempOp = AcpiPsGetArg (CurrentOp, 1);
   1474 
   1475                 /*
   1476                  * Move the Package Op to the child (predicate) of the
   1477                  * Case statement.
   1478                  */
   1479                 CurrentOp->Common.Value.Arg = PredicateOp;
   1480                 PredicateOp->Common.Parent = CurrentOp;
   1481 
   1482                 /* Add the block code */
   1483 
   1484                 PredicateOp->Common.Next = TempOp;
   1485 
   1486                 break;
   1487 
   1488             default:
   1489 
   1490                 /* Should never get here */
   1491 
   1492                 break;
   1493         }
   1494 
   1495         /* Advance to next Case block */
   1496 
   1497         CurrentOp = CurrentOp->Common.Next;
   1498     }
   1499 
   1500     /* If CurrentOp is now an Else, then this is a Default block */
   1501 
   1502     if (CurrentOp && CurrentOp->Common.AmlOpcode == AML_ELSE_OP)
   1503     {
   1504         CurrentOp->Common.DisasmOpcode = ACPI_DASM_DEFAULT;
   1505     }
   1506 
   1507     /*
   1508      * From the first If advance to the Break op. It's possible to
   1509      * have an Else (Default) op here when there is only one Case
   1510      * statement, so check for it.
   1511      */
   1512     CurrentOp = StoreOp->Common.Next->Common.Next;
   1513     if (CurrentOp->Common.AmlOpcode == AML_ELSE_OP)
   1514     {
   1515         CurrentOp = CurrentOp->Common.Next;
   1516     }
   1517 
   1518     /* Ignore the Break Op */
   1519 
   1520     CurrentOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
   1521 
   1522     return (TRUE);
   1523 }
   1524 
   1525 /*******************************************************************************
   1526  *
   1527  * FUNCTION:    AcpiDmIsCaseBlock
   1528  *
   1529  * PARAMETERS:  Op              - Object to test
   1530  *
   1531  * RETURN:      TRUE if Object is beginning of a Case block.
   1532  *
   1533  * DESCRIPTION: Determines if an Object is the beginning of a Case block for a
   1534  *              Switch/Case statement. Parse tree must be one of the following
   1535  *              forms:
   1536  *
   1537  *              Else (Optional)
   1538  *                  If
   1539  *                      LEqual
   1540  *                          -NamePath- _T_x
   1541  *
   1542  *              Else (Optional)
   1543  *                  If
   1544  *                      LNot
   1545  *                          LEqual
   1546  *                              Match
   1547  *                                  Package
   1548  *                                      ByteConst
   1549  *                                      -NamePath- _T_x
   1550  *
   1551  ******************************************************************************/
   1552 
   1553 static BOOLEAN
   1554 AcpiDmIsCaseBlock (
   1555     ACPI_PARSE_OBJECT       *Op)
   1556 {
   1557     ACPI_PARSE_OBJECT       *CurrentOp;
   1558 
   1559     if (!Op)
   1560     {
   1561         return (FALSE);
   1562     }
   1563 
   1564     /* Look for an If or ElseIf */
   1565 
   1566     CurrentOp = Op;
   1567     if (CurrentOp->Common.AmlOpcode == AML_ELSE_OP)
   1568     {
   1569         CurrentOp = AcpiPsGetArg (CurrentOp, 0);
   1570         if (!CurrentOp)
   1571         {
   1572             return (FALSE);
   1573         }
   1574     }
   1575 
   1576     if (!CurrentOp || CurrentOp->Common.AmlOpcode != AML_IF_OP)
   1577     {
   1578         return (FALSE);
   1579     }
   1580 
   1581     /* Child must be LEqual or LNot */
   1582 
   1583     CurrentOp = AcpiPsGetArg (CurrentOp, 0);
   1584     if (!CurrentOp)
   1585     {
   1586         return (FALSE);
   1587     }
   1588 
   1589     switch (CurrentOp->Common.AmlOpcode)
   1590     {
   1591         case (AML_LEQUAL_OP):
   1592 
   1593             /* Next child must be NamePath with string _T_ */
   1594 
   1595             CurrentOp = AcpiPsGetArg (CurrentOp, 0);
   1596             if (!CurrentOp || !CurrentOp->Common.Value.Name ||
   1597                 strncmp(CurrentOp->Common.Value.Name, "_T_", 3))
   1598             {
   1599                 return (FALSE);
   1600             }
   1601 
   1602             break;
   1603 
   1604         case (AML_LNOT_OP):
   1605 
   1606             /* Child of LNot must be LEqual op */
   1607 
   1608             CurrentOp = AcpiPsGetArg (CurrentOp, 0);
   1609             if (!CurrentOp || (CurrentOp->Common.AmlOpcode != AML_LEQUAL_OP))
   1610             {
   1611                 return (FALSE);
   1612             }
   1613 
   1614             /* Child of LNot must be Match op */
   1615 
   1616             CurrentOp = AcpiPsGetArg (CurrentOp, 0);
   1617             if (!CurrentOp || (CurrentOp->Common.AmlOpcode != AML_MATCH_OP))
   1618             {
   1619                 return (FALSE);
   1620             }
   1621 
   1622             /* First child of Match must be Package op */
   1623 
   1624             CurrentOp = AcpiPsGetArg (CurrentOp, 0);
   1625             if (!CurrentOp || (CurrentOp->Common.AmlOpcode != AML_PACKAGE_OP))
   1626             {
   1627                 return (FALSE);
   1628             }
   1629 
   1630             /* Third child of Match must be NamePath with string _T_ */
   1631 
   1632             CurrentOp = AcpiPsGetArg (CurrentOp->Common.Parent, 2);
   1633             if (!CurrentOp || !CurrentOp->Common.Value.Name ||
   1634                 strncmp(CurrentOp->Common.Value.Name, "_T_", 3))
   1635             {
   1636                 return (FALSE);
   1637             }
   1638 
   1639             break;
   1640 
   1641         default:
   1642 
   1643             return (FALSE);
   1644     }
   1645 
   1646     return (TRUE);
   1647 }
   1648