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