Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/disassembler/dmopcode.c
48524 views
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 - 2025, 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
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
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
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
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
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
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
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
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
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
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
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
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
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
1365