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