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