dmwalk.c revision 167802
1/*******************************************************************************
2 *
3 * Module Name: dmwalk - AML disassembly tree walk
4 *              $Revision: 1.33 $
5 *
6 ******************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#include <contrib/dev/acpica/acpi.h>
119#include <contrib/dev/acpica/acparser.h>
120#include <contrib/dev/acpica/amlcode.h>
121#include <contrib/dev/acpica/acdisasm.h>
122#include <contrib/dev/acpica/acdebug.h>
123
124
125#ifdef ACPI_DISASSEMBLER
126
127#define _COMPONENT          ACPI_CA_DEBUGGER
128        ACPI_MODULE_NAME    ("dmwalk")
129
130
131#define DB_FULL_OP_INFO     "[%4.4s] @%5.5X #%4.4X:  "
132
133/* Local prototypes */
134
135static ACPI_STATUS
136AcpiDmDescendingOp (
137    ACPI_PARSE_OBJECT       *Op,
138    UINT32                  Level,
139    void                    *Context);
140
141static ACPI_STATUS
142AcpiDmAscendingOp (
143    ACPI_PARSE_OBJECT       *Op,
144    UINT32                  Level,
145    void                    *Context);
146
147static UINT32
148AcpiDmBlockType (
149    ACPI_PARSE_OBJECT       *Op);
150
151
152/*******************************************************************************
153 *
154 * FUNCTION:    AcpiDmDisassemble
155 *
156 * PARAMETERS:  WalkState       - Current state
157 *              Origin          - Starting object
158 *              NumOpcodes      - Max number of opcodes to be displayed
159 *
160 * RETURN:      None
161 *
162 * DESCRIPTION: Disassemble parser object and its children.  This is the
163 *              main entry point of the disassembler.
164 *
165 ******************************************************************************/
166
167void
168AcpiDmDisassemble (
169    ACPI_WALK_STATE         *WalkState,
170    ACPI_PARSE_OBJECT       *Origin,
171    UINT32                  NumOpcodes)
172{
173    ACPI_PARSE_OBJECT       *Op = Origin;
174    ACPI_OP_WALK_INFO       Info;
175
176
177    if (!Op)
178    {
179        return;
180    }
181
182    Info.Flags = 0;
183    Info.Level = 0;
184    Info.Count = 0;
185    Info.WalkState = WalkState;
186    AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
187    return;
188}
189
190
191/*******************************************************************************
192 *
193 * FUNCTION:    AcpiDmWalkParseTree
194 *
195 * PARAMETERS:  Op                      - Root Op object
196 *              DescendingCallback      - Called during tree descent
197 *              AscendingCallback       - Called during tree ascent
198 *              Context                 - To be passed to the callbacks
199 *
200 * RETURN:      Status from callback(s)
201 *
202 * DESCRIPTION: Walk the entire parse tree.
203 *
204 ******************************************************************************/
205
206void
207AcpiDmWalkParseTree (
208    ACPI_PARSE_OBJECT       *Op,
209    ASL_WALK_CALLBACK       DescendingCallback,
210    ASL_WALK_CALLBACK       AscendingCallback,
211    void                    *Context)
212{
213    BOOLEAN                 NodePreviouslyVisited;
214    ACPI_PARSE_OBJECT       *StartOp = Op;
215    ACPI_STATUS             Status;
216    ACPI_PARSE_OBJECT       *Next;
217    ACPI_OP_WALK_INFO       *Info = Context;
218
219
220    Info->Level = 0;
221    NodePreviouslyVisited = FALSE;
222
223    while (Op)
224    {
225        if (NodePreviouslyVisited)
226        {
227            if (AscendingCallback)
228            {
229                Status = AscendingCallback (Op, Info->Level, Context);
230                if (ACPI_FAILURE (Status))
231                {
232                    return;
233                }
234            }
235        }
236        else
237        {
238            /* Let the callback process the node */
239
240            Status = DescendingCallback (Op, Info->Level, Context);
241            if (ACPI_SUCCESS (Status))
242            {
243                /* Visit children first, once */
244
245                Next = AcpiPsGetArg (Op, 0);
246                if (Next)
247                {
248                    Info->Level++;
249                    Op = Next;
250                    continue;
251                }
252            }
253            else if (Status != AE_CTRL_DEPTH)
254            {
255                /* Exit immediately on any error */
256
257                return;
258            }
259        }
260
261        /* Terminate walk at start op */
262
263        if (Op == StartOp)
264        {
265            break;
266        }
267
268        /* No more children, re-visit this node */
269
270        if (!NodePreviouslyVisited)
271        {
272            NodePreviouslyVisited = TRUE;
273            continue;
274        }
275
276        /* No more children, visit peers */
277
278        if (Op->Common.Next)
279        {
280            Op = Op->Common.Next;
281            NodePreviouslyVisited = FALSE;
282        }
283        else
284        {
285            /* No peers, re-visit parent */
286
287            if (Info->Level != 0 )
288            {
289                Info->Level--;
290            }
291
292            Op = Op->Common.Parent;
293            NodePreviouslyVisited = TRUE;
294        }
295    }
296
297    /* If we get here, the walk completed with no errors */
298
299    return;
300}
301
302
303/*******************************************************************************
304 *
305 * FUNCTION:    AcpiDmBlockType
306 *
307 * PARAMETERS:  Op              - Object to be examined
308 *
309 * RETURN:      BlockType - not a block, parens, braces, or even both.
310 *
311 * DESCRIPTION: Type of block for this op (parens or braces)
312 *
313 ******************************************************************************/
314
315static UINT32
316AcpiDmBlockType (
317    ACPI_PARSE_OBJECT       *Op)
318{
319    const ACPI_OPCODE_INFO  *OpInfo;
320
321
322    if (!Op)
323    {
324        return (BLOCK_NONE);
325    }
326
327    switch (Op->Common.AmlOpcode)
328    {
329    case AML_ELSE_OP:
330
331        return (BLOCK_BRACE);
332
333    case AML_METHOD_OP:
334    case AML_DEVICE_OP:
335    case AML_SCOPE_OP:
336    case AML_PROCESSOR_OP:
337    case AML_POWER_RES_OP:
338    case AML_THERMAL_ZONE_OP:
339    case AML_IF_OP:
340    case AML_WHILE_OP:
341    case AML_FIELD_OP:
342    case AML_INDEX_FIELD_OP:
343    case AML_BANK_FIELD_OP:
344
345        return (BLOCK_PAREN | BLOCK_BRACE);
346
347    case AML_BUFFER_OP:
348
349        if (Op->Common.DisasmOpcode == ACPI_DASM_UNICODE)
350        {
351            return (BLOCK_NONE);
352        }
353
354        /*lint -fallthrough */
355
356    case AML_PACKAGE_OP:
357    case AML_VAR_PACKAGE_OP:
358
359        return (BLOCK_PAREN | BLOCK_BRACE);
360
361    case AML_EVENT_OP:
362
363        return (BLOCK_PAREN);
364
365    default:
366
367        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
368        if (OpInfo->Flags & AML_HAS_ARGS)
369        {
370            return (BLOCK_PAREN);
371        }
372
373        return (BLOCK_NONE);
374    }
375}
376
377
378/*******************************************************************************
379 *
380 * FUNCTION:    AcpiDmListType
381 *
382 * PARAMETERS:  Op              - Object to be examined
383 *
384 * RETURN:      ListType - has commas or not.
385 *
386 * DESCRIPTION: Type of block for this op (parens or braces)
387 *
388 ******************************************************************************/
389
390UINT32
391AcpiDmListType (
392    ACPI_PARSE_OBJECT       *Op)
393{
394    const ACPI_OPCODE_INFO  *OpInfo;
395
396
397    if (!Op)
398    {
399        return (BLOCK_NONE);
400    }
401
402    switch (Op->Common.AmlOpcode)
403    {
404
405    case AML_ELSE_OP:
406    case AML_METHOD_OP:
407    case AML_DEVICE_OP:
408    case AML_SCOPE_OP:
409    case AML_POWER_RES_OP:
410    case AML_PROCESSOR_OP:
411    case AML_THERMAL_ZONE_OP:
412    case AML_IF_OP:
413    case AML_WHILE_OP:
414    case AML_FIELD_OP:
415    case AML_INDEX_FIELD_OP:
416    case AML_BANK_FIELD_OP:
417
418        return (BLOCK_NONE);
419
420    case AML_BUFFER_OP:
421    case AML_PACKAGE_OP:
422    case AML_VAR_PACKAGE_OP:
423
424        return (BLOCK_COMMA_LIST);
425
426    default:
427
428        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
429        if (OpInfo->Flags & AML_HAS_ARGS)
430        {
431            return (BLOCK_COMMA_LIST);
432        }
433
434        return (BLOCK_NONE);
435    }
436}
437
438
439/*******************************************************************************
440 *
441 * FUNCTION:    AcpiDmDescendingOp
442 *
443 * PARAMETERS:  ASL_WALK_CALLBACK
444 *
445 * RETURN:      Status
446 *
447 * DESCRIPTION: First visitation of a parse object during tree descent.
448 *              Decode opcode name and begin parameter list(s), if any.
449 *
450 ******************************************************************************/
451
452static ACPI_STATUS
453AcpiDmDescendingOp (
454    ACPI_PARSE_OBJECT       *Op,
455    UINT32                  Level,
456    void                    *Context)
457{
458    ACPI_OP_WALK_INFO       *Info = Context;
459    const ACPI_OPCODE_INFO  *OpInfo;
460    UINT32                  Name;
461    ACPI_PARSE_OBJECT       *NextOp;
462    ACPI_EXTERNAL_LIST      *NextExternal;
463
464
465    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
466    {
467        /* Ignore this op -- it was handled elsewhere */
468
469        return (AE_CTRL_DEPTH);
470    }
471
472    /* Level 0 is at the Definition Block level */
473
474    if (Level == 0)
475    {
476        /* In verbose mode, print the AML offset, opcode and depth count */
477
478        if (Info->WalkState)
479        {
480            VERBOSE_PRINT ((DB_FULL_OP_INFO,
481                (Info->WalkState->MethodNode ?
482                    Info->WalkState->MethodNode->Name.Ascii : "   "),
483                Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode));
484        }
485
486        if (Op->Common.AmlOpcode == AML_SCOPE_OP)
487        {
488            /* This is the beginning of the Definition Block */
489
490            AcpiOsPrintf ("{\n");
491
492            /* Emit all External() declarations here */
493
494            if (AcpiGbl_ExternalList)
495            {
496                /*
497                 * Walk the list of externals (unresolved references)
498                 * found during parsing
499                 */
500                while (AcpiGbl_ExternalList)
501                {
502                    AcpiOsPrintf ("    External (%s",
503                        AcpiGbl_ExternalList->Path);
504
505                    /* TBD: should be a lookup table */
506
507                    switch (AcpiGbl_ExternalList->Type)
508                    {
509                    case ACPI_TYPE_DEVICE:
510                        AcpiOsPrintf (", DeviceObj");
511                        break;
512
513                    case ACPI_TYPE_METHOD:
514                        AcpiOsPrintf (", MethodObj");
515                        break;
516
517                    case ACPI_TYPE_INTEGER:
518                        AcpiOsPrintf (", IntObj");
519                        break;
520
521                    default:
522                        break;
523                    }
524
525                    if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
526                    {
527                        AcpiOsPrintf (")    // %d Arguments\n", AcpiGbl_ExternalList->Value);
528                    }
529                    else
530                    {
531                        AcpiOsPrintf (")\n");
532                    }
533
534                    NextExternal = AcpiGbl_ExternalList->Next;
535                    ACPI_FREE (AcpiGbl_ExternalList->Path);
536                    ACPI_FREE (AcpiGbl_ExternalList);
537                    AcpiGbl_ExternalList = NextExternal;
538                }
539                AcpiOsPrintf ("\n");
540            }
541
542            return (AE_OK);
543        }
544    }
545    else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
546             (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
547             (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
548    {
549            /*
550             * This is a first-level element of a term list,
551             * indent a new line
552             */
553            AcpiDmIndent (Level);
554            Info->LastLevel = Level;
555            Info->Count = 0;
556    }
557
558    /*
559     * This is an inexpensive mechanism to try and keep lines from getting
560     * too long. When the limit is hit, start a new line at the previous
561     * indent plus one. A better but more expensive mechanism would be to
562     * keep track of the current column.
563     */
564    Info->Count++;
565    if (Info->Count /*+Info->LastLevel*/ > 10)
566    {
567        Info->Count = 0;
568        AcpiOsPrintf ("\n");
569        AcpiDmIndent (Info->LastLevel + 1);
570    }
571
572    /* Print the opcode name */
573
574    AcpiDmDisassembleOneOp (NULL, Info, Op);
575
576    if (Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX)
577    {
578        return (AE_OK);
579    }
580
581    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
582        (Op->Common.AmlOpcode == AML_RETURN_OP))
583    {
584        Info->Level--;
585    }
586
587    /* Start the opcode argument list if necessary */
588
589    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
590
591    if ((OpInfo->Flags & AML_HAS_ARGS) ||
592        (Op->Common.AmlOpcode == AML_EVENT_OP))
593    {
594        /* This opcode has an argument list */
595
596        if (AcpiDmBlockType (Op) & BLOCK_PAREN)
597        {
598            AcpiOsPrintf (" (");
599        }
600
601        /* If this is a named opcode, print the associated name value */
602
603        if (OpInfo->Flags & AML_NAMED)
604        {
605            switch (Op->Common.AmlOpcode)
606            {
607            case AML_ALIAS_OP:
608
609                NextOp = AcpiPsGetDepthNext (NULL, Op);
610                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
611                AcpiDmNamestring (NextOp->Common.Value.Name);
612                AcpiOsPrintf (", ");
613
614                /*lint -fallthrough */
615
616            default:
617
618                Name = AcpiPsGetName (Op);
619                if (Op->Named.Path)
620                {
621                    AcpiDmNamestring ((char *) Op->Named.Path);
622                }
623                else
624                {
625                    AcpiDmDumpName ((char *) &Name);
626                }
627
628                if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
629                {
630                    if (AcpiGbl_DbOpt_verbose)
631                    {
632                        (void) AcpiPsDisplayObjectPathname (NULL, Op);
633                    }
634                }
635                break;
636            }
637
638            switch (Op->Common.AmlOpcode)
639            {
640            case AML_METHOD_OP:
641
642                AcpiDmMethodFlags (Op);
643                AcpiOsPrintf (")");
644                break;
645
646
647            case AML_NAME_OP:
648
649                /* Check for _HID and related EISAID() */
650
651                AcpiDmIsEisaId (Op);
652                AcpiOsPrintf (", ");
653                break;
654
655
656            case AML_REGION_OP:
657
658                AcpiDmRegionFlags (Op);
659                break;
660
661
662            case AML_POWER_RES_OP:
663
664                /* Mark the next two Ops as part of the parameter list */
665
666                AcpiOsPrintf (", ");
667                NextOp = AcpiPsGetDepthNext (NULL, Op);
668                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
669
670                NextOp = NextOp->Common.Next;
671                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
672                return (AE_OK);
673
674
675            case AML_PROCESSOR_OP:
676
677                /* Mark the next three Ops as part of the parameter list */
678
679                AcpiOsPrintf (", ");
680                NextOp = AcpiPsGetDepthNext (NULL, Op);
681                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
682
683                NextOp = NextOp->Common.Next;
684                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
685
686                NextOp = NextOp->Common.Next;
687                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
688                return (AE_OK);
689
690
691            case AML_MUTEX_OP:
692            case AML_DATA_REGION_OP:
693
694                AcpiOsPrintf (", ");
695                return (AE_OK);
696
697
698            case AML_EVENT_OP:
699            case AML_ALIAS_OP:
700
701                return (AE_OK);
702
703
704            case AML_SCOPE_OP:
705            case AML_DEVICE_OP:
706            case AML_THERMAL_ZONE_OP:
707
708                AcpiOsPrintf (")");
709                break;
710
711
712            default:
713
714                AcpiOsPrintf ("*** Unhandled named opcode %X\n", Op->Common.AmlOpcode);
715                break;
716            }
717        }
718
719        else switch (Op->Common.AmlOpcode)
720        {
721        case AML_FIELD_OP:
722        case AML_BANK_FIELD_OP:
723        case AML_INDEX_FIELD_OP:
724
725            Info->BitOffset = 0;
726
727            /* Name of the parent OperationRegion */
728
729            NextOp = AcpiPsGetDepthNext (NULL, Op);
730            AcpiDmNamestring (NextOp->Common.Value.Name);
731            AcpiOsPrintf (", ");
732            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
733
734            switch (Op->Common.AmlOpcode)
735            {
736            case AML_BANK_FIELD_OP:
737
738                /* Namestring - Bank Name */
739
740                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
741                AcpiDmNamestring (NextOp->Common.Value.Name);
742                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
743                AcpiOsPrintf (", ");
744
745                /*
746                 * Bank Value. This is a TermArg in the middle of the parameter
747                 * list, must handle it here.
748                 *
749                 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
750                 * eliminates newline in the output.
751                 */
752                NextOp = NextOp->Common.Next;
753
754                Info->Flags = ACPI_PARSEOP_PARAMLIST;
755                AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp, AcpiDmAscendingOp, Info);
756                Info->Flags = 0;
757                Info->Level = Level;
758
759                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
760                AcpiOsPrintf (", ");
761                break;
762
763            case AML_INDEX_FIELD_OP:
764
765                /* Namestring - Data Name */
766
767                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
768                AcpiDmNamestring (NextOp->Common.Value.Name);
769                AcpiOsPrintf (", ");
770                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
771                break;
772
773            default:
774
775                break;
776            }
777
778            AcpiDmFieldFlags (NextOp);
779            break;
780
781
782        case AML_BUFFER_OP:
783
784            /* The next op is the size parameter */
785
786            NextOp = AcpiPsGetDepthNext (NULL, Op);
787            if (!NextOp)
788            {
789                /* Single-step support */
790
791                return (AE_OK);
792            }
793
794            if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
795            {
796                /*
797                 * We have a resource list.  Don't need to output
798                 * the buffer size Op.  Open up a new block
799                 */
800                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
801                NextOp = NextOp->Common.Next;
802                AcpiOsPrintf (")\n");
803                AcpiDmIndent (Info->Level);
804                AcpiOsPrintf ("{\n");
805                return (AE_OK);
806            }
807
808            /* Normal Buffer, mark size as in the parameter list */
809
810            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
811            return (AE_OK);
812
813
814        case AML_VAR_PACKAGE_OP:
815        case AML_IF_OP:
816        case AML_WHILE_OP:
817
818            /* The next op is the size or predicate parameter */
819
820            NextOp = AcpiPsGetDepthNext (NULL, Op);
821            if (NextOp)
822            {
823                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
824            }
825            return (AE_OK);
826
827
828        case AML_PACKAGE_OP:
829
830            /* The next op is the size or predicate parameter */
831
832            NextOp = AcpiPsGetDepthNext (NULL, Op);
833            if (NextOp)
834            {
835                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
836            }
837            return (AE_OK);
838
839
840        case AML_MATCH_OP:
841
842            AcpiDmMatchOp (Op);
843            break;
844
845
846        default:
847
848            break;
849        }
850
851        if (AcpiDmBlockType (Op) & BLOCK_BRACE)
852        {
853            AcpiOsPrintf ("\n");
854            AcpiDmIndent (Level);
855            AcpiOsPrintf ("{\n");
856        }
857    }
858
859    return (AE_OK);
860}
861
862
863/*******************************************************************************
864 *
865 * FUNCTION:    AcpiDmAscendingOp
866 *
867 * PARAMETERS:  ASL_WALK_CALLBACK
868 *
869 * RETURN:      Status
870 *
871 * DESCRIPTION: Second visitation of a parse object, during ascent of parse
872 *              tree.  Close out any parameter lists and complete the opcode.
873 *
874 ******************************************************************************/
875
876static ACPI_STATUS
877AcpiDmAscendingOp (
878    ACPI_PARSE_OBJECT       *Op,
879    UINT32                  Level,
880    void                    *Context)
881{
882    ACPI_OP_WALK_INFO       *Info = Context;
883
884
885    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
886    {
887        /* Ignore this op -- it was handled elsewhere */
888
889        return (AE_OK);
890    }
891
892    if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
893    {
894        /* Indicates the end of the current descriptor block (table) */
895
896        AcpiOsPrintf ("}\n\n");
897        return (AE_OK);
898    }
899
900    switch (AcpiDmBlockType (Op))
901    {
902    case BLOCK_PAREN:
903
904        /* Completed an op that has arguments, add closing paren */
905
906        AcpiOsPrintf (")");
907
908        /* Could be a nested operator, check if comma required */
909
910        if (!AcpiDmCommaIfListMember (Op))
911        {
912            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
913                     (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
914                     (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
915            {
916                /*
917                 * This is a first-level element of a term list
918                 * start a new line
919                 */
920                if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST))
921                {
922                    AcpiOsPrintf ("\n");
923                }
924            }
925        }
926        break;
927
928
929    case BLOCK_BRACE:
930    case (BLOCK_BRACE | BLOCK_PAREN):
931
932        /* Completed an op that has a term list, add closing brace */
933
934        if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
935        {
936            AcpiOsPrintf ("}");
937        }
938        else
939        {
940            AcpiDmIndent (Level);
941            AcpiOsPrintf ("}");
942        }
943
944        AcpiDmCommaIfListMember (Op);
945
946        if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
947        {
948            AcpiOsPrintf ("\n");
949            if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
950            {
951                if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
952                    (Op->Common.Next) &&
953                    (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
954                {
955                    break;
956                }
957
958                if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
959                    (!Op->Common.Next))
960                {
961                    break;
962                }
963                AcpiOsPrintf ("\n");
964            }
965        }
966        break;
967
968
969    case BLOCK_NONE:
970    default:
971
972        /* Could be a nested operator, check if comma required */
973
974        if (!AcpiDmCommaIfListMember (Op))
975        {
976            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
977                     (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
978                     (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
979            {
980                /*
981                 * This is a first-level element of a term list
982                 * start a new line
983                 */
984                AcpiOsPrintf ("\n");
985            }
986        }
987        else if (Op->Common.Parent)
988        {
989            switch (Op->Common.Parent->Common.AmlOpcode)
990            {
991            case AML_PACKAGE_OP:
992            case AML_VAR_PACKAGE_OP:
993
994                if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
995                {
996                    AcpiOsPrintf ("\n");
997                }
998                break;
999
1000            default:
1001
1002                break;
1003            }
1004        }
1005        break;
1006    }
1007
1008    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
1009    {
1010        if ((Op->Common.Next) &&
1011            (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
1012        {
1013            return (AE_OK);
1014        }
1015
1016        /*
1017         * Just completed a parameter node for something like "Buffer (param)".
1018         * Close the paren and open up the term list block with a brace
1019         */
1020        if (Op->Common.Next)
1021        {
1022            AcpiOsPrintf (")\n");
1023            AcpiDmIndent (Level - 1);
1024            AcpiOsPrintf ("{\n");
1025        }
1026        else
1027        {
1028            Op->Common.Parent->Common.DisasmFlags |=
1029                                    ACPI_PARSEOP_EMPTY_TERMLIST;
1030            AcpiOsPrintf (") {");
1031        }
1032    }
1033
1034    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
1035        (Op->Common.AmlOpcode == AML_RETURN_OP))
1036    {
1037        Info->Level++;
1038    }
1039    return (AE_OK);
1040}
1041
1042
1043#endif  /* ACPI_DISASSEMBLER */
1044