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