dmwalk.c revision 237412
198944Sobrien/*******************************************************************************
298944Sobrien *
3130803Smarcel * Module Name: dmwalk - AML disassembly tree walk
4130803Smarcel *
598944Sobrien ******************************************************************************/
698944Sobrien
798944Sobrien/*
898944Sobrien * Copyright (C) 2000 - 2012, Intel Corp.
998944Sobrien * All rights reserved.
1098944Sobrien *
1198944Sobrien * Redistribution and use in source and binary forms, with or without
1298944Sobrien * modification, are permitted provided that the following conditions
1398944Sobrien * are met:
1498944Sobrien * 1. Redistributions of source code must retain the above copyright
1598944Sobrien *    notice, this list of conditions, and the following disclaimer,
1698944Sobrien *    without modification.
1798944Sobrien * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1898944Sobrien *    substantially similar to the "NO WARRANTY" disclaimer below
1998944Sobrien *    ("Disclaimer") and any redistribution must be conditioned upon
2098944Sobrien *    including a substantially similar Disclaimer requirement for further
2198944Sobrien *    binary redistribution.
2298944Sobrien * 3. Neither the names of the above-listed copyright holders nor the names
23130803Smarcel *    of any contributors may be used to endorse or promote products derived
24130803Smarcel *    from this software without specific prior written permission.
2598944Sobrien *
2698944Sobrien * Alternatively, this software may be distributed under the terms of the
27130803Smarcel * GNU General Public License ("GPL") version 2 as published by the Free
2898944Sobrien * Software Foundation.
2998944Sobrien *
30130803Smarcel * NO WARRANTY
3198944Sobrien * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32130803Smarcel * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3398944Sobrien * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34130803Smarcel * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35130803Smarcel * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36130803Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37130803Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38130803Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39130803Smarcel * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40130803Smarcel * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4198944Sobrien * POSSIBILITY OF SUCH DAMAGES.
4298944Sobrien */
4398944Sobrien
4498944Sobrien
4598944Sobrien#include <contrib/dev/acpica/include/acpi.h>
4698944Sobrien#include <contrib/dev/acpica/include/accommon.h>
4798944Sobrien#include <contrib/dev/acpica/include/acparser.h>
4898944Sobrien#include <contrib/dev/acpica/include/amlcode.h>
4998944Sobrien#include <contrib/dev/acpica/include/acdisasm.h>
5098944Sobrien#include <contrib/dev/acpica/include/acdebug.h>
5198944Sobrien
52130803Smarcel
5398944Sobrien#ifdef ACPI_DISASSEMBLER
5498944Sobrien
5598944Sobrien#define _COMPONENT          ACPI_CA_DEBUGGER
5698944Sobrien        ACPI_MODULE_NAME    ("dmwalk")
5798944Sobrien
5898944Sobrien
5998944Sobrien#define DB_FULL_OP_INFO     "[%4.4s] @%5.5X #%4.4X:  "
6098944Sobrien
6198944Sobrien/* Stub for non-compiler code */
6298944Sobrien
6398944Sobrien#ifndef ACPI_ASL_COMPILER
6498944Sobrienvoid
65130803SmarcelAcpiDmEmitExternals (
6698944Sobrien    void)
6798944Sobrien{
68130803Smarcel    return;
69130803Smarcel}
70130803Smarcel#endif
71130803Smarcel
7298944Sobrien/* Local prototypes */
73130803Smarcel
7498944Sobrienstatic ACPI_STATUS
7598944SobrienAcpiDmDescendingOp (
7698944Sobrien    ACPI_PARSE_OBJECT       *Op,
7798944Sobrien    UINT32                  Level,
7898944Sobrien    void                    *Context);
79130803Smarcel
80130803Smarcelstatic ACPI_STATUS
8198944SobrienAcpiDmAscendingOp (
82130803Smarcel    ACPI_PARSE_OBJECT       *Op,
8398944Sobrien    UINT32                  Level,
8498944Sobrien    void                    *Context);
85130803Smarcel
86130803Smarcelstatic UINT32
87130803SmarcelAcpiDmBlockType (
8898944Sobrien    ACPI_PARSE_OBJECT       *Op);
8998944Sobrien
9098944Sobrien
91130803Smarcel/*******************************************************************************
9298944Sobrien *
9398944Sobrien * FUNCTION:    AcpiDmDisassemble
9498944Sobrien *
9598944Sobrien * PARAMETERS:  WalkState       - Current state
9698944Sobrien *              Origin          - Starting object
97130803Smarcel *              NumOpcodes      - Max number of opcodes to be displayed
9898944Sobrien *
9998944Sobrien * RETURN:      None
10098944Sobrien *
101130803Smarcel * DESCRIPTION: Disassemble parser object and its children.  This is the
10298944Sobrien *              main entry point of the disassembler.
10398944Sobrien *
10498944Sobrien ******************************************************************************/
105130803Smarcel
10698944Sobrienvoid
10798944SobrienAcpiDmDisassemble (
108130803Smarcel    ACPI_WALK_STATE         *WalkState,
109130803Smarcel    ACPI_PARSE_OBJECT       *Origin,
11098944Sobrien    UINT32                  NumOpcodes)
111130803Smarcel{
11298944Sobrien    ACPI_PARSE_OBJECT       *Op = Origin;
11398944Sobrien    ACPI_OP_WALK_INFO       Info;
11498944Sobrien
11598944Sobrien
11698944Sobrien    if (!Op)
11798944Sobrien    {
11898944Sobrien        return;
119130803Smarcel    }
12098944Sobrien
12198944Sobrien    Info.Flags = 0;
12298944Sobrien    Info.Level = 0;
123130803Smarcel    Info.Count = 0;
12498944Sobrien    Info.WalkState = WalkState;
12598944Sobrien    AcpiDmWalkParseTree (Op, AcpiDmDescendingOp, AcpiDmAscendingOp, &Info);
12698944Sobrien    return;
12798944Sobrien}
12898944Sobrien
12998944Sobrien
13098944Sobrien/*******************************************************************************
13198944Sobrien *
13298944Sobrien * FUNCTION:    AcpiDmWalkParseTree
13398944Sobrien *
13498944Sobrien * PARAMETERS:  Op                      - Root Op object
13598944Sobrien *              DescendingCallback      - Called during tree descent
13698944Sobrien *              AscendingCallback       - Called during tree ascent
13798944Sobrien *              Context                 - To be passed to the callbacks
13898944Sobrien *
13998944Sobrien * RETURN:      Status from callback(s)
14098944Sobrien *
14198944Sobrien * DESCRIPTION: Walk the entire parse tree.
14298944Sobrien *
14398944Sobrien ******************************************************************************/
14498944Sobrien
14598944Sobrienvoid
14698944SobrienAcpiDmWalkParseTree (
14798944Sobrien    ACPI_PARSE_OBJECT       *Op,
14898944Sobrien    ASL_WALK_CALLBACK       DescendingCallback,
14998944Sobrien    ASL_WALK_CALLBACK       AscendingCallback,
15098944Sobrien    void                    *Context)
15198944Sobrien{
15298944Sobrien    BOOLEAN                 NodePreviouslyVisited;
153130803Smarcel    ACPI_PARSE_OBJECT       *StartOp = Op;
15498944Sobrien    ACPI_STATUS             Status;
15598944Sobrien    ACPI_PARSE_OBJECT       *Next;
15698944Sobrien    ACPI_OP_WALK_INFO       *Info = Context;
15798944Sobrien
15898944Sobrien
15998944Sobrien    Info->Level = 0;
160130803Smarcel    NodePreviouslyVisited = FALSE;
161130803Smarcel
162130803Smarcel    while (Op)
16398944Sobrien    {
164130803Smarcel        if (NodePreviouslyVisited)
165130803Smarcel        {
16698944Sobrien            if (AscendingCallback)
16798944Sobrien            {
16898944Sobrien                Status = AscendingCallback (Op, Info->Level, Context);
169130803Smarcel                if (ACPI_FAILURE (Status))
170130803Smarcel                {
17198944Sobrien                    return;
172130803Smarcel                }
17398944Sobrien            }
174130803Smarcel        }
17598944Sobrien        else
176130803Smarcel        {
177130803Smarcel            /* Let the callback process the node */
178130803Smarcel
179130803Smarcel            Status = DescendingCallback (Op, Info->Level, Context);
18098944Sobrien            if (ACPI_SUCCESS (Status))
181130803Smarcel            {
182130803Smarcel                /* Visit children first, once */
183130803Smarcel
18498944Sobrien                Next = AcpiPsGetArg (Op, 0);
18598944Sobrien                if (Next)
18698944Sobrien                {
187130803Smarcel                    Info->Level++;
18898944Sobrien                    Op = Next;
18998944Sobrien                    continue;
19098944Sobrien                }
191130803Smarcel            }
192130803Smarcel            else if (Status != AE_CTRL_DEPTH)
19398944Sobrien            {
194130803Smarcel                /* Exit immediately on any error */
195130803Smarcel
19698944Sobrien                return;
19798944Sobrien            }
198130803Smarcel        }
199130803Smarcel
20098944Sobrien        /* Terminate walk at start op */
20198944Sobrien
20298944Sobrien        if (Op == StartOp)
20398944Sobrien        {
20498944Sobrien            break;
205130803Smarcel        }
20698944Sobrien
20798944Sobrien        /* No more children, re-visit this node */
208130803Smarcel
209130803Smarcel        if (!NodePreviouslyVisited)
210130803Smarcel        {
211130803Smarcel            NodePreviouslyVisited = TRUE;
21298944Sobrien            continue;
213130803Smarcel        }
21498944Sobrien
21598944Sobrien        /* No more children, visit peers */
21698944Sobrien
21798944Sobrien        if (Op->Common.Next)
21898944Sobrien        {
21998944Sobrien            Op = Op->Common.Next;
22098944Sobrien            NodePreviouslyVisited = FALSE;
22198944Sobrien        }
222130803Smarcel        else
223130803Smarcel        {
22498944Sobrien            /* No peers, re-visit parent */
225130803Smarcel
226130803Smarcel            if (Info->Level != 0 )
22798944Sobrien            {
228130803Smarcel                Info->Level--;
22998944Sobrien            }
230130803Smarcel
231130803Smarcel            Op = Op->Common.Parent;
23298944Sobrien            NodePreviouslyVisited = TRUE;
233130803Smarcel        }
234130803Smarcel    }
235130803Smarcel
236130803Smarcel    /* If we get here, the walk completed with no errors */
237130803Smarcel
238130803Smarcel    return;
239130803Smarcel}
240130803Smarcel
24198944Sobrien
24298944Sobrien/*******************************************************************************
243130803Smarcel *
244130803Smarcel * FUNCTION:    AcpiDmBlockType
24598944Sobrien *
24698944Sobrien * PARAMETERS:  Op              - Object to be examined
247218822Sdim *
24898944Sobrien * RETURN:      BlockType - not a block, parens, braces, or even both.
24998944Sobrien *
25098944Sobrien * DESCRIPTION: Type of block for this op (parens or braces)
25198944Sobrien *
252130803Smarcel ******************************************************************************/
25398944Sobrien
254130803Smarcelstatic UINT32
255130803SmarcelAcpiDmBlockType (
256130803Smarcel    ACPI_PARSE_OBJECT       *Op)
257130803Smarcel{
258130803Smarcel    const ACPI_OPCODE_INFO  *OpInfo;
259130803Smarcel
260130803Smarcel
261130803Smarcel    if (!Op)
262130803Smarcel    {
263130803Smarcel        return (BLOCK_NONE);
264130803Smarcel    }
265130803Smarcel
266130803Smarcel    switch (Op->Common.AmlOpcode)
26798944Sobrien    {
268130803Smarcel    case AML_ELSE_OP:
269130803Smarcel
270130803Smarcel        return (BLOCK_BRACE);
271130803Smarcel
272130803Smarcel    case AML_METHOD_OP:
27398944Sobrien    case AML_DEVICE_OP:
27498944Sobrien    case AML_SCOPE_OP:
27598944Sobrien    case AML_PROCESSOR_OP:
276130803Smarcel    case AML_POWER_RES_OP:
27798944Sobrien    case AML_THERMAL_ZONE_OP:
27898944Sobrien    case AML_IF_OP:
27998944Sobrien    case AML_WHILE_OP:
28098944Sobrien    case AML_FIELD_OP:
281130803Smarcel    case AML_INDEX_FIELD_OP:
28298944Sobrien    case AML_BANK_FIELD_OP:
28398944Sobrien
284130803Smarcel        return (BLOCK_PAREN | BLOCK_BRACE);
285130803Smarcel
28698944Sobrien    case AML_BUFFER_OP:
28798944Sobrien
28898944Sobrien        if (Op->Common.DisasmOpcode == ACPI_DASM_UNICODE)
28998944Sobrien        {
29098944Sobrien            return (BLOCK_NONE);
29198944Sobrien        }
29298944Sobrien
29398944Sobrien        /*lint -fallthrough */
29498944Sobrien
295130803Smarcel    case AML_PACKAGE_OP:
29698944Sobrien    case AML_VAR_PACKAGE_OP:
29798944Sobrien
29898944Sobrien        return (BLOCK_PAREN | BLOCK_BRACE);
29998944Sobrien
30098944Sobrien    case AML_EVENT_OP:
30198944Sobrien
30298944Sobrien        return (BLOCK_PAREN);
30398944Sobrien
30498944Sobrien    default:
30598944Sobrien
306130803Smarcel        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
30798944Sobrien        if (OpInfo->Flags & AML_HAS_ARGS)
30898944Sobrien        {
309130803Smarcel            return (BLOCK_PAREN);
310130803Smarcel        }
311130803Smarcel
31298944Sobrien        return (BLOCK_NONE);
313130803Smarcel    }
31498944Sobrien}
315130803Smarcel
31698944Sobrien
317130803Smarcel/*******************************************************************************
318130803Smarcel *
319130803Smarcel * FUNCTION:    AcpiDmListType
320130803Smarcel *
32198944Sobrien * PARAMETERS:  Op              - Object to be examined
322130803Smarcel *
323130803Smarcel * RETURN:      ListType - has commas or not.
324130803Smarcel *
325130803Smarcel * DESCRIPTION: Type of block for this op (parens or braces)
326130803Smarcel *
327130803Smarcel ******************************************************************************/
328130803Smarcel
32998944SobrienUINT32
33098944SobrienAcpiDmListType (
331130803Smarcel    ACPI_PARSE_OBJECT       *Op)
33298944Sobrien{
333130803Smarcel    const ACPI_OPCODE_INFO  *OpInfo;
334130803Smarcel
335130803Smarcel
336130803Smarcel    if (!Op)
33798944Sobrien    {
338130803Smarcel        return (BLOCK_NONE);
339130803Smarcel    }
340130803Smarcel
341130803Smarcel    switch (Op->Common.AmlOpcode)
342130803Smarcel    {
343130803Smarcel
344130803Smarcel    case AML_ELSE_OP:
345130803Smarcel    case AML_METHOD_OP:
346130803Smarcel    case AML_DEVICE_OP:
347130803Smarcel    case AML_SCOPE_OP:
348130803Smarcel    case AML_POWER_RES_OP:
349130803Smarcel    case AML_PROCESSOR_OP:
35098944Sobrien    case AML_THERMAL_ZONE_OP:
351130803Smarcel    case AML_IF_OP:
352130803Smarcel    case AML_WHILE_OP:
353130803Smarcel    case AML_FIELD_OP:
354130803Smarcel    case AML_INDEX_FIELD_OP:
355130803Smarcel    case AML_BANK_FIELD_OP:
356130803Smarcel
357130803Smarcel        return (BLOCK_NONE);
358130803Smarcel
359130803Smarcel    case AML_BUFFER_OP:
360130803Smarcel    case AML_PACKAGE_OP:
36198944Sobrien    case AML_VAR_PACKAGE_OP:
362130803Smarcel
36398944Sobrien        return (BLOCK_COMMA_LIST);
36498944Sobrien
365130803Smarcel    default:
36698944Sobrien
367130803Smarcel        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
368130803Smarcel        if (OpInfo->Flags & AML_HAS_ARGS)
369130803Smarcel        {
370130803Smarcel            return (BLOCK_COMMA_LIST);
371130803Smarcel        }
372130803Smarcel
37398944Sobrien        return (BLOCK_NONE);
374130803Smarcel    }
375130803Smarcel}
376130803Smarcel
37798944Sobrien
378130803Smarcel/*******************************************************************************
379130803Smarcel *
38098944Sobrien * FUNCTION:    AcpiDmDescendingOp
381130803Smarcel *
382130803Smarcel * PARAMETERS:  ASL_WALK_CALLBACK
38398944Sobrien *
38498944Sobrien * RETURN:      Status
385130803Smarcel *
386130803Smarcel * DESCRIPTION: First visitation of a parse object during tree descent.
387130803Smarcel *              Decode opcode name and begin parameter list(s), if any.
388130803Smarcel *
389130803Smarcel ******************************************************************************/
39098944Sobrien
39198944Sobrienstatic ACPI_STATUS
39298944SobrienAcpiDmDescendingOp (
393130803Smarcel    ACPI_PARSE_OBJECT       *Op,
394130803Smarcel    UINT32                  Level,
39598944Sobrien    void                    *Context)
39698944Sobrien{
397130803Smarcel    ACPI_OP_WALK_INFO       *Info = Context;
39898944Sobrien    const ACPI_OPCODE_INFO  *OpInfo;
39998944Sobrien    UINT32                  Name;
40098944Sobrien    ACPI_PARSE_OBJECT       *NextOp;
40198944Sobrien
402130803Smarcel
40398944Sobrien    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
40498944Sobrien    {
40598944Sobrien        /* Ignore this op -- it was handled elsewhere */
40698944Sobrien
40798944Sobrien        return (AE_CTRL_DEPTH);
40898944Sobrien    }
40998944Sobrien
41098944Sobrien    /* Level 0 is at the Definition Block level */
41198944Sobrien
41298944Sobrien    if (Level == 0)
41398944Sobrien    {
41498944Sobrien        /* In verbose mode, print the AML offset, opcode and depth count */
415130803Smarcel
416130803Smarcel        if (Info->WalkState)
417130803Smarcel        {
418130803Smarcel            VERBOSE_PRINT ((DB_FULL_OP_INFO,
419130803Smarcel                (Info->WalkState->MethodNode ?
420130803Smarcel                    Info->WalkState->MethodNode->Name.Ascii : "   "),
42198944Sobrien                Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode));
42298944Sobrien        }
42398944Sobrien
42498944Sobrien        if (Op->Common.AmlOpcode == AML_SCOPE_OP)
425130803Smarcel        {
42698944Sobrien            /* This is the beginning of the Definition Block */
427130803Smarcel
428130803Smarcel            AcpiOsPrintf ("{\n");
429130803Smarcel
430130803Smarcel            /* Emit all External() declarations here */
43198944Sobrien
43298944Sobrien            AcpiDmEmitExternals ();
43398944Sobrien            return (AE_OK);
43498944Sobrien        }
435130803Smarcel    }
436130803Smarcel    else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
437130803Smarcel             (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
438130803Smarcel             (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
43998944Sobrien    {
440130803Smarcel            /*
44198944Sobrien             * This is a first-level element of a term list,
44298944Sobrien             * indent a new line
44398944Sobrien             */
44498944Sobrien            AcpiDmIndent (Level);
44598944Sobrien            Info->LastLevel = Level;
44698944Sobrien            Info->Count = 0;
44798944Sobrien    }
44898944Sobrien
44998944Sobrien    /*
45098944Sobrien     * This is an inexpensive mechanism to try and keep lines from getting
451130803Smarcel     * too long. When the limit is hit, start a new line at the previous
452130803Smarcel     * indent plus one. A better but more expensive mechanism would be to
453130803Smarcel     * keep track of the current column.
45498944Sobrien     */
455130803Smarcel    Info->Count++;
456130803Smarcel    if (Info->Count /* +Info->LastLevel */ > 10)
457130803Smarcel    {
458130803Smarcel        Info->Count = 0;
459130803Smarcel        AcpiOsPrintf ("\n");
460130803Smarcel        AcpiDmIndent (Info->LastLevel + 1);
461130803Smarcel    }
46298944Sobrien
46398944Sobrien    /* Print the opcode name */
46498944Sobrien
465130803Smarcel    AcpiDmDisassembleOneOp (NULL, Info, Op);
46698944Sobrien
467130803Smarcel    if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
468130803Smarcel        (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
46998944Sobrien    {
470130803Smarcel        return (AE_OK);
47198944Sobrien    }
47298944Sobrien
473130803Smarcel    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
47498944Sobrien        (Op->Common.AmlOpcode == AML_RETURN_OP))
47598944Sobrien    {
47698944Sobrien        Info->Level--;
47798944Sobrien    }
47898944Sobrien
47998944Sobrien    /* Start the opcode argument list if necessary */
480130803Smarcel
48198944Sobrien    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
482130803Smarcel
48398944Sobrien    if ((OpInfo->Flags & AML_HAS_ARGS) ||
48498944Sobrien        (Op->Common.AmlOpcode == AML_EVENT_OP))
485130803Smarcel    {
48698944Sobrien        /* This opcode has an argument list */
48798944Sobrien
488130803Smarcel        if (AcpiDmBlockType (Op) & BLOCK_PAREN)
48998944Sobrien        {
49098944Sobrien            AcpiOsPrintf (" (");
49198944Sobrien        }
49298944Sobrien
49398944Sobrien        /* If this is a named opcode, print the associated name value */
49498944Sobrien
495130803Smarcel        if (OpInfo->Flags & AML_NAMED)
496130803Smarcel        {
49798944Sobrien            switch (Op->Common.AmlOpcode)
49898944Sobrien            {
49998944Sobrien            case AML_ALIAS_OP:
50098944Sobrien
50198944Sobrien                NextOp = AcpiPsGetDepthNext (NULL, Op);
502                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
503                AcpiDmNamestring (NextOp->Common.Value.Name);
504                AcpiOsPrintf (", ");
505
506                /*lint -fallthrough */
507
508            default:
509
510                Name = AcpiPsGetName (Op);
511                if (Op->Named.Path)
512                {
513                    AcpiDmNamestring ((char *) Op->Named.Path);
514                }
515                else
516                {
517                    AcpiDmDumpName (Name);
518                }
519
520                if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
521                {
522                    if (AcpiGbl_DbOpt_verbose)
523                    {
524                        (void) AcpiPsDisplayObjectPathname (NULL, Op);
525                    }
526                }
527                break;
528            }
529
530            switch (Op->Common.AmlOpcode)
531            {
532            case AML_METHOD_OP:
533
534                AcpiDmMethodFlags (Op);
535                AcpiOsPrintf (")");
536
537                /* Emit description comment for Method() with a predefined ACPI name */
538
539                AcpiDmPredefinedDescription (Op);
540                break;
541
542
543            case AML_NAME_OP:
544
545                /* Check for _HID and related EISAID() */
546
547                AcpiDmIsEisaId (Op);
548                AcpiOsPrintf (", ");
549                break;
550
551
552            case AML_REGION_OP:
553
554                AcpiDmRegionFlags (Op);
555                break;
556
557
558            case AML_POWER_RES_OP:
559
560                /* Mark the next two Ops as part of the parameter list */
561
562                AcpiOsPrintf (", ");
563                NextOp = AcpiPsGetDepthNext (NULL, Op);
564                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
565
566                NextOp = NextOp->Common.Next;
567                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
568                return (AE_OK);
569
570
571            case AML_PROCESSOR_OP:
572
573                /* Mark the next three Ops as part of the parameter list */
574
575                AcpiOsPrintf (", ");
576                NextOp = AcpiPsGetDepthNext (NULL, Op);
577                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
578
579                NextOp = NextOp->Common.Next;
580                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
581
582                NextOp = NextOp->Common.Next;
583                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
584                return (AE_OK);
585
586
587            case AML_MUTEX_OP:
588            case AML_DATA_REGION_OP:
589
590                AcpiOsPrintf (", ");
591                return (AE_OK);
592
593
594            case AML_EVENT_OP:
595            case AML_ALIAS_OP:
596
597                return (AE_OK);
598
599
600            case AML_SCOPE_OP:
601            case AML_DEVICE_OP:
602            case AML_THERMAL_ZONE_OP:
603
604                AcpiOsPrintf (")");
605                break;
606
607
608            default:
609
610                AcpiOsPrintf ("*** Unhandled named opcode %X\n",
611                    Op->Common.AmlOpcode);
612                break;
613            }
614        }
615
616        else switch (Op->Common.AmlOpcode)
617        {
618        case AML_FIELD_OP:
619        case AML_BANK_FIELD_OP:
620        case AML_INDEX_FIELD_OP:
621
622            Info->BitOffset = 0;
623
624            /* Name of the parent OperationRegion */
625
626            NextOp = AcpiPsGetDepthNext (NULL, Op);
627            AcpiDmNamestring (NextOp->Common.Value.Name);
628            AcpiOsPrintf (", ");
629            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
630
631            switch (Op->Common.AmlOpcode)
632            {
633            case AML_BANK_FIELD_OP:
634
635                /* Namestring - Bank Name */
636
637                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
638                AcpiDmNamestring (NextOp->Common.Value.Name);
639                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
640                AcpiOsPrintf (", ");
641
642                /*
643                 * Bank Value. This is a TermArg in the middle of the parameter
644                 * list, must handle it here.
645                 *
646                 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
647                 * eliminates newline in the output.
648                 */
649                NextOp = NextOp->Common.Next;
650
651                Info->Flags = ACPI_PARSEOP_PARAMLIST;
652                AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
653                    AcpiDmAscendingOp, Info);
654                Info->Flags = 0;
655                Info->Level = Level;
656
657                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
658                AcpiOsPrintf (", ");
659                break;
660
661            case AML_INDEX_FIELD_OP:
662
663                /* Namestring - Data Name */
664
665                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
666                AcpiDmNamestring (NextOp->Common.Value.Name);
667                AcpiOsPrintf (", ");
668                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
669                break;
670
671            default:
672
673                break;
674            }
675
676            AcpiDmFieldFlags (NextOp);
677            break;
678
679
680        case AML_BUFFER_OP:
681
682            /* The next op is the size parameter */
683
684            NextOp = AcpiPsGetDepthNext (NULL, Op);
685            if (!NextOp)
686            {
687                /* Single-step support */
688
689                return (AE_OK);
690            }
691
692            if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
693            {
694                /*
695                 * We have a resource list. Don't need to output
696                 * the buffer size Op. Open up a new block
697                 */
698                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
699                NextOp = NextOp->Common.Next;
700                AcpiOsPrintf (")");
701
702                /* Emit description comment for Name() with a predefined ACPI name */
703
704                AcpiDmPredefinedDescription (Op->Asl.Parent);
705
706                AcpiOsPrintf ("\n");
707                AcpiDmIndent (Info->Level);
708                AcpiOsPrintf ("{\n");
709                return (AE_OK);
710            }
711
712            /* Normal Buffer, mark size as in the parameter list */
713
714            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
715            return (AE_OK);
716
717
718        case AML_VAR_PACKAGE_OP:
719        case AML_IF_OP:
720        case AML_WHILE_OP:
721
722            /* The next op is the size or predicate parameter */
723
724            NextOp = AcpiPsGetDepthNext (NULL, Op);
725            if (NextOp)
726            {
727                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
728            }
729            return (AE_OK);
730
731
732        case AML_PACKAGE_OP:
733
734            /* The next op is the size parameter */
735
736            NextOp = AcpiPsGetDepthNext (NULL, Op);
737            if (NextOp)
738            {
739                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
740            }
741            return (AE_OK);
742
743
744        case AML_MATCH_OP:
745
746            AcpiDmMatchOp (Op);
747            break;
748
749
750        default:
751
752            break;
753        }
754
755        if (AcpiDmBlockType (Op) & BLOCK_BRACE)
756        {
757            AcpiOsPrintf ("\n");
758            AcpiDmIndent (Level);
759            AcpiOsPrintf ("{\n");
760        }
761    }
762
763    return (AE_OK);
764}
765
766
767/*******************************************************************************
768 *
769 * FUNCTION:    AcpiDmAscendingOp
770 *
771 * PARAMETERS:  ASL_WALK_CALLBACK
772 *
773 * RETURN:      Status
774 *
775 * DESCRIPTION: Second visitation of a parse object, during ascent of parse
776 *              tree.  Close out any parameter lists and complete the opcode.
777 *
778 ******************************************************************************/
779
780static ACPI_STATUS
781AcpiDmAscendingOp (
782    ACPI_PARSE_OBJECT       *Op,
783    UINT32                  Level,
784    void                    *Context)
785{
786    ACPI_OP_WALK_INFO       *Info = Context;
787    ACPI_PARSE_OBJECT       *ParentOp;
788
789
790    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
791    {
792        /* Ignore this op -- it was handled elsewhere */
793
794        return (AE_OK);
795    }
796
797    if ((Level == 0) && (Op->Common.AmlOpcode == AML_SCOPE_OP))
798    {
799        /* Indicates the end of the current descriptor block (table) */
800
801        AcpiOsPrintf ("}\n\n");
802        return (AE_OK);
803    }
804
805    switch (AcpiDmBlockType (Op))
806    {
807    case BLOCK_PAREN:
808
809        /* Completed an op that has arguments, add closing paren */
810
811        AcpiOsPrintf (")");
812
813        if (Op->Common.AmlOpcode == AML_NAME_OP)
814        {
815            /* Emit description comment for Name() with a predefined ACPI name */
816
817            AcpiDmPredefinedDescription (Op);
818        }
819        else
820        {
821            /* For Create* operators, attempt to emit resource tag description */
822
823            AcpiDmFieldPredefinedDescription (Op);
824        }
825
826        /* Could be a nested operator, check if comma required */
827
828        if (!AcpiDmCommaIfListMember (Op))
829        {
830            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
831                     (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
832                     (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
833            {
834                /*
835                 * This is a first-level element of a term list
836                 * start a new line
837                 */
838                if (!(Info->Flags & ACPI_PARSEOP_PARAMLIST))
839                {
840                    AcpiOsPrintf ("\n");
841                }
842            }
843        }
844        break;
845
846
847    case BLOCK_BRACE:
848    case (BLOCK_BRACE | BLOCK_PAREN):
849
850        /* Completed an op that has a term list, add closing brace */
851
852        if (Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST)
853        {
854            AcpiOsPrintf ("}");
855        }
856        else
857        {
858            AcpiDmIndent (Level);
859            AcpiOsPrintf ("}");
860        }
861
862        AcpiDmCommaIfListMember (Op);
863
864        if (AcpiDmBlockType (Op->Common.Parent) != BLOCK_PAREN)
865        {
866            AcpiOsPrintf ("\n");
867            if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_EMPTY_TERMLIST))
868            {
869                if ((Op->Common.AmlOpcode == AML_IF_OP)  &&
870                    (Op->Common.Next) &&
871                    (Op->Common.Next->Common.AmlOpcode == AML_ELSE_OP))
872                {
873                    break;
874                }
875
876                if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
877                    (!Op->Common.Next))
878                {
879                    break;
880                }
881                AcpiOsPrintf ("\n");
882            }
883        }
884        break;
885
886
887    case BLOCK_NONE:
888    default:
889
890        /* Could be a nested operator, check if comma required */
891
892        if (!AcpiDmCommaIfListMember (Op))
893        {
894            if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
895                     (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
896                     (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
897            {
898                /*
899                 * This is a first-level element of a term list
900                 * start a new line
901                 */
902                AcpiOsPrintf ("\n");
903            }
904        }
905        else if (Op->Common.Parent)
906        {
907            switch (Op->Common.Parent->Common.AmlOpcode)
908            {
909            case AML_PACKAGE_OP:
910            case AML_VAR_PACKAGE_OP:
911
912                if (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
913                {
914                    AcpiOsPrintf ("\n");
915                }
916                break;
917
918            default:
919
920                break;
921            }
922        }
923        break;
924    }
925
926    if (Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)
927    {
928        if ((Op->Common.Next) &&
929            (Op->Common.Next->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST))
930        {
931            return (AE_OK);
932        }
933
934        /*
935         * Just completed a parameter node for something like "Buffer (param)".
936         * Close the paren and open up the term list block with a brace
937         */
938        if (Op->Common.Next)
939        {
940            AcpiOsPrintf (")");
941
942            /* Emit description comment for Name() with a predefined ACPI name */
943
944            ParentOp = Op->Common.Parent;
945            if (ParentOp)
946            {
947                ParentOp = ParentOp->Common.Parent;
948                if (ParentOp && ParentOp->Asl.AmlOpcode == AML_NAME_OP)
949                {
950                    AcpiDmPredefinedDescription (ParentOp);
951                }
952            }
953            AcpiOsPrintf ("\n");
954            AcpiDmIndent (Level - 1);
955            AcpiOsPrintf ("{\n");
956        }
957        else
958        {
959            Op->Common.Parent->Common.DisasmFlags |=
960                                    ACPI_PARSEOP_EMPTY_TERMLIST;
961            AcpiOsPrintf (") {");
962        }
963    }
964
965    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
966        (Op->Common.AmlOpcode == AML_RETURN_OP))
967    {
968        Info->Level++;
969    }
970    return (AE_OK);
971}
972
973
974#endif  /* ACPI_DISASSEMBLER */
975