dmwalk.c revision 278970
1132720Skan/*******************************************************************************
2132720Skan *
3132720Skan * Module Name: dmwalk - AML disassembly tree walk
4132720Skan *
5132720Skan ******************************************************************************/
6132720Skan
7132720Skan/*
8132720Skan * Copyright (C) 2000 - 2015, Intel Corp.
9132720Skan * All rights reserved.
10132720Skan *
11132720Skan * Redistribution and use in source and binary forms, with or without
12132720Skan * modification, are permitted provided that the following conditions
13132720Skan * are met:
14132720Skan * 1. Redistributions of source code must retain the above copyright
15132720Skan *    notice, this list of conditions, and the following disclaimer,
16132720Skan *    without modification.
17132720Skan * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18132720Skan *    substantially similar to the "NO WARRANTY" disclaimer below
19132720Skan *    ("Disclaimer") and any redistribution must be conditioned upon
20169691Skan *    including a substantially similar Disclaimer requirement for further
21169691Skan *    binary redistribution.
22132720Skan * 3. Neither the names of the above-listed copyright holders nor the names
23132720Skan *    of any contributors may be used to endorse or promote products derived
24132720Skan *    from this software without specific prior written permission.
25132720Skan *
26132720Skan * Alternatively, this software may be distributed under the terms of the
27132720Skan * GNU General Public License ("GPL") version 2 as published by the Free
28132720Skan * Software Foundation.
29132720Skan *
30132720Skan * NO WARRANTY
31132720Skan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32132720Skan * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33169691Skan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34169691Skan * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35169691Skan * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36132720Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37132720Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38132720Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39132720Skan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40132720Skan * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41132720Skan * POSSIBILITY OF SUCH DAMAGES.
42169691Skan */
43169691Skan
44169691Skan#include <contrib/dev/acpica/include/acpi.h>
45132720Skan#include <contrib/dev/acpica/include/accommon.h>
46132720Skan#include <contrib/dev/acpica/include/acparser.h>
47132720Skan#include <contrib/dev/acpica/include/amlcode.h>
48132720Skan#include <contrib/dev/acpica/include/acdisasm.h>
49132720Skan#include <contrib/dev/acpica/include/acdebug.h>
50132720Skan
51132720Skan
52132720Skan#ifdef ACPI_DISASSEMBLER
53132720Skan
54132720Skan#define _COMPONENT          ACPI_CA_DEBUGGER
55132720Skan        ACPI_MODULE_NAME    ("dmwalk")
56132720Skan
57132720Skan
58132720Skan#define DB_FULL_OP_INFO     "[%4.4s] @%5.5X #%4.4X:  "
59132720Skan
60132720Skan/* Stub for non-compiler code */
61132720Skan
62132720Skan#ifndef ACPI_ASL_COMPILER
63132720Skanvoid
64132720SkanAcpiDmEmitExternals (
65132720Skan    void)
66132720Skan{
67132720Skan    return;
68132720Skan}
69132720Skan#endif
70169691Skan
71169691Skan/* Local prototypes */
72169691Skan
73169691Skanstatic ACPI_STATUS
74132720SkanAcpiDmDescendingOp (
75132720Skan    ACPI_PARSE_OBJECT       *Op,
76132720Skan    UINT32                  Level,
77132720Skan    void                    *Context);
78169691Skan
79169691Skanstatic ACPI_STATUS
80132720SkanAcpiDmAscendingOp (
81132720Skan    ACPI_PARSE_OBJECT       *Op,
82132720Skan    UINT32                  Level,
83132720Skan    void                    *Context);
84132720Skan
85169691Skanstatic UINT32
86169691SkanAcpiDmBlockType (
87169691Skan    ACPI_PARSE_OBJECT       *Op);
88132720Skan
89132720Skan
90132720Skan/*******************************************************************************
91132720Skan *
92132720Skan * FUNCTION:    AcpiDmDisassemble
93132720Skan *
94132720Skan * PARAMETERS:  WalkState       - Current state
95169691Skan *              Origin          - Starting object
96132720Skan *              NumOpcodes      - Max number of opcodes to be displayed
97132720Skan *
98132720Skan * RETURN:      None
99132720Skan *
100132720Skan * DESCRIPTION: Disassemble parser object and its children. This is the
101132720Skan *              main entry point of the disassembler.
102132720Skan *
103132720Skan ******************************************************************************/
104132720Skan
105132720Skanvoid
106132720SkanAcpiDmDisassemble (
107169691Skan    ACPI_WALK_STATE         *WalkState,
108132720Skan    ACPI_PARSE_OBJECT       *Origin,
109132720Skan    UINT32                  NumOpcodes)
110169691Skan{
111169691Skan    ACPI_PARSE_OBJECT       *Op = Origin;
112169691Skan    ACPI_OP_WALK_INFO       Info;
113169691Skan
114169691Skan
115169691Skan    if (!Op)
116169691Skan    {
117169691Skan        return;
118169691Skan    }
119169691Skan
120169691Skan    Info.Flags = 0;
121169691Skan    Info.Level = 0;
122169691Skan    Info.Count = 0;
123169691Skan    Info.WalkState = WalkState;
124132720Skan    AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
125132720Skan    return;
126132720Skan}
127169691Skan
128132720Skan
129132720Skan/*******************************************************************************
130132720Skan *
131169691Skan * FUNCTION:    AcpiDmWalkParseTree
132169691Skan *
133169691Skan * PARAMETERS:  Op                      - Root Op object
134132720Skan *              DescendingCallback      - Called during tree descent
135132720Skan *              AscendingCallback       - Called during tree ascent
136132720Skan *              Context                 - To be passed to the callbacks
137169691Skan *
138169691Skan * RETURN:      Status from callback(s)
139169691Skan *
140169691Skan * DESCRIPTION: Walk the entire parse tree.
141169691Skan *
142169691Skan ******************************************************************************/
143132720Skan
144132720Skanvoid
145132720SkanAcpiDmWalkParseTree (
146132720Skan    ACPI_PARSE_OBJECT       *Op,
147132720Skan    ASL_WALK_CALLBACK       DescendingCallback,
148132720Skan    ASL_WALK_CALLBACK       AscendingCallback,
149169691Skan    void                    *Context)
150169691Skan{
151169691Skan    BOOLEAN                 NodePreviouslyVisited;
152169691Skan    ACPI_PARSE_OBJECT       *StartOp = Op;
153169691Skan    ACPI_STATUS             Status;
154169691Skan    ACPI_PARSE_OBJECT       *Next;
155132720Skan    ACPI_OP_WALK_INFO       *Info = Context;
156169691Skan
157169691Skan
158169691Skan    Info->Level = 0;
159169691Skan    NodePreviouslyVisited = FALSE;
160169691Skan
161169691Skan    while (Op)
162132720Skan    {
163132720Skan        if (NodePreviouslyVisited)
164132720Skan        {
165132720Skan            if (AscendingCallback)
166132720Skan            {
167132720Skan                Status = AscendingCallback (Op, Info->Level, Context);
168132720Skan                if (ACPI_FAILURE (Status))
169132720Skan                {
170132720Skan                    return;
171132720Skan                }
172132720Skan            }
173132720Skan        }
174132720Skan        else
175169691Skan        {
176132720Skan            /* Let the callback process the node */
177132720Skan
178132720Skan            Status = DescendingCallback (Op, Info->Level, Context);
179132720Skan            if (ACPI_SUCCESS (Status))
180132720Skan            {
181169691Skan                /* Visit children first, once */
182132720Skan
183132720Skan                Next = AcpiPsGetArg (Op, 0);
184132720Skan                if (Next)
185132720Skan                {
186132720Skan                    Info->Level++;
187132720Skan                    Op = Next;
188132720Skan                    continue;
189132720Skan                }
190132720Skan            }
191132720Skan            else if (Status != AE_CTRL_DEPTH)
192132720Skan            {
193132720Skan                /* Exit immediately on any error */
194169691Skan
195169691Skan                return;
196169691Skan            }
197169691Skan        }
198169691Skan
199169691Skan        /* Terminate walk at start op */
200169691Skan
201169691Skan        if (Op == StartOp)
202169691Skan        {
203169691Skan            break;
204169691Skan        }
205169691Skan
206169691Skan        /* No more children, re-visit this node */
207132720Skan
208132720Skan        if (!NodePreviouslyVisited)
209132720Skan        {
210132720Skan            NodePreviouslyVisited = TRUE;
211132720Skan            continue;
212132720Skan        }
213132720Skan
214169691Skan        /* No more children, visit peers */
215169691Skan
216169691Skan        if (Op->Common.Next)
217169691Skan        {
218169691Skan            Op = Op->Common.Next;
219132720Skan            NodePreviouslyVisited = FALSE;
220132720Skan        }
221132720Skan        else
222132720Skan        {
223132720Skan            /* No peers, re-visit parent */
224132720Skan
225132720Skan            if (Info->Level != 0 )
226132720Skan            {
227132720Skan                Info->Level--;
228132720Skan            }
229132720Skan
230132720Skan            Op = Op->Common.Parent;
231132720Skan            NodePreviouslyVisited = TRUE;
232132720Skan        }
233132720Skan    }
234132720Skan
235132720Skan    /* If we get here, the walk completed with no errors */
236132720Skan
237132720Skan    return;
238132720Skan}
239132720Skan
240132720Skan
241132720Skan/*******************************************************************************
242132720Skan *
243132720Skan * FUNCTION:    AcpiDmBlockType
244132720Skan *
245132720Skan * PARAMETERS:  Op              - Object to be examined
246132720Skan *
247132720Skan * RETURN:      BlockType - not a block, parens, braces, or even both.
248169691Skan *
249132720Skan * DESCRIPTION: Type of block for this op (parens or braces)
250132720Skan *
251132720Skan ******************************************************************************/
252132720Skan
253132720Skanstatic UINT32
254132720SkanAcpiDmBlockType (
255132720Skan    ACPI_PARSE_OBJECT       *Op)
256132720Skan{
257132720Skan    const ACPI_OPCODE_INFO  *OpInfo;
258132720Skan
259132720Skan
260132720Skan    if (!Op)
261132720Skan    {
262132720Skan        return (BLOCK_NONE);
263132720Skan    }
264132720Skan
265132720Skan    switch (Op->Common.AmlOpcode)
266132720Skan    {
267132720Skan    case AML_ELSE_OP:
268132720Skan
269132720Skan        return (BLOCK_BRACE);
270132720Skan
271132720Skan    case AML_METHOD_OP:
272132720Skan    case AML_DEVICE_OP:
273132720Skan    case AML_SCOPE_OP:
274132720Skan    case AML_PROCESSOR_OP:
275132720Skan    case AML_POWER_RES_OP:
276132720Skan    case AML_THERMAL_ZONE_OP:
277169691Skan    case AML_IF_OP:
278169691Skan    case AML_WHILE_OP:
279169691Skan    case AML_FIELD_OP:
280169691Skan    case AML_INDEX_FIELD_OP:
281169691Skan    case AML_BANK_FIELD_OP:
282169691Skan
283169691Skan        return (BLOCK_PAREN | BLOCK_BRACE);
284169691Skan
285169691Skan    case AML_BUFFER_OP:
286169691Skan
287169691Skan        if ((Op->Common.DisasmOpcode == ACPI_DASM_UNICODE) ||
288169691Skan            (Op->Common.DisasmOpcode == ACPI_DASM_UUID) ||
289169691Skan            (Op->Common.DisasmOpcode == ACPI_DASM_PLD_METHOD))
290169691Skan        {
291169691Skan            return (BLOCK_NONE);
292169691Skan        }
293169691Skan
294169691Skan        /*lint -fallthrough */
295169691Skan
296169691Skan    case AML_PACKAGE_OP:
297169691Skan    case AML_VAR_PACKAGE_OP:
298169691Skan
299132720Skan        return (BLOCK_PAREN | BLOCK_BRACE);
300169691Skan
301169691Skan    case AML_EVENT_OP:
302169691Skan
303169691Skan        return (BLOCK_PAREN);
304169691Skan
305169691Skan    case AML_INT_METHODCALL_OP:
306169691Skan
307169691Skan        if (Op->Common.Parent &&
308146897Skan            ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
309169691Skan             (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)))
310169691Skan        {
311132720Skan            /* This is a reference to a method, not an invocation */
312132720Skan
313            return (BLOCK_NONE);
314        }
315
316    default:
317
318        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
319        if (OpInfo->Flags & AML_HAS_ARGS)
320        {
321            return (BLOCK_PAREN);
322        }
323
324        return (BLOCK_NONE);
325    }
326}
327
328
329/*******************************************************************************
330 *
331 * FUNCTION:    AcpiDmListType
332 *
333 * PARAMETERS:  Op              - Object to be examined
334 *
335 * RETURN:      ListType - has commas or not.
336 *
337 * DESCRIPTION: Type of block for this op (parens or braces)
338 *
339 ******************************************************************************/
340
341UINT32
342AcpiDmListType (
343    ACPI_PARSE_OBJECT       *Op)
344{
345    const ACPI_OPCODE_INFO  *OpInfo;
346
347
348    if (!Op)
349    {
350        return (BLOCK_NONE);
351    }
352
353    switch (Op->Common.AmlOpcode)
354    {
355
356    case AML_ELSE_OP:
357    case AML_METHOD_OP:
358    case AML_DEVICE_OP:
359    case AML_SCOPE_OP:
360    case AML_POWER_RES_OP:
361    case AML_PROCESSOR_OP:
362    case AML_THERMAL_ZONE_OP:
363    case AML_IF_OP:
364    case AML_WHILE_OP:
365    case AML_FIELD_OP:
366    case AML_INDEX_FIELD_OP:
367    case AML_BANK_FIELD_OP:
368
369        return (BLOCK_NONE);
370
371    case AML_BUFFER_OP:
372    case AML_PACKAGE_OP:
373    case AML_VAR_PACKAGE_OP:
374
375        return (BLOCK_COMMA_LIST);
376
377    default:
378
379        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
380        if (OpInfo->Flags & AML_HAS_ARGS)
381        {
382            return (BLOCK_COMMA_LIST);
383        }
384
385        return (BLOCK_NONE);
386    }
387}
388
389
390/*******************************************************************************
391 *
392 * FUNCTION:    AcpiDmDescendingOp
393 *
394 * PARAMETERS:  ASL_WALK_CALLBACK
395 *
396 * RETURN:      Status
397 *
398 * DESCRIPTION: First visitation of a parse object during tree descent.
399 *              Decode opcode name and begin parameter list(s), if any.
400 *
401 ******************************************************************************/
402
403static ACPI_STATUS
404AcpiDmDescendingOp (
405    ACPI_PARSE_OBJECT       *Op,
406    UINT32                  Level,
407    void                    *Context)
408{
409    ACPI_OP_WALK_INFO       *Info = Context;
410    const ACPI_OPCODE_INFO  *OpInfo;
411    UINT32                  Name;
412    ACPI_PARSE_OBJECT       *NextOp;
413
414
415    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
416    {
417        /* Ignore this op -- it was handled elsewhere */
418
419        return (AE_CTRL_DEPTH);
420    }
421
422    /* Level 0 is at the Definition Block level */
423
424    if (Level == 0)
425    {
426        /* In verbose mode, print the AML offset, opcode and depth count */
427
428        if (Info->WalkState)
429        {
430            VERBOSE_PRINT ((DB_FULL_OP_INFO,
431                (Info->WalkState->MethodNode ?
432                    Info->WalkState->MethodNode->Name.Ascii : "   "),
433                Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode));
434        }
435
436        if (Op->Common.AmlOpcode == AML_SCOPE_OP)
437        {
438            /* This is the beginning of the Definition Block */
439
440            AcpiOsPrintf ("{\n");
441
442            /* Emit all External() declarations here */
443
444            AcpiDmEmitExternals ();
445            return (AE_OK);
446        }
447    }
448    else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
449             (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
450             (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
451    {
452            /*
453             * This is a first-level element of a term list,
454             * indent a new line
455             */
456            switch (Op->Common.AmlOpcode)
457            {
458            case AML_NOOP_OP:
459                /*
460                 * Optionally just ignore this opcode. Some tables use
461                 * NoOp opcodes for "padding" out packages that the BIOS
462                 * changes dynamically. This can leave hundreds or
463                 * thousands of NoOp opcodes that if disassembled,
464                 * cannot be compiled because they are syntactically
465                 * incorrect.
466                 */
467                if (AcpiGbl_IgnoreNoopOperator)
468                {
469                    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
470                    return (AE_OK);
471                }
472
473                /* Fallthrough */
474
475            default:
476
477                AcpiDmIndent (Level);
478                break;
479            }
480
481            Info->LastLevel = Level;
482            Info->Count = 0;
483    }
484
485    /*
486     * This is an inexpensive mechanism to try and keep lines from getting
487     * too long. When the limit is hit, start a new line at the previous
488     * indent plus one. A better but more expensive mechanism would be to
489     * keep track of the current column.
490     */
491    Info->Count++;
492    if (Info->Count /* +Info->LastLevel */ > 12)
493    {
494        Info->Count = 0;
495        AcpiOsPrintf ("\n");
496        AcpiDmIndent (Info->LastLevel + 1);
497    }
498
499    /* If ASL+ is enabled, check for a C-style operator */
500
501    if (AcpiDmCheckForSymbolicOpcode (Op, Info))
502    {
503        return (AE_OK);
504    }
505
506    /* Print the opcode name */
507
508    AcpiDmDisassembleOneOp (NULL, Info, Op);
509
510    if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
511        (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
512    {
513        return (AE_OK);
514    }
515
516    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
517        (Op->Common.AmlOpcode == AML_RETURN_OP))
518    {
519        Info->Level--;
520    }
521
522    /* Start the opcode argument list if necessary */
523
524    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
525
526    if ((OpInfo->Flags & AML_HAS_ARGS) ||
527        (Op->Common.AmlOpcode == AML_EVENT_OP))
528    {
529        /* This opcode has an argument list */
530
531        if (AcpiDmBlockType (Op) & BLOCK_PAREN)
532        {
533            AcpiOsPrintf (" (");
534        }
535
536        /* If this is a named opcode, print the associated name value */
537
538        if (OpInfo->Flags & AML_NAMED)
539        {
540            switch (Op->Common.AmlOpcode)
541            {
542            case AML_ALIAS_OP:
543
544                NextOp = AcpiPsGetDepthNext (NULL, Op);
545                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
546                AcpiDmNamestring (NextOp->Common.Value.Name);
547                AcpiOsPrintf (", ");
548
549                /*lint -fallthrough */
550
551            default:
552
553                Name = AcpiPsGetName (Op);
554                if (Op->Named.Path)
555                {
556                    AcpiDmNamestring ((char *) Op->Named.Path);
557                }
558                else
559                {
560                    AcpiDmDumpName (Name);
561                }
562
563                if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
564                {
565                    if (AcpiGbl_DbOpt_verbose)
566                    {
567                        (void) AcpiPsDisplayObjectPathname (NULL, Op);
568                    }
569                }
570                break;
571            }
572
573            switch (Op->Common.AmlOpcode)
574            {
575            case AML_METHOD_OP:
576
577                AcpiDmMethodFlags (Op);
578                AcpiOsPrintf (")");
579
580                /* Emit description comment for Method() with a predefined ACPI name */
581
582                AcpiDmPredefinedDescription (Op);
583                break;
584
585            case AML_NAME_OP:
586
587                /* Check for _HID and related EISAID() */
588
589                AcpiDmCheckForHardwareId (Op);
590                AcpiOsPrintf (", ");
591                break;
592
593            case AML_REGION_OP:
594
595                AcpiDmRegionFlags (Op);
596                break;
597
598            case AML_POWER_RES_OP:
599
600                /* Mark the next two Ops as part of the parameter list */
601
602                AcpiOsPrintf (", ");
603                NextOp = AcpiPsGetDepthNext (NULL, Op);
604                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
605
606                NextOp = NextOp->Common.Next;
607                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
608                return (AE_OK);
609
610            case AML_PROCESSOR_OP:
611
612                /* Mark the next three Ops as part of the parameter list */
613
614                AcpiOsPrintf (", ");
615                NextOp = AcpiPsGetDepthNext (NULL, Op);
616                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
617
618                NextOp = NextOp->Common.Next;
619                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
620
621                NextOp = NextOp->Common.Next;
622                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
623                return (AE_OK);
624
625            case AML_MUTEX_OP:
626            case AML_DATA_REGION_OP:
627
628                AcpiOsPrintf (", ");
629                return (AE_OK);
630
631            case AML_EVENT_OP:
632            case AML_ALIAS_OP:
633
634                return (AE_OK);
635
636            case AML_SCOPE_OP:
637            case AML_DEVICE_OP:
638            case AML_THERMAL_ZONE_OP:
639
640                AcpiOsPrintf (")");
641                break;
642
643            default:
644
645                AcpiOsPrintf ("*** Unhandled named opcode %X\n",
646                    Op->Common.AmlOpcode);
647                break;
648            }
649        }
650
651        else switch (Op->Common.AmlOpcode)
652        {
653        case AML_FIELD_OP:
654        case AML_BANK_FIELD_OP:
655        case AML_INDEX_FIELD_OP:
656
657            Info->BitOffset = 0;
658
659            /* Name of the parent OperationRegion */
660
661            NextOp = AcpiPsGetDepthNext (NULL, Op);
662            AcpiDmNamestring (NextOp->Common.Value.Name);
663            AcpiOsPrintf (", ");
664            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
665
666            switch (Op->Common.AmlOpcode)
667            {
668            case AML_BANK_FIELD_OP:
669
670                /* Namestring - Bank Name */
671
672                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
673                AcpiDmNamestring (NextOp->Common.Value.Name);
674                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
675                AcpiOsPrintf (", ");
676
677                /*
678                 * Bank Value. This is a TermArg in the middle of the parameter
679                 * list, must handle it here.
680                 *
681                 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
682                 * eliminates newline in the output.
683                 */
684                NextOp = NextOp->Common.Next;
685
686                Info->Flags = ACPI_PARSEOP_PARAMLIST;
687                AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
688                    AcpiDmAscendingOp, Info);
689                Info->Flags = 0;
690                Info->Level = Level;
691
692                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
693                AcpiOsPrintf (", ");
694                break;
695
696            case AML_INDEX_FIELD_OP:
697
698                /* Namestring - Data Name */
699
700                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
701                AcpiDmNamestring (NextOp->Common.Value.Name);
702                AcpiOsPrintf (", ");
703                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
704                break;
705
706            default:
707
708                break;
709            }
710
711            AcpiDmFieldFlags (NextOp);
712            break;
713
714        case AML_BUFFER_OP:
715
716            /* The next op is the size parameter */
717
718            NextOp = AcpiPsGetDepthNext (NULL, Op);
719            if (!NextOp)
720            {
721                /* Single-step support */
722
723                return (AE_OK);
724            }
725
726            if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
727            {
728                /*
729                 * We have a resource list. Don't need to output
730                 * the buffer size Op. Open up a new block
731                 */
732                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
733                NextOp = NextOp->Common.Next;
734                AcpiOsPrintf (")");
735
736                /* Emit description comment for Name() with a predefined ACPI name */
737
738                AcpiDmPredefinedDescription (Op->Asl.Parent);
739
740                AcpiOsPrintf ("\n");
741                AcpiDmIndent (Info->Level);
742                AcpiOsPrintf ("{\n");
743                return (AE_OK);
744            }
745
746            /* Normal Buffer, mark size as in the parameter list */
747
748            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
749            return (AE_OK);
750
751        case AML_VAR_PACKAGE_OP:
752        case AML_IF_OP:
753        case AML_WHILE_OP:
754
755            /* The next op is the size or predicate parameter */
756
757            NextOp = AcpiPsGetDepthNext (NULL, Op);
758            if (NextOp)
759            {
760                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
761            }
762            return (AE_OK);
763
764        case AML_PACKAGE_OP:
765
766            /* The next op is the size parameter */
767
768            NextOp = AcpiPsGetDepthNext (NULL, Op);
769            if (NextOp)
770            {
771                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
772            }
773            return (AE_OK);
774
775        case AML_MATCH_OP:
776
777            AcpiDmMatchOp (Op);
778            break;
779
780        default:
781
782            break;
783        }
784
785        if (AcpiDmBlockType (Op) & BLOCK_BRACE)
786        {
787            AcpiOsPrintf ("\n");
788            AcpiDmIndent (Level);
789            AcpiOsPrintf ("{\n");
790        }
791    }
792
793    return (AE_OK);
794}
795
796
797/*******************************************************************************
798 *
799 * FUNCTION:    AcpiDmAscendingOp
800 *
801 * PARAMETERS:  ASL_WALK_CALLBACK
802 *
803 * RETURN:      Status
804 *
805 * DESCRIPTION: Second visitation of a parse object, during ascent of parse
806 *              tree. Close out any parameter lists and complete the opcode.
807 *
808 ******************************************************************************/
809
810static ACPI_STATUS
811AcpiDmAscendingOp (
812    ACPI_PARSE_OBJECT       *Op,
813    UINT32                  Level,
814    void                    *Context)
815{
816    ACPI_OP_WALK_INFO       *Info = Context;
817    ACPI_PARSE_OBJECT       *ParentOp;
818
819
820    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
821    {
822        /* Ignore this op -- it was handled elsewhere */
823
824        return (AE_OK);
825    }
826
827    if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
828    {
829        /* Indicates the end of the current descriptor block (table) */
830
831        AcpiOsPrintf ("}\n\n");
832        return (AE_OK);
833    }
834
835    switch (AcpiDmBlockType (Op))
836    {
837    case BLOCK_PAREN:
838
839        /* Completed an op that has arguments, add closing paren if needed */
840
841        AcpiDmCloseOperator (Op);
842
843        if (Op->Common.AmlOpcode == AML_NAME_OP)
844        {
845            /* Emit description comment for Name() with a predefined ACPI name */
846
847            AcpiDmPredefinedDescription (Op);
848        }
849        else
850        {
851            /* For Create* operators, attempt to emit resource tag description */
852
853            AcpiDmFieldPredefinedDescription (Op);
854        }
855
856        /* Decode Notify() values */
857
858        if (Op->Common.AmlOpcode == AML_NOTIFY_OP)
859        {
860            AcpiDmNotifyDescription (Op);
861        }
862
863        AcpiDmDisplayTargetPathname (Op);
864
865        /* Could be a nested operator, check if comma required */
866
867        if (!AcpiDmCommaIfListMember (Op))
868        {
869            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
870                     (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
871                     (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
872            {
873                /*
874                 * This is a first-level element of a term list
875                 * start a new line
876                 */
877                if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST))
878                {
879                    AcpiOsPrintf ("\n");
880                }
881            }
882        }
883        break;
884
885    case BLOCK_BRACE:
886    case (BLOCK_BRACE | BLOCK_PAREN):
887
888        /* Completed an op that has a term list, add closing brace */
889
890        if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
891        {
892            AcpiOsPrintf ("}");
893        }
894        else
895        {
896            AcpiDmIndent (Level);
897            AcpiOsPrintf ("}");
898        }
899
900        AcpiDmCommaIfListMember (Op);
901
902        if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
903        {
904            AcpiOsPrintf ("\n");
905            if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
906            {
907                if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
908                    (Op->Common.Next) &&
909                    (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
910                {
911                    break;
912                }
913
914                if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
915                    (!Op->Common.Next))
916                {
917                    break;
918                }
919                AcpiOsPrintf ("\n");
920            }
921        }
922        break;
923
924    case BLOCK_NONE:
925    default:
926
927        /* Could be a nested operator, check if comma required */
928
929        if (!AcpiDmCommaIfListMember (Op))
930        {
931            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
932                     (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
933                     (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
934            {
935                /*
936                 * This is a first-level element of a term list
937                 * start a new line
938                 */
939                AcpiOsPrintf ("\n");
940            }
941        }
942        else if (Op->Common.Parent)
943        {
944            switch (Op->Common.Parent->Common.AmlOpcode)
945            {
946            case AML_PACKAGE_OP:
947            case AML_VAR_PACKAGE_OP:
948
949                if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
950                {
951                    AcpiOsPrintf ("\n");
952                }
953                break;
954
955            default:
956
957                break;
958            }
959        }
960        break;
961    }
962
963    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
964    {
965        if ((Op->Common.Next) &&
966            (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
967        {
968            return (AE_OK);
969        }
970
971        /*
972         * The parent Op is guaranteed to be valid because of the flag
973         * ACPI_PARSEOP_PARAMLIST -- which means that this op is part of
974         * a parameter list and thus has a valid parent.
975         */
976        ParentOp = Op->Common.Parent;
977
978        /*
979         * Just completed a parameter node for something like "Buffer (param)".
980         * Close the paren and open up the term list block with a brace
981         */
982        if (Op->Common.Next)
983        {
984            AcpiOsPrintf (")");
985
986            /*
987             * Emit a description comment for a Name() operator that is a
988             * predefined ACPI name. Must check the grandparent.
989             */
990            ParentOp = ParentOp->Common.Parent;
991            if (ParentOp &&
992                (ParentOp->Asl.AmlOpcode == AML_NAME_OP))
993            {
994                AcpiDmPredefinedDescription (ParentOp);
995            }
996
997            AcpiOsPrintf ("\n");
998            AcpiDmIndent (Level - 1);
999            AcpiOsPrintf ("{\n");
1000        }
1001        else
1002        {
1003            ParentOp->Common.DisasmFlags |= ACPI_PARSEOP_EMPTY_TERMLIST;
1004            AcpiOsPrintf (") {");
1005        }
1006    }
1007
1008    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
1009        (Op->Common.AmlOpcode == AML_RETURN_OP))
1010    {
1011        Info->Level++;
1012    }
1013
1014    /*
1015     * For ASL+, check for and emit a C-style symbol. If valid, the
1016     * symbol string has been deferred until after the first operand
1017     */
1018    if (AcpiGbl_CstyleDisassembly)
1019    {
1020        if (Op->Asl.OperatorSymbol)
1021        {
1022            AcpiOsPrintf ("%s", Op->Asl.OperatorSymbol);
1023            Op->Asl.OperatorSymbol = NULL;
1024        }
1025    }
1026
1027    return (AE_OK);
1028}
1029
1030#endif  /* ACPI_DISASSEMBLER */
1031