dmopcode.c revision 1.1.1.10 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
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 }
1187