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