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