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 - 2009, 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
117#include "acpi.h"
118#include "accommon.h"
119#include "acparser.h"
120#include "amlcode.h"
121#include "acdisasm.h"
122#include "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/* Stub for non-compiler code */
134
135#ifndef ACPI_ASL_COMPILER
136void
137AcpiDmEmitExternals (
138    void)
139{
140    return;
141}
142#endif
143
144/* Local prototypes */
145
146static ACPI_STATUS
147AcpiDmDescendingOp (
148    ACPI_PARSE_OBJECT       *Op,
149    UINT32                  Level,
150    void                    *Context);
151
152static ACPI_STATUS
153AcpiDmAscendingOp (
154    ACPI_PARSE_OBJECT       *Op,
155    UINT32                  Level,
156    void                    *Context);
157
158static UINT32
159AcpiDmBlockType (
160    ACPI_PARSE_OBJECT       *Op);
161
162
163
164/*******************************************************************************
165 *
166 * FUNCTION:    AcpiDmDisassemble
167 *
168 * PARAMETERS:  WalkState       - Current state
169 *              Origin          - Starting object
170 *              NumOpcodes      - Max number of opcodes to be displayed
171 *
172 * RETURN:      None
173 *
174 * DESCRIPTION: Disassemble parser object and its children.  This is the
175 *              main entry point of the disassembler.
176 *
177 ******************************************************************************/
178
179void
180AcpiDmDisassemble (
181    ACPI_WALK_STATE         *WalkState,
182    ACPI_PARSE_OBJECT       *Origin,
183    UINT32                  NumOpcodes)
184{
185    ACPI_PARSE_OBJECT       *Op = Origin;
186    ACPI_OP_WALK_INFO       Info;
187
188
189    if (!Op)
190    {
191        return;
192    }
193
194    Info.Flags = 0;
195    Info.Level = 0;
196    Info.Count = 0;
197    Info.WalkState = WalkState;
198    AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
199    return;
200}
201
202
203/*******************************************************************************
204 *
205 * FUNCTION:    AcpiDmWalkParseTree
206 *
207 * PARAMETERS:  Op                      - Root Op object
208 *              DescendingCallback      - Called during tree descent
209 *              AscendingCallback       - Called during tree ascent
210 *              Context                 - To be passed to the callbacks
211 *
212 * RETURN:      Status from callback(s)
213 *
214 * DESCRIPTION: Walk the entire parse tree.
215 *
216 ******************************************************************************/
217
218void
219AcpiDmWalkParseTree (
220    ACPI_PARSE_OBJECT       *Op,
221    ASL_WALK_CALLBACK       DescendingCallback,
222    ASL_WALK_CALLBACK       AscendingCallback,
223    void                    *Context)
224{
225    BOOLEAN                 NodePreviouslyVisited;
226    ACPI_PARSE_OBJECT       *StartOp = Op;
227    ACPI_STATUS             Status;
228    ACPI_PARSE_OBJECT       *Next;
229    ACPI_OP_WALK_INFO       *Info = Context;
230
231
232    Info->Level = 0;
233    NodePreviouslyVisited = FALSE;
234
235    while (Op)
236    {
237        if (NodePreviouslyVisited)
238        {
239            if (AscendingCallback)
240            {
241                Status = AscendingCallback (Op, Info->Level, Context);
242                if (ACPI_FAILURE (Status))
243                {
244                    return;
245                }
246            }
247        }
248        else
249        {
250            /* Let the callback process the node */
251
252            Status = DescendingCallback (Op, Info->Level, Context);
253            if (ACPI_SUCCESS (Status))
254            {
255                /* Visit children first, once */
256
257                Next = AcpiPsGetArg (Op, 0);
258                if (Next)
259                {
260                    Info->Level++;
261                    Op = Next;
262                    continue;
263                }
264            }
265            else if (Status != AE_CTRL_DEPTH)
266            {
267                /* Exit immediately on any error */
268
269                return;
270            }
271        }
272
273        /* Terminate walk at start op */
274
275        if (Op == StartOp)
276        {
277            break;
278        }
279
280        /* No more children, re-visit this node */
281
282        if (!NodePreviouslyVisited)
283        {
284            NodePreviouslyVisited = TRUE;
285            continue;
286        }
287
288        /* No more children, visit peers */
289
290        if (Op->Common.Next)
291        {
292            Op = Op->Common.Next;
293            NodePreviouslyVisited = FALSE;
294        }
295        else
296        {
297            /* No peers, re-visit parent */
298
299            if (Info->Level != 0 )
300            {
301                Info->Level--;
302            }
303
304            Op = Op->Common.Parent;
305            NodePreviouslyVisited = TRUE;
306        }
307    }
308
309    /* If we get here, the walk completed with no errors */
310
311    return;
312}
313
314
315/*******************************************************************************
316 *
317 * FUNCTION:    AcpiDmBlockType
318 *
319 * PARAMETERS:  Op              - Object to be examined
320 *
321 * RETURN:      BlockType - not a block, parens, braces, or even both.
322 *
323 * DESCRIPTION: Type of block for this op (parens or braces)
324 *
325 ******************************************************************************/
326
327static UINT32
328AcpiDmBlockType (
329    ACPI_PARSE_OBJECT       *Op)
330{
331    const ACPI_OPCODE_INFO  *OpInfo;
332
333
334    if (!Op)
335    {
336        return (BLOCK_NONE);
337    }
338
339    switch (Op->Common.AmlOpcode)
340    {
341    case AML_ELSE_OP:
342
343        return (BLOCK_BRACE);
344
345    case AML_METHOD_OP:
346    case AML_DEVICE_OP:
347    case AML_SCOPE_OP:
348    case AML_PROCESSOR_OP:
349    case AML_POWER_RES_OP:
350    case AML_THERMAL_ZONE_OP:
351    case AML_IF_OP:
352    case AML_WHILE_OP:
353    case AML_FIELD_OP:
354    case AML_INDEX_FIELD_OP:
355    case AML_BANK_FIELD_OP:
356
357        return (BLOCK_PAREN | BLOCK_BRACE);
358
359    case AML_BUFFER_OP:
360
361        if (Op->Common.DisasmOpcode == ACPI_DASM_UNICODE)
362        {
363            return (BLOCK_NONE);
364        }
365
366        /*lint -fallthrough */
367
368    case AML_PACKAGE_OP:
369    case AML_VAR_PACKAGE_OP:
370
371        return (BLOCK_PAREN | BLOCK_BRACE);
372
373    case AML_EVENT_OP:
374
375        return (BLOCK_PAREN);
376
377    default:
378
379        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
380        if (OpInfo->Flags & AML_HAS_ARGS)
381        {
382            return (BLOCK_PAREN);
383        }
384
385        return (BLOCK_NONE);
386    }
387}
388
389
390/*******************************************************************************
391 *
392 * FUNCTION:    AcpiDmListType
393 *
394 * PARAMETERS:  Op              - Object to be examined
395 *
396 * RETURN:      ListType - has commas or not.
397 *
398 * DESCRIPTION: Type of block for this op (parens or braces)
399 *
400 ******************************************************************************/
401
402UINT32
403AcpiDmListType (
404    ACPI_PARSE_OBJECT       *Op)
405{
406    const ACPI_OPCODE_INFO  *OpInfo;
407
408
409    if (!Op)
410    {
411        return (BLOCK_NONE);
412    }
413
414    switch (Op->Common.AmlOpcode)
415    {
416
417    case AML_ELSE_OP:
418    case AML_METHOD_OP:
419    case AML_DEVICE_OP:
420    case AML_SCOPE_OP:
421    case AML_POWER_RES_OP:
422    case AML_PROCESSOR_OP:
423    case AML_THERMAL_ZONE_OP:
424    case AML_IF_OP:
425    case AML_WHILE_OP:
426    case AML_FIELD_OP:
427    case AML_INDEX_FIELD_OP:
428    case AML_BANK_FIELD_OP:
429
430        return (BLOCK_NONE);
431
432    case AML_BUFFER_OP:
433    case AML_PACKAGE_OP:
434    case AML_VAR_PACKAGE_OP:
435
436        return (BLOCK_COMMA_LIST);
437
438    default:
439
440        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
441        if (OpInfo->Flags & AML_HAS_ARGS)
442        {
443            return (BLOCK_COMMA_LIST);
444        }
445
446        return (BLOCK_NONE);
447    }
448}
449
450
451/*******************************************************************************
452 *
453 * FUNCTION:    AcpiDmDescendingOp
454 *
455 * PARAMETERS:  ASL_WALK_CALLBACK
456 *
457 * RETURN:      Status
458 *
459 * DESCRIPTION: First visitation of a parse object during tree descent.
460 *              Decode opcode name and begin parameter list(s), if any.
461 *
462 ******************************************************************************/
463
464static ACPI_STATUS
465AcpiDmDescendingOp (
466    ACPI_PARSE_OBJECT       *Op,
467    UINT32                  Level,
468    void                    *Context)
469{
470    ACPI_OP_WALK_INFO       *Info = Context;
471    const ACPI_OPCODE_INFO  *OpInfo;
472    UINT32                  Name;
473    ACPI_PARSE_OBJECT       *NextOp;
474
475
476    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
477    {
478        /* Ignore this op -- it was handled elsewhere */
479
480        return (AE_CTRL_DEPTH);
481    }
482
483    /* Level 0 is at the Definition Block level */
484
485    if (Level == 0)
486    {
487        /* In verbose mode, print the AML offset, opcode and depth count */
488
489        if (Info->WalkState)
490        {
491            VERBOSE_PRINT ((DB_FULL_OP_INFO,
492                (Info->WalkState->MethodNode ?
493                    Info->WalkState->MethodNode->Name.Ascii : "   "),
494                Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode));
495        }
496
497        if (Op->Common.AmlOpcode == AML_SCOPE_OP)
498        {
499            /* This is the beginning of the Definition Block */
500
501            AcpiOsPrintf ("{\n");
502
503            /* Emit all External() declarations here */
504
505            AcpiDmEmitExternals ();
506            return (AE_OK);
507        }
508    }
509    else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
510             (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
511             (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
512    {
513            /*
514             * This is a first-level element of a term list,
515             * indent a new line
516             */
517            AcpiDmIndent (Level);
518            Info->LastLevel = Level;
519            Info->Count = 0;
520    }
521
522    /*
523     * This is an inexpensive mechanism to try and keep lines from getting
524     * too long. When the limit is hit, start a new line at the previous
525     * indent plus one. A better but more expensive mechanism would be to
526     * keep track of the current column.
527     */
528    Info->Count++;
529    if (Info->Count /*+Info->LastLevel*/ > 10)
530    {
531        Info->Count = 0;
532        AcpiOsPrintf ("\n");
533        AcpiDmIndent (Info->LastLevel + 1);
534    }
535
536    /* Print the opcode name */
537
538    AcpiDmDisassembleOneOp (NULL, Info, Op);
539
540    if (Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX)
541    {
542        return (AE_OK);
543    }
544
545    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
546        (Op->Common.AmlOpcode == AML_RETURN_OP))
547    {
548        Info->Level--;
549    }
550
551    /* Start the opcode argument list if necessary */
552
553    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
554
555    if ((OpInfo->Flags & AML_HAS_ARGS) ||
556        (Op->Common.AmlOpcode == AML_EVENT_OP))
557    {
558        /* This opcode has an argument list */
559
560        if (AcpiDmBlockType (Op) & BLOCK_PAREN)
561        {
562            AcpiOsPrintf (" (");
563        }
564
565        /* If this is a named opcode, print the associated name value */
566
567        if (OpInfo->Flags & AML_NAMED)
568        {
569            switch (Op->Common.AmlOpcode)
570            {
571            case AML_ALIAS_OP:
572
573                NextOp = AcpiPsGetDepthNext (NULL, Op);
574                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
575                AcpiDmNamestring (NextOp->Common.Value.Name);
576                AcpiOsPrintf (", ");
577
578                /*lint -fallthrough */
579
580            default:
581
582                Name = AcpiPsGetName (Op);
583                if (Op->Named.Path)
584                {
585                    AcpiDmNamestring ((char *) Op->Named.Path);
586                }
587                else
588                {
589                    AcpiDmDumpName (Name);
590                }
591
592                if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
593                {
594                    if (AcpiGbl_DbOpt_verbose)
595                    {
596                        (void) AcpiPsDisplayObjectPathname (NULL, Op);
597                    }
598                }
599                break;
600            }
601
602            switch (Op->Common.AmlOpcode)
603            {
604            case AML_METHOD_OP:
605
606                AcpiDmMethodFlags (Op);
607                AcpiOsPrintf (")");
608                break;
609
610
611            case AML_NAME_OP:
612
613                /* Check for _HID and related EISAID() */
614
615                AcpiDmIsEisaId (Op);
616                AcpiOsPrintf (", ");
617                break;
618
619
620            case AML_REGION_OP:
621
622                AcpiDmRegionFlags (Op);
623                break;
624
625
626            case AML_POWER_RES_OP:
627
628                /* Mark the next two Ops as part of the parameter list */
629
630                AcpiOsPrintf (", ");
631                NextOp = AcpiPsGetDepthNext (NULL, Op);
632                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
633
634                NextOp = NextOp->Common.Next;
635                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
636                return (AE_OK);
637
638
639            case AML_PROCESSOR_OP:
640
641                /* Mark the next three Ops as part of the parameter list */
642
643                AcpiOsPrintf (", ");
644                NextOp = AcpiPsGetDepthNext (NULL, Op);
645                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
646
647                NextOp = NextOp->Common.Next;
648                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
649
650                NextOp = NextOp->Common.Next;
651                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
652                return (AE_OK);
653
654
655            case AML_MUTEX_OP:
656            case AML_DATA_REGION_OP:
657
658                AcpiOsPrintf (", ");
659                return (AE_OK);
660
661
662            case AML_EVENT_OP:
663            case AML_ALIAS_OP:
664
665                return (AE_OK);
666
667
668            case AML_SCOPE_OP:
669            case AML_DEVICE_OP:
670            case AML_THERMAL_ZONE_OP:
671
672                AcpiOsPrintf (")");
673                break;
674
675
676            default:
677
678                AcpiOsPrintf ("*** Unhandled named opcode %X\n", Op->Common.AmlOpcode);
679                break;
680            }
681        }
682
683        else switch (Op->Common.AmlOpcode)
684        {
685        case AML_FIELD_OP:
686        case AML_BANK_FIELD_OP:
687        case AML_INDEX_FIELD_OP:
688
689            Info->BitOffset = 0;
690
691            /* Name of the parent OperationRegion */
692
693            NextOp = AcpiPsGetDepthNext (NULL, Op);
694            AcpiDmNamestring (NextOp->Common.Value.Name);
695            AcpiOsPrintf (", ");
696            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
697
698            switch (Op->Common.AmlOpcode)
699            {
700            case AML_BANK_FIELD_OP:
701
702                /* Namestring - Bank Name */
703
704                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
705                AcpiDmNamestring (NextOp->Common.Value.Name);
706                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
707                AcpiOsPrintf (", ");
708
709                /*
710                 * Bank Value. This is a TermArg in the middle of the parameter
711                 * list, must handle it here.
712                 *
713                 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
714                 * eliminates newline in the output.
715                 */
716                NextOp = NextOp->Common.Next;
717
718                Info->Flags = ACPI_PARSEOP_PARAMLIST;
719                AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp, AcpiDmAscendingOp, Info);
720                Info->Flags = 0;
721                Info->Level = Level;
722
723                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
724                AcpiOsPrintf (", ");
725                break;
726
727            case AML_INDEX_FIELD_OP:
728
729                /* Namestring - Data Name */
730
731                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
732                AcpiDmNamestring (NextOp->Common.Value.Name);
733                AcpiOsPrintf (", ");
734                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
735                break;
736
737            default:
738
739                break;
740            }
741
742            AcpiDmFieldFlags (NextOp);
743            break;
744
745
746        case AML_BUFFER_OP:
747
748            /* The next op is the size parameter */
749
750            NextOp = AcpiPsGetDepthNext (NULL, Op);
751            if (!NextOp)
752            {
753                /* Single-step support */
754
755                return (AE_OK);
756            }
757
758            if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
759            {
760                /*
761                 * We have a resource list.  Don't need to output
762                 * the buffer size Op.  Open up a new block
763                 */
764                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
765                NextOp = NextOp->Common.Next;
766                AcpiOsPrintf (")\n");
767                AcpiDmIndent (Info->Level);
768                AcpiOsPrintf ("{\n");
769                return (AE_OK);
770            }
771
772            /* Normal Buffer, mark size as in the parameter list */
773
774            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
775            return (AE_OK);
776
777
778        case AML_VAR_PACKAGE_OP:
779        case AML_IF_OP:
780        case AML_WHILE_OP:
781
782            /* The next op is the size or predicate parameter */
783
784            NextOp = AcpiPsGetDepthNext (NULL, Op);
785            if (NextOp)
786            {
787                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
788            }
789            return (AE_OK);
790
791
792        case AML_PACKAGE_OP:
793
794            /* The next op is the size or predicate parameter */
795
796            NextOp = AcpiPsGetDepthNext (NULL, Op);
797            if (NextOp)
798            {
799                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
800            }
801            return (AE_OK);
802
803
804        case AML_MATCH_OP:
805
806            AcpiDmMatchOp (Op);
807            break;
808
809
810        default:
811
812            break;
813        }
814
815        if (AcpiDmBlockType (Op) & BLOCK_BRACE)
816        {
817            AcpiOsPrintf ("\n");
818            AcpiDmIndent (Level);
819            AcpiOsPrintf ("{\n");
820        }
821    }
822
823    return (AE_OK);
824}
825
826
827/*******************************************************************************
828 *
829 * FUNCTION:    AcpiDmAscendingOp
830 *
831 * PARAMETERS:  ASL_WALK_CALLBACK
832 *
833 * RETURN:      Status
834 *
835 * DESCRIPTION: Second visitation of a parse object, during ascent of parse
836 *              tree.  Close out any parameter lists and complete the opcode.
837 *
838 ******************************************************************************/
839
840static ACPI_STATUS
841AcpiDmAscendingOp (
842    ACPI_PARSE_OBJECT       *Op,
843    UINT32                  Level,
844    void                    *Context)
845{
846    ACPI_OP_WALK_INFO       *Info = Context;
847
848
849    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
850    {
851        /* Ignore this op -- it was handled elsewhere */
852
853        return (AE_OK);
854    }
855
856    if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
857    {
858        /* Indicates the end of the current descriptor block (table) */
859
860        AcpiOsPrintf ("}\n\n");
861        return (AE_OK);
862    }
863
864    switch (AcpiDmBlockType (Op))
865    {
866    case BLOCK_PAREN:
867
868        /* Completed an op that has arguments, add closing paren */
869
870        AcpiOsPrintf (")");
871
872        /* Could be a nested operator, check if comma required */
873
874        if (!AcpiDmCommaIfListMember (Op))
875        {
876            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
877                     (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
878                     (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
879            {
880                /*
881                 * This is a first-level element of a term list
882                 * start a new line
883                 */
884                if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST))
885                {
886                    AcpiOsPrintf ("\n");
887                }
888            }
889        }
890        break;
891
892
893    case BLOCK_BRACE:
894    case (BLOCK_BRACE | BLOCK_PAREN):
895
896        /* Completed an op that has a term list, add closing brace */
897
898        if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
899        {
900            AcpiOsPrintf ("}");
901        }
902        else
903        {
904            AcpiDmIndent (Level);
905            AcpiOsPrintf ("}");
906        }
907
908        AcpiDmCommaIfListMember (Op);
909
910        if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
911        {
912            AcpiOsPrintf ("\n");
913            if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
914            {
915                if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
916                    (Op->Common.Next) &&
917                    (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
918                {
919                    break;
920                }
921
922                if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
923                    (!Op->Common.Next))
924                {
925                    break;
926                }
927                AcpiOsPrintf ("\n");
928            }
929        }
930        break;
931
932
933    case BLOCK_NONE:
934    default:
935
936        /* Could be a nested operator, check if comma required */
937
938        if (!AcpiDmCommaIfListMember (Op))
939        {
940            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
941                     (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
942                     (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
943            {
944                /*
945                 * This is a first-level element of a term list
946                 * start a new line
947                 */
948                AcpiOsPrintf ("\n");
949            }
950        }
951        else if (Op->Common.Parent)
952        {
953            switch (Op->Common.Parent->Common.AmlOpcode)
954            {
955            case AML_PACKAGE_OP:
956            case AML_VAR_PACKAGE_OP:
957
958                if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
959                {
960                    AcpiOsPrintf ("\n");
961                }
962                break;
963
964            default:
965
966                break;
967            }
968        }
969        break;
970    }
971
972    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
973    {
974        if ((Op->Common.Next) &&
975            (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
976        {
977            return (AE_OK);
978        }
979
980        /*
981         * Just completed a parameter node for something like "Buffer (param)".
982         * Close the paren and open up the term list block with a brace
983         */
984        if (Op->Common.Next)
985        {
986            AcpiOsPrintf (")\n");
987            AcpiDmIndent (Level - 1);
988            AcpiOsPrintf ("{\n");
989        }
990        else
991        {
992            Op->Common.Parent->Common.DisasmFlags |=
993                                    ACPI_PARSEOP_EMPTY_TERMLIST;
994            AcpiOsPrintf (") {");
995        }
996    }
997
998    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
999        (Op->Common.AmlOpcode == AML_RETURN_OP))
1000    {
1001        Info->Level++;
1002    }
1003    return (AE_OK);
1004}
1005
1006
1007#endif  /* ACPI_DISASSEMBLER */
1008