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