dmopcode.c revision 1.1.1.4.2.3 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
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
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
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_PREDEF_CHECKED)
253 {
254 return;
255 }
256 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_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
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_PREDEF_CHECKED)
389 {
390 return;
391 }
392 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEF_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
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
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
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
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
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
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", ACPI_CAST_PTR (char,
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
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 default:
973
974 /* Just get the opcode name and print it */
975
976 AcpiOsPrintf ("%s", OpInfo->Name);
977
978
979 #ifdef ACPI_DEBUGGER
980
981 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
982 (WalkState) &&
983 (WalkState->Results) &&
984 (WalkState->ResultCount))
985 {
986 AcpiDbDecodeInternalObject (
987 WalkState->Results->Results.ObjDesc [
988 (WalkState->ResultCount - 1) %
989 ACPI_RESULTS_FRAME_OBJ_NUM]);
990 }
991 #endif
992
993 break;
994 }
995 }
996
997
998 /*******************************************************************************
999 *
1000 * FUNCTION: AcpiDmConvertToElseIf
1001 *
1002 * PARAMETERS: OriginalElseOp - ELSE Object to be examined
1003 *
1004 * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator.
1005 *
1006 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
1007 *
1008 * EXAMPLE:
1009 *
1010 * This If..Else..If nested sequence:
1011 *
1012 * If (Arg0 == 1)
1013 * {
1014 * Local0 = 4
1015 * }
1016 * Else
1017 * {
1018 * If (Arg0 == 2)
1019 * {
1020 * Local0 = 5
1021 * }
1022 * }
1023 *
1024 * Is converted to this simpler If..ElseIf sequence:
1025 *
1026 * If (Arg0 == 1)
1027 * {
1028 * Local0 = 4
1029 * }
1030 * ElseIf (Arg0 == 2)
1031 * {
1032 * Local0 = 5
1033 * }
1034 *
1035 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
1036 * macro that emits an Else opcode followed by an If opcode. This function
1037 * reverses these AML sequences back to an ElseIf macro where possible. This
1038 * can make the disassembled ASL code simpler and more like the original code.
1039 *
1040 ******************************************************************************/
1041
1042 static void
1043 AcpiDmConvertToElseIf (
1044 ACPI_PARSE_OBJECT *OriginalElseOp)
1045 {
1046 ACPI_PARSE_OBJECT *IfOp;
1047 ACPI_PARSE_OBJECT *ElseOp;
1048
1049
1050 /* Examine the first child of the Else */
1051
1052 IfOp = OriginalElseOp->Common.Value.Arg;
1053 if (!IfOp || (IfOp->Common.AmlOpcode != AML_IF_OP))
1054 {
1055 /* Not an Else..If sequence, cannot convert to ElseIf */
1056
1057 AcpiOsPrintf ("%s", "Else");
1058 return;
1059 }
1060
1061 /* Emit ElseIf, mark the IF as now an ELSEIF */
1062
1063 AcpiOsPrintf ("%s", "ElseIf");
1064 IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
1065
1066 /* The IF parent will now be the same as the original ELSE parent */
1067
1068 IfOp->Common.Parent = OriginalElseOp->Common.Parent;
1069
1070 /*
1071 * Update the NEXT pointers to restructure the parse tree, essentially
1072 * promoting an If..Else block up to the same level as the original
1073 * Else.
1074 *
1075 * Check if the IF has a corresponding ELSE peer
1076 */
1077 ElseOp = IfOp->Common.Next;
1078 if (ElseOp &&
1079 (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
1080 {
1081 /* If an ELSE matches the IF, promote it also */
1082
1083 ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
1084 ElseOp->Common.Next = OriginalElseOp->Common.Next;
1085 }
1086 else
1087 {
1088 /* Otherwise, set the IF NEXT to the original ELSE NEXT */
1089
1090 IfOp->Common.Next = OriginalElseOp->Common.Next;
1091 }
1092
1093 /* Detach the child IF block from the original ELSE */
1094
1095 OriginalElseOp->Common.Value.Arg = NULL;
1096
1097 /* Ignore the original ELSE from now on */
1098
1099 OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1100 OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
1101
1102 /* Insert IF (now ELSEIF) as next peer of the original ELSE */
1103
1104 OriginalElseOp->Common.Next = IfOp;
1105 }
1106