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