1/*******************************************************************************
2 *
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
4 *
5 ******************************************************************************/
6
7/******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************
115 *
116 * Alternatively, you may choose to be licensed under the terms of the
117 * following license:
118 *
119 * Redistribution and use in source and binary forms, with or without
120 * modification, are permitted provided that the following conditions
121 * are met:
122 * 1. Redistributions of source code must retain the above copyright
123 *    notice, this list of conditions, and the following disclaimer,
124 *    without modification.
125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126 *    substantially similar to the "NO WARRANTY" disclaimer below
127 *    ("Disclaimer") and any redistribution must be conditioned upon
128 *    including a substantially similar Disclaimer requirement for further
129 *    binary redistribution.
130 * 3. Neither the names of the above-listed copyright holders nor the names
131 *    of any contributors may be used to endorse or promote products derived
132 *    from this software without specific prior written permission.
133 *
134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 *
146 * Alternatively, you may choose to be licensed under the terms of the
147 * GNU General Public License ("GPL") version 2 as published by the Free
148 * Software Foundation.
149 *
150 *****************************************************************************/
151
152#include <contrib/dev/acpica/include/acpi.h>
153#include <contrib/dev/acpica/include/accommon.h>
154#include <contrib/dev/acpica/include/acparser.h>
155#include <contrib/dev/acpica/include/amlcode.h>
156#include <contrib/dev/acpica/include/acinterp.h>
157#include <contrib/dev/acpica/include/acnamesp.h>
158#include <contrib/dev/acpica/include/acdebug.h>
159#include <contrib/dev/acpica/include/acconvert.h>
160
161
162#define _COMPONENT          ACPI_CA_DEBUGGER
163        ACPI_MODULE_NAME    ("dmopcode")
164
165
166/* Local prototypes */
167
168static void
169AcpiDmMatchKeyword (
170    ACPI_PARSE_OBJECT       *Op);
171
172static void
173AcpiDmConvertToElseIf (
174    ACPI_PARSE_OBJECT       *Op);
175
176static void
177AcpiDmPromoteSubtree (
178    ACPI_PARSE_OBJECT       *StartOp);
179
180/*******************************************************************************
181 *
182 * FUNCTION:    AcpiDmDisplayTargetPathname
183 *
184 * PARAMETERS:  Op              - Parse object
185 *
186 * RETURN:      None
187 *
188 * DESCRIPTION: For AML opcodes that have a target operand, display the full
189 *              pathname for the target, in a comment field. Handles Return()
190 *              statements also.
191 *
192 ******************************************************************************/
193
194void
195AcpiDmDisplayTargetPathname (
196    ACPI_PARSE_OBJECT       *Op)
197{
198    ACPI_PARSE_OBJECT       *NextOp;
199    ACPI_PARSE_OBJECT       *PrevOp = NULL;
200    char                    *Pathname;
201    const ACPI_OPCODE_INFO  *OpInfo;
202
203
204    if (Op->Common.AmlOpcode == AML_RETURN_OP)
205    {
206        PrevOp = Op->Asl.Value.Arg;
207    }
208    else
209    {
210        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
211        if (!(OpInfo->Flags & AML_HAS_TARGET))
212        {
213            return;
214        }
215
216        /* Target is the last Op in the arg list */
217
218        NextOp = Op->Asl.Value.Arg;
219        while (NextOp)
220        {
221            PrevOp = NextOp;
222            NextOp = PrevOp->Asl.Next;
223        }
224    }
225
226    if (!PrevOp)
227    {
228        return;
229    }
230
231    /* We must have a namepath AML opcode */
232
233    if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
234    {
235        return;
236    }
237
238    /* A null string is the "no target specified" case */
239
240    if (!PrevOp->Asl.Value.String)
241    {
242        return;
243    }
244
245    /* No node means "unresolved external reference" */
246
247    if (!PrevOp->Asl.Node)
248    {
249        AcpiOsPrintf (" /* External reference */");
250        return;
251    }
252
253    /* Ignore if path is already from the root */
254
255    if (*PrevOp->Asl.Value.String == '\\')
256    {
257        return;
258    }
259
260    /* Now: we can get the full pathname */
261
262    Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
263    if (!Pathname)
264    {
265        return;
266    }
267
268    AcpiOsPrintf (" /* %s */", Pathname);
269    ACPI_FREE (Pathname);
270}
271
272
273/*******************************************************************************
274 *
275 * FUNCTION:    AcpiDmNotifyDescription
276 *
277 * PARAMETERS:  Op              - Name() parse object
278 *
279 * RETURN:      None
280 *
281 * DESCRIPTION: Emit a description comment for the value associated with a
282 *              Notify() operator.
283 *
284 ******************************************************************************/
285
286void
287AcpiDmNotifyDescription (
288    ACPI_PARSE_OBJECT       *Op)
289{
290    ACPI_PARSE_OBJECT       *NextOp;
291    ACPI_NAMESPACE_NODE     *Node;
292    UINT8                   NotifyValue;
293    UINT8                   Type = ACPI_TYPE_ANY;
294
295
296    /* The notify value is the second argument */
297
298    NextOp = Op->Asl.Value.Arg;
299    NextOp = NextOp->Asl.Next;
300
301    switch (NextOp->Common.AmlOpcode)
302    {
303    case AML_ZERO_OP:
304    case AML_ONE_OP:
305
306        NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
307        break;
308
309    case AML_BYTE_OP:
310
311        NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
312        break;
313
314    default:
315        return;
316    }
317
318    /*
319     * Attempt to get the namespace node so we can determine the object type.
320     * Some notify values are dependent on the object type (Device, Thermal,
321     * or Processor).
322     */
323    Node = Op->Asl.Node;
324    if (Node)
325    {
326        Type = Node->Type;
327    }
328
329    AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
330}
331
332
333/*******************************************************************************
334 *
335 * FUNCTION:    AcpiDmPredefinedDescription
336 *
337 * PARAMETERS:  Op              - Name() parse object
338 *
339 * RETURN:      None
340 *
341 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
342 *              Used for iASL compiler only.
343 *
344 ******************************************************************************/
345
346void
347AcpiDmPredefinedDescription (
348    ACPI_PARSE_OBJECT       *Op)
349{
350#ifdef ACPI_ASL_COMPILER
351    const AH_PREDEFINED_NAME    *Info;
352    char                        *NameString;
353    int                         LastCharIsDigit;
354    int                         LastCharsAreHex;
355
356
357    if (!Op)
358    {
359        return;
360    }
361
362    /* Ensure that the comment field is emitted only once */
363
364    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
365    {
366        return;
367    }
368    Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
369
370    /* Predefined name must start with an underscore */
371
372    NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
373    if (NameString[0] != '_')
374    {
375        return;
376    }
377
378    /*
379     * Check for the special ACPI names:
380     * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
381     * (where d=decimal_digit, x=hex_digit, a=anything)
382     *
383     * Convert these to the generic name for table lookup.
384     * Note: NameString is guaranteed to be upper case here.
385     */
386    LastCharIsDigit =
387        (isdigit ((int) NameString[3]));    /* d */
388    LastCharsAreHex =
389        (isxdigit ((int) NameString[2]) &&  /* xx */
390         isxdigit ((int) NameString[3]));
391
392    switch (NameString[1])
393    {
394    case 'A':
395
396        if ((NameString[2] == 'C') && (LastCharIsDigit))
397        {
398            NameString = "_ACx";
399        }
400        else if ((NameString[2] == 'L') && (LastCharIsDigit))
401        {
402            NameString = "_ALx";
403        }
404        break;
405
406    case 'E':
407
408        if ((NameString[2] == 'J') && (LastCharIsDigit))
409        {
410            NameString = "_EJx";
411        }
412        else if (LastCharsAreHex)
413        {
414            NameString = "_Exx";
415        }
416        break;
417
418    case 'L':
419
420        if (LastCharsAreHex)
421        {
422            NameString = "_Lxx";
423        }
424        break;
425
426    case 'Q':
427
428        if (LastCharsAreHex)
429        {
430            NameString = "_Qxx";
431        }
432        break;
433
434    case 'T':
435
436        if (NameString[2] == '_')
437        {
438            NameString = "_T_x";
439        }
440        break;
441
442    case 'W':
443
444        if (LastCharsAreHex)
445        {
446            NameString = "_Wxx";
447        }
448        break;
449
450    default:
451
452        break;
453    }
454
455    /* Match the name in the info table */
456
457    Info = AcpiAhMatchPredefinedName (NameString);
458    if (Info)
459    {
460        AcpiOsPrintf ("  // %4.4s: %s",
461            NameString, ACPI_CAST_PTR (char, Info->Description));
462    }
463
464#endif
465    return;
466}
467
468
469/*******************************************************************************
470 *
471 * FUNCTION:    AcpiDmFieldPredefinedDescription
472 *
473 * PARAMETERS:  Op              - Parse object
474 *
475 * RETURN:      None
476 *
477 * DESCRIPTION: Emit a description comment for a resource descriptor tag
478 *              (which is a predefined ACPI name.) Used for iASL compiler only.
479 *
480 ******************************************************************************/
481
482void
483AcpiDmFieldPredefinedDescription (
484    ACPI_PARSE_OBJECT       *Op)
485{
486#ifdef ACPI_ASL_COMPILER
487    ACPI_PARSE_OBJECT       *IndexOp;
488    char                    *Tag;
489    const ACPI_OPCODE_INFO  *OpInfo;
490    const AH_PREDEFINED_NAME *Info;
491
492
493    if (!Op)
494    {
495        return;
496    }
497
498    /* Ensure that the comment field is emitted only once */
499
500    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
501    {
502        return;
503    }
504    Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
505
506    /*
507     * Op must be one of the Create* operators: CreateField, CreateBitField,
508     * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
509     */
510    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
511    if (!(OpInfo->Flags & AML_CREATE))
512    {
513        return;
514    }
515
516    /* Second argument is the Index argument */
517
518    IndexOp = Op->Common.Value.Arg;
519    IndexOp = IndexOp->Common.Next;
520
521    /* Index argument must be a namepath */
522
523    if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
524    {
525        return;
526    }
527
528    /* Major cheat: We previously put the Tag ptr in the Node field */
529
530    Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
531    if (!Tag || (*Tag == 0))
532    {
533        return;
534    }
535
536    /* Is the tag a predefined name? */
537
538    Info = AcpiAhMatchPredefinedName (Tag);
539    if (!Info)
540    {
541        /* Not a predefined name (does not start with underscore) */
542
543        return;
544    }
545
546    AcpiOsPrintf ("  // %4.4s: %s", Tag,
547        ACPI_CAST_PTR (char, Info->Description));
548
549    /* String contains the prefix path, free it */
550
551    ACPI_FREE (IndexOp->Common.Value.String);
552    IndexOp->Common.Value.String = NULL;
553#endif
554
555    return;
556}
557
558
559/*******************************************************************************
560 *
561 * FUNCTION:    AcpiDmMethodFlags
562 *
563 * PARAMETERS:  Op              - Method Object to be examined
564 *
565 * RETURN:      None
566 *
567 * DESCRIPTION: Decode control method flags
568 *
569 ******************************************************************************/
570
571void
572AcpiDmMethodFlags (
573    ACPI_PARSE_OBJECT       *Op)
574{
575    UINT32                  Flags;
576    UINT32                  Args;
577
578
579    /* The next Op contains the flags */
580
581    Op = AcpiPsGetDepthNext (NULL, Op);
582    Flags = (UINT8) Op->Common.Value.Integer;
583    Args = Flags & 0x07;
584
585    /* Mark the Op as completed */
586
587    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
588
589    /* 1) Method argument count */
590
591    AcpiOsPrintf (", %u, ", Args);
592
593    /* 2) Serialize rule */
594
595    if (!(Flags & 0x08))
596    {
597        AcpiOsPrintf ("Not");
598    }
599
600    AcpiOsPrintf ("Serialized");
601
602    /* 3) SyncLevel */
603
604    if (Flags & 0xF0)
605    {
606        AcpiOsPrintf (", %u", Flags >> 4);
607    }
608}
609
610
611/*******************************************************************************
612 *
613 * FUNCTION:    AcpiDmFieldFlags
614 *
615 * PARAMETERS:  Op              - Field Object to be examined
616 *
617 * RETURN:      None
618 *
619 * DESCRIPTION: Decode Field definition flags
620 *
621 ******************************************************************************/
622
623void
624AcpiDmFieldFlags (
625    ACPI_PARSE_OBJECT       *Op)
626{
627    UINT32                  Flags;
628
629
630    Op = Op->Common.Next;
631    Flags = (UINT8) Op->Common.Value.Integer;
632
633    /* Mark the Op as completed */
634
635    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
636
637    AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
638    AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
639    AcpiOsPrintf ("%s)",  AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
640}
641
642
643/*******************************************************************************
644 *
645 * FUNCTION:    AcpiDmAddressSpace
646 *
647 * PARAMETERS:  SpaceId         - ID to be translated
648 *
649 * RETURN:      None
650 *
651 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
652 *
653 ******************************************************************************/
654
655void
656AcpiDmAddressSpace (
657    UINT8                   SpaceId)
658{
659
660    if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
661    {
662        if (SpaceId == 0x7F)
663        {
664            AcpiOsPrintf ("FFixedHW, ");
665        }
666        else
667        {
668            AcpiOsPrintf ("0x%.2X, ", SpaceId);
669        }
670    }
671    else
672    {
673        AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
674    }
675}
676
677
678/*******************************************************************************
679 *
680 * FUNCTION:    AcpiDmRegionFlags
681 *
682 * PARAMETERS:  Op              - Object to be examined
683 *
684 * RETURN:      None
685 *
686 * DESCRIPTION: Decode OperationRegion flags
687 *
688 ******************************************************************************/
689
690void
691AcpiDmRegionFlags (
692    ACPI_PARSE_OBJECT       *Op)
693{
694
695    /* The next Op contains the SpaceId */
696
697    Op = AcpiPsGetDepthNext (NULL, Op);
698
699    /* Mark the Op as completed */
700
701    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
702
703    AcpiOsPrintf (", ");
704    AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
705}
706
707
708/*******************************************************************************
709 *
710 * FUNCTION:    AcpiDmMatchOp
711 *
712 * PARAMETERS:  Op              - Match Object to be examined
713 *
714 * RETURN:      None
715 *
716 * DESCRIPTION: Decode Match opcode operands
717 *
718 ******************************************************************************/
719
720void
721AcpiDmMatchOp (
722    ACPI_PARSE_OBJECT       *Op)
723{
724    ACPI_PARSE_OBJECT       *NextOp;
725
726
727    NextOp = AcpiPsGetDepthNext (NULL, Op);
728    NextOp = NextOp->Common.Next;
729
730    if (!NextOp)
731    {
732        /* Handle partial tree during single-step */
733
734        return;
735    }
736
737    /* Mark the two nodes that contain the encoding for the match keywords */
738
739    NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
740
741    NextOp = NextOp->Common.Next;
742    NextOp = NextOp->Common.Next;
743    NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
744}
745
746
747/*******************************************************************************
748 *
749 * FUNCTION:    AcpiDmMatchKeyword
750 *
751 * PARAMETERS:  Op              - Match Object to be examined
752 *
753 * RETURN:      None
754 *
755 * DESCRIPTION: Decode Match opcode operands
756 *
757 ******************************************************************************/
758
759static void
760AcpiDmMatchKeyword (
761    ACPI_PARSE_OBJECT       *Op)
762{
763
764    if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
765    {
766        AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
767    }
768    else
769    {
770        AcpiOsPrintf ("%s",
771            AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]);
772    }
773}
774
775
776/*******************************************************************************
777 *
778 * FUNCTION:    AcpiDmDisassembleOneOp
779 *
780 * PARAMETERS:  WalkState           - Current walk info
781 *              Info                - Parse tree walk info
782 *              Op                  - Op that is to be printed
783 *
784 * RETURN:      None
785 *
786 * DESCRIPTION: Disassemble a single AML opcode
787 *
788 ******************************************************************************/
789
790void
791AcpiDmDisassembleOneOp (
792    ACPI_WALK_STATE         *WalkState,
793    ACPI_OP_WALK_INFO       *Info,
794    ACPI_PARSE_OBJECT       *Op)
795{
796    const ACPI_OPCODE_INFO  *OpInfo = NULL;
797    UINT32                  Offset;
798    UINT32                  Length;
799    ACPI_PARSE_OBJECT       *Child;
800    ACPI_STATUS             Status;
801    UINT8                   *Aml;
802    const AH_DEVICE_ID      *IdInfo;
803
804
805    if (!Op)
806    {
807        AcpiOsPrintf ("<NULL OP PTR>");
808        return;
809    }
810
811    if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
812    {
813        return; /* ElseIf macro was already emitted */
814    }
815
816    switch (Op->Common.DisasmOpcode)
817    {
818    case ACPI_DASM_MATCHOP:
819
820        AcpiDmMatchKeyword (Op);
821        return;
822
823    case ACPI_DASM_LNOT_SUFFIX:
824
825        if (!AcpiGbl_CstyleDisassembly)
826        {
827            switch (Op->Common.AmlOpcode)
828            {
829            case AML_LOGICAL_EQUAL_OP:
830                AcpiOsPrintf ("LNotEqual");
831                break;
832
833            case AML_LOGICAL_GREATER_OP:
834                AcpiOsPrintf ("LLessEqual");
835                break;
836
837            case AML_LOGICAL_LESS_OP:
838                AcpiOsPrintf ("LGreaterEqual");
839                break;
840
841            default:
842                break;
843            }
844        }
845
846        Op->Common.DisasmOpcode = 0;
847        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
848        return;
849
850    default:
851        break;
852    }
853
854    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
855
856    /* The op and arguments */
857
858    switch (Op->Common.AmlOpcode)
859    {
860    case AML_LOGICAL_NOT_OP:
861
862        Child = Op->Common.Value.Arg;
863        if ((Child->Common.AmlOpcode == AML_LOGICAL_EQUAL_OP) ||
864            (Child->Common.AmlOpcode == AML_LOGICAL_GREATER_OP) ||
865            (Child->Common.AmlOpcode == AML_LOGICAL_LESS_OP))
866        {
867            Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
868            Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
869        }
870        else
871        {
872            AcpiOsPrintf ("%s", OpInfo->Name);
873        }
874        break;
875
876    case AML_BYTE_OP:
877
878        AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
879        break;
880
881    case AML_WORD_OP:
882
883        if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
884        {
885            AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
886        }
887        else
888        {
889            AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
890        }
891        break;
892
893    case AML_DWORD_OP:
894
895        if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
896        {
897            AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
898        }
899        else
900        {
901            AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
902        }
903        break;
904
905    case AML_QWORD_OP:
906
907        AcpiOsPrintf ("0x%8.8X%8.8X",
908            ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
909        break;
910
911    case AML_STRING_OP:
912
913        AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
914
915        /* For _HID/_CID strings, attempt to output a descriptive comment */
916
917        if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
918        {
919            /* If we know about the ID, emit the description */
920
921            IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
922            if (IdInfo)
923            {
924                AcpiOsPrintf (" /* %s */", IdInfo->Description);
925            }
926        }
927        break;
928
929    case AML_BUFFER_OP:
930        /*
931         * Determine the type of buffer. We can have one of the following:
932         *
933         * 1) ResourceTemplate containing Resource Descriptors.
934         * 2) Unicode String buffer
935         * 3) ASCII String buffer
936         * 4) Raw data buffer (if none of the above)
937         *
938         * Since there are no special AML opcodes to differentiate these
939         * types of buffers, we have to closely look at the data in the
940         * buffer to determine the type.
941         */
942        if (!AcpiGbl_NoResourceDisassembly)
943        {
944            Status = AcpiDmIsResourceTemplate (WalkState, Op);
945            if (ACPI_SUCCESS (Status))
946            {
947                Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
948                AcpiOsPrintf ("ResourceTemplate");
949                break;
950            }
951            else if (Status == AE_AML_NO_RESOURCE_END_TAG)
952            {
953                AcpiOsPrintf (
954                    "/**** Is ResourceTemplate, "
955                    "but EndTag not at buffer end ****/ ");
956            }
957        }
958
959        if (AcpiDmIsUuidBuffer (Op))
960        {
961            Op->Common.DisasmOpcode = ACPI_DASM_UUID;
962            AcpiOsPrintf ("ToUUID (");
963        }
964        else if (AcpiDmIsUnicodeBuffer (Op))
965        {
966            Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
967            AcpiOsPrintf ("Unicode (");
968        }
969        else if (AcpiDmIsStringBuffer (Op))
970        {
971            Op->Common.DisasmOpcode = ACPI_DASM_STRING;
972            AcpiOsPrintf ("Buffer");
973        }
974        else if (AcpiDmIsPldBuffer (Op))
975        {
976            Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
977            AcpiOsPrintf ("ToPLD (");
978        }
979        else
980        {
981            Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
982            AcpiOsPrintf ("Buffer");
983        }
984        break;
985
986    case AML_INT_NAMEPATH_OP:
987
988        AcpiDmNamestring (Op->Common.Value.Name);
989        break;
990
991    case AML_INT_NAMEDFIELD_OP:
992
993        Length = AcpiDmDumpName (Op->Named.Name);
994
995        AcpiOsPrintf (",");
996        ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
997        AcpiOsPrintf ("%*.s  %u", (unsigned) (5 - Length), " ",
998            (UINT32) Op->Common.Value.Integer);
999
1000        AcpiDmCommaIfFieldMember (Op);
1001
1002        Info->BitOffset += (UINT32) Op->Common.Value.Integer;
1003        break;
1004
1005    case AML_INT_RESERVEDFIELD_OP:
1006
1007        /* Offset() -- Must account for previous offsets */
1008
1009        Offset = (UINT32) Op->Common.Value.Integer;
1010        Info->BitOffset += Offset;
1011
1012        if (Info->BitOffset % 8 == 0)
1013        {
1014            AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
1015        }
1016        else
1017        {
1018            AcpiOsPrintf ("    ,   %u", Offset);
1019        }
1020
1021        AcpiDmCommaIfFieldMember (Op);
1022        break;
1023
1024    case AML_INT_ACCESSFIELD_OP:
1025    case AML_INT_EXTACCESSFIELD_OP:
1026
1027        AcpiOsPrintf ("AccessAs (%s, ",
1028            AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
1029
1030        AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
1031
1032        if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
1033        {
1034            AcpiOsPrintf (" (0x%2.2X)", (unsigned)
1035                ((Op->Common.Value.Integer >> 16) & 0xFF));
1036        }
1037
1038        AcpiOsPrintf (")");
1039        AcpiDmCommaIfFieldMember (Op);
1040        ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
1041        break;
1042
1043    case AML_INT_CONNECTION_OP:
1044        /*
1045         * Two types of Connection() - one with a buffer object, the
1046         * other with a namestring that points to a buffer object.
1047         */
1048        AcpiOsPrintf ("Connection (");
1049        Child = Op->Common.Value.Arg;
1050
1051        if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
1052        {
1053            AcpiOsPrintf ("\n");
1054
1055            Aml = Child->Named.Data;
1056            Length = (UINT32) Child->Common.Value.Integer;
1057
1058            Info->Level += 1;
1059            Info->MappingOp = Op;
1060            Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
1061
1062            AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
1063
1064            Info->Level -= 1;
1065            AcpiDmIndent (Info->Level);
1066        }
1067        else
1068        {
1069            AcpiDmNamestring (Child->Common.Value.Name);
1070        }
1071
1072        AcpiOsPrintf (")");
1073        AcpiDmCommaIfFieldMember (Op);
1074        ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
1075        ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, NULL, 0);
1076        AcpiOsPrintf ("\n");
1077
1078        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
1079        Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1080        break;
1081
1082    case AML_INT_BYTELIST_OP:
1083
1084        AcpiDmByteList (Info, Op);
1085        break;
1086
1087    case AML_INT_METHODCALL_OP:
1088
1089        Op = AcpiPsGetDepthNext (NULL, Op);
1090        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1091
1092        AcpiDmNamestring (Op->Common.Value.Name);
1093        break;
1094
1095    case AML_WHILE_OP:
1096
1097        if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH)
1098        {
1099            AcpiOsPrintf ("%s", "Switch");
1100            break;
1101        }
1102
1103        AcpiOsPrintf ("%s", OpInfo->Name);
1104        break;
1105
1106    case AML_IF_OP:
1107
1108        if (Op->Common.DisasmOpcode == ACPI_DASM_CASE)
1109        {
1110            AcpiOsPrintf ("%s", "Case");
1111            break;
1112        }
1113
1114        AcpiOsPrintf ("%s", OpInfo->Name);
1115        break;
1116
1117    case AML_ELSE_OP:
1118
1119        AcpiDmConvertToElseIf (Op);
1120        break;
1121
1122    case AML_EXTERNAL_OP:
1123
1124        if (AcpiGbl_DmEmitExternalOpcodes)
1125        {
1126            AcpiDmEmitExternal (Op, AcpiPsGetArg(Op, 0));
1127        }
1128
1129        break;
1130
1131    default:
1132
1133        /* Just get the opcode name and print it */
1134
1135        AcpiOsPrintf ("%s", OpInfo->Name);
1136
1137
1138#ifdef ACPI_DEBUGGER
1139
1140        if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
1141            (WalkState) &&
1142            (WalkState->Results) &&
1143            (WalkState->ResultCount))
1144        {
1145            AcpiDbDecodeInternalObject (
1146                WalkState->Results->Results.ObjDesc [
1147                    (WalkState->ResultCount - 1) %
1148                        ACPI_RESULTS_FRAME_OBJ_NUM]);
1149        }
1150#endif
1151
1152        break;
1153    }
1154}
1155
1156
1157/*******************************************************************************
1158 *
1159 * FUNCTION:    AcpiDmConvertToElseIf
1160 *
1161 * PARAMETERS:  OriginalElseOp          - ELSE Object to be examined
1162 *
1163 * RETURN:      None. Emits either an "Else" or an "ElseIf" ASL operator.
1164 *
1165 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
1166 *
1167 * EXAMPLE:
1168 *
1169 * This If..Else..If nested sequence:
1170 *
1171 *        If (Arg0 == 1)
1172 *        {
1173 *            Local0 = 4
1174 *        }
1175 *        Else
1176 *        {
1177 *            If (Arg0 == 2)
1178 *            {
1179 *                Local0 = 5
1180 *            }
1181 *        }
1182 *
1183 * Is converted to this simpler If..ElseIf sequence:
1184 *
1185 *        If (Arg0 == 1)
1186 *        {
1187 *            Local0 = 4
1188 *        }
1189 *        ElseIf (Arg0 == 2)
1190 *        {
1191 *            Local0 = 5
1192 *        }
1193 *
1194 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
1195 * macro that emits an Else opcode followed by an If opcode. This function
1196 * reverses these AML sequences back to an ElseIf macro where possible. This
1197 * can make the disassembled ASL code simpler and more like the original code.
1198 *
1199 ******************************************************************************/
1200
1201static void
1202AcpiDmConvertToElseIf (
1203    ACPI_PARSE_OBJECT       *OriginalElseOp)
1204{
1205    ACPI_PARSE_OBJECT       *IfOp;
1206    ACPI_PARSE_OBJECT       *ElseOp;
1207
1208
1209    /*
1210     * To be able to perform the conversion, two conditions must be satisfied:
1211     * 1) The first child of the Else must be an If statement.
1212     * 2) The If block can only be followed by an Else block and these must
1213     *    be the only blocks under the original Else.
1214     */
1215    IfOp = OriginalElseOp->Common.Value.Arg;
1216
1217    if (!IfOp ||
1218        (IfOp->Common.AmlOpcode != AML_IF_OP) ||
1219        (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
1220    {
1221        /* Not a proper Else..If sequence, cannot convert to ElseIf */
1222
1223        if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1224        {
1225            AcpiOsPrintf ("%s", "Default");
1226            return;
1227        }
1228
1229        AcpiOsPrintf ("%s", "Else");
1230        return;
1231    }
1232
1233    /* Cannot have anything following the If...Else block */
1234
1235    ElseOp = IfOp->Common.Next;
1236    if (ElseOp && ElseOp->Common.Next)
1237    {
1238        if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1239        {
1240            AcpiOsPrintf ("%s", "Default");
1241            return;
1242        }
1243
1244        AcpiOsPrintf ("%s", "Else");
1245        return;
1246    }
1247
1248    if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1249    {
1250        /*
1251         * There is an ElseIf but in this case the Else is actually
1252         * a Default block for a Switch/Case statement. No conversion.
1253         */
1254        AcpiOsPrintf ("%s", "Default");
1255        return;
1256    }
1257
1258    if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE)
1259    {
1260        /*
1261         * This ElseIf is actually a Case block for a Switch/Case
1262         * statement. Print Case but do not return so that we can
1263         * promote the subtree and keep the indentation level.
1264         */
1265        AcpiOsPrintf ("%s", "Case");
1266    }
1267    else
1268    {
1269       /* Emit ElseIf, mark the IF as now an ELSEIF */
1270
1271        AcpiOsPrintf ("%s", "ElseIf");
1272    }
1273
1274    IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
1275
1276    /* The IF parent will now be the same as the original ELSE parent */
1277
1278    IfOp->Common.Parent = OriginalElseOp->Common.Parent;
1279
1280    /*
1281     * Update the NEXT pointers to restructure the parse tree, essentially
1282     * promoting an If..Else block up to the same level as the original
1283     * Else.
1284     *
1285     * Check if the IF has a corresponding ELSE peer
1286     */
1287    ElseOp = IfOp->Common.Next;
1288    if (ElseOp &&
1289        (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
1290    {
1291        /* If an ELSE matches the IF, promote it also */
1292
1293        ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
1294
1295        /* Promote the entire block under the ElseIf (All Next OPs) */
1296
1297        AcpiDmPromoteSubtree (OriginalElseOp);
1298    }
1299    else
1300    {
1301        /* Otherwise, set the IF NEXT to the original ELSE NEXT */
1302
1303        IfOp->Common.Next = OriginalElseOp->Common.Next;
1304    }
1305
1306    /* Detach the child IF block from the original ELSE */
1307
1308    OriginalElseOp->Common.Value.Arg = NULL;
1309
1310    /* Ignore the original ELSE from now on */
1311
1312    OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1313    OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
1314
1315    /* Insert IF (now ELSEIF) as next peer of the original ELSE */
1316
1317    OriginalElseOp->Common.Next = IfOp;
1318}
1319
1320
1321/*******************************************************************************
1322 *
1323 * FUNCTION:    AcpiDmPromoteSubtree
1324 *
1325 * PARAMETERS:  StartOpOp           - Original parent of the entire subtree
1326 *
1327 * RETURN:      None
1328 *
1329 * DESCRIPTION: Promote an entire parse subtree up one level.
1330 *
1331 ******************************************************************************/
1332
1333static void
1334AcpiDmPromoteSubtree (
1335    ACPI_PARSE_OBJECT       *StartOp)
1336{
1337    ACPI_PARSE_OBJECT       *Op;
1338    ACPI_PARSE_OBJECT       *ParentOp;
1339
1340
1341    /* New parent for subtree elements */
1342
1343    ParentOp = StartOp->Common.Parent;
1344
1345    /* First child starts the subtree */
1346
1347    Op = StartOp->Common.Value.Arg;
1348
1349    /* Walk the top-level elements of the subtree */
1350
1351    while (Op)
1352    {
1353        Op->Common.Parent = ParentOp;
1354        if (!Op->Common.Next)
1355        {
1356            /* Last Op in list, update its next field */
1357
1358            Op->Common.Next = StartOp->Common.Next;
1359            break;
1360        }
1361        Op = Op->Common.Next;
1362    }
1363}
1364