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