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 - 2020, 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
167void
168AcpiDmEmitExternals (
169    void)
170{
171    return;
172}
173
174void
175AcpiDmEmitExternal (
176    ACPI_PARSE_OBJECT       *NameOp,
177    ACPI_PARSE_OBJECT       *TypeOp)
178{
179    return;
180}
181#endif
182
183/* Local prototypes */
184
185static ACPI_STATUS
186AcpiDmDescendingOp (
187    ACPI_PARSE_OBJECT       *Op,
188    UINT32                  Level,
189    void                    *Context);
190
191static ACPI_STATUS
192AcpiDmAscendingOp (
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
213void
214AcpiDmDisassemble (
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
253void
254AcpiDmWalkParseTree (
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
362UINT32
363AcpiDmBlockType (
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        /*lint -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        /*lint -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
452UINT32
453AcpiDmListType (
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
514static ACPI_STATUS
515AcpiDmDescendingOp (
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            /* 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                /*lint -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                /* Emit description comment for Name() with a predefined ACPI name */
963
964                AcpiDmPredefinedDescription (Op->Asl.Parent);
965
966                AcpiOsPrintf ("\n");
967                AcpiDmIndent (Info->Level);
968                AcpiOsPrintf ("{\n");
969                return (AE_OK);
970            }
971
972            /* Normal Buffer, mark size as in the parameter list */
973
974            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
975            return (AE_OK);
976
977        case AML_IF_OP:
978        case AML_VARIABLE_PACKAGE_OP:
979        case AML_WHILE_OP:
980
981            /* The next op is the size or predicate parameter */
982
983            NextOp = AcpiPsGetDepthNext (NULL, Op);
984            if (NextOp)
985            {
986                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
987            }
988            return (AE_OK);
989
990        case AML_PACKAGE_OP:
991
992            /* The next op is the size parameter */
993
994            NextOp = AcpiPsGetDepthNext (NULL, Op);
995            if (NextOp)
996            {
997                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
998            }
999            return (AE_OK);
1000
1001        case AML_MATCH_OP:
1002
1003            AcpiDmMatchOp (Op);
1004            break;
1005
1006        default:
1007
1008            break;
1009        }
1010
1011        if (AcpiDmBlockType (Op) & BLOCK_BRACE)
1012        {
1013            AcpiOsPrintf ("\n");
1014            AcpiDmIndent (Level);
1015            AcpiOsPrintf ("{\n");
1016        }
1017    }
1018
1019    return (AE_OK);
1020}
1021
1022
1023/*******************************************************************************
1024 *
1025 * FUNCTION:    AcpiDmAscendingOp
1026 *
1027 * PARAMETERS:  ASL_WALK_CALLBACK
1028 *
1029 * RETURN:      Status
1030 *
1031 * DESCRIPTION: Second visitation of a parse object, during ascent of parse
1032 *              tree. Close out any parameter lists and complete the opcode.
1033 *
1034 ******************************************************************************/
1035
1036static ACPI_STATUS
1037AcpiDmAscendingOp (
1038    ACPI_PARSE_OBJECT       *Op,
1039    UINT32                  Level,
1040    void                    *Context)
1041{
1042    ACPI_OP_WALK_INFO       *Info = Context;
1043    ACPI_PARSE_OBJECT       *ParentOp;
1044
1045
1046    /* Point the Op's filename pointer to the proper file */
1047
1048    if (AcpiGbl_CaptureComments)
1049    {
1050        ASL_CV_LABEL_FILENODE (Op);
1051
1052        /* Switch the output of these files if necessary */
1053
1054        if (ASL_CV_FILE_HAS_SWITCHED (Op))
1055        {
1056            ASL_CV_SWITCH_FILES (Level, Op);
1057        }
1058    }
1059
1060    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE ||
1061        Op->Common.DisasmOpcode == ACPI_DASM_IGNORE_SINGLE)
1062    {
1063        /* Ignore this op -- it was handled elsewhere */
1064
1065        return (AE_OK);
1066    }
1067
1068    if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
1069    {
1070        /* Indicates the end of the current descriptor block (table) */
1071
1072        ASL_CV_CLOSE_BRACE (Op, Level);
1073
1074        /* Print any comments that are at the end of the file here */
1075
1076        if (AcpiGbl_CaptureComments && AcpiGbl_LastListHead)
1077        {
1078            AcpiOsPrintf ("\n");
1079            ASL_CV_PRINT_ONE_COMMENT_LIST (AcpiGbl_LastListHead, 0);
1080        }
1081        AcpiOsPrintf ("\n\n");
1082
1083        return (AE_OK);
1084    }
1085
1086    switch (AcpiDmBlockType (Op))
1087    {
1088    case BLOCK_PAREN:
1089
1090        /* Completed an op that has arguments, add closing paren if needed */
1091
1092        AcpiDmCloseOperator (Op);
1093
1094        if (Op->Common.AmlOpcode == AML_NAME_OP)
1095        {
1096            /* Emit description comment for Name() with a predefined ACPI name */
1097
1098            AcpiDmPredefinedDescription (Op);
1099        }
1100        else
1101        {
1102            /* For Create* operators, attempt to emit resource tag description */
1103
1104            AcpiDmFieldPredefinedDescription (Op);
1105        }
1106
1107        /* Decode Notify() values */
1108
1109        if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
1110        {
1111            AcpiDmNotifyDescription (Op);
1112        }
1113
1114        AcpiDmDisplayTargetPathname (Op);
1115
1116        /* Could be a nested operator, check if comma required */
1117
1118        if (!AcpiDmCommaIfListMember (Op))
1119        {
1120            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1121                 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1122                 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1123            {
1124                /*
1125                 * This is a first-level element of a term list
1126                 * start a new line
1127                 */
1128                if (!(Info->Flags & ACPI_PARSEOP_PARAMETER_LIST))
1129                {
1130                    AcpiOsPrintf ("\n");
1131                }
1132            }
1133        }
1134        break;
1135
1136    case BLOCK_BRACE:
1137    case (BLOCK_BRACE | BLOCK_PAREN):
1138
1139        /* Completed an op that has a term list, add closing brace */
1140
1141        if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
1142        {
1143            ASL_CV_CLOSE_BRACE (Op, Level);
1144        }
1145        else
1146        {
1147            AcpiDmIndent (Level);
1148            ASL_CV_CLOSE_BRACE (Op, Level);
1149        }
1150
1151        AcpiDmCommaIfListMember (Op);
1152
1153        if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
1154        {
1155            AcpiOsPrintf ("\n");
1156            if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
1157            {
1158                if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
1159                    (Op->Common.Next) &&
1160                    (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
1161                {
1162                    break;
1163                }
1164
1165                if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1166                    (!Op->Common.Next))
1167                {
1168                    break;
1169                }
1170                AcpiOsPrintf ("\n");
1171            }
1172        }
1173        break;
1174
1175    case BLOCK_NONE:
1176    default:
1177
1178        /* Could be a nested operator, check if comma required */
1179
1180        if (!AcpiDmCommaIfListMember (Op))
1181        {
1182            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1183                 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1184                 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1185            {
1186                /*
1187                 * This is a first-level element of a term list
1188                 * start a new line
1189                 */
1190                AcpiOsPrintf ("\n");
1191            }
1192        }
1193        else if (Op->Common.Parent)
1194        {
1195            switch (Op->Common.Parent->Common.AmlOpcode)
1196            {
1197            case AML_PACKAGE_OP:
1198            case AML_VARIABLE_PACKAGE_OP:
1199
1200                if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1201                {
1202                    AcpiOsPrintf ("\n");
1203                }
1204                break;
1205
1206            default:
1207
1208                break;
1209            }
1210        }
1211        break;
1212    }
1213
1214    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)
1215    {
1216        if ((Op->Common.Next) &&
1217            (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1218        {
1219            return (AE_OK);
1220        }
1221
1222        /*
1223         * The parent Op is guaranteed to be valid because of the flag
1224         * ACPI_PARSEOP_PARAMETER_LIST -- which means that this op is part of
1225         * a parameter list and thus has a valid parent.
1226         */
1227        ParentOp = Op->Common.Parent;
1228
1229        /*
1230         * Just completed a parameter node for something like "Buffer (param)".
1231         * Close the paren and open up the term list block with a brace.
1232         *
1233         * Switch predicates don't have a Next node but require a closing paren
1234         * and opening brace.
1235         */
1236        if (Op->Common.Next || Op->Common.DisasmOpcode == ACPI_DASM_SWITCH_PREDICATE)
1237        {
1238            ASL_CV_CLOSE_PAREN (Op, Level);
1239
1240            /*
1241             * Emit a description comment for a Name() operator that is a
1242             * predefined ACPI name. Must check the grandparent.
1243             */
1244            ParentOp = ParentOp->Common.Parent;
1245            if (ParentOp &&
1246                (ParentOp->Asl.AmlOpcode == AML_NAME_OP))
1247            {
1248                AcpiDmPredefinedDescription (ParentOp);
1249            }
1250
1251            /* Correct the indentation level for Switch and Case predicates */
1252
1253            if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH_PREDICATE)
1254            {
1255                --Level;
1256            }
1257
1258            AcpiOsPrintf ("\n");
1259            AcpiDmIndent (Level - 1);
1260            AcpiOsPrintf ("{\n");
1261        }
1262        else
1263        {
1264            ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
1265            ASL_CV_CLOSE_PAREN (Op, Level);
1266            AcpiOsPrintf ("{");
1267        }
1268    }
1269
1270    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
1271        (Op->Common.AmlOpcode == AML_RETURN_OP))
1272    {
1273        Info->Level++;
1274    }
1275
1276    /*
1277     * For ASL+, check for and emit a C-style symbol. If valid, the
1278     * symbol string has been deferred until after the first operand
1279     */
1280    if (AcpiGbl_CstyleDisassembly)
1281    {
1282        if (Op->Asl.OperatorSymbol)
1283        {
1284            AcpiOsPrintf ("%s", Op->Asl.OperatorSymbol);
1285            Op->Asl.OperatorSymbol = NULL;
1286        }
1287    }
1288
1289    return (AE_OK);
1290}
1291