]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/components/disassembler/dmopcode.c
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304659, and update
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / components / disassembler / dmopcode.c
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
168 static void
169 AcpiDmMatchKeyword (
170     ACPI_PARSE_OBJECT       *Op);
171
172 static void
173 AcpiDmConvertToElseIf (
174     ACPI_PARSE_OBJECT       *Op);
175
176 static void
177 AcpiDmPromoteSubtree (
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
194 void
195 AcpiDmDisplayTargetPathname (
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
286 void
287 AcpiDmNotifyDescription (
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
346 void
347 AcpiDmPredefinedDescription (
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
482 void
483 AcpiDmFieldPredefinedDescription (
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)
532     {
533         return;
534     }
535
536     /* Match the name in the info table */
537
538     Info = AcpiAhMatchPredefinedName (Tag);
539     if (Info)
540     {
541         AcpiOsPrintf ("  // %4.4s: %s", Tag,
542             ACPI_CAST_PTR (char, Info->Description));
543     }
544
545     /* AML buffer (String) was allocated in AcpiGetTagPathname */
546
547     ACPI_FREE (IndexOp->Common.Value.String);
548
549 #endif
550     return;
551 }
552
553
554 /*******************************************************************************
555  *
556  * FUNCTION:    AcpiDmMethodFlags
557  *
558  * PARAMETERS:  Op              - Method Object to be examined
559  *
560  * RETURN:      None
561  *
562  * DESCRIPTION: Decode control method flags
563  *
564  ******************************************************************************/
565
566 void
567 AcpiDmMethodFlags (
568     ACPI_PARSE_OBJECT       *Op)
569 {
570     UINT32                  Flags;
571     UINT32                  Args;
572
573
574     /* The next Op contains the flags */
575
576     Op = AcpiPsGetDepthNext (NULL, Op);
577     Flags = (UINT8) Op->Common.Value.Integer;
578     Args = Flags & 0x07;
579
580     /* Mark the Op as completed */
581
582     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
583
584     /* 1) Method argument count */
585
586     AcpiOsPrintf (", %u, ", Args);
587
588     /* 2) Serialize rule */
589
590     if (!(Flags & 0x08))
591     {
592         AcpiOsPrintf ("Not");
593     }
594
595     AcpiOsPrintf ("Serialized");
596
597     /* 3) SyncLevel */
598
599     if (Flags & 0xF0)
600     {
601         AcpiOsPrintf (", %u", Flags >> 4);
602     }
603 }
604
605
606 /*******************************************************************************
607  *
608  * FUNCTION:    AcpiDmFieldFlags
609  *
610  * PARAMETERS:  Op              - Field Object to be examined
611  *
612  * RETURN:      None
613  *
614  * DESCRIPTION: Decode Field definition flags
615  *
616  ******************************************************************************/
617
618 void
619 AcpiDmFieldFlags (
620     ACPI_PARSE_OBJECT       *Op)
621 {
622     UINT32                  Flags;
623
624
625     Op = Op->Common.Next;
626     Flags = (UINT8) Op->Common.Value.Integer;
627
628     /* Mark the Op as completed */
629
630     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
631
632     AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
633     AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
634     AcpiOsPrintf ("%s)",  AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
635 }
636
637
638 /*******************************************************************************
639  *
640  * FUNCTION:    AcpiDmAddressSpace
641  *
642  * PARAMETERS:  SpaceId         - ID to be translated
643  *
644  * RETURN:      None
645  *
646  * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
647  *
648  ******************************************************************************/
649
650 void
651 AcpiDmAddressSpace (
652     UINT8                   SpaceId)
653 {
654
655     if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
656     {
657         if (SpaceId == 0x7F)
658         {
659             AcpiOsPrintf ("FFixedHW, ");
660         }
661         else
662         {
663             AcpiOsPrintf ("0x%.2X, ", SpaceId);
664         }
665     }
666     else
667     {
668         AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
669     }
670 }
671
672
673 /*******************************************************************************
674  *
675  * FUNCTION:    AcpiDmRegionFlags
676  *
677  * PARAMETERS:  Op              - Object to be examined
678  *
679  * RETURN:      None
680  *
681  * DESCRIPTION: Decode OperationRegion flags
682  *
683  ******************************************************************************/
684
685 void
686 AcpiDmRegionFlags (
687     ACPI_PARSE_OBJECT       *Op)
688 {
689
690     /* The next Op contains the SpaceId */
691
692     Op = AcpiPsGetDepthNext (NULL, Op);
693
694     /* Mark the Op as completed */
695
696     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
697
698     AcpiOsPrintf (", ");
699     AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
700 }
701
702
703 /*******************************************************************************
704  *
705  * FUNCTION:    AcpiDmMatchOp
706  *
707  * PARAMETERS:  Op              - Match Object to be examined
708  *
709  * RETURN:      None
710  *
711  * DESCRIPTION: Decode Match opcode operands
712  *
713  ******************************************************************************/
714
715 void
716 AcpiDmMatchOp (
717     ACPI_PARSE_OBJECT       *Op)
718 {
719     ACPI_PARSE_OBJECT       *NextOp;
720
721
722     NextOp = AcpiPsGetDepthNext (NULL, Op);
723     NextOp = NextOp->Common.Next;
724
725     if (!NextOp)
726     {
727         /* Handle partial tree during single-step */
728
729         return;
730     }
731
732     /* Mark the two nodes that contain the encoding for the match keywords */
733
734     NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
735
736     NextOp = NextOp->Common.Next;
737     NextOp = NextOp->Common.Next;
738     NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
739 }
740
741
742 /*******************************************************************************
743  *
744  * FUNCTION:    AcpiDmMatchKeyword
745  *
746  * PARAMETERS:  Op              - Match Object to be examined
747  *
748  * RETURN:      None
749  *
750  * DESCRIPTION: Decode Match opcode operands
751  *
752  ******************************************************************************/
753
754 static void
755 AcpiDmMatchKeyword (
756     ACPI_PARSE_OBJECT       *Op)
757 {
758
759     if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
760     {
761         AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
762     }
763     else
764     {
765         AcpiOsPrintf ("%s",
766             AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]);
767     }
768 }
769
770
771 /*******************************************************************************
772  *
773  * FUNCTION:    AcpiDmDisassembleOneOp
774  *
775  * PARAMETERS:  WalkState           - Current walk info
776  *              Info                - Parse tree walk info
777  *              Op                  - Op that is to be printed
778  *
779  * RETURN:      None
780  *
781  * DESCRIPTION: Disassemble a single AML opcode
782  *
783  ******************************************************************************/
784
785 void
786 AcpiDmDisassembleOneOp (
787     ACPI_WALK_STATE         *WalkState,
788     ACPI_OP_WALK_INFO       *Info,
789     ACPI_PARSE_OBJECT       *Op)
790 {
791     const ACPI_OPCODE_INFO  *OpInfo = NULL;
792     UINT32                  Offset;
793     UINT32                  Length;
794     ACPI_PARSE_OBJECT       *Child;
795     ACPI_STATUS             Status;
796     UINT8                   *Aml;
797     const AH_DEVICE_ID      *IdInfo;
798
799
800     if (!Op)
801     {
802         AcpiOsPrintf ("<NULL OP PTR>");
803         return;
804     }
805
806     if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
807     {
808         return; /* ElseIf macro was already emitted */
809     }
810
811     switch (Op->Common.DisasmOpcode)
812     {
813     case ACPI_DASM_MATCHOP:
814
815         AcpiDmMatchKeyword (Op);
816         return;
817
818     case ACPI_DASM_LNOT_SUFFIX:
819
820         if (!AcpiGbl_CstyleDisassembly)
821         {
822             switch (Op->Common.AmlOpcode)
823             {
824             case AML_LOGICAL_EQUAL_OP:
825                 AcpiOsPrintf ("LNotEqual");
826                 break;
827
828             case AML_LOGICAL_GREATER_OP:
829                 AcpiOsPrintf ("LLessEqual");
830                 break;
831
832             case AML_LOGICAL_LESS_OP:
833                 AcpiOsPrintf ("LGreaterEqual");
834                 break;
835
836             default:
837                 break;
838             }
839         }
840
841         Op->Common.DisasmOpcode = 0;
842         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
843         return;
844
845     default:
846         break;
847     }
848
849     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
850
851     /* The op and arguments */
852
853     switch (Op->Common.AmlOpcode)
854     {
855     case AML_LOGICAL_NOT_OP:
856
857         Child = Op->Common.Value.Arg;
858         if ((Child->Common.AmlOpcode == AML_LOGICAL_EQUAL_OP) ||
859             (Child->Common.AmlOpcode == AML_LOGICAL_GREATER_OP) ||
860             (Child->Common.AmlOpcode == AML_LOGICAL_LESS_OP))
861         {
862             Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
863             Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
864         }
865         else
866         {
867             AcpiOsPrintf ("%s", OpInfo->Name);
868         }
869         break;
870
871     case AML_BYTE_OP:
872
873         AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
874         break;
875
876     case AML_WORD_OP:
877
878         if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
879         {
880             AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
881         }
882         else
883         {
884             AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
885         }
886         break;
887
888     case AML_DWORD_OP:
889
890         if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
891         {
892             AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
893         }
894         else
895         {
896             AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
897         }
898         break;
899
900     case AML_QWORD_OP:
901
902         AcpiOsPrintf ("0x%8.8X%8.8X",
903             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
904         break;
905
906     case AML_STRING_OP:
907
908         AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
909
910         /* For _HID/_CID strings, attempt to output a descriptive comment */
911
912         if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
913         {
914             /* If we know about the ID, emit the description */
915
916             IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
917             if (IdInfo)
918             {
919                 AcpiOsPrintf (" /* %s */", IdInfo->Description);
920             }
921         }
922         break;
923
924     case AML_BUFFER_OP:
925         /*
926          * Determine the type of buffer. We can have one of the following:
927          *
928          * 1) ResourceTemplate containing Resource Descriptors.
929          * 2) Unicode String buffer
930          * 3) ASCII String buffer
931          * 4) Raw data buffer (if none of the above)
932          *
933          * Since there are no special AML opcodes to differentiate these
934          * types of buffers, we have to closely look at the data in the
935          * buffer to determine the type.
936          */
937         if (!AcpiGbl_NoResourceDisassembly)
938         {
939             Status = AcpiDmIsResourceTemplate (WalkState, Op);
940             if (ACPI_SUCCESS (Status))
941             {
942                 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
943                 AcpiOsPrintf ("ResourceTemplate");
944                 break;
945             }
946             else if (Status == AE_AML_NO_RESOURCE_END_TAG)
947             {
948                 AcpiOsPrintf (
949                     "/**** Is ResourceTemplate, "
950                     "but EndTag not at buffer end ****/ ");
951             }
952         }
953
954         if (AcpiDmIsUuidBuffer (Op))
955         {
956             Op->Common.DisasmOpcode = ACPI_DASM_UUID;
957             AcpiOsPrintf ("ToUUID (");
958         }
959         else if (AcpiDmIsUnicodeBuffer (Op))
960         {
961             Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
962             AcpiOsPrintf ("Unicode (");
963         }
964         else if (AcpiDmIsStringBuffer (Op))
965         {
966             Op->Common.DisasmOpcode = ACPI_DASM_STRING;
967             AcpiOsPrintf ("Buffer");
968         }
969         else if (AcpiDmIsPldBuffer (Op))
970         {
971             Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
972             AcpiOsPrintf ("ToPLD (");
973         }
974         else
975         {
976             Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
977             AcpiOsPrintf ("Buffer");
978         }
979         break;
980
981     case AML_INT_NAMEPATH_OP:
982
983         AcpiDmNamestring (Op->Common.Value.Name);
984         break;
985
986     case AML_INT_NAMEDFIELD_OP:
987
988         Length = AcpiDmDumpName (Op->Named.Name);
989
990         AcpiOsPrintf (",");
991         ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
992         AcpiOsPrintf ("%*.s  %u", (unsigned) (5 - Length), " ",
993             (UINT32) Op->Common.Value.Integer);
994
995         AcpiDmCommaIfFieldMember (Op);
996
997         Info->BitOffset += (UINT32) Op->Common.Value.Integer;
998         break;
999
1000     case AML_INT_RESERVEDFIELD_OP:
1001
1002         /* Offset() -- Must account for previous offsets */
1003
1004         Offset = (UINT32) Op->Common.Value.Integer;
1005         Info->BitOffset += Offset;
1006
1007         if (Info->BitOffset % 8 == 0)
1008         {
1009             AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
1010         }
1011         else
1012         {
1013             AcpiOsPrintf ("    ,   %u", Offset);
1014         }
1015
1016         AcpiDmCommaIfFieldMember (Op);
1017         break;
1018
1019     case AML_INT_ACCESSFIELD_OP:
1020     case AML_INT_EXTACCESSFIELD_OP:
1021
1022         AcpiOsPrintf ("AccessAs (%s, ",
1023             AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
1024
1025         AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
1026
1027         if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
1028         {
1029             AcpiOsPrintf (" (0x%2.2X)", (unsigned)
1030                 ((Op->Common.Value.Integer >> 16) & 0xFF));
1031         }
1032
1033         AcpiOsPrintf (")");
1034         AcpiDmCommaIfFieldMember (Op);
1035         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
1036         break;
1037
1038     case AML_INT_CONNECTION_OP:
1039         /*
1040          * Two types of Connection() - one with a buffer object, the
1041          * other with a namestring that points to a buffer object.
1042          */
1043         AcpiOsPrintf ("Connection (");
1044         Child = Op->Common.Value.Arg;
1045
1046         if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
1047         {
1048             AcpiOsPrintf ("\n");
1049
1050             Aml = Child->Named.Data;
1051             Length = (UINT32) Child->Common.Value.Integer;
1052
1053             Info->Level += 1;
1054             Info->MappingOp = Op;
1055             Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
1056
1057             AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
1058
1059             Info->Level -= 1;
1060             AcpiDmIndent (Info->Level);
1061         }
1062         else
1063         {
1064             AcpiDmNamestring (Child->Common.Value.Name);
1065         }
1066
1067         AcpiOsPrintf (")");
1068         AcpiDmCommaIfFieldMember (Op);
1069         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
1070         ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, NULL, 0);
1071         AcpiOsPrintf ("\n");
1072
1073         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
1074         Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1075         break;
1076
1077     case AML_INT_BYTELIST_OP:
1078
1079         AcpiDmByteList (Info, Op);
1080         break;
1081
1082     case AML_INT_METHODCALL_OP:
1083
1084         Op = AcpiPsGetDepthNext (NULL, Op);
1085         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1086
1087         AcpiDmNamestring (Op->Common.Value.Name);
1088         break;
1089
1090     case AML_WHILE_OP:
1091
1092         if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH)
1093         {
1094             AcpiOsPrintf ("%s", "Switch");
1095             break;
1096         }
1097
1098         AcpiOsPrintf ("%s", OpInfo->Name);
1099         break;
1100
1101     case AML_IF_OP:
1102
1103         if (Op->Common.DisasmOpcode == ACPI_DASM_CASE)
1104         {
1105             AcpiOsPrintf ("%s", "Case");
1106             break;
1107         }
1108
1109         AcpiOsPrintf ("%s", OpInfo->Name);
1110         break;
1111
1112     case AML_ELSE_OP:
1113
1114         AcpiDmConvertToElseIf (Op);
1115         break;
1116
1117     case AML_EXTERNAL_OP:
1118
1119         if (AcpiGbl_DmEmitExternalOpcodes)
1120         {
1121             AcpiDmEmitExternal (Op, AcpiPsGetArg(Op, 0));
1122         }
1123
1124         break;
1125
1126     default:
1127
1128         /* Just get the opcode name and print it */
1129
1130         AcpiOsPrintf ("%s", OpInfo->Name);
1131
1132
1133 #ifdef ACPI_DEBUGGER
1134
1135         if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
1136             (WalkState) &&
1137             (WalkState->Results) &&
1138             (WalkState->ResultCount))
1139         {
1140             AcpiDbDecodeInternalObject (
1141                 WalkState->Results->Results.ObjDesc [
1142                     (WalkState->ResultCount - 1) %
1143                         ACPI_RESULTS_FRAME_OBJ_NUM]);
1144         }
1145 #endif
1146
1147         break;
1148     }
1149 }
1150
1151
1152 /*******************************************************************************
1153  *
1154  * FUNCTION:    AcpiDmConvertToElseIf
1155  *
1156  * PARAMETERS:  OriginalElseOp          - ELSE Object to be examined
1157  *
1158  * RETURN:      None. Emits either an "Else" or an "ElseIf" ASL operator.
1159  *
1160  * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
1161  *
1162  * EXAMPLE:
1163  *
1164  * This If..Else..If nested sequence:
1165  *
1166  *        If (Arg0 == 1)
1167  *        {
1168  *            Local0 = 4
1169  *        }
1170  *        Else
1171  *        {
1172  *            If (Arg0 == 2)
1173  *            {
1174  *                Local0 = 5
1175  *            }
1176  *        }
1177  *
1178  * Is converted to this simpler If..ElseIf sequence:
1179  *
1180  *        If (Arg0 == 1)
1181  *        {
1182  *            Local0 = 4
1183  *        }
1184  *        ElseIf (Arg0 == 2)
1185  *        {
1186  *            Local0 = 5
1187  *        }
1188  *
1189  * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
1190  * macro that emits an Else opcode followed by an If opcode. This function
1191  * reverses these AML sequences back to an ElseIf macro where possible. This
1192  * can make the disassembled ASL code simpler and more like the original code.
1193  *
1194  ******************************************************************************/
1195
1196 static void
1197 AcpiDmConvertToElseIf (
1198     ACPI_PARSE_OBJECT       *OriginalElseOp)
1199 {
1200     ACPI_PARSE_OBJECT       *IfOp;
1201     ACPI_PARSE_OBJECT       *ElseOp;
1202
1203
1204     /*
1205      * To be able to perform the conversion, two conditions must be satisfied:
1206      * 1) The first child of the Else must be an If statement.
1207      * 2) The If block can only be followed by an Else block and these must
1208      *    be the only blocks under the original Else.
1209      */
1210     IfOp = OriginalElseOp->Common.Value.Arg;
1211
1212     if (!IfOp ||
1213         (IfOp->Common.AmlOpcode != AML_IF_OP) ||
1214         (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
1215     {
1216         /* Not a proper Else..If sequence, cannot convert to ElseIf */
1217
1218         if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1219         {
1220             AcpiOsPrintf ("%s", "Default");
1221             return;
1222         }
1223
1224         AcpiOsPrintf ("%s", "Else");
1225         return;
1226     }
1227
1228     /* Cannot have anything following the If...Else block */
1229
1230     ElseOp = IfOp->Common.Next;
1231     if (ElseOp && ElseOp->Common.Next)
1232     {
1233         if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1234         {
1235             AcpiOsPrintf ("%s", "Default");
1236             return;
1237         }
1238
1239         AcpiOsPrintf ("%s", "Else");
1240         return;
1241     }
1242
1243     if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1244     {
1245         /*
1246          * There is an ElseIf but in this case the Else is actually
1247          * a Default block for a Switch/Case statement. No conversion.
1248          */
1249         AcpiOsPrintf ("%s", "Default");
1250         return;
1251     }
1252
1253     if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE)
1254     {
1255         /*
1256          * This ElseIf is actually a Case block for a Switch/Case
1257          * statement. Print Case but do not return so that we can
1258          * promote the subtree and keep the indentation level.
1259          */
1260         AcpiOsPrintf ("%s", "Case");
1261     }
1262     else
1263     {
1264        /* Emit ElseIf, mark the IF as now an ELSEIF */
1265
1266         AcpiOsPrintf ("%s", "ElseIf");
1267     }
1268
1269     IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
1270
1271     /* The IF parent will now be the same as the original ELSE parent */
1272
1273     IfOp->Common.Parent = OriginalElseOp->Common.Parent;
1274
1275     /*
1276      * Update the NEXT pointers to restructure the parse tree, essentially
1277      * promoting an If..Else block up to the same level as the original
1278      * Else.
1279      *
1280      * Check if the IF has a corresponding ELSE peer
1281      */
1282     ElseOp = IfOp->Common.Next;
1283     if (ElseOp &&
1284         (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
1285     {
1286         /* If an ELSE matches the IF, promote it also */
1287
1288         ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
1289
1290         /* Promote the entire block under the ElseIf (All Next OPs) */
1291
1292         AcpiDmPromoteSubtree (OriginalElseOp);
1293     }
1294     else
1295     {
1296         /* Otherwise, set the IF NEXT to the original ELSE NEXT */
1297
1298         IfOp->Common.Next = OriginalElseOp->Common.Next;
1299     }
1300
1301     /* Detach the child IF block from the original ELSE */
1302
1303     OriginalElseOp->Common.Value.Arg = NULL;
1304
1305     /* Ignore the original ELSE from now on */
1306
1307     OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1308     OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
1309
1310     /* Insert IF (now ELSEIF) as next peer of the original ELSE */
1311
1312     OriginalElseOp->Common.Next = IfOp;
1313 }
1314
1315
1316 /*******************************************************************************
1317  *
1318  * FUNCTION:    AcpiDmPromoteSubtree
1319  *
1320  * PARAMETERS:  StartOpOp           - Original parent of the entire subtree
1321  *
1322  * RETURN:      None
1323  *
1324  * DESCRIPTION: Promote an entire parse subtree up one level.
1325  *
1326  ******************************************************************************/
1327
1328 static void
1329 AcpiDmPromoteSubtree (
1330     ACPI_PARSE_OBJECT       *StartOp)
1331 {
1332     ACPI_PARSE_OBJECT       *Op;
1333     ACPI_PARSE_OBJECT       *ParentOp;
1334
1335
1336     /* New parent for subtree elements */
1337
1338     ParentOp = StartOp->Common.Parent;
1339
1340     /* First child starts the subtree */
1341
1342     Op = StartOp->Common.Value.Arg;
1343
1344     /* Walk the top-level elements of the subtree */
1345
1346     while (Op)
1347     {
1348         Op->Common.Parent = ParentOp;
1349         if (!Op->Common.Next)
1350         {
1351             /* Last Op in list, update its next field */
1352
1353             Op->Common.Next = StartOp->Common.Next;
1354             break;
1355         }
1356         Op = Op->Common.Next;
1357     }
1358 }