]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/components/disassembler/dmwalk.c
Import ACPICA 20130117.
[FreeBSD/FreeBSD.git] / source / components / disassembler / dmwalk.c
1 /*******************************************************************************
2  *
3  * Module Name: dmwalk - AML disassembly tree walk
4  *
5  ******************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2013, 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             switch (Op->Common.AmlOpcode)
445             {
446             case AML_NOOP_OP:
447                 /*
448                  * Optionally just ignore this opcode. Some tables use
449                  * NoOp opcodes for "padding" out packages that the BIOS
450                  * changes dynamically. This can leave hundreds or
451                  * thousands of NoOp opcodes that if disassembled,
452                  * cannot be compiled because they are syntactically
453                  * incorrect.
454                  */
455                 if (AcpiGbl_IgnoreNoopOperator)
456                 {
457                     Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
458                     return (AE_OK);
459                 }
460
461                 /* Fallthrough */
462
463             default:
464                 AcpiDmIndent (Level);
465                 break;
466             }
467
468             Info->LastLevel = Level;
469             Info->Count = 0;
470     }
471
472     /*
473      * This is an inexpensive mechanism to try and keep lines from getting
474      * too long. When the limit is hit, start a new line at the previous
475      * indent plus one. A better but more expensive mechanism would be to
476      * keep track of the current column.
477      */
478     Info->Count++;
479     if (Info->Count /* +Info->LastLevel */ > 10)
480     {
481         Info->Count = 0;
482         AcpiOsPrintf ("\n");
483         AcpiDmIndent (Info->LastLevel + 1);
484     }
485
486     /* Print the opcode name */
487
488     AcpiDmDisassembleOneOp (NULL, Info, Op);
489
490     if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
491         (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
492     {
493         return (AE_OK);
494     }
495
496     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
497         (Op->Common.AmlOpcode == AML_RETURN_OP))
498     {
499         Info->Level--;
500     }
501
502     /* Start the opcode argument list if necessary */
503
504     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
505
506     if ((OpInfo->Flags & AML_HAS_ARGS) ||
507         (Op->Common.AmlOpcode == AML_EVENT_OP))
508     {
509         /* This opcode has an argument list */
510
511         if (AcpiDmBlockType (Op) & BLOCK_PAREN)
512         {
513             AcpiOsPrintf (" (");
514         }
515
516         /* If this is a named opcode, print the associated name value */
517
518         if (OpInfo->Flags & AML_NAMED)
519         {
520             switch (Op->Common.AmlOpcode)
521             {
522             case AML_ALIAS_OP:
523
524                 NextOp = AcpiPsGetDepthNext (NULL, Op);
525                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
526                 AcpiDmNamestring (NextOp->Common.Value.Name);
527                 AcpiOsPrintf (", ");
528
529                 /*lint -fallthrough */
530
531             default:
532
533                 Name = AcpiPsGetName (Op);
534                 if (Op->Named.Path)
535                 {
536                     AcpiDmNamestring ((char *) Op->Named.Path);
537                 }
538                 else
539                 {
540                     AcpiDmDumpName (Name);
541                 }
542
543                 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
544                 {
545                     if (AcpiGbl_DbOpt_verbose)
546                     {
547                         (void) AcpiPsDisplayObjectPathname (NULL, Op);
548                     }
549                 }
550                 break;
551             }
552
553             switch (Op->Common.AmlOpcode)
554             {
555             case AML_METHOD_OP:
556
557                 AcpiDmMethodFlags (Op);
558                 AcpiOsPrintf (")");
559
560                 /* Emit description comment for Method() with a predefined ACPI name */
561
562                 AcpiDmPredefinedDescription (Op);
563                 break;
564
565
566             case AML_NAME_OP:
567
568                 /* Check for _HID and related EISAID() */
569
570                 AcpiDmIsEisaId (Op);
571                 AcpiOsPrintf (", ");
572                 break;
573
574
575             case AML_REGION_OP:
576
577                 AcpiDmRegionFlags (Op);
578                 break;
579
580
581             case AML_POWER_RES_OP:
582
583                 /* Mark the next two Ops as part of the parameter list */
584
585                 AcpiOsPrintf (", ");
586                 NextOp = AcpiPsGetDepthNext (NULL, Op);
587                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
588
589                 NextOp = NextOp->Common.Next;
590                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
591                 return (AE_OK);
592
593
594             case AML_PROCESSOR_OP:
595
596                 /* Mark the next three Ops as part of the parameter list */
597
598                 AcpiOsPrintf (", ");
599                 NextOp = AcpiPsGetDepthNext (NULL, Op);
600                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
601
602                 NextOp = NextOp->Common.Next;
603                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
604
605                 NextOp = NextOp->Common.Next;
606                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
607                 return (AE_OK);
608
609
610             case AML_MUTEX_OP:
611             case AML_DATA_REGION_OP:
612
613                 AcpiOsPrintf (", ");
614                 return (AE_OK);
615
616
617             case AML_EVENT_OP:
618             case AML_ALIAS_OP:
619
620                 return (AE_OK);
621
622
623             case AML_SCOPE_OP:
624             case AML_DEVICE_OP:
625             case AML_THERMAL_ZONE_OP:
626
627                 AcpiOsPrintf (")");
628                 break;
629
630
631             default:
632
633                 AcpiOsPrintf ("*** Unhandled named opcode %X\n",
634                     Op->Common.AmlOpcode);
635                 break;
636             }
637         }
638
639         else switch (Op->Common.AmlOpcode)
640         {
641         case AML_FIELD_OP:
642         case AML_BANK_FIELD_OP:
643         case AML_INDEX_FIELD_OP:
644
645             Info->BitOffset = 0;
646
647             /* Name of the parent OperationRegion */
648
649             NextOp = AcpiPsGetDepthNext (NULL, Op);
650             AcpiDmNamestring (NextOp->Common.Value.Name);
651             AcpiOsPrintf (", ");
652             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
653
654             switch (Op->Common.AmlOpcode)
655             {
656             case AML_BANK_FIELD_OP:
657
658                 /* Namestring - Bank Name */
659
660                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
661                 AcpiDmNamestring (NextOp->Common.Value.Name);
662                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
663                 AcpiOsPrintf (", ");
664
665                 /*
666                  * Bank Value. This is a TermArg in the middle of the parameter
667                  * list, must handle it here.
668                  *
669                  * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
670                  * eliminates newline in the output.
671                  */
672                 NextOp = NextOp->Common.Next;
673
674                 Info->Flags = ACPI_PARSEOP_PARAMLIST;
675                 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
676                     AcpiDmAscendingOp, Info);
677                 Info->Flags = 0;
678                 Info->Level = Level;
679
680                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
681                 AcpiOsPrintf (", ");
682                 break;
683
684             case AML_INDEX_FIELD_OP:
685
686                 /* Namestring - Data Name */
687
688                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
689                 AcpiDmNamestring (NextOp->Common.Value.Name);
690                 AcpiOsPrintf (", ");
691                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
692                 break;
693
694             default:
695
696                 break;
697             }
698
699             AcpiDmFieldFlags (NextOp);
700             break;
701
702
703         case AML_BUFFER_OP:
704
705             /* The next op is the size parameter */
706
707             NextOp = AcpiPsGetDepthNext (NULL, Op);
708             if (!NextOp)
709             {
710                 /* Single-step support */
711
712                 return (AE_OK);
713             }
714
715             if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
716             {
717                 /*
718                  * We have a resource list. Don't need to output
719                  * the buffer size Op. Open up a new block
720                  */
721                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
722                 NextOp = NextOp->Common.Next;
723                 AcpiOsPrintf (")");
724
725                 /* Emit description comment for Name() with a predefined ACPI name */
726
727                 AcpiDmPredefinedDescription (Op->Asl.Parent);
728
729                 AcpiOsPrintf ("\n");
730                 AcpiDmIndent (Info->Level);
731                 AcpiOsPrintf ("{\n");
732                 return (AE_OK);
733             }
734
735             /* Normal Buffer, mark size as in the parameter list */
736
737             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
738             return (AE_OK);
739
740
741         case AML_VAR_PACKAGE_OP:
742         case AML_IF_OP:
743         case AML_WHILE_OP:
744
745             /* The next op is the size or predicate parameter */
746
747             NextOp = AcpiPsGetDepthNext (NULL, Op);
748             if (NextOp)
749             {
750                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
751             }
752             return (AE_OK);
753
754
755         case AML_PACKAGE_OP:
756
757             /* The next op is the size parameter */
758
759             NextOp = AcpiPsGetDepthNext (NULL, Op);
760             if (NextOp)
761             {
762                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
763             }
764             return (AE_OK);
765
766
767         case AML_MATCH_OP:
768
769             AcpiDmMatchOp (Op);
770             break;
771
772
773         default:
774
775             break;
776         }
777
778         if (AcpiDmBlockType (Op) & BLOCK_BRACE)
779         {
780             AcpiOsPrintf ("\n");
781             AcpiDmIndent (Level);
782             AcpiOsPrintf ("{\n");
783         }
784     }
785
786     return (AE_OK);
787 }
788
789
790 /*******************************************************************************
791  *
792  * FUNCTION:    AcpiDmAscendingOp
793  *
794  * PARAMETERS:  ASL_WALK_CALLBACK
795  *
796  * RETURN:      Status
797  *
798  * DESCRIPTION: Second visitation of a parse object, during ascent of parse
799  *              tree. Close out any parameter lists and complete the opcode.
800  *
801  ******************************************************************************/
802
803 static ACPI_STATUS
804 AcpiDmAscendingOp (
805     ACPI_PARSE_OBJECT       *Op,
806     UINT32                  Level,
807     void                    *Context)
808 {
809     ACPI_OP_WALK_INFO       *Info = Context;
810     ACPI_PARSE_OBJECT       *ParentOp;
811
812
813     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
814     {
815         /* Ignore this op -- it was handled elsewhere */
816
817         return (AE_OK);
818     }
819
820     if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
821     {
822         /* Indicates the end of the current descriptor block (table) */
823
824         AcpiOsPrintf ("}\n\n");
825         return (AE_OK);
826     }
827
828     switch (AcpiDmBlockType (Op))
829     {
830     case BLOCK_PAREN:
831
832         /* Completed an op that has arguments, add closing paren */
833
834         AcpiOsPrintf (")");
835
836         if (Op->Common.AmlOpcode == AML_NAME_OP)
837         {
838             /* Emit description comment for Name() with a predefined ACPI name */
839
840             AcpiDmPredefinedDescription (Op);
841         }
842         else
843         {
844             /* For Create* operators, attempt to emit resource tag description */
845
846             AcpiDmFieldPredefinedDescription (Op);
847         }
848
849         /* Could be a nested operator, check if comma required */
850
851         if (!AcpiDmCommaIfListMember (Op))
852         {
853             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
854                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
855                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
856             {
857                 /*
858                  * This is a first-level element of a term list
859                  * start a new line
860                  */
861                 if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST))
862                 {
863                     AcpiOsPrintf ("\n");
864                 }
865             }
866         }
867         break;
868
869
870     case BLOCK_BRACE:
871     case (BLOCK_BRACE | BLOCK_PAREN):
872
873         /* Completed an op that has a term list, add closing brace */
874
875         if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
876         {
877             AcpiOsPrintf ("}");
878         }
879         else
880         {
881             AcpiDmIndent (Level);
882             AcpiOsPrintf ("}");
883         }
884
885         AcpiDmCommaIfListMember (Op);
886
887         if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
888         {
889             AcpiOsPrintf ("\n");
890             if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
891             {
892                 if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
893                     (Op->Common.Next) &&
894                     (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
895                 {
896                     break;
897                 }
898
899                 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
900                     (!Op->Common.Next))
901                 {
902                     break;
903                 }
904                 AcpiOsPrintf ("\n");
905             }
906         }
907         break;
908
909
910     case BLOCK_NONE:
911     default:
912
913         /* Could be a nested operator, check if comma required */
914
915         if (!AcpiDmCommaIfListMember (Op))
916         {
917             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
918                      (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
919                      (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
920             {
921                 /*
922                  * This is a first-level element of a term list
923                  * start a new line
924                  */
925                 AcpiOsPrintf ("\n");
926             }
927         }
928         else if (Op->Common.Parent)
929         {
930             switch (Op->Common.Parent->Common.AmlOpcode)
931             {
932             case AML_PACKAGE_OP:
933             case AML_VAR_PACKAGE_OP:
934
935                 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
936                 {
937                     AcpiOsPrintf ("\n");
938                 }
939                 break;
940
941             default:
942
943                 break;
944             }
945         }
946         break;
947     }
948
949     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
950     {
951         if ((Op->Common.Next) &&
952             (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
953         {
954             return (AE_OK);
955         }
956
957         /*
958          * Just completed a parameter node for something like "Buffer (param)".
959          * Close the paren and open up the term list block with a brace
960          */
961         if (Op->Common.Next)
962         {
963             AcpiOsPrintf (")");
964
965             /* Emit description comment for Name() with a predefined ACPI name */
966
967             ParentOp = Op->Common.Parent;
968             if (ParentOp)
969             {
970                 ParentOp = ParentOp->Common.Parent;
971                 if (ParentOp && ParentOp->Asl.AmlOpcode == AML_NAME_OP)
972                 {
973                     AcpiDmPredefinedDescription (ParentOp);
974                 }
975             }
976             AcpiOsPrintf ("\n");
977             AcpiDmIndent (Level - 1);
978             AcpiOsPrintf ("{\n");
979         }
980         else
981         {
982             Op->Common.Parent->Common.DisasmFlags |=
983                                     ACPI_PARSEOP_EMPTY_TERMLIST;
984             AcpiOsPrintf (") {");
985         }
986     }
987
988     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
989         (Op->Common.AmlOpcode == AML_RETURN_OP))
990     {
991         Info->Level++;
992     }
993     return (AE_OK);
994 }
995
996
997 #endif  /* ACPI_DISASSEMBLER */