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