Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/acpica/components/disassembler/dmwalk.c
48524 views
1
/*******************************************************************************
2
*
3
* Module Name: dmwalk - AML disassembly tree walk
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/acdebug.h>
157
#include <contrib/dev/acpica/include/acconvert.h>
158
159
160
#define _COMPONENT ACPI_CA_DEBUGGER
161
ACPI_MODULE_NAME ("dmwalk")
162
163
164
/* Stub for non-compiler code */
165
166
#ifndef ACPI_ASL_COMPILER
167
void
168
AcpiDmEmitExternals (
169
void)
170
{
171
return;
172
}
173
174
void
175
AcpiDmEmitExternal (
176
ACPI_PARSE_OBJECT *NameOp,
177
ACPI_PARSE_OBJECT *TypeOp)
178
{
179
return;
180
}
181
#endif
182
183
/* Local prototypes */
184
185
static ACPI_STATUS
186
AcpiDmDescendingOp (
187
ACPI_PARSE_OBJECT *Op,
188
UINT32 Level,
189
void *Context);
190
191
static ACPI_STATUS
192
AcpiDmAscendingOp (
193
ACPI_PARSE_OBJECT *Op,
194
UINT32 Level,
195
void *Context);
196
197
198
/*******************************************************************************
199
*
200
* FUNCTION: AcpiDmDisassemble
201
*
202
* PARAMETERS: WalkState - Current state
203
* Origin - Starting object
204
* NumOpcodes - Max number of opcodes to be displayed
205
*
206
* RETURN: None
207
*
208
* DESCRIPTION: Disassemble parser object and its children. This is the
209
* main entry point of the disassembler.
210
*
211
******************************************************************************/
212
213
void
214
AcpiDmDisassemble (
215
ACPI_WALK_STATE *WalkState,
216
ACPI_PARSE_OBJECT *Origin,
217
UINT32 NumOpcodes)
218
{
219
ACPI_PARSE_OBJECT *Op = Origin;
220
ACPI_OP_WALK_INFO Info;
221
222
223
if (!Op)
224
{
225
return;
226
}
227
228
memset (&Info, 0, sizeof (ACPI_OP_WALK_INFO));
229
Info.WalkState = WalkState;
230
Info.StartAml = Op->Common.Aml - sizeof (ACPI_TABLE_HEADER);
231
Info.AmlOffset = Op->Common.Aml - Info.StartAml;
232
233
AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
234
return;
235
}
236
237
238
/*******************************************************************************
239
*
240
* FUNCTION: AcpiDmWalkParseTree
241
*
242
* PARAMETERS: Op - Root Op object
243
* DescendingCallback - Called during tree descent
244
* AscendingCallback - Called during tree ascent
245
* Context - To be passed to the callbacks
246
*
247
* RETURN: Status from callback(s)
248
*
249
* DESCRIPTION: Walk the entire parse tree.
250
*
251
******************************************************************************/
252
253
void
254
AcpiDmWalkParseTree (
255
ACPI_PARSE_OBJECT *Op,
256
ASL_WALK_CALLBACK DescendingCallback,
257
ASL_WALK_CALLBACK AscendingCallback,
258
void *Context)
259
{
260
BOOLEAN NodePreviouslyVisited;
261
ACPI_PARSE_OBJECT *StartOp = Op;
262
ACPI_STATUS Status;
263
ACPI_PARSE_OBJECT *Next;
264
ACPI_OP_WALK_INFO *Info = Context;
265
266
267
Info->Level = 0;
268
NodePreviouslyVisited = FALSE;
269
270
while (Op)
271
{
272
if (NodePreviouslyVisited)
273
{
274
if (AscendingCallback)
275
{
276
Status = AscendingCallback (Op, Info->Level, Context);
277
if (ACPI_FAILURE (Status))
278
{
279
return;
280
}
281
}
282
}
283
else
284
{
285
/* Let the callback process the node */
286
287
Status = DescendingCallback (Op, Info->Level, Context);
288
if (ACPI_SUCCESS (Status))
289
{
290
/* Visit children first, once */
291
292
Next = AcpiPsGetArg (Op, 0);
293
if (Next)
294
{
295
Info->Level++;
296
Op = Next;
297
continue;
298
}
299
}
300
else if (Status != AE_CTRL_DEPTH)
301
{
302
/* Exit immediately on any error */
303
304
return;
305
}
306
}
307
308
/* Terminate walk at start op */
309
310
if (Op == StartOp)
311
{
312
break;
313
}
314
315
/* No more children, re-visit this node */
316
317
if (!NodePreviouslyVisited)
318
{
319
NodePreviouslyVisited = TRUE;
320
continue;
321
}
322
323
/* No more children, visit peers */
324
325
if (Op->Common.Next)
326
{
327
Op = Op->Common.Next;
328
NodePreviouslyVisited = FALSE;
329
}
330
else
331
{
332
/* No peers, re-visit parent */
333
334
if (Info->Level != 0 )
335
{
336
Info->Level--;
337
}
338
339
Op = Op->Common.Parent;
340
NodePreviouslyVisited = TRUE;
341
}
342
}
343
344
/* If we get here, the walk completed with no errors */
345
346
return;
347
}
348
349
350
/*******************************************************************************
351
*
352
* FUNCTION: AcpiDmBlockType
353
*
354
* PARAMETERS: Op - Object to be examined
355
*
356
* RETURN: BlockType - not a block, parens, braces, or even both.
357
*
358
* DESCRIPTION: Type of block for this op (parens or braces)
359
*
360
******************************************************************************/
361
362
UINT32
363
AcpiDmBlockType (
364
ACPI_PARSE_OBJECT *Op)
365
{
366
const ACPI_OPCODE_INFO *OpInfo;
367
368
369
if (!Op)
370
{
371
return (BLOCK_NONE);
372
}
373
374
switch (Op->Common.AmlOpcode)
375
{
376
case AML_ELSE_OP:
377
378
return (BLOCK_BRACE);
379
380
case AML_METHOD_OP:
381
case AML_DEVICE_OP:
382
case AML_SCOPE_OP:
383
case AML_PROCESSOR_OP:
384
case AML_POWER_RESOURCE_OP:
385
case AML_THERMAL_ZONE_OP:
386
case AML_IF_OP:
387
case AML_WHILE_OP:
388
case AML_FIELD_OP:
389
case AML_INDEX_FIELD_OP:
390
case AML_BANK_FIELD_OP:
391
392
return (BLOCK_PAREN | BLOCK_BRACE);
393
394
case AML_BUFFER_OP:
395
396
if ((Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) ||
397
(Op->Common.DisasmOpcode == ACPI_DASM_UUID) ||
398
(Op->Common.DisasmOpcode == ACPI_DASM_PLD_METHOD))
399
{
400
return (BLOCK_NONE);
401
}
402
403
ACPI_FALLTHROUGH;
404
405
case AML_PACKAGE_OP:
406
case AML_VARIABLE_PACKAGE_OP:
407
408
return (BLOCK_PAREN | BLOCK_BRACE);
409
410
case AML_EVENT_OP:
411
412
return (BLOCK_PAREN);
413
414
case AML_INT_METHODCALL_OP:
415
416
if (Op->Common.Parent &&
417
((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
418
(Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
419
{
420
/* This is a reference to a method, not an invocation */
421
422
return (BLOCK_NONE);
423
}
424
425
ACPI_FALLTHROUGH;
426
427
default:
428
429
OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
430
if (OpInfo->Flags & AML_HAS_ARGS)
431
{
432
return (BLOCK_PAREN);
433
}
434
435
return (BLOCK_NONE);
436
}
437
}
438
439
440
/*******************************************************************************
441
*
442
* FUNCTION: AcpiDmListType
443
*
444
* PARAMETERS: Op - Object to be examined
445
*
446
* RETURN: ListType - has commas or not.
447
*
448
* DESCRIPTION: Type of block for this op (parens or braces)
449
*
450
******************************************************************************/
451
452
UINT32
453
AcpiDmListType (
454
ACPI_PARSE_OBJECT *Op)
455
{
456
const ACPI_OPCODE_INFO *OpInfo;
457
458
459
if (!Op)
460
{
461
return (BLOCK_NONE);
462
}
463
464
switch (Op->Common.AmlOpcode)
465
{
466
467
case AML_ELSE_OP:
468
case AML_METHOD_OP:
469
case AML_DEVICE_OP:
470
case AML_SCOPE_OP:
471
case AML_POWER_RESOURCE_OP:
472
case AML_PROCESSOR_OP:
473
case AML_THERMAL_ZONE_OP:
474
case AML_IF_OP:
475
case AML_WHILE_OP:
476
case AML_FIELD_OP:
477
case AML_INDEX_FIELD_OP:
478
case AML_BANK_FIELD_OP:
479
480
return (BLOCK_NONE);
481
482
case AML_BUFFER_OP:
483
case AML_PACKAGE_OP:
484
case AML_VARIABLE_PACKAGE_OP:
485
486
return (BLOCK_COMMA_LIST);
487
488
default:
489
490
OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
491
if (OpInfo->Flags & AML_HAS_ARGS)
492
{
493
return (BLOCK_COMMA_LIST);
494
}
495
496
return (BLOCK_NONE);
497
}
498
}
499
500
501
/*******************************************************************************
502
*
503
* FUNCTION: AcpiDmDescendingOp
504
*
505
* PARAMETERS: ASL_WALK_CALLBACK
506
*
507
* RETURN: Status
508
*
509
* DESCRIPTION: First visitation of a parse object during tree descent.
510
* Decode opcode name and begin parameter list(s), if any.
511
*
512
******************************************************************************/
513
514
static ACPI_STATUS
515
AcpiDmDescendingOp (
516
ACPI_PARSE_OBJECT *Op,
517
UINT32 Level,
518
void *Context)
519
{
520
ACPI_OP_WALK_INFO *Info = Context;
521
const ACPI_OPCODE_INFO *OpInfo;
522
UINT32 Name;
523
ACPI_PARSE_OBJECT *NextOp;
524
ACPI_PARSE_OBJECT *NextOp2;
525
UINT32 AmlOffset;
526
527
528
/* Determine which file this parse node is contained in. */
529
530
if (AcpiGbl_CaptureComments)
531
{
532
ASL_CV_LABEL_FILENODE (Op);
533
534
if (Level != 0 && ASL_CV_FILE_HAS_SWITCHED (Op))
535
{
536
ASL_CV_SWITCH_FILES (Level, Op);
537
}
538
539
/* If this parse node has regular comments, print them here. */
540
541
ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_STANDARD, NULL, Level);
542
}
543
544
OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
545
546
/* Listing support to dump the AML code after the ASL statement */
547
548
if (AcpiGbl_DmOpt_Listing)
549
{
550
/* We only care about these classes of objects */
551
552
if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) ||
553
(OpInfo->Class == AML_CLASS_CONTROL) ||
554
(OpInfo->Class == AML_CLASS_CREATE) ||
555
((OpInfo->Class == AML_CLASS_EXECUTE) && (!Op->Common.Next)))
556
{
557
if (AcpiGbl_DmOpt_Listing && Info->PreviousAml)
558
{
559
/* Dump the AML byte code for the previous Op */
560
561
if (Op->Common.Aml > Info->PreviousAml)
562
{
563
AcpiOsPrintf ("\n");
564
AcpiUtDumpBuffer (
565
(Info->StartAml + Info->AmlOffset),
566
(Op->Common.Aml - Info->PreviousAml),
567
DB_BYTE_DISPLAY, Info->AmlOffset);
568
AcpiOsPrintf ("\n");
569
}
570
571
Info->AmlOffset = (Op->Common.Aml - Info->StartAml);
572
}
573
574
Info->PreviousAml = Op->Common.Aml;
575
}
576
}
577
578
if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
579
{
580
/* Ignore this op -- it was handled elsewhere */
581
582
return (AE_CTRL_DEPTH);
583
}
584
585
if (Op->Common.DisasmOpcode == ACPI_DASM_IGNORE_SINGLE)
586
{
587
/* Ignore this op, but not it's children */
588
589
return (AE_OK);
590
}
591
592
if (Op->Common.AmlOpcode == AML_IF_OP)
593
{
594
NextOp = AcpiPsGetDepthNext (NULL, Op);
595
if (NextOp)
596
{
597
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
598
599
/* Don't emit the actual embedded externals unless asked */
600
601
if (!AcpiGbl_DmEmitExternalOpcodes)
602
{
603
/*
604
* A Zero predicate indicates the possibility of one or more
605
* External() opcodes within the If() block.
606
*/
607
if (NextOp->Common.AmlOpcode == AML_ZERO_OP)
608
{
609
NextOp2 = NextOp->Common.Next;
610
611
if (NextOp2 &&
612
(NextOp2->Common.AmlOpcode == AML_EXTERNAL_OP))
613
{
614
/* Ignore the If 0 block and all children */
615
616
Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
617
return (AE_CTRL_DEPTH);
618
}
619
}
620
}
621
}
622
}
623
624
/* Level 0 is at the Definition Block level */
625
626
if (Level == 0)
627
{
628
/* In verbose mode, print the AML offset, opcode and depth count */
629
630
if (Info->WalkState)
631
{
632
AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,
633
Info->WalkState->ParserState.AmlStart);
634
if (AcpiGbl_DmOpt_Verbose)
635
{
636
if (AcpiGbl_CmSingleStep)
637
{
638
AcpiOsPrintf ("%5.5X/%4.4X: ",
639
AmlOffset, (UINT32) Op->Common.AmlOpcode);
640
}
641
else
642
{
643
AcpiOsPrintf ("AML Offset %5.5X, Opcode %4.4X: ",
644
AmlOffset, (UINT32) Op->Common.AmlOpcode);
645
}
646
}
647
}
648
649
if (Op->Common.AmlOpcode == AML_SCOPE_OP)
650
{
651
/* This is the beginning of the Definition Block */
652
653
AcpiOsPrintf ("{\n");
654
655
/* Emit all External() declarations here */
656
657
if (!AcpiGbl_DmEmitExternalOpcodes)
658
{
659
AcpiDmEmitExternals ();
660
}
661
662
return (AE_OK);
663
}
664
}
665
else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
666
(!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
667
(!(Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)) &&
668
(Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
669
{
670
/*
671
* This is a first-level element of a term list,
672
* indent a new line
673
*/
674
switch (Op->Common.AmlOpcode)
675
{
676
case AML_NOOP_OP:
677
/*
678
* Optionally just ignore this opcode. Some tables use
679
* NoOp opcodes for "padding" out packages that the BIOS
680
* changes dynamically. This can leave hundreds or
681
* thousands of NoOp opcodes that if disassembled,
682
* cannot be compiled because they are syntactically
683
* incorrect.
684
*/
685
if (AcpiGbl_IgnoreNoopOperator)
686
{
687
Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
688
return (AE_OK);
689
}
690
691
ACPI_FALLTHROUGH;
692
693
default:
694
695
AcpiDmIndent (Level);
696
break;
697
}
698
699
Info->LastLevel = Level;
700
Info->Count = 0;
701
}
702
703
/*
704
* This is an inexpensive mechanism to try and keep lines from getting
705
* too long. When the limit is hit, start a new line at the previous
706
* indent plus one. A better but more expensive mechanism would be to
707
* keep track of the current column.
708
*/
709
Info->Count++;
710
if (Info->Count /* +Info->LastLevel */ > 12)
711
{
712
Info->Count = 0;
713
AcpiOsPrintf ("\n");
714
AcpiDmIndent (Info->LastLevel + 1);
715
}
716
717
/* If ASL+ is enabled, check for a C-style operator */
718
719
if (AcpiDmCheckForSymbolicOpcode (Op, Info))
720
{
721
return (AE_OK);
722
}
723
724
/* Print the opcode name */
725
726
AcpiDmDisassembleOneOp (NULL, Info, Op);
727
728
if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
729
(Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
730
{
731
return (AE_OK);
732
}
733
734
if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
735
(Op->Common.AmlOpcode == AML_RETURN_OP))
736
{
737
Info->Level--;
738
}
739
740
if (Op->Common.AmlOpcode == AML_EXTERNAL_OP)
741
{
742
Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
743
return (AE_CTRL_DEPTH);
744
}
745
746
/* Start the opcode argument list if necessary */
747
748
if ((OpInfo->Flags & AML_HAS_ARGS) ||
749
(Op->Common.AmlOpcode == AML_EVENT_OP))
750
{
751
/* This opcode has an argument list */
752
753
if (AcpiDmBlockType (Op) & BLOCK_PAREN)
754
{
755
AcpiOsPrintf (" (");
756
if (!(AcpiDmBlockType (Op) & BLOCK_BRACE))
757
{
758
ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, " ", 0);
759
}
760
}
761
762
/* If this is a named opcode, print the associated name value */
763
764
if (OpInfo->Flags & AML_NAMED)
765
{
766
switch (Op->Common.AmlOpcode)
767
{
768
case AML_ALIAS_OP:
769
770
NextOp = AcpiPsGetDepthNext (NULL, Op);
771
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
772
AcpiDmNamestring (NextOp->Common.Value.Name);
773
AcpiOsPrintf (", ");
774
775
ACPI_FALLTHROUGH;
776
777
default:
778
779
Name = AcpiPsGetName (Op);
780
if (Op->Named.Path)
781
{
782
AcpiDmNamestring (Op->Named.Path);
783
}
784
else
785
{
786
AcpiDmDumpName (Name);
787
}
788
789
if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
790
{
791
if (AcpiGbl_DmOpt_Verbose)
792
{
793
(void) AcpiPsDisplayObjectPathname (NULL, Op);
794
}
795
}
796
break;
797
}
798
799
switch (Op->Common.AmlOpcode)
800
{
801
case AML_METHOD_OP:
802
803
AcpiDmMethodFlags (Op);
804
ASL_CV_CLOSE_PAREN (Op, Level);
805
806
/* Emit description comment for Method() with a predefined ACPI name */
807
808
AcpiDmPredefinedDescription (Op);
809
break;
810
811
case AML_NAME_OP:
812
813
/* Check for _HID and related EISAID() */
814
815
AcpiDmCheckForHardwareId (Op);
816
AcpiOsPrintf (", ");
817
ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
818
break;
819
820
case AML_REGION_OP:
821
822
AcpiDmRegionFlags (Op);
823
break;
824
825
case AML_POWER_RESOURCE_OP:
826
827
/* Mark the next two Ops as part of the parameter list */
828
829
AcpiOsPrintf (", ");
830
NextOp = AcpiPsGetDepthNext (NULL, Op);
831
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
832
833
NextOp = NextOp->Common.Next;
834
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
835
return (AE_OK);
836
837
case AML_PROCESSOR_OP:
838
839
/* Mark the next three Ops as part of the parameter list */
840
841
AcpiOsPrintf (", ");
842
NextOp = AcpiPsGetDepthNext (NULL, Op);
843
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
844
845
NextOp = NextOp->Common.Next;
846
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
847
848
NextOp = NextOp->Common.Next;
849
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
850
return (AE_OK);
851
852
case AML_MUTEX_OP:
853
case AML_DATA_REGION_OP:
854
855
AcpiOsPrintf (", ");
856
return (AE_OK);
857
858
case AML_EVENT_OP:
859
case AML_ALIAS_OP:
860
861
return (AE_OK);
862
863
case AML_SCOPE_OP:
864
case AML_DEVICE_OP:
865
case AML_THERMAL_ZONE_OP:
866
867
ASL_CV_CLOSE_PAREN (Op, Level);
868
break;
869
870
default:
871
872
AcpiOsPrintf ("*** Unhandled named opcode %X\n",
873
Op->Common.AmlOpcode);
874
break;
875
}
876
}
877
878
else switch (Op->Common.AmlOpcode)
879
{
880
case AML_FIELD_OP:
881
case AML_BANK_FIELD_OP:
882
case AML_INDEX_FIELD_OP:
883
884
Info->BitOffset = 0;
885
886
/* Name of the parent OperationRegion */
887
888
NextOp = AcpiPsGetDepthNext (NULL, Op);
889
AcpiDmNamestring (NextOp->Common.Value.Name);
890
AcpiOsPrintf (", ");
891
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
892
893
switch (Op->Common.AmlOpcode)
894
{
895
case AML_BANK_FIELD_OP:
896
897
/* Namestring - Bank Name */
898
899
NextOp = AcpiPsGetDepthNext (NULL, NextOp);
900
AcpiDmNamestring (NextOp->Common.Value.Name);
901
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
902
AcpiOsPrintf (", ");
903
904
/*
905
* Bank Value. This is a TermArg in the middle of the parameter
906
* list, must handle it here.
907
*
908
* Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMETER_LIST
909
* eliminates newline in the output.
910
*/
911
NextOp = NextOp->Common.Next;
912
913
Info->Flags = ACPI_PARSEOP_PARAMETER_LIST;
914
AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
915
AcpiDmAscendingOp, Info);
916
Info->Flags = 0;
917
Info->Level = Level;
918
919
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
920
AcpiOsPrintf (", ");
921
break;
922
923
case AML_INDEX_FIELD_OP:
924
925
/* Namestring - Data Name */
926
927
NextOp = AcpiPsGetDepthNext (NULL, NextOp);
928
AcpiDmNamestring (NextOp->Common.Value.Name);
929
AcpiOsPrintf (", ");
930
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
931
break;
932
933
default:
934
935
break;
936
}
937
938
AcpiDmFieldFlags (NextOp);
939
break;
940
941
case AML_BUFFER_OP:
942
943
/* The next op is the size parameter */
944
945
NextOp = AcpiPsGetDepthNext (NULL, Op);
946
if (!NextOp)
947
{
948
/* Single-step support */
949
950
return (AE_OK);
951
}
952
953
if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
954
{
955
/*
956
* We have a resource list. Don't need to output
957
* the buffer size Op. Open up a new block
958
*/
959
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
960
ASL_CV_CLOSE_PAREN (Op, Level);
961
962
if (Op->Asl.Parent->Common.AmlOpcode == AML_NAME_OP)
963
{
964
/*
965
* Emit description comment showing the full ACPI name
966
* of the ResourceTemplate only if it was defined using a
967
* Name statement.
968
*/
969
AcpiDmPredefinedDescription (Op->Asl.Parent);
970
}
971
972
AcpiOsPrintf ("\n");
973
AcpiDmIndent (Info->Level);
974
AcpiOsPrintf ("{\n");
975
return (AE_OK);
976
}
977
978
/* Normal Buffer, mark size as in the parameter list */
979
980
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
981
return (AE_OK);
982
983
case AML_IF_OP:
984
case AML_VARIABLE_PACKAGE_OP:
985
case AML_WHILE_OP:
986
987
/* The next op is the size or predicate parameter */
988
989
NextOp = AcpiPsGetDepthNext (NULL, Op);
990
if (NextOp)
991
{
992
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
993
}
994
return (AE_OK);
995
996
case AML_PACKAGE_OP:
997
998
/* The next op is the size parameter */
999
1000
NextOp = AcpiPsGetDepthNext (NULL, Op);
1001
if (NextOp)
1002
{
1003
NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
1004
}
1005
return (AE_OK);
1006
1007
case AML_MATCH_OP:
1008
1009
AcpiDmMatchOp (Op);
1010
break;
1011
1012
default:
1013
1014
break;
1015
}
1016
1017
if (AcpiDmBlockType (Op) & BLOCK_BRACE)
1018
{
1019
AcpiOsPrintf ("\n");
1020
AcpiDmIndent (Level);
1021
AcpiOsPrintf ("{\n");
1022
}
1023
}
1024
1025
return (AE_OK);
1026
}
1027
1028
1029
/*******************************************************************************
1030
*
1031
* FUNCTION: AcpiDmAscendingOp
1032
*
1033
* PARAMETERS: ASL_WALK_CALLBACK
1034
*
1035
* RETURN: Status
1036
*
1037
* DESCRIPTION: Second visitation of a parse object, during ascent of parse
1038
* tree. Close out any parameter lists and complete the opcode.
1039
*
1040
******************************************************************************/
1041
1042
static ACPI_STATUS
1043
AcpiDmAscendingOp (
1044
ACPI_PARSE_OBJECT *Op,
1045
UINT32 Level,
1046
void *Context)
1047
{
1048
ACPI_OP_WALK_INFO *Info = Context;
1049
ACPI_PARSE_OBJECT *ParentOp;
1050
1051
1052
/* Point the Op's filename pointer to the proper file */
1053
1054
if (AcpiGbl_CaptureComments)
1055
{
1056
ASL_CV_LABEL_FILENODE (Op);
1057
1058
/* Switch the output of these files if necessary */
1059
1060
if (ASL_CV_FILE_HAS_SWITCHED (Op))
1061
{
1062
ASL_CV_SWITCH_FILES (Level, Op);
1063
}
1064
}
1065
1066
if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE ||
1067
Op->Common.DisasmOpcode == ACPI_DASM_IGNORE_SINGLE)
1068
{
1069
/* Ignore this op -- it was handled elsewhere */
1070
1071
return (AE_OK);
1072
}
1073
1074
if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
1075
{
1076
/* Indicates the end of the current descriptor block (table) */
1077
1078
ASL_CV_CLOSE_BRACE (Op, Level);
1079
1080
/* Print any comments that are at the end of the file here */
1081
1082
if (AcpiGbl_CaptureComments && AcpiGbl_LastListHead)
1083
{
1084
AcpiOsPrintf ("\n");
1085
ASL_CV_PRINT_ONE_COMMENT_LIST (AcpiGbl_LastListHead, 0);
1086
}
1087
AcpiOsPrintf ("\n\n");
1088
1089
return (AE_OK);
1090
}
1091
1092
switch (AcpiDmBlockType (Op))
1093
{
1094
case BLOCK_PAREN:
1095
1096
/* Completed an op that has arguments, add closing paren if needed */
1097
1098
AcpiDmCloseOperator (Op);
1099
1100
if (Op->Common.AmlOpcode == AML_NAME_OP)
1101
{
1102
/* Emit description comment for Name() with a predefined ACPI name */
1103
1104
AcpiDmPredefinedDescription (Op);
1105
}
1106
else
1107
{
1108
/* For Create* operators, attempt to emit resource tag description */
1109
1110
AcpiDmFieldPredefinedDescription (Op);
1111
}
1112
1113
/* Decode Notify() values */
1114
1115
if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
1116
{
1117
AcpiDmNotifyDescription (Op);
1118
}
1119
1120
AcpiDmDisplayTargetPathname (Op);
1121
1122
/* Could be a nested operator, check if comma required */
1123
1124
if (!AcpiDmCommaIfListMember (Op))
1125
{
1126
if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1127
(!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1128
(Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1129
{
1130
/*
1131
* This is a first-level element of a term list
1132
* start a new line
1133
*/
1134
if (!(Info->Flags & ACPI_PARSEOP_PARAMETER_LIST))
1135
{
1136
AcpiOsPrintf ("\n");
1137
}
1138
}
1139
}
1140
break;
1141
1142
case BLOCK_BRACE:
1143
case (BLOCK_BRACE | BLOCK_PAREN):
1144
1145
/* Completed an op that has a term list, add closing brace */
1146
1147
if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
1148
{
1149
ASL_CV_CLOSE_BRACE (Op, Level);
1150
}
1151
else
1152
{
1153
AcpiDmIndent (Level);
1154
ASL_CV_CLOSE_BRACE (Op, Level);
1155
}
1156
1157
AcpiDmCommaIfListMember (Op);
1158
1159
if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
1160
{
1161
AcpiOsPrintf ("\n");
1162
if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
1163
{
1164
if ((Op->Common.AmlOpcode == AML_IF_OP) &&
1165
(Op->Common.Next) &&
1166
(Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
1167
{
1168
break;
1169
}
1170
1171
if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1172
(!Op->Common.Next))
1173
{
1174
break;
1175
}
1176
AcpiOsPrintf ("\n");
1177
}
1178
}
1179
break;
1180
1181
case BLOCK_NONE:
1182
default:
1183
1184
/* Could be a nested operator, check if comma required */
1185
1186
if (!AcpiDmCommaIfListMember (Op))
1187
{
1188
if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1189
(!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1190
(Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1191
{
1192
/*
1193
* This is a first-level element of a term list
1194
* start a new line
1195
*/
1196
AcpiOsPrintf ("\n");
1197
}
1198
}
1199
else if (Op->Common.Parent)
1200
{
1201
switch (Op->Common.Parent->Common.AmlOpcode)
1202
{
1203
case AML_PACKAGE_OP:
1204
case AML_VARIABLE_PACKAGE_OP:
1205
1206
if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1207
{
1208
AcpiOsPrintf ("\n");
1209
}
1210
break;
1211
1212
default:
1213
1214
break;
1215
}
1216
}
1217
break;
1218
}
1219
1220
if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)
1221
{
1222
if ((Op->Common.Next) &&
1223
(Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1224
{
1225
return (AE_OK);
1226
}
1227
1228
/*
1229
* The parent Op is guaranteed to be valid because of the flag
1230
* ACPI_PARSEOP_PARAMETER_LIST -- which means that this op is part of
1231
* a parameter list and thus has a valid parent.
1232
*/
1233
ParentOp = Op->Common.Parent;
1234
1235
/*
1236
* Just completed a parameter node for something like "Buffer (param)".
1237
* Close the paren and open up the term list block with a brace.
1238
*
1239
* Switch predicates don't have a Next node but require a closing paren
1240
* and opening brace.
1241
*/
1242
if (Op->Common.Next || Op->Common.DisasmOpcode == ACPI_DASM_SWITCH_PREDICATE)
1243
{
1244
ASL_CV_CLOSE_PAREN (Op, Level);
1245
1246
/*
1247
* Emit a description comment for a Name() operator that is a
1248
* predefined ACPI name. Must check the grandparent.
1249
*/
1250
ParentOp = ParentOp->Common.Parent;
1251
if (ParentOp &&
1252
(ParentOp->Asl.AmlOpcode == AML_NAME_OP))
1253
{
1254
AcpiDmPredefinedDescription (ParentOp);
1255
}
1256
1257
/* Correct the indentation level for Switch and Case predicates */
1258
1259
if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH_PREDICATE)
1260
{
1261
--Level;
1262
}
1263
1264
AcpiOsPrintf ("\n");
1265
AcpiDmIndent (Level - 1);
1266
AcpiOsPrintf ("{\n");
1267
}
1268
else
1269
{
1270
ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
1271
ASL_CV_CLOSE_PAREN (Op, Level);
1272
AcpiOsPrintf ("{");
1273
}
1274
}
1275
1276
if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
1277
(Op->Common.AmlOpcode == AML_RETURN_OP))
1278
{
1279
Info->Level++;
1280
}
1281
1282
/*
1283
* For ASL+, check for and emit a C-style symbol. If valid, the
1284
* symbol string has been deferred until after the first operand
1285
*/
1286
if (AcpiGbl_CstyleDisassembly)
1287
{
1288
if (Op->Asl.OperatorSymbol)
1289
{
1290
AcpiOsPrintf ("%s", Op->Asl.OperatorSymbol);
1291
Op->Asl.OperatorSymbol = NULL;
1292
}
1293
}
1294
1295
return (AE_OK);
1296
}
1297
1298