xref: /dflybsd-src/sys/contrib/dev/acpica/source/components/disassembler/dmwalk.c (revision d638c6eedc81671c3ceddd06ef20463940cb6a43)
1 /*******************************************************************************
2  *
3  * Module Name: dmwalk - AML disassembly tree walk
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, 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 #include "acpi.h"
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 #include "acdebug.h"
49 #include "acconvert.h"
50 
51 
52 #ifdef ACPI_DISASSEMBLER
53 
54 #define _COMPONENT          ACPI_CA_DEBUGGER
55         ACPI_MODULE_NAME    ("dmwalk")
56 
57 
58 #define DB_FULL_OP_INFO     "[%4.4s] @%5.5X #%4.4X:  "
59 
60 /* Stub for non-compiler code */
61 
62 #ifndef ACPI_ASL_COMPILER
63 void
64 AcpiDmEmitExternals (
65     void)
66 {
67     return;
68 }
69 
70 void
71 AcpiDmEmitExternal (
72     ACPI_PARSE_OBJECT       *NameOp,
73     ACPI_PARSE_OBJECT       *TypeOp)
74 {
75     return;
76 }
77 #endif
78 
79 /* Local prototypes */
80 
81 static ACPI_STATUS
82 AcpiDmDescendingOp (
83     ACPI_PARSE_OBJECT       *Op,
84     UINT32                  Level,
85     void                    *Context);
86 
87 static ACPI_STATUS
88 AcpiDmAscendingOp (
89     ACPI_PARSE_OBJECT       *Op,
90     UINT32                  Level,
91     void                    *Context);
92 
93 
94 /*******************************************************************************
95  *
96  * FUNCTION:    AcpiDmDisassemble
97  *
98  * PARAMETERS:  WalkState       - Current state
99  *              Origin          - Starting object
100  *              NumOpcodes      - Max number of opcodes to be displayed
101  *
102  * RETURN:      None
103  *
104  * DESCRIPTION: Disassemble parser object and its children. This is the
105  *              main entry point of the disassembler.
106  *
107  ******************************************************************************/
108 
109 void
110 AcpiDmDisassemble (
111     ACPI_WALK_STATE         *WalkState,
112     ACPI_PARSE_OBJECT       *Origin,
113     UINT32                  NumOpcodes)
114 {
115     ACPI_PARSE_OBJECT       *Op = Origin;
116     ACPI_OP_WALK_INFO       Info;
117 
118 
119     if (!Op)
120     {
121         return;
122     }
123 
124     memset (&Info, 0, sizeof (ACPI_OP_WALK_INFO));
125     Info.WalkState = WalkState;
126     Info.StartAml = Op->Common.Aml - sizeof (ACPI_TABLE_HEADER);
127     Info.AmlOffset = Op->Common.Aml - Info.StartAml;
128 
129     AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
130     return;
131 }
132 
133 
134 /*******************************************************************************
135  *
136  * FUNCTION:    AcpiDmWalkParseTree
137  *
138  * PARAMETERS:  Op                      - Root Op object
139  *              DescendingCallback      - Called during tree descent
140  *              AscendingCallback       - Called during tree ascent
141  *              Context                 - To be passed to the callbacks
142  *
143  * RETURN:      Status from callback(s)
144  *
145  * DESCRIPTION: Walk the entire parse tree.
146  *
147  ******************************************************************************/
148 
149 void
150 AcpiDmWalkParseTree (
151     ACPI_PARSE_OBJECT       *Op,
152     ASL_WALK_CALLBACK       DescendingCallback,
153     ASL_WALK_CALLBACK       AscendingCallback,
154     void                    *Context)
155 {
156     BOOLEAN                 NodePreviouslyVisited;
157     ACPI_PARSE_OBJECT       *StartOp = Op;
158     ACPI_STATUS             Status;
159     ACPI_PARSE_OBJECT       *Next;
160     ACPI_OP_WALK_INFO       *Info = Context;
161 
162 
163     Info->Level = 0;
164     NodePreviouslyVisited = FALSE;
165 
166     while (Op)
167     {
168         if (NodePreviouslyVisited)
169         {
170             if (AscendingCallback)
171             {
172                 Status = AscendingCallback (Op, Info->Level, Context);
173                 if (ACPI_FAILURE (Status))
174                 {
175                     return;
176                 }
177             }
178         }
179         else
180         {
181             /* Let the callback process the node */
182 
183             Status = DescendingCallback (Op, Info->Level, Context);
184             if (ACPI_SUCCESS (Status))
185             {
186                 /* Visit children first, once */
187 
188                 Next = AcpiPsGetArg (Op, 0);
189                 if (Next)
190                 {
191                     Info->Level++;
192                     Op = Next;
193                     continue;
194                 }
195             }
196             else if (Status != AE_CTRL_DEPTH)
197             {
198                 /* Exit immediately on any error */
199 
200                 return;
201             }
202         }
203 
204         /* Terminate walk at start op */
205 
206         if (Op == StartOp)
207         {
208             break;
209         }
210 
211         /* No more children, re-visit this node */
212 
213         if (!NodePreviouslyVisited)
214         {
215             NodePreviouslyVisited = TRUE;
216             continue;
217         }
218 
219         /* No more children, visit peers */
220 
221         if (Op->Common.Next)
222         {
223             Op = Op->Common.Next;
224             NodePreviouslyVisited = FALSE;
225         }
226         else
227         {
228             /* No peers, re-visit parent */
229 
230             if (Info->Level != 0 )
231             {
232                 Info->Level--;
233             }
234 
235             Op = Op->Common.Parent;
236             NodePreviouslyVisited = TRUE;
237         }
238     }
239 
240     /* If we get here, the walk completed with no errors */
241 
242     return;
243 }
244 
245 
246 /*******************************************************************************
247  *
248  * FUNCTION:    AcpiDmBlockType
249  *
250  * PARAMETERS:  Op              - Object to be examined
251  *
252  * RETURN:      BlockType - not a block, parens, braces, or even both.
253  *
254  * DESCRIPTION: Type of block for this op (parens or braces)
255  *
256  ******************************************************************************/
257 
258 UINT32
259 AcpiDmBlockType (
260     ACPI_PARSE_OBJECT       *Op)
261 {
262     const ACPI_OPCODE_INFO  *OpInfo;
263 
264 
265     if (!Op)
266     {
267         return (BLOCK_NONE);
268     }
269 
270     switch (Op->Common.AmlOpcode)
271     {
272     case AML_ELSE_OP:
273 
274         return (BLOCK_BRACE);
275 
276     case AML_METHOD_OP:
277     case AML_DEVICE_OP:
278     case AML_SCOPE_OP:
279     case AML_PROCESSOR_OP:
280     case AML_POWER_RESOURCE_OP:
281     case AML_THERMAL_ZONE_OP:
282     case AML_IF_OP:
283     case AML_WHILE_OP:
284     case AML_FIELD_OP:
285     case AML_INDEX_FIELD_OP:
286     case AML_BANK_FIELD_OP:
287 
288         return (BLOCK_PAREN | BLOCK_BRACE);
289 
290     case AML_BUFFER_OP:
291 
292         if ((Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) ||
293             (Op->Common.DisasmOpcode == ACPI_DASM_UUID) ||
294             (Op->Common.DisasmOpcode == ACPI_DASM_PLD_METHOD))
295         {
296             return (BLOCK_NONE);
297         }
298 
299         /*lint -fallthrough */
300 
301     case AML_PACKAGE_OP:
302     case AML_VARIABLE_PACKAGE_OP:
303 
304         return (BLOCK_PAREN | BLOCK_BRACE);
305 
306     case AML_EVENT_OP:
307 
308         return (BLOCK_PAREN);
309 
310     case AML_INT_METHODCALL_OP:
311 
312         if (Op->Common.Parent &&
313             ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
314              (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)))
315         {
316             /* This is a reference to a method, not an invocation */
317 
318             return (BLOCK_NONE);
319         }
320 
321         /*lint -fallthrough */
322 
323     default:
324 
325         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
326         if (OpInfo->Flags & AML_HAS_ARGS)
327         {
328             return (BLOCK_PAREN);
329         }
330 
331         return (BLOCK_NONE);
332     }
333 }
334 
335 
336 /*******************************************************************************
337  *
338  * FUNCTION:    AcpiDmListType
339  *
340  * PARAMETERS:  Op              - Object to be examined
341  *
342  * RETURN:      ListType - has commas or not.
343  *
344  * DESCRIPTION: Type of block for this op (parens or braces)
345  *
346  ******************************************************************************/
347 
348 UINT32
349 AcpiDmListType (
350     ACPI_PARSE_OBJECT       *Op)
351 {
352     const ACPI_OPCODE_INFO  *OpInfo;
353 
354 
355     if (!Op)
356     {
357         return (BLOCK_NONE);
358     }
359 
360     switch (Op->Common.AmlOpcode)
361     {
362 
363     case AML_ELSE_OP:
364     case AML_METHOD_OP:
365     case AML_DEVICE_OP:
366     case AML_SCOPE_OP:
367     case AML_POWER_RESOURCE_OP:
368     case AML_PROCESSOR_OP:
369     case AML_THERMAL_ZONE_OP:
370     case AML_IF_OP:
371     case AML_WHILE_OP:
372     case AML_FIELD_OP:
373     case AML_INDEX_FIELD_OP:
374     case AML_BANK_FIELD_OP:
375 
376         return (BLOCK_NONE);
377 
378     case AML_BUFFER_OP:
379     case AML_PACKAGE_OP:
380     case AML_VARIABLE_PACKAGE_OP:
381 
382         return (BLOCK_COMMA_LIST);
383 
384     default:
385 
386         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
387         if (OpInfo->Flags & AML_HAS_ARGS)
388         {
389             return (BLOCK_COMMA_LIST);
390         }
391 
392         return (BLOCK_NONE);
393     }
394 }
395 
396 
397 /*******************************************************************************
398  *
399  * FUNCTION:    AcpiDmDescendingOp
400  *
401  * PARAMETERS:  ASL_WALK_CALLBACK
402  *
403  * RETURN:      Status
404  *
405  * DESCRIPTION: First visitation of a parse object during tree descent.
406  *              Decode opcode name and begin parameter list(s), if any.
407  *
408  ******************************************************************************/
409 
410 static ACPI_STATUS
411 AcpiDmDescendingOp (
412     ACPI_PARSE_OBJECT       *Op,
413     UINT32                  Level,
414     void                    *Context)
415 {
416     ACPI_OP_WALK_INFO       *Info = Context;
417     const ACPI_OPCODE_INFO  *OpInfo;
418     UINT32                  Name;
419     ACPI_PARSE_OBJECT       *NextOp;
420     ACPI_PARSE_OBJECT       *NextOp2;
421     UINT32                  AmlOffset;
422 
423 
424     /* Determine which file this parse node is contained in. */
425 
426     if (Gbl_CaptureComments)
427     {
428         ASL_CV_LABEL_FILENODE (Op);
429 
430         if (Level != 0 && ASL_CV_FILE_HAS_SWITCHED (Op))
431         {
432             ASL_CV_SWITCH_FILES (Level, Op);
433         }
434 
435         /* If this parse node has regular comments, print them here. */
436 
437         ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_STANDARD, NULL, Level);
438     }
439 
440     OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
441 
442     /* Listing support to dump the AML code after the ASL statement */
443 
444     if (AcpiGbl_DmOpt_Listing)
445     {
446         /* We only care about these classes of objects */
447 
448         if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) ||
449             (OpInfo->Class == AML_CLASS_CONTROL) ||
450             (OpInfo->Class == AML_CLASS_CREATE) ||
451             ((OpInfo->Class == AML_CLASS_EXECUTE) && (!Op->Common.Next)))
452         {
453             if (AcpiGbl_DmOpt_Listing && Info->PreviousAml)
454             {
455                 /* Dump the AML byte code for the previous Op */
456 
457                 if (Op->Common.Aml > Info->PreviousAml)
458                 {
459                     AcpiOsPrintf ("\n");
460                     AcpiUtDumpBuffer (
461                         (Info->StartAml + Info->AmlOffset),
462                         (Op->Common.Aml - Info->PreviousAml),
463                         DB_BYTE_DISPLAY, Info->AmlOffset);
464                     AcpiOsPrintf ("\n");
465                 }
466 
467                 Info->AmlOffset = (Op->Common.Aml - Info->StartAml);
468             }
469 
470             Info->PreviousAml = Op->Common.Aml;
471         }
472     }
473 
474     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
475     {
476         /* Ignore this op -- it was handled elsewhere */
477 
478         return (AE_CTRL_DEPTH);
479     }
480 
481     if (AcpiDmIsTempName(Op))
482     {
483         /* Ignore compiler generated temporary names */
484 
485         return (AE_CTRL_DEPTH);
486     }
487 
488     if (Op->Common.DisasmOpcode == ACPI_DASM_IGNORE_SINGLE)
489     {
490         /* Ignore this op, but not it's children */
491 
492         return (AE_OK);
493     }
494 
495     if (Op->Common.AmlOpcode == AML_IF_OP)
496     {
497         NextOp = AcpiPsGetDepthNext (NULL, Op);
498         if (NextOp)
499         {
500             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
501 
502             /* Don't emit the actual embedded externals unless asked */
503 
504             if (!AcpiGbl_DmEmitExternalOpcodes)
505             {
506                 /*
507                  * A Zero predicate indicates the possibility of one or more
508                  * External() opcodes within the If() block.
509                  */
510                 if (NextOp->Common.AmlOpcode == AML_ZERO_OP)
511                 {
512                     NextOp2 = NextOp->Common.Next;
513 
514                     if (NextOp2 &&
515                         (NextOp2->Common.AmlOpcode == AML_EXTERNAL_OP))
516                     {
517                         /* Ignore the If 0 block and all children */
518 
519                         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
520                         return (AE_CTRL_DEPTH);
521                     }
522                 }
523             }
524         }
525     }
526 
527     /* Level 0 is at the Definition Block level */
528 
529     if (Level == 0)
530     {
531         /* In verbose mode, print the AML offset, opcode and depth count */
532 
533         if (Info->WalkState)
534         {
535             AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,
536                 Info->WalkState->ParserState.AmlStart);
537             if (AcpiGbl_DmOpt_Verbose)
538             {
539                 AcpiOsPrintf (DB_FULL_OP_INFO,
540                     (Info->WalkState->MethodNode ?
541                         Info->WalkState->MethodNode->Name.Ascii : "   "),
542                     AmlOffset, (UINT32) Op->Common.AmlOpcode);
543             }
544         }
545 
546         if (Op->Common.AmlOpcode == AML_SCOPE_OP)
547         {
548             /* This is the beginning of the Definition Block */
549 
550             AcpiOsPrintf ("{\n");
551 
552             /* Emit all External() declarations here */
553 
554             if (!AcpiGbl_DmEmitExternalOpcodes)
555             {
556                 AcpiDmEmitExternals ();
557             }
558 
559             return (AE_OK);
560         }
561     }
562     else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
563          (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
564          (!(Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)) &&
565          (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
566     {
567         /*
568          * This is a first-level element of a term list,
569          * indent a new line
570          */
571         switch (Op->Common.AmlOpcode)
572         {
573         case AML_NOOP_OP:
574             /*
575              * Optionally just ignore this opcode. Some tables use
576              * NoOp opcodes for "padding" out packages that the BIOS
577              * changes dynamically. This can leave hundreds or
578              * thousands of NoOp opcodes that if disassembled,
579              * cannot be compiled because they are syntactically
580              * incorrect.
581              */
582             if (AcpiGbl_IgnoreNoopOperator)
583             {
584                 Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
585                 return (AE_OK);
586             }
587 
588             /* Fallthrough */
589 
590         default:
591 
592             AcpiDmIndent (Level);
593             break;
594         }
595 
596         Info->LastLevel = Level;
597         Info->Count = 0;
598     }
599 
600     /*
601      * This is an inexpensive mechanism to try and keep lines from getting
602      * too long. When the limit is hit, start a new line at the previous
603      * indent plus one. A better but more expensive mechanism would be to
604      * keep track of the current column.
605      */
606     Info->Count++;
607     if (Info->Count /* +Info->LastLevel */ > 12)
608     {
609         Info->Count = 0;
610         AcpiOsPrintf ("\n");
611         AcpiDmIndent (Info->LastLevel + 1);
612     }
613 
614     /* If ASL+ is enabled, check for a C-style operator */
615 
616     if (AcpiDmCheckForSymbolicOpcode (Op, Info))
617     {
618         return (AE_OK);
619     }
620 
621     /* Print the opcode name */
622 
623     AcpiDmDisassembleOneOp (NULL, Info, Op);
624 
625     if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
626         (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
627     {
628         return (AE_OK);
629     }
630 
631     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
632         (Op->Common.AmlOpcode == AML_RETURN_OP))
633     {
634         Info->Level--;
635     }
636 
637     if (Op->Common.AmlOpcode == AML_EXTERNAL_OP)
638     {
639         Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
640         return (AE_CTRL_DEPTH);
641     }
642 
643     /* Start the opcode argument list if necessary */
644 
645     if ((OpInfo->Flags & AML_HAS_ARGS) ||
646         (Op->Common.AmlOpcode == AML_EVENT_OP))
647     {
648         /* This opcode has an argument list */
649 
650         if (AcpiDmBlockType (Op) & BLOCK_PAREN)
651         {
652             AcpiOsPrintf (" (");
653             if (!(AcpiDmBlockType (Op) & BLOCK_BRACE))
654             {
655                 ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, " ", 0);
656             }
657         }
658 
659         /* If this is a named opcode, print the associated name value */
660 
661         if (OpInfo->Flags & AML_NAMED)
662         {
663             switch (Op->Common.AmlOpcode)
664             {
665             case AML_ALIAS_OP:
666 
667                 NextOp = AcpiPsGetDepthNext (NULL, Op);
668                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
669                 AcpiDmNamestring (NextOp->Common.Value.Name);
670                 AcpiOsPrintf (", ");
671 
672                 /*lint -fallthrough */
673 
674             default:
675 
676                 Name = AcpiPsGetName (Op);
677                 if (Op->Named.Path)
678                 {
679                     AcpiDmNamestring ((char *) Op->Named.Path);
680                 }
681                 else
682                 {
683                     AcpiDmDumpName (Name);
684                 }
685 
686                 if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
687                 {
688                     if (AcpiGbl_DmOpt_Verbose)
689                     {
690                         (void) AcpiPsDisplayObjectPathname (NULL, Op);
691                     }
692                 }
693                 break;
694             }
695 
696             switch (Op->Common.AmlOpcode)
697             {
698             case AML_METHOD_OP:
699 
700                 AcpiDmMethodFlags (Op);
701                 ASL_CV_CLOSE_PAREN (Op, Level);
702 
703                 /* Emit description comment for Method() with a predefined ACPI name */
704 
705                 AcpiDmPredefinedDescription (Op);
706                 break;
707 
708             case AML_NAME_OP:
709 
710                 /* Check for _HID and related EISAID() */
711 
712                 AcpiDmCheckForHardwareId (Op);
713                 AcpiOsPrintf (", ");
714                 ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
715                 break;
716 
717             case AML_REGION_OP:
718 
719                 AcpiDmRegionFlags (Op);
720                 break;
721 
722             case AML_POWER_RESOURCE_OP:
723 
724                 /* Mark the next two Ops as part of the parameter list */
725 
726                 AcpiOsPrintf (", ");
727                 NextOp = AcpiPsGetDepthNext (NULL, Op);
728                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
729 
730                 NextOp = NextOp->Common.Next;
731                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
732                 return (AE_OK);
733 
734             case AML_PROCESSOR_OP:
735 
736                 /* Mark the next three Ops as part of the parameter list */
737 
738                 AcpiOsPrintf (", ");
739                 NextOp = AcpiPsGetDepthNext (NULL, Op);
740                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
741 
742                 NextOp = NextOp->Common.Next;
743                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
744 
745                 NextOp = NextOp->Common.Next;
746                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
747                 return (AE_OK);
748 
749             case AML_MUTEX_OP:
750             case AML_DATA_REGION_OP:
751 
752                 AcpiOsPrintf (", ");
753                 return (AE_OK);
754 
755             case AML_EVENT_OP:
756             case AML_ALIAS_OP:
757 
758                 return (AE_OK);
759 
760             case AML_SCOPE_OP:
761             case AML_DEVICE_OP:
762             case AML_THERMAL_ZONE_OP:
763 
764                 ASL_CV_CLOSE_PAREN (Op, Level);
765                 break;
766 
767             default:
768 
769                 AcpiOsPrintf ("*** Unhandled named opcode %X\n",
770                     Op->Common.AmlOpcode);
771                 break;
772             }
773         }
774 
775         else switch (Op->Common.AmlOpcode)
776         {
777         case AML_FIELD_OP:
778         case AML_BANK_FIELD_OP:
779         case AML_INDEX_FIELD_OP:
780 
781             Info->BitOffset = 0;
782 
783             /* Name of the parent OperationRegion */
784 
785             NextOp = AcpiPsGetDepthNext (NULL, Op);
786             AcpiDmNamestring (NextOp->Common.Value.Name);
787             AcpiOsPrintf (", ");
788             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
789 
790             switch (Op->Common.AmlOpcode)
791             {
792             case AML_BANK_FIELD_OP:
793 
794                 /* Namestring - Bank Name */
795 
796                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
797                 AcpiDmNamestring (NextOp->Common.Value.Name);
798                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
799                 AcpiOsPrintf (", ");
800 
801                 /*
802                  * Bank Value. This is a TermArg in the middle of the parameter
803                  * list, must handle it here.
804                  *
805                  * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMETER_LIST
806                  * eliminates newline in the output.
807                  */
808                 NextOp = NextOp->Common.Next;
809 
810                 Info->Flags = ACPI_PARSEOP_PARAMETER_LIST;
811                 AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
812                     AcpiDmAscendingOp, Info);
813                 Info->Flags = 0;
814                 Info->Level = Level;
815 
816                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
817                 AcpiOsPrintf (", ");
818                 break;
819 
820             case AML_INDEX_FIELD_OP:
821 
822                 /* Namestring - Data Name */
823 
824                 NextOp = AcpiPsGetDepthNext (NULL, NextOp);
825                 AcpiDmNamestring (NextOp->Common.Value.Name);
826                 AcpiOsPrintf (", ");
827                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
828                 break;
829 
830             default:
831 
832                 break;
833             }
834 
835             AcpiDmFieldFlags (NextOp);
836             break;
837 
838         case AML_BUFFER_OP:
839 
840             /* The next op is the size parameter */
841 
842             NextOp = AcpiPsGetDepthNext (NULL, Op);
843             if (!NextOp)
844             {
845                 /* Single-step support */
846 
847                 return (AE_OK);
848             }
849 
850             if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
851             {
852                 /*
853                  * We have a resource list. Don't need to output
854                  * the buffer size Op. Open up a new block
855                  */
856                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
857                 NextOp = NextOp->Common.Next;
858                 ASL_CV_CLOSE_PAREN (Op, Level);
859 
860                 /* Emit description comment for Name() with a predefined ACPI name */
861 
862                 AcpiDmPredefinedDescription (Op->Asl.Parent);
863 
864                 AcpiOsPrintf ("\n");
865                 AcpiDmIndent (Info->Level);
866                 AcpiOsPrintf ("{\n");
867                 return (AE_OK);
868             }
869 
870             /* Normal Buffer, mark size as in the parameter list */
871 
872             NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
873             return (AE_OK);
874 
875         case AML_IF_OP:
876         case AML_VARIABLE_PACKAGE_OP:
877         case AML_WHILE_OP:
878 
879             /* The next op is the size or predicate parameter */
880 
881             NextOp = AcpiPsGetDepthNext (NULL, Op);
882             if (NextOp)
883             {
884                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
885             }
886             return (AE_OK);
887 
888         case AML_PACKAGE_OP:
889 
890             /* The next op is the size parameter */
891 
892             NextOp = AcpiPsGetDepthNext (NULL, Op);
893             if (NextOp)
894             {
895                 NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
896             }
897             return (AE_OK);
898 
899         case AML_MATCH_OP:
900 
901             AcpiDmMatchOp (Op);
902             break;
903 
904         default:
905 
906             break;
907         }
908 
909         if (AcpiDmBlockType (Op) & BLOCK_BRACE)
910         {
911             AcpiOsPrintf ("\n");
912             AcpiDmIndent (Level);
913             AcpiOsPrintf ("{\n");
914         }
915     }
916 
917     return (AE_OK);
918 }
919 
920 
921 /*******************************************************************************
922  *
923  * FUNCTION:    AcpiDmAscendingOp
924  *
925  * PARAMETERS:  ASL_WALK_CALLBACK
926  *
927  * RETURN:      Status
928  *
929  * DESCRIPTION: Second visitation of a parse object, during ascent of parse
930  *              tree. Close out any parameter lists and complete the opcode.
931  *
932  ******************************************************************************/
933 
934 static ACPI_STATUS
935 AcpiDmAscendingOp (
936     ACPI_PARSE_OBJECT       *Op,
937     UINT32                  Level,
938     void                    *Context)
939 {
940     ACPI_OP_WALK_INFO       *Info = Context;
941     ACPI_PARSE_OBJECT       *ParentOp;
942 
943 
944     /* Point the Op's filename pointer to the proper file */
945 
946     if (Gbl_CaptureComments)
947     {
948         ASL_CV_LABEL_FILENODE (Op);
949 
950         /* Switch the output of these files if necessary */
951 
952         if (ASL_CV_FILE_HAS_SWITCHED (Op))
953         {
954             ASL_CV_SWITCH_FILES (Level, Op);
955         }
956     }
957 
958     if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE ||
959         Op->Common.DisasmOpcode == ACPI_DASM_IGNORE_SINGLE)
960     {
961         /* Ignore this op -- it was handled elsewhere */
962 
963         return (AE_OK);
964     }
965 
966     if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
967     {
968         /* Indicates the end of the current descriptor block (table) */
969 
970         ASL_CV_CLOSE_BRACE (Op, Level);
971 
972         /* Print any comments that are at the end of the file here */
973 
974         if (Gbl_CaptureComments && AcpiGbl_LastListHead)
975         {
976             AcpiOsPrintf ("\n");
977             ASL_CV_PRINT_ONE_COMMENT_LIST (AcpiGbl_LastListHead, 0);
978         }
979         AcpiOsPrintf ("\n\n");
980 
981         return (AE_OK);
982     }
983 
984     switch (AcpiDmBlockType (Op))
985     {
986     case BLOCK_PAREN:
987 
988         /* Completed an op that has arguments, add closing paren if needed */
989 
990         AcpiDmCloseOperator (Op);
991 
992         if (Op->Common.AmlOpcode == AML_NAME_OP)
993         {
994             /* Emit description comment for Name() with a predefined ACPI name */
995 
996             AcpiDmPredefinedDescription (Op);
997         }
998         else
999         {
1000             /* For Create* operators, attempt to emit resource tag description */
1001 
1002             AcpiDmFieldPredefinedDescription (Op);
1003         }
1004 
1005         /* Decode Notify() values */
1006 
1007         if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
1008         {
1009             AcpiDmNotifyDescription (Op);
1010         }
1011 
1012         AcpiDmDisplayTargetPathname (Op);
1013 
1014         /* Could be a nested operator, check if comma required */
1015 
1016         if (!AcpiDmCommaIfListMember (Op))
1017         {
1018             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1019                  (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1020                  (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1021             {
1022                 /*
1023                  * This is a first-level element of a term list
1024                  * start a new line
1025                  */
1026                 if (!(Info->Flags & ACPI_PARSEOP_PARAMETER_LIST))
1027                 {
1028                     AcpiOsPrintf ("\n");
1029                 }
1030             }
1031         }
1032         break;
1033 
1034     case BLOCK_BRACE:
1035     case (BLOCK_BRACE | BLOCK_PAREN):
1036 
1037         /* Completed an op that has a term list, add closing brace */
1038 
1039         if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
1040         {
1041             ASL_CV_CLOSE_BRACE (Op, Level);
1042         }
1043         else
1044         {
1045             AcpiDmIndent (Level);
1046             ASL_CV_CLOSE_BRACE (Op, Level);
1047         }
1048 
1049         AcpiDmCommaIfListMember (Op);
1050 
1051         if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
1052         {
1053             AcpiOsPrintf ("\n");
1054             if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
1055             {
1056                 if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
1057                     (Op->Common.Next) &&
1058                     (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
1059                 {
1060                     break;
1061                 }
1062 
1063                 if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1064                     (!Op->Common.Next))
1065                 {
1066                     break;
1067                 }
1068                 AcpiOsPrintf ("\n");
1069             }
1070         }
1071         break;
1072 
1073     case BLOCK_NONE:
1074     default:
1075 
1076         /* Could be a nested operator, check if comma required */
1077 
1078         if (!AcpiDmCommaIfListMember (Op))
1079         {
1080             if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
1081                  (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
1082                  (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
1083             {
1084                 /*
1085                  * This is a first-level element of a term list
1086                  * start a new line
1087                  */
1088                 AcpiOsPrintf ("\n");
1089             }
1090         }
1091         else if (Op->Common.Parent)
1092         {
1093             switch (Op->Common.Parent->Common.AmlOpcode)
1094             {
1095             case AML_PACKAGE_OP:
1096             case AML_VARIABLE_PACKAGE_OP:
1097 
1098                 if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1099                 {
1100                     AcpiOsPrintf ("\n");
1101                 }
1102                 break;
1103 
1104             default:
1105 
1106                 break;
1107             }
1108         }
1109         break;
1110     }
1111 
1112     if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)
1113     {
1114         if ((Op->Common.Next) &&
1115             (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST))
1116         {
1117             return (AE_OK);
1118         }
1119 
1120         /*
1121          * The parent Op is guaranteed to be valid because of the flag
1122          * ACPI_PARSEOP_PARAMETER_LIST -- which means that this op is part of
1123          * a parameter list and thus has a valid parent.
1124          */
1125         ParentOp = Op->Common.Parent;
1126 
1127         /*
1128          * Just completed a parameter node for something like "Buffer (param)".
1129          * Close the paren and open up the term list block with a brace.
1130          *
1131          * Switch predicates don't have a Next node but require a closing paren
1132          * and opening brace.
1133          */
1134         if (Op->Common.Next || Op->Common.DisasmOpcode == ACPI_DASM_SWITCH_PREDICATE)
1135         {
1136             ASL_CV_CLOSE_PAREN (Op, Level);
1137 
1138             /*
1139              * Emit a description comment for a Name() operator that is a
1140              * predefined ACPI name. Must check the grandparent.
1141              */
1142             ParentOp = ParentOp->Common.Parent;
1143             if (ParentOp &&
1144                 (ParentOp->Asl.AmlOpcode == AML_NAME_OP))
1145             {
1146                 AcpiDmPredefinedDescription (ParentOp);
1147             }
1148 
1149             /* Correct the indentation level for Switch and Case predicates */
1150 
1151             if (Op->Common.DisasmOpcode == ACPI_DASM_SWITCH_PREDICATE)
1152             {
1153                 --Level;
1154             }
1155 
1156             AcpiOsPrintf ("\n");
1157             AcpiDmIndent (Level - 1);
1158             AcpiOsPrintf ("{\n");
1159         }
1160         else
1161         {
1162             ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
1163             ASL_CV_CLOSE_PAREN (Op, Level);
1164             AcpiOsPrintf ("{");
1165         }
1166     }
1167 
1168     if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
1169         (Op->Common.AmlOpcode == AML_RETURN_OP))
1170     {
1171         Info->Level++;
1172     }
1173 
1174     /*
1175      * For ASL+, check for and emit a C-style symbol. If valid, the
1176      * symbol string has been deferred until after the first operand
1177      */
1178     if (AcpiGbl_CstyleDisassembly)
1179     {
1180         if (Op->Asl.OperatorSymbol)
1181         {
1182             AcpiOsPrintf ("%s", Op->Asl.OperatorSymbol);
1183             Op->Asl.OperatorSymbol = NULL;
1184         }
1185     }
1186 
1187     return (AE_OK);
1188 }
1189 
1190 #endif  /* ACPI_DISASSEMBLER */
1191