1 /*******************************************************************************
2 *
3 * Module Name: dmopcode - AML disassembler, specific AML opcodes
4 *
5 ******************************************************************************/
6
7 /******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************
115 *
116 * Alternatively, you may choose to be licensed under the terms of the
117 * following license:
118 *
119 * Redistribution and use in source and binary forms, with or without
120 * modification, are permitted provided that the following conditions
121 * are met:
122 * 1. Redistributions of source code must retain the above copyright
123 * notice, this list of conditions, and the following disclaimer,
124 * without modification.
125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126 * substantially similar to the "NO WARRANTY" disclaimer below
127 * ("Disclaimer") and any redistribution must be conditioned upon
128 * including a substantially similar Disclaimer requirement for further
129 * binary redistribution.
130 * 3. Neither the names of the above-listed copyright holders nor the names
131 * of any contributors may be used to endorse or promote products derived
132 * from this software without specific prior written permission.
133 *
134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 *
146 * Alternatively, you may choose to be licensed under the terms of the
147 * GNU General Public License ("GPL") version 2 as published by the Free
148 * Software Foundation.
149 *
150 *****************************************************************************/
151
152 #include <contrib/dev/acpica/include/acpi.h>
153 #include <contrib/dev/acpica/include/accommon.h>
154 #include <contrib/dev/acpica/include/acparser.h>
155 #include <contrib/dev/acpica/include/amlcode.h>
156 #include <contrib/dev/acpica/include/acinterp.h>
157 #include <contrib/dev/acpica/include/acnamesp.h>
158 #include <contrib/dev/acpica/include/acdebug.h>
159 #include <contrib/dev/acpica/include/acconvert.h>
160
161
162 #define _COMPONENT ACPI_CA_DEBUGGER
163 ACPI_MODULE_NAME ("dmopcode")
164
165
166 /* Local prototypes */
167
168 static void
169 AcpiDmMatchKeyword (
170 ACPI_PARSE_OBJECT *Op);
171
172 static void
173 AcpiDmConvertToElseIf (
174 ACPI_PARSE_OBJECT *Op);
175
176 static void
177 AcpiDmPromoteSubtree (
178 ACPI_PARSE_OBJECT *StartOp);
179
180 /*******************************************************************************
181 *
182 * FUNCTION: AcpiDmDisplayTargetPathname
183 *
184 * PARAMETERS: Op - Parse object
185 *
186 * RETURN: None
187 *
188 * DESCRIPTION: For AML opcodes that have a target operand, display the full
189 * pathname for the target, in a comment field. Handles Return()
190 * statements also.
191 *
192 ******************************************************************************/
193
194 void
AcpiDmDisplayTargetPathname(ACPI_PARSE_OBJECT * Op)195 AcpiDmDisplayTargetPathname (
196 ACPI_PARSE_OBJECT *Op)
197 {
198 ACPI_PARSE_OBJECT *NextOp;
199 ACPI_PARSE_OBJECT *PrevOp = NULL;
200 char *Pathname;
201 const ACPI_OPCODE_INFO *OpInfo;
202
203
204 if (Op->Common.AmlOpcode == AML_RETURN_OP)
205 {
206 PrevOp = Op->Asl.Value.Arg;
207 }
208 else
209 {
210 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
211 if (!(OpInfo->Flags & AML_HAS_TARGET))
212 {
213 return;
214 }
215
216 /* Target is the last Op in the arg list */
217
218 NextOp = Op->Asl.Value.Arg;
219 while (NextOp)
220 {
221 PrevOp = NextOp;
222 NextOp = PrevOp->Asl.Next;
223 }
224 }
225
226 if (!PrevOp)
227 {
228 return;
229 }
230
231 /* We must have a namepath AML opcode */
232
233 if (PrevOp->Asl.AmlOpcode != AML_INT_NAMEPATH_OP)
234 {
235 return;
236 }
237
238 /* A null string is the "no target specified" case */
239
240 if (!PrevOp->Asl.Value.String)
241 {
242 return;
243 }
244
245 /* No node means "unresolved external reference" */
246
247 if (!PrevOp->Asl.Node)
248 {
249 AcpiOsPrintf (" /* External reference */");
250 return;
251 }
252
253 /* Ignore if path is already from the root */
254
255 if (*PrevOp->Asl.Value.String == '\\')
256 {
257 return;
258 }
259
260 /* Now: we can get the full pathname */
261
262 Pathname = AcpiNsGetExternalPathname (PrevOp->Asl.Node);
263 if (!Pathname)
264 {
265 return;
266 }
267
268 AcpiOsPrintf (" /* %s */", Pathname);
269 ACPI_FREE (Pathname);
270 }
271
272
273 /*******************************************************************************
274 *
275 * FUNCTION: AcpiDmNotifyDescription
276 *
277 * PARAMETERS: Op - Name() parse object
278 *
279 * RETURN: None
280 *
281 * DESCRIPTION: Emit a description comment for the value associated with a
282 * Notify() operator.
283 *
284 ******************************************************************************/
285
286 void
AcpiDmNotifyDescription(ACPI_PARSE_OBJECT * Op)287 AcpiDmNotifyDescription (
288 ACPI_PARSE_OBJECT *Op)
289 {
290 ACPI_PARSE_OBJECT *NextOp;
291 ACPI_NAMESPACE_NODE *Node;
292 UINT8 NotifyValue;
293 UINT8 Type = ACPI_TYPE_ANY;
294
295
296 /* The notify value is the second argument */
297
298 NextOp = Op->Asl.Value.Arg;
299 NextOp = NextOp->Asl.Next;
300
301 switch (NextOp->Common.AmlOpcode)
302 {
303 case AML_ZERO_OP:
304 case AML_ONE_OP:
305
306 NotifyValue = (UINT8) NextOp->Common.AmlOpcode;
307 break;
308
309 case AML_BYTE_OP:
310
311 NotifyValue = (UINT8) NextOp->Asl.Value.Integer;
312 break;
313
314 default:
315 return;
316 }
317
318 /*
319 * Attempt to get the namespace node so we can determine the object type.
320 * Some notify values are dependent on the object type (Device, Thermal,
321 * or Processor).
322 */
323 Node = Op->Asl.Node;
324 if (Node)
325 {
326 Type = Node->Type;
327 }
328
329 AcpiOsPrintf (" // %s", AcpiUtGetNotifyName (NotifyValue, Type));
330 }
331
332
333 /*******************************************************************************
334 *
335 * FUNCTION: AcpiDmPredefinedDescription
336 *
337 * PARAMETERS: Op - Name() parse object
338 *
339 * RETURN: None
340 *
341 * DESCRIPTION: Emit a description comment for a predefined ACPI name.
342 * Used for iASL compiler only.
343 *
344 ******************************************************************************/
345
346 void
AcpiDmPredefinedDescription(ACPI_PARSE_OBJECT * Op)347 AcpiDmPredefinedDescription (
348 ACPI_PARSE_OBJECT *Op)
349 {
350 #ifdef ACPI_ASL_COMPILER
351 const AH_PREDEFINED_NAME *Info;
352 char *NameString;
353 int LastCharIsDigit;
354 int LastCharsAreHex;
355
356
357 if (!Op)
358 {
359 return;
360 }
361
362 /* Ensure that the comment field is emitted only once */
363
364 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
365 {
366 return;
367 }
368 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
369
370 /* Predefined name must start with an underscore */
371
372 NameString = ACPI_CAST_PTR (char, &Op->Named.Name);
373 if (NameString[0] != '_')
374 {
375 return;
376 }
377
378 /*
379 * Check for the special ACPI names:
380 * _ACd, _ALd, _EJd, _Exx, _Lxx, _Qxx, _Wxx, _T_a
381 * (where d=decimal_digit, x=hex_digit, a=anything)
382 *
383 * Convert these to the generic name for table lookup.
384 * Note: NameString is guaranteed to be upper case here.
385 */
386 LastCharIsDigit =
387 (isdigit ((int) NameString[3])); /* d */
388 LastCharsAreHex =
389 (isxdigit ((int) NameString[2]) && /* xx */
390 isxdigit ((int) NameString[3]));
391
392 switch (NameString[1])
393 {
394 case 'A':
395
396 if ((NameString[2] == 'C') && (LastCharIsDigit))
397 {
398 NameString = "_ACx";
399 }
400 else if ((NameString[2] == 'L') && (LastCharIsDigit))
401 {
402 NameString = "_ALx";
403 }
404 break;
405
406 case 'E':
407
408 if ((NameString[2] == 'J') && (LastCharIsDigit))
409 {
410 NameString = "_EJx";
411 }
412 else if (LastCharsAreHex)
413 {
414 NameString = "_Exx";
415 }
416 break;
417
418 case 'L':
419
420 if (LastCharsAreHex)
421 {
422 NameString = "_Lxx";
423 }
424 break;
425
426 case 'Q':
427
428 if (LastCharsAreHex)
429 {
430 NameString = "_Qxx";
431 }
432 break;
433
434 case 'T':
435
436 if (NameString[2] == '_')
437 {
438 NameString = "_T_x";
439 }
440 break;
441
442 case 'W':
443
444 if (LastCharsAreHex)
445 {
446 NameString = "_Wxx";
447 }
448 break;
449
450 default:
451
452 break;
453 }
454
455 /* Match the name in the info table */
456
457 Info = AcpiAhMatchPredefinedName (NameString);
458 if (Info)
459 {
460 AcpiOsPrintf (" // %4.4s: %s",
461 NameString, ACPI_CAST_PTR (char, Info->Description));
462 }
463
464 #endif
465 return;
466 }
467
468
469 /*******************************************************************************
470 *
471 * FUNCTION: AcpiDmFieldPredefinedDescription
472 *
473 * PARAMETERS: Op - Parse object
474 *
475 * RETURN: None
476 *
477 * DESCRIPTION: Emit a description comment for a resource descriptor tag
478 * (which is a predefined ACPI name.) Used for iASL compiler only.
479 *
480 ******************************************************************************/
481
482 void
AcpiDmFieldPredefinedDescription(ACPI_PARSE_OBJECT * Op)483 AcpiDmFieldPredefinedDescription (
484 ACPI_PARSE_OBJECT *Op)
485 {
486 #ifdef ACPI_ASL_COMPILER
487 ACPI_PARSE_OBJECT *IndexOp;
488 char *Tag;
489 const ACPI_OPCODE_INFO *OpInfo;
490 const AH_PREDEFINED_NAME *Info;
491
492
493 if (!Op)
494 {
495 return;
496 }
497
498 /* Ensure that the comment field is emitted only once */
499
500 if (Op->Common.DisasmFlags & ACPI_PARSEOP_PREDEFINED_CHECKED)
501 {
502 return;
503 }
504 Op->Common.DisasmFlags |= ACPI_PARSEOP_PREDEFINED_CHECKED;
505
506 /*
507 * Op must be one of the Create* operators: CreateField, CreateBitField,
508 * CreateByteField, CreateWordField, CreateDwordField, CreateQwordField
509 */
510 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
511 if (!(OpInfo->Flags & AML_CREATE))
512 {
513 return;
514 }
515
516 /* Second argument is the Index argument */
517
518 IndexOp = Op->Common.Value.Arg;
519 IndexOp = IndexOp->Common.Next;
520
521 /* Index argument must be a namepath */
522
523 if (IndexOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
524 {
525 return;
526 }
527
528 /* Major cheat: We previously put the Tag ptr in the Node field */
529
530 Tag = ACPI_CAST_PTR (char, IndexOp->Common.Node);
531 if (!Tag || (*Tag == 0))
532 {
533 return;
534 }
535
536 /* Is the tag a predefined name? */
537
538 Info = AcpiAhMatchPredefinedName (Tag);
539 if (!Info)
540 {
541 /* Not a predefined name (does not start with underscore) */
542
543 return;
544 }
545
546 AcpiOsPrintf (" // %4.4s: %s", Tag,
547 ACPI_CAST_PTR (char, Info->Description));
548
549 /* String contains the prefix path, free it */
550
551 ACPI_FREE (IndexOp->Common.Value.String);
552 IndexOp->Common.Value.String = NULL;
553 #endif
554
555 return;
556 }
557
558
559 /*******************************************************************************
560 *
561 * FUNCTION: AcpiDmMethodFlags
562 *
563 * PARAMETERS: Op - Method Object to be examined
564 *
565 * RETURN: None
566 *
567 * DESCRIPTION: Decode control method flags
568 *
569 ******************************************************************************/
570
571 void
AcpiDmMethodFlags(ACPI_PARSE_OBJECT * Op)572 AcpiDmMethodFlags (
573 ACPI_PARSE_OBJECT *Op)
574 {
575 UINT32 Flags;
576 UINT32 Args;
577
578
579 /* The next Op contains the flags */
580
581 Op = AcpiPsGetDepthNext (NULL, Op);
582 Flags = (UINT8) Op->Common.Value.Integer;
583 Args = Flags & 0x07;
584
585 /* Mark the Op as completed */
586
587 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
588
589 /* 1) Method argument count */
590
591 AcpiOsPrintf (", %u, ", Args);
592
593 /* 2) Serialize rule */
594
595 if (!(Flags & 0x08))
596 {
597 AcpiOsPrintf ("Not");
598 }
599
600 AcpiOsPrintf ("Serialized");
601
602 /* 3) SyncLevel */
603
604 if (Flags & 0xF0)
605 {
606 AcpiOsPrintf (", %u", Flags >> 4);
607 }
608 }
609
610
611 /*******************************************************************************
612 *
613 * FUNCTION: AcpiDmFieldFlags
614 *
615 * PARAMETERS: Op - Field Object to be examined
616 *
617 * RETURN: None
618 *
619 * DESCRIPTION: Decode Field definition flags
620 *
621 ******************************************************************************/
622
623 void
AcpiDmFieldFlags(ACPI_PARSE_OBJECT * Op)624 AcpiDmFieldFlags (
625 ACPI_PARSE_OBJECT *Op)
626 {
627 UINT32 Flags;
628
629
630 Op = Op->Common.Next;
631 Flags = (UINT8) Op->Common.Value.Integer;
632
633 /* Mark the Op as completed */
634
635 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
636
637 AcpiOsPrintf ("%s, ", AcpiGbl_AccessTypes [Flags & 0x07]);
638 AcpiOsPrintf ("%s, ", AcpiGbl_LockRule [(Flags & 0x10) >> 4]);
639 AcpiOsPrintf ("%s)", AcpiGbl_UpdateRules [(Flags & 0x60) >> 5]);
640 }
641
642
643 /*******************************************************************************
644 *
645 * FUNCTION: AcpiDmAddressSpace
646 *
647 * PARAMETERS: SpaceId - ID to be translated
648 *
649 * RETURN: None
650 *
651 * DESCRIPTION: Decode a SpaceId to an AddressSpaceKeyword
652 *
653 ******************************************************************************/
654
655 void
AcpiDmAddressSpace(UINT8 SpaceId)656 AcpiDmAddressSpace (
657 UINT8 SpaceId)
658 {
659
660 if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS)
661 {
662 if (SpaceId == 0x7F)
663 {
664 AcpiOsPrintf ("FFixedHW, ");
665 }
666 else
667 {
668 AcpiOsPrintf ("0x%.2X, ", SpaceId);
669 }
670 }
671 else
672 {
673 AcpiOsPrintf ("%s, ", AcpiGbl_RegionTypes [SpaceId]);
674 }
675 }
676
677
678 /*******************************************************************************
679 *
680 * FUNCTION: AcpiDmRegionFlags
681 *
682 * PARAMETERS: Op - Object to be examined
683 *
684 * RETURN: None
685 *
686 * DESCRIPTION: Decode OperationRegion flags
687 *
688 ******************************************************************************/
689
690 void
AcpiDmRegionFlags(ACPI_PARSE_OBJECT * Op)691 AcpiDmRegionFlags (
692 ACPI_PARSE_OBJECT *Op)
693 {
694
695 /* The next Op contains the SpaceId */
696
697 Op = AcpiPsGetDepthNext (NULL, Op);
698
699 /* Mark the Op as completed */
700
701 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
702
703 AcpiOsPrintf (", ");
704 AcpiDmAddressSpace ((UINT8) Op->Common.Value.Integer);
705 }
706
707
708 /*******************************************************************************
709 *
710 * FUNCTION: AcpiDmMatchOp
711 *
712 * PARAMETERS: Op - Match Object to be examined
713 *
714 * RETURN: None
715 *
716 * DESCRIPTION: Decode Match opcode operands
717 *
718 ******************************************************************************/
719
720 void
AcpiDmMatchOp(ACPI_PARSE_OBJECT * Op)721 AcpiDmMatchOp (
722 ACPI_PARSE_OBJECT *Op)
723 {
724 ACPI_PARSE_OBJECT *NextOp;
725
726
727 NextOp = AcpiPsGetDepthNext (NULL, Op);
728 NextOp = NextOp->Common.Next;
729
730 if (!NextOp)
731 {
732 /* Handle partial tree during single-step */
733
734 return;
735 }
736
737 /* Mark the two nodes that contain the encoding for the match keywords */
738
739 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
740
741 NextOp = NextOp->Common.Next;
742 NextOp = NextOp->Common.Next;
743 NextOp->Common.DisasmOpcode = ACPI_DASM_MATCHOP;
744 }
745
746
747 /*******************************************************************************
748 *
749 * FUNCTION: AcpiDmMatchKeyword
750 *
751 * PARAMETERS: Op - Match Object to be examined
752 *
753 * RETURN: None
754 *
755 * DESCRIPTION: Decode Match opcode operands
756 *
757 ******************************************************************************/
758
759 static void
AcpiDmMatchKeyword(ACPI_PARSE_OBJECT * Op)760 AcpiDmMatchKeyword (
761 ACPI_PARSE_OBJECT *Op)
762 {
763
764 if (((UINT32) Op->Common.Value.Integer) > ACPI_MAX_MATCH_OPCODE)
765 {
766 AcpiOsPrintf ("/* Unknown Match Keyword encoding */");
767 }
768 else
769 {
770 AcpiOsPrintf ("%s",
771 AcpiGbl_MatchOps[(ACPI_SIZE) Op->Common.Value.Integer]);
772 }
773 }
774
775
776 /*******************************************************************************
777 *
778 * FUNCTION: AcpiDmDisassembleOneOp
779 *
780 * PARAMETERS: WalkState - Current walk info
781 * Info - Parse tree walk info
782 * Op - Op that is to be printed
783 *
784 * RETURN: None
785 *
786 * DESCRIPTION: Disassemble a single AML opcode
787 *
788 ******************************************************************************/
789
790 void
AcpiDmDisassembleOneOp(ACPI_WALK_STATE * WalkState,ACPI_OP_WALK_INFO * Info,ACPI_PARSE_OBJECT * Op)791 AcpiDmDisassembleOneOp (
792 ACPI_WALK_STATE *WalkState,
793 ACPI_OP_WALK_INFO *Info,
794 ACPI_PARSE_OBJECT *Op)
795 {
796 const ACPI_OPCODE_INFO *OpInfo = NULL;
797 UINT32 Offset;
798 UINT32 Length;
799 ACPI_PARSE_OBJECT *Child;
800 ACPI_PARSE_OBJECT *MethodCallOp;
801 ACPI_STATUS Status;
802 UINT8 *Aml;
803 const AH_DEVICE_ID *IdInfo;
804
805
806 if (!Op)
807 {
808 AcpiOsPrintf ("<NULL OP PTR>");
809 return;
810 }
811
812 if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
813 {
814 return; /* ElseIf macro was already emitted */
815 }
816
817 switch (Op->Common.DisasmOpcode)
818 {
819 case ACPI_DASM_MATCHOP:
820
821 AcpiDmMatchKeyword (Op);
822 return;
823
824 case ACPI_DASM_LNOT_SUFFIX:
825
826 if (!AcpiGbl_CstyleDisassembly)
827 {
828 switch (Op->Common.AmlOpcode)
829 {
830 case AML_LOGICAL_EQUAL_OP:
831 AcpiOsPrintf ("LNotEqual");
832 break;
833
834 case AML_LOGICAL_GREATER_OP:
835 AcpiOsPrintf ("LLessEqual");
836 break;
837
838 case AML_LOGICAL_LESS_OP:
839 AcpiOsPrintf ("LGreaterEqual");
840 break;
841
842 default:
843 break;
844 }
845 }
846
847 Op->Common.DisasmOpcode = 0;
848 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
849 return;
850
851 default:
852 break;
853 }
854
855 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
856
857 /* The op and arguments */
858
859 switch (Op->Common.AmlOpcode)
860 {
861 case AML_LOGICAL_NOT_OP:
862
863 Child = Op->Common.Value.Arg;
864 if ((Child->Common.AmlOpcode == AML_LOGICAL_EQUAL_OP) ||
865 (Child->Common.AmlOpcode == AML_LOGICAL_GREATER_OP) ||
866 (Child->Common.AmlOpcode == AML_LOGICAL_LESS_OP))
867 {
868 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
869 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
870 }
871 else
872 {
873 AcpiOsPrintf ("%s", OpInfo->Name);
874 }
875 break;
876
877 case AML_BYTE_OP:
878
879 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
880 break;
881
882 case AML_WORD_OP:
883
884 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
885 {
886 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
887 }
888 else
889 {
890 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
891 }
892 break;
893
894 case AML_DWORD_OP:
895
896 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
897 {
898 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
899 }
900 else
901 {
902 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
903 }
904 break;
905
906 case AML_QWORD_OP:
907
908 AcpiOsPrintf ("0x%8.8X%8.8X",
909 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
910 break;
911
912 case AML_STRING_OP:
913
914 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
915
916 /* For _HID/_CID strings, attempt to output a descriptive comment */
917
918 if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
919 {
920 /* If we know about the ID, emit the description */
921
922 IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
923 if (IdInfo)
924 {
925 AcpiOsPrintf (" /* %s */", IdInfo->Description);
926 }
927 }
928 break;
929
930 case AML_BUFFER_OP:
931 /*
932 * Determine the type of buffer. We can have one of the following:
933 *
934 * 1) ResourceTemplate containing Resource Descriptors.
935 * 2) Unicode String buffer
936 * 3) ASCII String buffer
937 * 4) Raw data buffer (if none of the above)
938 *
939 * Since there are no special AML opcodes to differentiate these
940 * types of buffers, we have to closely look at the data in the
941 * buffer to determine the type.
942 */
943 if (!AcpiGbl_NoResourceDisassembly)
944 {
945 Status = AcpiDmIsResourceTemplate (WalkState, Op);
946 if (ACPI_SUCCESS (Status))
947 {
948 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
949 AcpiOsPrintf ("ResourceTemplate");
950 break;
951 }
952 else if (Status == AE_AML_NO_RESOURCE_END_TAG)
953 {
954 AcpiOsPrintf (
955 "/**** Is ResourceTemplate, "
956 "but EndTag not at buffer end ****/ ");
957 }
958 }
959
960 if (AcpiDmIsUuidBuffer (Op))
961 {
962 Op->Common.DisasmOpcode = ACPI_DASM_UUID;
963 AcpiOsPrintf ("ToUUID (");
964 }
965 else if (AcpiDmIsUnicodeBuffer (Op))
966 {
967 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
968 AcpiOsPrintf ("Unicode (");
969 }
970 else if (AcpiDmIsStringBuffer (Op))
971 {
972 Op->Common.DisasmOpcode = ACPI_DASM_STRING;
973 AcpiOsPrintf ("Buffer");
974 }
975 else if (AcpiDmIsPldBuffer (Op))
976 {
977 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
978 AcpiOsPrintf ("ToPLD (");
979 }
980 else
981 {
982 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
983 AcpiOsPrintf ("Buffer");
984 }
985 break;
986
987 case AML_INT_NAMEPATH_OP:
988
989 AcpiDmNamestring (Op->Common.Value.Name);
990 /* If this namepath is a Package element, emit a separating comma */
991 if ((Op->Common.Parent) &&
992 ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
993 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
994 {
995 AcpiOsPrintf (", ");
996 }
997 break;
998
999 case AML_INT_NAMEDFIELD_OP:
1000
1001 Length = AcpiDmDumpName (Op->Named.Name);
1002
1003 AcpiOsPrintf (",");
1004 ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
1005 AcpiOsPrintf ("%*.s %u", (unsigned) (5 - Length), " ",
1006 (UINT32) Op->Common.Value.Integer);
1007
1008 AcpiDmCommaIfFieldMember (Op);
1009
1010 Info->BitOffset += (UINT32) Op->Common.Value.Integer;
1011 break;
1012
1013 case AML_INT_RESERVEDFIELD_OP:
1014
1015 /* Offset() -- Must account for previous offsets */
1016
1017 Offset = (UINT32) Op->Common.Value.Integer;
1018 Info->BitOffset += Offset;
1019
1020 if (Info->BitOffset % 8 == 0)
1021 {
1022 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
1023 }
1024 else
1025 {
1026 AcpiOsPrintf (" , %u", Offset);
1027 }
1028
1029 AcpiDmCommaIfFieldMember (Op);
1030 break;
1031
1032 case AML_INT_ACCESSFIELD_OP:
1033 case AML_INT_EXTACCESSFIELD_OP:
1034
1035 AcpiOsPrintf ("AccessAs (%s, ",
1036 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
1037
1038 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
1039
1040 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
1041 {
1042 AcpiOsPrintf (" (0x%2.2X)", (unsigned)
1043 ((Op->Common.Value.Integer >> 16) & 0xFF));
1044 }
1045
1046 AcpiOsPrintf (")");
1047 AcpiDmCommaIfFieldMember (Op);
1048 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
1049 break;
1050
1051 case AML_INT_CONNECTION_OP:
1052 /*
1053 * Two types of Connection() - one with a buffer object, the
1054 * other with a namestring that points to a buffer object.
1055 */
1056 AcpiOsPrintf ("Connection (");
1057 Child = Op->Common.Value.Arg;
1058
1059 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
1060 {
1061 AcpiOsPrintf ("\n");
1062
1063 Aml = Child->Named.Data;
1064 Length = (UINT32) Child->Common.Value.Integer;
1065
1066 Info->Level += 1;
1067 Info->MappingOp = Op;
1068 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
1069
1070 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
1071
1072 Info->Level -= 1;
1073 AcpiDmIndent (Info->Level);
1074 }
1075 else
1076 {
1077 AcpiDmNamestring (Child->Common.Value.Name);
1078 }
1079
1080 AcpiOsPrintf (")");
1081 AcpiDmCommaIfFieldMember (Op);
1082 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
1083 ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, NULL, 0);
1084 AcpiOsPrintf ("\n");
1085
1086 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
1087 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1088 break;
1089
1090 case AML_INT_BYTELIST_OP:
1091
1092 AcpiDmByteList (Info, Op);
1093 break;
1094
1095 case AML_INT_METHODCALL_OP:
1096
1097 MethodCallOp = Op;
1098 Op = AcpiPsGetDepthNext (NULL, Op);
1099 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1100
1101 AcpiDmNamestring (Op->Common.Value.Name);
1102
1103 /* If the method name is a Package element, emit a separating comma */
1104 if ((MethodCallOp->Common.Parent) &&
1105 ((MethodCallOp->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
1106 (MethodCallOp->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
1107 {
1108 AcpiOsPrintf (", ");
1109 }
1110 break;
1111
1112 case AML_WHILE_OP:
1113
1114 if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH)
1115 {
1116 AcpiOsPrintf ("%s", "Switch");
1117 break;
1118 }
1119
1120 AcpiOsPrintf ("%s", OpInfo->Name);
1121 break;
1122
1123 case AML_IF_OP:
1124
1125 if (Op->Common.DisasmOpcode == ACPI_DASM_CASE)
1126 {
1127 AcpiOsPrintf ("%s", "Case");
1128 break;
1129 }
1130
1131 AcpiOsPrintf ("%s", OpInfo->Name);
1132 break;
1133
1134 case AML_ELSE_OP:
1135
1136 AcpiDmConvertToElseIf (Op);
1137 break;
1138
1139 case AML_EXTERNAL_OP:
1140
1141 if (AcpiGbl_DmEmitExternalOpcodes)
1142 {
1143 AcpiDmEmitExternal (Op, AcpiPsGetArg(Op, 0));
1144 }
1145
1146 break;
1147
1148 default:
1149
1150 /* Just get the opcode name and print it */
1151
1152 AcpiOsPrintf ("%s", OpInfo->Name);
1153
1154
1155 #ifdef ACPI_DEBUGGER
1156
1157 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
1158 (WalkState) &&
1159 (WalkState->Results) &&
1160 (WalkState->ResultCount))
1161 {
1162 AcpiDbDecodeInternalObject (
1163 WalkState->Results->Results.ObjDesc [
1164 (WalkState->ResultCount - 1) %
1165 ACPI_RESULTS_FRAME_OBJ_NUM]);
1166 }
1167 #endif
1168
1169 break;
1170 }
1171 }
1172
1173
1174 /*******************************************************************************
1175 *
1176 * FUNCTION: AcpiDmConvertToElseIf
1177 *
1178 * PARAMETERS: OriginalElseOp - ELSE Object to be examined
1179 *
1180 * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator.
1181 *
1182 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
1183 *
1184 * EXAMPLE:
1185 *
1186 * This If..Else..If nested sequence:
1187 *
1188 * If (Arg0 == 1)
1189 * {
1190 * Local0 = 4
1191 * }
1192 * Else
1193 * {
1194 * If (Arg0 == 2)
1195 * {
1196 * Local0 = 5
1197 * }
1198 * }
1199 *
1200 * Is converted to this simpler If..ElseIf sequence:
1201 *
1202 * If (Arg0 == 1)
1203 * {
1204 * Local0 = 4
1205 * }
1206 * ElseIf (Arg0 == 2)
1207 * {
1208 * Local0 = 5
1209 * }
1210 *
1211 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
1212 * macro that emits an Else opcode followed by an If opcode. This function
1213 * reverses these AML sequences back to an ElseIf macro where possible. This
1214 * can make the disassembled ASL code simpler and more like the original code.
1215 *
1216 ******************************************************************************/
1217
1218 static void
AcpiDmConvertToElseIf(ACPI_PARSE_OBJECT * OriginalElseOp)1219 AcpiDmConvertToElseIf (
1220 ACPI_PARSE_OBJECT *OriginalElseOp)
1221 {
1222 ACPI_PARSE_OBJECT *IfOp;
1223 ACPI_PARSE_OBJECT *ElseOp;
1224
1225
1226 /*
1227 * To be able to perform the conversion, two conditions must be satisfied:
1228 * 1) The first child of the Else must be an If statement.
1229 * 2) The If block can only be followed by an Else block and these must
1230 * be the only blocks under the original Else.
1231 */
1232 IfOp = OriginalElseOp->Common.Value.Arg;
1233
1234 if (!IfOp ||
1235 (IfOp->Common.AmlOpcode != AML_IF_OP) ||
1236 (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
1237 {
1238 /* Not a proper Else..If sequence, cannot convert to ElseIf */
1239
1240 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1241 {
1242 AcpiOsPrintf ("%s", "Default");
1243 return;
1244 }
1245
1246 AcpiOsPrintf ("%s", "Else");
1247 return;
1248 }
1249
1250 /* Cannot have anything following the If...Else block */
1251
1252 ElseOp = IfOp->Common.Next;
1253 if (ElseOp && ElseOp->Common.Next)
1254 {
1255 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1256 {
1257 AcpiOsPrintf ("%s", "Default");
1258 return;
1259 }
1260
1261 AcpiOsPrintf ("%s", "Else");
1262 return;
1263 }
1264
1265 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1266 {
1267 /*
1268 * There is an ElseIf but in this case the Else is actually
1269 * a Default block for a Switch/Case statement. No conversion.
1270 */
1271 AcpiOsPrintf ("%s", "Default");
1272 return;
1273 }
1274
1275 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE)
1276 {
1277 /*
1278 * This ElseIf is actually a Case block for a Switch/Case
1279 * statement. Print Case but do not return so that we can
1280 * promote the subtree and keep the indentation level.
1281 */
1282 AcpiOsPrintf ("%s", "Case");
1283 }
1284 else
1285 {
1286 /* Emit ElseIf, mark the IF as now an ELSEIF */
1287
1288 AcpiOsPrintf ("%s", "ElseIf");
1289 }
1290
1291 IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
1292
1293 /* The IF parent will now be the same as the original ELSE parent */
1294
1295 IfOp->Common.Parent = OriginalElseOp->Common.Parent;
1296
1297 /*
1298 * Update the NEXT pointers to restructure the parse tree, essentially
1299 * promoting an If..Else block up to the same level as the original
1300 * Else.
1301 *
1302 * Check if the IF has a corresponding ELSE peer
1303 */
1304 ElseOp = IfOp->Common.Next;
1305 if (ElseOp &&
1306 (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
1307 {
1308 /* If an ELSE matches the IF, promote it also */
1309
1310 ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
1311
1312 /* Promote the entire block under the ElseIf (All Next OPs) */
1313
1314 AcpiDmPromoteSubtree (OriginalElseOp);
1315 }
1316 else
1317 {
1318 /* Otherwise, set the IF NEXT to the original ELSE NEXT */
1319
1320 IfOp->Common.Next = OriginalElseOp->Common.Next;
1321 }
1322
1323 /* Detach the child IF block from the original ELSE */
1324
1325 OriginalElseOp->Common.Value.Arg = NULL;
1326
1327 /* Ignore the original ELSE from now on */
1328
1329 OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1330 OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
1331
1332 /* Insert IF (now ELSEIF) as next peer of the original ELSE */
1333
1334 OriginalElseOp->Common.Next = IfOp;
1335 }
1336
1337
1338 /*******************************************************************************
1339 *
1340 * FUNCTION: AcpiDmPromoteSubtree
1341 *
1342 * PARAMETERS: StartOpOp - Original parent of the entire subtree
1343 *
1344 * RETURN: None
1345 *
1346 * DESCRIPTION: Promote an entire parse subtree up one level.
1347 *
1348 ******************************************************************************/
1349
1350 static void
AcpiDmPromoteSubtree(ACPI_PARSE_OBJECT * StartOp)1351 AcpiDmPromoteSubtree (
1352 ACPI_PARSE_OBJECT *StartOp)
1353 {
1354 ACPI_PARSE_OBJECT *Op;
1355 ACPI_PARSE_OBJECT *ParentOp;
1356
1357
1358 /* New parent for subtree elements */
1359
1360 ParentOp = StartOp->Common.Parent;
1361
1362 /* First child starts the subtree */
1363
1364 Op = StartOp->Common.Value.Arg;
1365
1366 /* Walk the top-level elements of the subtree */
1367
1368 while (Op)
1369 {
1370 Op->Common.Parent = ParentOp;
1371 if (!Op->Common.Next)
1372 {
1373 /* Last Op in list, update its next field */
1374
1375 Op->Common.Next = StartOp->Common.Next;
1376 break;
1377 }
1378 Op = Op->Common.Next;
1379 }
1380 }
1381