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 - 2023, 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_STATUS Status;
801 UINT8 *Aml;
802 const AH_DEVICE_ID *IdInfo;
803
804
805 if (!Op)
806 {
807 AcpiOsPrintf ("<NULL OP PTR>");
808 return;
809 }
810
811 if (Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)
812 {
813 return; /* ElseIf macro was already emitted */
814 }
815
816 switch (Op->Common.DisasmOpcode)
817 {
818 case ACPI_DASM_MATCHOP:
819
820 AcpiDmMatchKeyword (Op);
821 return;
822
823 case ACPI_DASM_LNOT_SUFFIX:
824
825 if (!AcpiGbl_CstyleDisassembly)
826 {
827 switch (Op->Common.AmlOpcode)
828 {
829 case AML_LOGICAL_EQUAL_OP:
830 AcpiOsPrintf ("LNotEqual");
831 break;
832
833 case AML_LOGICAL_GREATER_OP:
834 AcpiOsPrintf ("LLessEqual");
835 break;
836
837 case AML_LOGICAL_LESS_OP:
838 AcpiOsPrintf ("LGreaterEqual");
839 break;
840
841 default:
842 break;
843 }
844 }
845
846 Op->Common.DisasmOpcode = 0;
847 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
848 return;
849
850 default:
851 break;
852 }
853
854 OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
855
856 /* The op and arguments */
857
858 switch (Op->Common.AmlOpcode)
859 {
860 case AML_LOGICAL_NOT_OP:
861
862 Child = Op->Common.Value.Arg;
863 if ((Child->Common.AmlOpcode == AML_LOGICAL_EQUAL_OP) ||
864 (Child->Common.AmlOpcode == AML_LOGICAL_GREATER_OP) ||
865 (Child->Common.AmlOpcode == AML_LOGICAL_LESS_OP))
866 {
867 Child->Common.DisasmOpcode = ACPI_DASM_LNOT_SUFFIX;
868 Op->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
869 }
870 else
871 {
872 AcpiOsPrintf ("%s", OpInfo->Name);
873 }
874 break;
875
876 case AML_BYTE_OP:
877
878 AcpiOsPrintf ("0x%2.2X", (UINT32) Op->Common.Value.Integer);
879 break;
880
881 case AML_WORD_OP:
882
883 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
884 {
885 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
886 }
887 else
888 {
889 AcpiOsPrintf ("0x%4.4X", (UINT32) Op->Common.Value.Integer);
890 }
891 break;
892
893 case AML_DWORD_OP:
894
895 if (Op->Common.DisasmOpcode == ACPI_DASM_EISAID)
896 {
897 AcpiDmDecompressEisaId ((UINT32) Op->Common.Value.Integer);
898 }
899 else
900 {
901 AcpiOsPrintf ("0x%8.8X", (UINT32) Op->Common.Value.Integer);
902 }
903 break;
904
905 case AML_QWORD_OP:
906
907 AcpiOsPrintf ("0x%8.8X%8.8X",
908 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
909 break;
910
911 case AML_STRING_OP:
912
913 AcpiUtPrintString (Op->Common.Value.String, ACPI_UINT16_MAX);
914
915 /* For _HID/_CID strings, attempt to output a descriptive comment */
916
917 if (Op->Common.DisasmOpcode == ACPI_DASM_HID_STRING)
918 {
919 /* If we know about the ID, emit the description */
920
921 IdInfo = AcpiAhMatchHardwareId (Op->Common.Value.String);
922 if (IdInfo)
923 {
924 AcpiOsPrintf (" /* %s */", IdInfo->Description);
925 }
926 }
927 break;
928
929 case AML_BUFFER_OP:
930 /*
931 * Determine the type of buffer. We can have one of the following:
932 *
933 * 1) ResourceTemplate containing Resource Descriptors.
934 * 2) Unicode String buffer
935 * 3) ASCII String buffer
936 * 4) Raw data buffer (if none of the above)
937 *
938 * Since there are no special AML opcodes to differentiate these
939 * types of buffers, we have to closely look at the data in the
940 * buffer to determine the type.
941 */
942 if (!AcpiGbl_NoResourceDisassembly)
943 {
944 Status = AcpiDmIsResourceTemplate (WalkState, Op);
945 if (ACPI_SUCCESS (Status))
946 {
947 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
948 AcpiOsPrintf ("ResourceTemplate");
949 break;
950 }
951 else if (Status == AE_AML_NO_RESOURCE_END_TAG)
952 {
953 AcpiOsPrintf (
954 "/**** Is ResourceTemplate, "
955 "but EndTag not at buffer end ****/ ");
956 }
957 }
958
959 if (AcpiDmIsUuidBuffer (Op))
960 {
961 Op->Common.DisasmOpcode = ACPI_DASM_UUID;
962 AcpiOsPrintf ("ToUUID (");
963 }
964 else if (AcpiDmIsUnicodeBuffer (Op))
965 {
966 Op->Common.DisasmOpcode = ACPI_DASM_UNICODE;
967 AcpiOsPrintf ("Unicode (");
968 }
969 else if (AcpiDmIsStringBuffer (Op))
970 {
971 Op->Common.DisasmOpcode = ACPI_DASM_STRING;
972 AcpiOsPrintf ("Buffer");
973 }
974 else if (AcpiDmIsPldBuffer (Op))
975 {
976 Op->Common.DisasmOpcode = ACPI_DASM_PLD_METHOD;
977 AcpiOsPrintf ("ToPLD (");
978 }
979 else
980 {
981 Op->Common.DisasmOpcode = ACPI_DASM_BUFFER;
982 AcpiOsPrintf ("Buffer");
983 }
984 break;
985
986 case AML_INT_NAMEPATH_OP:
987
988 AcpiDmNamestring (Op->Common.Value.Name);
989 break;
990
991 case AML_INT_NAMEDFIELD_OP:
992
993 Length = AcpiDmDumpName (Op->Named.Name);
994
995 AcpiOsPrintf (",");
996 ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
997 AcpiOsPrintf ("%*.s %u", (unsigned) (5 - Length), " ",
998 (UINT32) Op->Common.Value.Integer);
999
1000 AcpiDmCommaIfFieldMember (Op);
1001
1002 Info->BitOffset += (UINT32) Op->Common.Value.Integer;
1003 break;
1004
1005 case AML_INT_RESERVEDFIELD_OP:
1006
1007 /* Offset() -- Must account for previous offsets */
1008
1009 Offset = (UINT32) Op->Common.Value.Integer;
1010 Info->BitOffset += Offset;
1011
1012 if (Info->BitOffset % 8 == 0)
1013 {
1014 AcpiOsPrintf ("Offset (0x%.2X)", ACPI_DIV_8 (Info->BitOffset));
1015 }
1016 else
1017 {
1018 AcpiOsPrintf (" , %u", Offset);
1019 }
1020
1021 AcpiDmCommaIfFieldMember (Op);
1022 break;
1023
1024 case AML_INT_ACCESSFIELD_OP:
1025 case AML_INT_EXTACCESSFIELD_OP:
1026
1027 AcpiOsPrintf ("AccessAs (%s, ",
1028 AcpiGbl_AccessTypes [(UINT32) (Op->Common.Value.Integer & 0x7)]);
1029
1030 AcpiDmDecodeAttribute ((UINT8) (Op->Common.Value.Integer >> 8));
1031
1032 if (Op->Common.AmlOpcode == AML_INT_EXTACCESSFIELD_OP)
1033 {
1034 AcpiOsPrintf (" (0x%2.2X)", (unsigned)
1035 ((Op->Common.Value.Integer >> 16) & 0xFF));
1036 }
1037
1038 AcpiOsPrintf (")");
1039 AcpiDmCommaIfFieldMember (Op);
1040 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
1041 break;
1042
1043 case AML_INT_CONNECTION_OP:
1044 /*
1045 * Two types of Connection() - one with a buffer object, the
1046 * other with a namestring that points to a buffer object.
1047 */
1048 AcpiOsPrintf ("Connection (");
1049 Child = Op->Common.Value.Arg;
1050
1051 if (Child->Common.AmlOpcode == AML_INT_BYTELIST_OP)
1052 {
1053 AcpiOsPrintf ("\n");
1054
1055 Aml = Child->Named.Data;
1056 Length = (UINT32) Child->Common.Value.Integer;
1057
1058 Info->Level += 1;
1059 Info->MappingOp = Op;
1060 Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
1061
1062 AcpiDmResourceTemplate (Info, Op->Common.Parent, Aml, Length);
1063
1064 Info->Level -= 1;
1065 AcpiDmIndent (Info->Level);
1066 }
1067 else
1068 {
1069 AcpiDmNamestring (Child->Common.Value.Name);
1070 }
1071
1072 AcpiOsPrintf (")");
1073 AcpiDmCommaIfFieldMember (Op);
1074 ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_END_NODE, NULL, 0);
1075 ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, NULL, 0);
1076 AcpiOsPrintf ("\n");
1077
1078 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE; /* for now, ignore in AcpiDmAscendingOp */
1079 Child->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1080 break;
1081
1082 case AML_INT_BYTELIST_OP:
1083
1084 AcpiDmByteList (Info, Op);
1085 break;
1086
1087 case AML_INT_METHODCALL_OP:
1088
1089 Op = AcpiPsGetDepthNext (NULL, Op);
1090 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1091
1092 AcpiDmNamestring (Op->Common.Value.Name);
1093 break;
1094
1095 case AML_WHILE_OP:
1096
1097 if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH)
1098 {
1099 AcpiOsPrintf ("%s", "Switch");
1100 break;
1101 }
1102
1103 AcpiOsPrintf ("%s", OpInfo->Name);
1104 break;
1105
1106 case AML_IF_OP:
1107
1108 if (Op->Common.DisasmOpcode == ACPI_DASM_CASE)
1109 {
1110 AcpiOsPrintf ("%s", "Case");
1111 break;
1112 }
1113
1114 AcpiOsPrintf ("%s", OpInfo->Name);
1115 break;
1116
1117 case AML_ELSE_OP:
1118
1119 AcpiDmConvertToElseIf (Op);
1120 break;
1121
1122 case AML_EXTERNAL_OP:
1123
1124 if (AcpiGbl_DmEmitExternalOpcodes)
1125 {
1126 AcpiDmEmitExternal (Op, AcpiPsGetArg(Op, 0));
1127 }
1128
1129 break;
1130
1131 default:
1132
1133 /* Just get the opcode name and print it */
1134
1135 AcpiOsPrintf ("%s", OpInfo->Name);
1136
1137
1138 #ifdef ACPI_DEBUGGER
1139
1140 if ((Op->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) &&
1141 (WalkState) &&
1142 (WalkState->Results) &&
1143 (WalkState->ResultCount))
1144 {
1145 AcpiDbDecodeInternalObject (
1146 WalkState->Results->Results.ObjDesc [
1147 (WalkState->ResultCount - 1) %
1148 ACPI_RESULTS_FRAME_OBJ_NUM]);
1149 }
1150 #endif
1151
1152 break;
1153 }
1154 }
1155
1156
1157 /*******************************************************************************
1158 *
1159 * FUNCTION: AcpiDmConvertToElseIf
1160 *
1161 * PARAMETERS: OriginalElseOp - ELSE Object to be examined
1162 *
1163 * RETURN: None. Emits either an "Else" or an "ElseIf" ASL operator.
1164 *
1165 * DESCRIPTION: Detect and convert an If..Else..If sequence to If..ElseIf
1166 *
1167 * EXAMPLE:
1168 *
1169 * This If..Else..If nested sequence:
1170 *
1171 * If (Arg0 == 1)
1172 * {
1173 * Local0 = 4
1174 * }
1175 * Else
1176 * {
1177 * If (Arg0 == 2)
1178 * {
1179 * Local0 = 5
1180 * }
1181 * }
1182 *
1183 * Is converted to this simpler If..ElseIf sequence:
1184 *
1185 * If (Arg0 == 1)
1186 * {
1187 * Local0 = 4
1188 * }
1189 * ElseIf (Arg0 == 2)
1190 * {
1191 * Local0 = 5
1192 * }
1193 *
1194 * NOTE: There is no actual ElseIf AML opcode. ElseIf is essentially an ASL
1195 * macro that emits an Else opcode followed by an If opcode. This function
1196 * reverses these AML sequences back to an ElseIf macro where possible. This
1197 * can make the disassembled ASL code simpler and more like the original code.
1198 *
1199 ******************************************************************************/
1200
1201 static void
AcpiDmConvertToElseIf(ACPI_PARSE_OBJECT * OriginalElseOp)1202 AcpiDmConvertToElseIf (
1203 ACPI_PARSE_OBJECT *OriginalElseOp)
1204 {
1205 ACPI_PARSE_OBJECT *IfOp;
1206 ACPI_PARSE_OBJECT *ElseOp;
1207
1208
1209 /*
1210 * To be able to perform the conversion, two conditions must be satisfied:
1211 * 1) The first child of the Else must be an If statement.
1212 * 2) The If block can only be followed by an Else block and these must
1213 * be the only blocks under the original Else.
1214 */
1215 IfOp = OriginalElseOp->Common.Value.Arg;
1216
1217 if (!IfOp ||
1218 (IfOp->Common.AmlOpcode != AML_IF_OP) ||
1219 (IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
1220 {
1221 /* Not a proper Else..If sequence, cannot convert to ElseIf */
1222
1223 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1224 {
1225 AcpiOsPrintf ("%s", "Default");
1226 return;
1227 }
1228
1229 AcpiOsPrintf ("%s", "Else");
1230 return;
1231 }
1232
1233 /* Cannot have anything following the If...Else block */
1234
1235 ElseOp = IfOp->Common.Next;
1236 if (ElseOp && ElseOp->Common.Next)
1237 {
1238 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1239 {
1240 AcpiOsPrintf ("%s", "Default");
1241 return;
1242 }
1243
1244 AcpiOsPrintf ("%s", "Else");
1245 return;
1246 }
1247
1248 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_DEFAULT)
1249 {
1250 /*
1251 * There is an ElseIf but in this case the Else is actually
1252 * a Default block for a Switch/Case statement. No conversion.
1253 */
1254 AcpiOsPrintf ("%s", "Default");
1255 return;
1256 }
1257
1258 if (OriginalElseOp->Common.DisasmOpcode == ACPI_DASM_CASE)
1259 {
1260 /*
1261 * This ElseIf is actually a Case block for a Switch/Case
1262 * statement. Print Case but do not return so that we can
1263 * promote the subtree and keep the indentation level.
1264 */
1265 AcpiOsPrintf ("%s", "Case");
1266 }
1267 else
1268 {
1269 /* Emit ElseIf, mark the IF as now an ELSEIF */
1270
1271 AcpiOsPrintf ("%s", "ElseIf");
1272 }
1273
1274 IfOp->Common.DisasmFlags |= ACPI_PARSEOP_ELSEIF;
1275
1276 /* The IF parent will now be the same as the original ELSE parent */
1277
1278 IfOp->Common.Parent = OriginalElseOp->Common.Parent;
1279
1280 /*
1281 * Update the NEXT pointers to restructure the parse tree, essentially
1282 * promoting an If..Else block up to the same level as the original
1283 * Else.
1284 *
1285 * Check if the IF has a corresponding ELSE peer
1286 */
1287 ElseOp = IfOp->Common.Next;
1288 if (ElseOp &&
1289 (ElseOp->Common.AmlOpcode == AML_ELSE_OP))
1290 {
1291 /* If an ELSE matches the IF, promote it also */
1292
1293 ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
1294
1295 /* Promote the entire block under the ElseIf (All Next OPs) */
1296
1297 AcpiDmPromoteSubtree (OriginalElseOp);
1298 }
1299 else
1300 {
1301 /* Otherwise, set the IF NEXT to the original ELSE NEXT */
1302
1303 IfOp->Common.Next = OriginalElseOp->Common.Next;
1304 }
1305
1306 /* Detach the child IF block from the original ELSE */
1307
1308 OriginalElseOp->Common.Value.Arg = NULL;
1309
1310 /* Ignore the original ELSE from now on */
1311
1312 OriginalElseOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
1313 OriginalElseOp->Common.DisasmOpcode = ACPI_DASM_LNOT_PREFIX;
1314
1315 /* Insert IF (now ELSEIF) as next peer of the original ELSE */
1316
1317 OriginalElseOp->Common.Next = IfOp;
1318 }
1319
1320
1321 /*******************************************************************************
1322 *
1323 * FUNCTION: AcpiDmPromoteSubtree
1324 *
1325 * PARAMETERS: StartOpOp - Original parent of the entire subtree
1326 *
1327 * RETURN: None
1328 *
1329 * DESCRIPTION: Promote an entire parse subtree up one level.
1330 *
1331 ******************************************************************************/
1332
1333 static void
AcpiDmPromoteSubtree(ACPI_PARSE_OBJECT * StartOp)1334 AcpiDmPromoteSubtree (
1335 ACPI_PARSE_OBJECT *StartOp)
1336 {
1337 ACPI_PARSE_OBJECT *Op;
1338 ACPI_PARSE_OBJECT *ParentOp;
1339
1340
1341 /* New parent for subtree elements */
1342
1343 ParentOp = StartOp->Common.Parent;
1344
1345 /* First child starts the subtree */
1346
1347 Op = StartOp->Common.Value.Arg;
1348
1349 /* Walk the top-level elements of the subtree */
1350
1351 while (Op)
1352 {
1353 Op->Common.Parent = ParentOp;
1354 if (!Op->Common.Next)
1355 {
1356 /* Last Op in list, update its next field */
1357
1358 Op->Common.Next = StartOp->Common.Next;
1359 break;
1360 }
1361 Op = Op->Common.Next;
1362 }
1363 }
1364