]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/components/disassembler/dmopcode.c
MFV r304732.
[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  * 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
59 static void
60 AcpiDmMatchKeyword (
61     ACPI_PARSE_OBJECT       *Op);
62
63 static void
64 AcpiDmConvertToElseIf (
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
82 void
83 AcpiDmDisplayTargetPathname (
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
174 void
175 AcpiDmNotifyDescription (
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
234 void
235 AcpiDmPredefinedDescription (
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
370 void
371 AcpiDmFieldPredefinedDescription (
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
450 void
451 AcpiDmMethodFlags (
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
502 void
503 AcpiDmFieldFlags (
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
534 void
535 AcpiDmAddressSpace (
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
569 void
570 AcpiDmRegionFlags (
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
599 void
600 AcpiDmMatchOp (
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
638 static void
639 AcpiDmMatchKeyword (
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
669 void
670 AcpiDmDisassembleOneOp (
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
1055 static void
1056 AcpiDmConvertToElseIf (
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 }