dmwalk.c revision 306536
1/*******************************************************************************
2 *
3 * Module Name: dmwalk - AML disassembly tree walk
4 *
5 ******************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <contrib/dev/acpica/include/acpi.h>
45#include <contrib/dev/acpica/include/accommon.h>
46#include <contrib/dev/acpica/include/acparser.h>
47#include <contrib/dev/acpica/include/amlcode.h>
48#include <contrib/dev/acpica/include/acdebug.h>
49
50
51#define _COMPONENT          ACPI_CA_DEBUGGER
52        ACPI_MODULE_NAME    ("dmwalk")
53
54
55#define DB_FULL_OP_INFO     "[%4.4s] @%5.5X #%4.4X:  "
56
57/* Stub for non-compiler code */
58
59#ifndef ACPI_ASL_COMPILER
60void
61AcpiDmEmitExternals (
62    void)
63{
64    return;
65}
66#endif
67
68/* Local prototypes */
69
70static ACPI_STATUS
71AcpiDmDescendingOp (
72    ACPI_PARSE_OBJECT       *Op,
73    UINT32                  Level,
74    void                    *Context);
75
76static ACPI_STATUS
77AcpiDmAscendingOp (
78    ACPI_PARSE_OBJECT       *Op,
79    UINT32                  Level,
80    void                    *Context);
81
82static UINT32
83AcpiDmBlockType (
84    ACPI_PARSE_OBJECT       *Op);
85
86
87/*******************************************************************************
88 *
89 * FUNCTION:    AcpiDmDisassemble
90 *
91 * PARAMETERS:  WalkState       - Current state
92 *              Origin          - Starting object
93 *              NumOpcodes      - Max number of opcodes to be displayed
94 *
95 * RETURN:      None
96 *
97 * DESCRIPTION: Disassemble parser object and its children. This is the
98 *              main entry point of the disassembler.
99 *
100 ******************************************************************************/
101
102void
103AcpiDmDisassemble (
104    ACPI_WALK_STATE         *WalkState,
105    ACPI_PARSE_OBJECT       *Origin,
106    UINT32                  NumOpcodes)
107{
108    ACPI_PARSE_OBJECT       *Op = Origin;
109    ACPI_OP_WALK_INFO       Info;
110
111
112    if (!Op)
113    {
114        return;
115    }
116
117    memset (&Info, 0, sizeof (ACPI_OP_WALK_INFO));
118    Info.WalkState = WalkState;
119    Info.StartAml = Op->Common.Aml - sizeof (ACPI_TABLE_HEADER);
120    Info.AmlOffset = Op->Common.Aml - Info.StartAml;
121
122    AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
123    return;
124}
125
126
127/*******************************************************************************
128 *
129 * FUNCTION:    AcpiDmWalkParseTree
130 *
131 * PARAMETERS:  Op                      - Root Op object
132 *              DescendingCallback      - Called during tree descent
133 *              AscendingCallback       - Called during tree ascent
134 *              Context                 - To be passed to the callbacks
135 *
136 * RETURN:      Status from callback(s)
137 *
138 * DESCRIPTION: Walk the entire parse tree.
139 *
140 ******************************************************************************/
141
142void
143AcpiDmWalkParseTree (
144    ACPI_PARSE_OBJECT       *Op,
145    ASL_WALK_CALLBACK       DescendingCallback,
146    ASL_WALK_CALLBACK       AscendingCallback,
147    void                    *Context)
148{
149    BOOLEAN                 NodePreviouslyVisited;
150    ACPI_PARSE_OBJECT       *StartOp = Op;
151    ACPI_STATUS             Status;
152    ACPI_PARSE_OBJECT       *Next;
153    ACPI_OP_WALK_INFO       *Info = Context;
154
155
156    Info->Level = 0;
157    NodePreviouslyVisited = FALSE;
158
159    while (Op)
160    {
161        if (NodePreviouslyVisited)
162        {
163            if (AscendingCallback)
164            {
165                Status = AscendingCallback (Op, Info->Level, Context);
166                if (ACPI_FAILURE (Status))
167                {
168                    return;
169                }
170            }
171        }
172        else
173        {
174            /* Let the callback process the node */
175
176            Status = DescendingCallback (Op, Info->Level, Context);
177            if (ACPI_SUCCESS (Status))
178            {
179                /* Visit children first, once */
180
181                Next = AcpiPsGetArg (Op, 0);
182                if (Next)
183                {
184                    Info->Level++;
185                    Op = Next;
186                    continue;
187                }
188            }
189            else if (Status != AE_CTRL_DEPTH)
190            {
191                /* Exit immediately on any error */
192
193                return;
194            }
195        }
196
197        /* Terminate walk at start op */
198
199        if (Op == StartOp)
200        {
201            break;
202        }
203
204        /* No more children, re-visit this node */
205
206        if (!NodePreviouslyVisited)
207        {
208            NodePreviouslyVisited = TRUE;
209            continue;
210        }
211
212        /* No more children, visit peers */
213
214        if (Op->Common.Next)
215        {
216            Op = Op->Common.Next;
217            NodePreviouslyVisited = FALSE;
218        }
219        else
220        {
221            /* No peers, re-visit parent */
222
223            if (Info->Level != 0 )
224            {
225                Info->Level--;
226            }
227
228            Op = Op->Common.Parent;
229            NodePreviouslyVisited = TRUE;
230        }
231    }
232
233    /* If we get here, the walk completed with no errors */
234
235    return;
236}
237
238
239/*******************************************************************************
240 *
241 * FUNCTION:    AcpiDmBlockType
242 *
243 * PARAMETERS:  Op              - Object to be examined
244 *
245 * RETURN:      BlockType - not a block, parens, braces, or even both.
246 *
247 * DESCRIPTION: Type of block for this op (parens or braces)
248 *
249 ******************************************************************************/
250
251static UINT32
252AcpiDmBlockType (
253    ACPI_PARSE_OBJECT       *Op)
254{
255    const ACPI_OPCODE_INFO  *OpInfo;
256
257
258    if (!Op)
259    {
260        return (BLOCK_NONE);
261    }
262
263    switch (Op->Common.AmlOpcode)
264    {
265    case AML_ELSE_OP:
266
267        return (BLOCK_BRACE);
268
269    case AML_METHOD_OP:
270    case AML_DEVICE_OP:
271    case AML_SCOPE_OP:
272    case AML_PROCESSOR_OP:
273    case AML_POWER_RES_OP:
274    case AML_THERMAL_ZONE_OP:
275    case AML_IF_OP:
276    case AML_WHILE_OP:
277    case AML_FIELD_OP:
278    case AML_INDEX_FIELD_OP:
279    case AML_BANK_FIELD_OP:
280
281        return (BLOCK_PAREN | BLOCK_BRACE);
282
283    case AML_BUFFER_OP:
284
285        if ((Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) ||
286            (Op->Common.DisasmOpcode == ACPI_DASM_UUID) ||
287            (Op->Common.DisasmOpcode == ACPI_DASM_PLD_METHOD))
288        {
289            return (BLOCK_NONE);
290        }
291
292        /*lint -fallthrough */
293
294    case AML_PACKAGE_OP:
295    case AML_VAR_PACKAGE_OP:
296
297        return (BLOCK_PAREN | BLOCK_BRACE);
298
299    case AML_EVENT_OP:
300
301        return (BLOCK_PAREN);
302
303    case AML_INT_METHODCALL_OP:
304
305        if (Op->Common.Parent &&
306            ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
307             (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)))
308        {
309            /* This is a reference to a method, not an invocation */
310
311            return (BLOCK_NONE);
312        }
313
314        /*lint -fallthrough */
315
316    default:
317
318        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
319        if (OpInfo->Flags & AML_HAS_ARGS)
320        {
321            return (BLOCK_PAREN);
322        }
323
324        return (BLOCK_NONE);
325    }
326}
327
328
329/*******************************************************************************
330 *
331 * FUNCTION:    AcpiDmListType
332 *
333 * PARAMETERS:  Op              - Object to be examined
334 *
335 * RETURN:      ListType - has commas or not.
336 *
337 * DESCRIPTION: Type of block for this op (parens or braces)
338 *
339 ******************************************************************************/
340
341UINT32
342AcpiDmListType (
343    ACPI_PARSE_OBJECT       *Op)
344{
345    const ACPI_OPCODE_INFO  *OpInfo;
346
347
348    if (!Op)
349    {
350        return (BLOCK_NONE);
351    }
352
353    switch (Op->Common.AmlOpcode)
354    {
355
356    case AML_ELSE_OP:
357    case AML_METHOD_OP:
358    case AML_DEVICE_OP:
359    case AML_SCOPE_OP:
360    case AML_POWER_RES_OP:
361    case AML_PROCESSOR_OP:
362    case AML_THERMAL_ZONE_OP:
363    case AML_IF_OP:
364    case AML_WHILE_OP:
365    case AML_FIELD_OP:
366    case AML_INDEX_FIELD_OP:
367    case AML_BANK_FIELD_OP:
368
369        return (BLOCK_NONE);
370
371    case AML_BUFFER_OP:
372    case AML_PACKAGE_OP:
373    case AML_VAR_PACKAGE_OP:
374
375        return (BLOCK_COMMA_LIST);
376
377    default:
378
379        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
380        if (OpInfo->Flags & AML_HAS_ARGS)
381        {
382            return (BLOCK_COMMA_LIST);
383        }
384
385        return (BLOCK_NONE);
386    }
387}
388
389
390/*******************************************************************************
391 *
392 * FUNCTION:    AcpiDmDescendingOp
393 *
394 * PARAMETERS:  ASL_WALK_CALLBACK
395 *
396 * RETURN:      Status
397 *
398 * DESCRIPTION: First visitation of a parse object during tree descent.
399 *              Decode opcode name and begin parameter list(s), if any.
400 *
401 ******************************************************************************/
402
403static ACPI_STATUS
404AcpiDmDescendingOp (
405    ACPI_PARSE_OBJECT       *Op,
406    UINT32                  Level,
407    void                    *Context)
408{
409    ACPI_OP_WALK_INFO       *Info = Context;
410    const ACPI_OPCODE_INFO  *OpInfo;
411    UINT32                  Name;
412    ACPI_PARSE_OBJECT       *NextOp;
413    ACPI_PARSE_OBJECT       *NextOp2;
414    UINT32                  AmlOffset;
415
416
417    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
418
419    /* Listing support to dump the AML code after the ASL statement */
420
421    if (AcpiGbl_DmOpt_Listing)
422    {
423        /* We only care about these classes of objects */
424
425        if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) ||
426            (OpInfo->Class == AML_CLASS_CONTROL) ||
427            (OpInfo->Class == AML_CLASS_CREATE) ||
428            ((OpInfo->Class == AML_CLASS_EXECUTE) && (!Op->Common.Next)))
429        {
430            if (AcpiGbl_DmOpt_Listing && Info->PreviousAml)
431            {
432                /* Dump the AML byte code for the previous Op */
433
434                if (Op->Common.Aml > Info->PreviousAml)
435                {
436                    AcpiOsPrintf ("\n");
437                    AcpiUtDumpBuffer (
438                        (Info->StartAml + Info->AmlOffset),
439                        (Op->Common.Aml - Info->PreviousAml),
440                        DB_BYTE_DISPLAY, Info->AmlOffset);
441                    AcpiOsPrintf ("\n");
442                }
443
444                Info->AmlOffset = (Op->Common.Aml - Info->StartAml);
445            }
446
447            Info->PreviousAml = Op->Common.Aml;
448        }
449    }
450
451    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
452    {
453        /* Ignore this op -- it was handled elsewhere */
454
455        return (AE_CTRL_DEPTH);
456    }
457
458    if (Op->Common.AmlOpcode == AML_IF_OP)
459    {
460        NextOp = AcpiPsGetDepthNext (NULL, Op);
461        if (NextOp)
462        {
463            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
464
465            /* Don't emit the actual embedded externals unless asked */
466
467            if (!AcpiGbl_DmEmitExternalOpcodes)
468            {
469                /*
470                 * A Zero predicate indicates the possibility of one or more
471                 * External() opcodes within the If() block.
472                 */
473                if (NextOp->Common.AmlOpcode == AML_ZERO_OP)
474                {
475                    NextOp2 = NextOp->Common.Next;
476
477                    if (NextOp2 &&
478                        (NextOp2->Common.AmlOpcode == AML_EXTERNAL_OP))
479                    {
480                        /* Ignore the If 0 block and all children */
481
482                        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
483                        return (AE_CTRL_DEPTH);
484                    }
485                }
486            }
487        }
488    }
489
490    /* Level 0 is at the Definition Block level */
491
492    if (Level == 0)
493    {
494        /* In verbose mode, print the AML offset, opcode and depth count */
495
496        if (Info->WalkState)
497        {
498            AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,
499                Info->WalkState->ParserState.AmlStart);
500            if (AcpiGbl_DmOpt_Verbose)
501            {
502                AcpiOsPrintf (DB_FULL_OP_INFO,
503                    (Info->WalkState->MethodNode ?
504                        Info->WalkState->MethodNode->Name.Ascii : "   "),
505                    AmlOffset, (UINT32) Op->Common.AmlOpcode);
506            }
507        }
508
509        if (Op->Common.AmlOpcode == AML_SCOPE_OP)
510        {
511            /* This is the beginning of the Definition Block */
512
513            AcpiOsPrintf ("{\n");
514
515            /* Emit all External() declarations here */
516
517            AcpiDmEmitExternals ();
518            return (AE_OK);
519        }
520    }
521    else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
522         (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
523         (!(Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)) &&
524         (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
525    {
526        /*
527         * This is a first-level element of a term list,
528         * indent a new line
529         */
530        switch (Op->Common.AmlOpcode)
531        {
532        case AML_NOOP_OP:
533            /*
534             * Optionally just ignore this opcode. Some tables use
535             * NoOp opcodes for "padding" out packages that the BIOS
536             * changes dynamically. This can leave hundreds or
537             * thousands of NoOp opcodes that if disassembled,
538             * cannot be compiled because they are syntactically
539             * incorrect.
540             */
541            if (AcpiGbl_IgnoreNoopOperator)
542            {
543                Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
544                return (AE_OK);
545            }
546
547            /* Fallthrough */
548
549        default:
550
551            AcpiDmIndent (Level);
552            break;
553        }
554
555        Info->LastLevel = Level;
556        Info->Count = 0;
557    }
558
559    /*
560     * This is an inexpensive mechanism to try and keep lines from getting
561     * too long. When the limit is hit, start a new line at the previous
562     * indent plus one. A better but more expensive mechanism would be to
563     * keep track of the current column.
564     */
565    Info->Count++;
566    if (Info->Count /* +Info->LastLevel */ > 12)
567    {
568        Info->Count = 0;
569        AcpiOsPrintf ("\n");
570        AcpiDmIndent (Info->LastLevel + 1);
571    }
572
573    /* If ASL+ is enabled, check for a C-style operator */
574
575    if (AcpiDmCheckForSymbolicOpcode (Op, Info))
576    {
577        return (AE_OK);
578    }
579
580    /* Print the opcode name */
581
582    AcpiDmDisassembleOneOp (NULL, Info, Op);
583
584    if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
585        (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
586    {
587        return (AE_OK);
588    }
589
590    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
591        (Op->Common.AmlOpcode == AML_RETURN_OP))
592    {
593        Info->Level--;
594    }
595
596    /* Start the opcode argument list if necessary */
597
598    if ((OpInfo->Flags & AML_HAS_ARGS) ||
599        (Op->Common.AmlOpcode == AML_EVENT_OP))
600    {
601        /* This opcode has an argument list */
602
603        if (AcpiDmBlockType (Op) & BLOCK_PAREN)
604        {
605            AcpiOsPrintf (" (");
606        }
607
608        /* If this is a named opcode, print the associated name value */
609
610        if (OpInfo->Flags & AML_NAMED)
611        {
612            switch (Op->Common.AmlOpcode)
613            {
614            case AML_ALIAS_OP:
615
616                NextOp = AcpiPsGetDepthNext (NULL, Op);
617                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
618                AcpiDmNamestring (NextOp->Common.Value.Name);
619                AcpiOsPrintf (", ");
620
621                /*lint -fallthrough */
622
623            default:
624
625                Name = AcpiPsGetName (Op);
626                if (Op->Named.Path)
627                {
628                    AcpiDmNamestring ((char *) Op->Named.Path);
629                }
630                else
631                {
632                    AcpiDmDumpName (Name);
633                }
634
635                if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
636                {
637                    if (AcpiGbl_DmOpt_Verbose)
638                    {
639                        (void) AcpiPsDisplayObjectPathname (NULL, Op);
640                    }
641                }
642                break;
643            }
644
645            switch (Op->Common.AmlOpcode)
646            {
647            case AML_METHOD_OP:
648
649                AcpiDmMethodFlags (Op);
650                AcpiOsPrintf (")");
651
652                /* Emit description comment for Method() with a predefined ACPI name */
653
654                AcpiDmPredefinedDescription (Op);
655                break;
656
657            case AML_NAME_OP:
658
659                /* Check for _HID and related EISAID() */
660
661                AcpiDmCheckForHardwareId (Op);
662                AcpiOsPrintf (", ");
663                break;
664
665            case AML_REGION_OP:
666
667                AcpiDmRegionFlags (Op);
668                break;
669
670            case AML_POWER_RES_OP:
671
672                /* Mark the next two Ops as part of the parameter list */
673
674                AcpiOsPrintf (", ");
675                NextOp = AcpiPsGetDepthNext (NULL, Op);
676                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
677
678                NextOp = NextOp->Common.Next;
679                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
680                return (AE_OK);
681
682            case AML_PROCESSOR_OP:
683
684                /* Mark the next three Ops as part of the parameter list */
685
686                AcpiOsPrintf (", ");
687                NextOp = AcpiPsGetDepthNext (NULL, Op);
688                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
689
690                NextOp = NextOp->Common.Next;
691                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
692
693                NextOp = NextOp->Common.Next;
694                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
695                return (AE_OK);
696
697            case AML_MUTEX_OP:
698            case AML_DATA_REGION_OP:
699
700                AcpiOsPrintf (", ");
701                return (AE_OK);
702
703            case AML_EVENT_OP:
704            case AML_ALIAS_OP:
705
706                return (AE_OK);
707
708            case AML_SCOPE_OP:
709            case AML_DEVICE_OP:
710            case AML_THERMAL_ZONE_OP:
711
712                AcpiOsPrintf (")");
713                break;
714
715            default:
716
717                AcpiOsPrintf ("*** Unhandled named opcode %X\n",
718                    Op->Common.AmlOpcode);
719                break;
720            }
721        }
722
723        else switch (Op->Common.AmlOpcode)
724        {
725        case AML_FIELD_OP:
726        case AML_BANK_FIELD_OP:
727        case AML_INDEX_FIELD_OP:
728
729            Info->BitOffset = 0;
730
731            /* Name of the parent OperationRegion */
732
733            NextOp = AcpiPsGetDepthNext (NULL, Op);
734            AcpiDmNamestring (NextOp->Common.Value.Name);
735            AcpiOsPrintf (", ");
736            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
737
738            switch (Op->Common.AmlOpcode)
739            {
740            case AML_BANK_FIELD_OP:
741
742                /* Namestring - Bank Name */
743
744                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
745                AcpiDmNamestring (NextOp->Common.Value.Name);
746                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
747                AcpiOsPrintf (", ");
748
749                /*
750                 * Bank Value. This is a TermArg in the middle of the parameter
751                 * list, must handle it here.
752                 *
753                 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMETER_LIST
754                 * eliminates newline in the output.
755                 */
756                NextOp = NextOp->Common.Next;
757
758                Info->Flags = ACPI_PARSEOP_PARAMETER_LIST;
759                AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
760                    AcpiDmAscendingOp, Info);
761                Info->Flags = 0;
762                Info->Level = Level;
763
764                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
765                AcpiOsPrintf (", ");
766                break;
767
768            case AML_INDEX_FIELD_OP:
769
770                /* Namestring - Data Name */
771
772                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
773                AcpiDmNamestring (NextOp->Common.Value.Name);
774                AcpiOsPrintf (", ");
775                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
776                break;
777
778            default:
779
780                break;
781            }
782
783            AcpiDmFieldFlags (NextOp);
784            break;
785
786        case AML_BUFFER_OP:
787
788            /* The next op is the size parameter */
789
790            NextOp = AcpiPsGetDepthNext (NULL, Op);
791            if (!NextOp)
792            {
793                /* Single-step support */
794
795                return (AE_OK);
796            }
797
798            if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
799            {
800                /*
801                 * We have a resource list. Don't need to output
802                 * the buffer size Op. Open up a new block
803                 */
804                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
805                NextOp = NextOp->Common.Next;
806                AcpiOsPrintf (")");
807
808                /* Emit description comment for Name() with a predefined ACPI name */
809
810                AcpiDmPredefinedDescription (Op->Asl.Parent);
811
812                AcpiOsPrintf ("\n");
813                AcpiDmIndent (Info->Level);
814                AcpiOsPrintf ("{\n");
815                return (AE_OK);
816            }
817
818            /* Normal Buffer, mark size as in the parameter list */
819
820            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
821            return (AE_OK);
822
823        case AML_IF_OP:
824        case AML_VAR_PACKAGE_OP:
825        case AML_WHILE_OP:
826
827            /* The next op is the size or predicate parameter */
828
829            NextOp = AcpiPsGetDepthNext (NULL, Op);
830            if (NextOp)
831            {
832                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
833            }
834            return (AE_OK);
835
836        case AML_PACKAGE_OP:
837
838            /* The next op is the size parameter */
839
840            NextOp = AcpiPsGetDepthNext (NULL, Op);
841            if (NextOp)
842            {
843                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
844            }
845            return (AE_OK);
846
847        case AML_MATCH_OP:
848
849            AcpiDmMatchOp (Op);
850            break;
851
852        default:
853
854            break;
855        }
856
857        if (AcpiDmBlockType (Op) & BLOCK_BRACE)
858        {
859            AcpiOsPrintf ("\n");
860            AcpiDmIndent (Level);
861            AcpiOsPrintf ("{\n");
862        }
863    }
864
865    return (AE_OK);
866}
867
868
869/*******************************************************************************
870 *
871 * FUNCTION:    AcpiDmAscendingOp
872 *
873 * PARAMETERS:  ASL_WALK_CALLBACK
874 *
875 * RETURN:      Status
876 *
877 * DESCRIPTION: Second visitation of a parse object, during ascent of parse
878 *              tree. Close out any parameter lists and complete the opcode.
879 *
880 ******************************************************************************/
881
882static ACPI_STATUS
883AcpiDmAscendingOp (
884    ACPI_PARSE_OBJECT       *Op,
885    UINT32                  Level,
886    void                    *Context)
887{
888    ACPI_OP_WALK_INFO       *Info = Context;
889    ACPI_PARSE_OBJECT       *ParentOp;
890
891
892    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
893    {
894        /* Ignore this op -- it was handled elsewhere */
895
896        return (AE_OK);
897    }
898
899    if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
900    {
901        /* Indicates the end of the current descriptor block (table) */
902
903        AcpiOsPrintf ("}\n\n");
904        return (AE_OK);
905    }
906
907    switch (AcpiDmBlockType (Op))
908    {
909    case BLOCK_PAREN:
910
911        /* Completed an op that has arguments, add closing paren if needed */
912
913        AcpiDmCloseOperator (Op);
914
915        if (Op->Common.AmlOpcode == AML_NAME_OP)
916        {
917            /* Emit description comment for Name() with a predefined ACPI name */
918
919            AcpiDmPredefinedDescription (Op);
920        }
921        else
922        {
923            /* For Create* operators, attempt to emit resource tag description */
924
925            AcpiDmFieldPredefinedDescription (Op);
926        }
927
928        /* Decode Notify() values */
929
930        if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
931        {
932            AcpiDmNotifyDescription (Op);
933        }
934
935        AcpiDmDisplayTargetPathname (Op);
936
937        /* Could be a nested operator, check if comma required */
938
939        if (!AcpiDmCommaIfListMember (Op))
940        {
941            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
942                 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
943                 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
944            {
945                /*
946                 * This is a first-level element of a term list
947                 * start a new line
948                 */
949                if (!(Info->Flags & ACPI_PARSEOP_PARAMETER_LIST))
950                {
951                    AcpiOsPrintf ("\n");
952                }
953            }
954        }
955        break;
956
957    case BLOCK_BRACE:
958    case (BLOCK_BRACE | BLOCK_PAREN):
959
960        /* Completed an op that has a term list, add closing brace */
961
962        if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
963        {
964            AcpiOsPrintf ("}");
965        }
966        else
967        {
968            AcpiDmIndent (Level);
969            AcpiOsPrintf ("}");
970        }
971
972        AcpiDmCommaIfListMember (Op);
973
974        if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
975        {
976            AcpiOsPrintf ("\n");
977            if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
978            {
979                if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
980                    (Op->Common.Next) &&
981                    (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
982                {
983                    break;
984                }
985
986                if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
987                    (!Op->Common.Next))
988                {
989                    break;
990                }
991                AcpiOsPrintf ("\n");
992            }
993        }
994        break;
995
996    case BLOCK_NONE:
997    default:
998
999        /* Could be a nested operator, check if comma required */
1000
1001        if (!AcpiDmCommaIfListMember (Op))
1002        {
1003            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1004                 (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1005                 (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1006            {
1007                /*
1008                 * This is a first-level element of a term list
1009                 * start a new line
1010                 */
1011                AcpiOsPrintf ("\n");
1012            }
1013        }
1014        else if (Op->Common.Parent)
1015        {
1016            switch (Op->Common.Parent->Common.AmlOpcode)
1017            {
1018            case AML_PACKAGE_OP:
1019            case AML_VAR_PACKAGE_OP:
1020
1021                if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1022                {
1023                    AcpiOsPrintf ("\n");
1024                }
1025                break;
1026
1027            default:
1028
1029                break;
1030            }
1031        }
1032        break;
1033    }
1034
1035    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)
1036    {
1037        if ((Op->Common.Next) &&
1038            (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1039        {
1040            return (AE_OK);
1041        }
1042
1043        /*
1044         * The parent Op is guaranteed to be valid because of the flag
1045         * ACPI_PARSEOP_PARAMETER_LIST -- which means that this op is part of
1046         * a parameter list and thus has a valid parent.
1047         */
1048        ParentOp = Op->Common.Parent;
1049
1050        /*
1051         * Just completed a parameter node for something like "Buffer (param)".
1052         * Close the paren and open up the term list block with a brace
1053         */
1054        if (Op->Common.Next)
1055        {
1056            AcpiOsPrintf (")");
1057
1058            /*
1059             * Emit a description comment for a Name() operator that is a
1060             * predefined ACPI name. Must check the grandparent.
1061             */
1062            ParentOp = ParentOp->Common.Parent;
1063            if (ParentOp &&
1064                (ParentOp->Asl.AmlOpcode == AML_NAME_OP))
1065            {
1066                AcpiDmPredefinedDescription (ParentOp);
1067            }
1068
1069            AcpiOsPrintf ("\n");
1070            AcpiDmIndent (Level - 1);
1071            AcpiOsPrintf ("{\n");
1072        }
1073        else
1074        {
1075            ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
1076            AcpiOsPrintf (") {");
1077        }
1078    }
1079
1080    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
1081        (Op->Common.AmlOpcode == AML_RETURN_OP))
1082    {
1083        Info->Level++;
1084    }
1085
1086    /*
1087     * For ASL+, check for and emit a C-style symbol. If valid, the
1088     * symbol string has been deferred until after the first operand
1089     */
1090    if (AcpiGbl_CstyleDisassembly)
1091    {
1092        if (Op->Asl.OperatorSymbol)
1093        {
1094            AcpiOsPrintf ("%s", Op->Asl.OperatorSymbol);
1095            Op->Asl.OperatorSymbol = NULL;
1096        }
1097    }
1098
1099    return (AE_OK);
1100}
1101