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