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