static ACPI_STATUS
AdParseDeferredOps (
    ACPI_PARSE_OBJECT       *Root)
{
    ACPI_PARSE_OBJECT       *Op = Root;
    ACPI_STATUS             Status = AE_OK;
    const ACPI_OPCODE_INFO  *OpInfo;


    ACPI_FUNCTION_NAME (AdParseDeferredOps);
    fprintf (stderr, "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n");

    while (Op)
    {
        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
        if (!(OpInfo->Flags & AML_DEFER))
        {
            Op = AcpiPsGetDepthNext (Root, Op);
            continue;
        }

        switch (Op->Common.AmlOpcode)
        {
        case AML_METHOD_OP:
        case AML_BUFFER_OP:
        case AML_PACKAGE_OP:
        case AML_VAR_PACKAGE_OP:

            Status = AdDeferredParse (Op, Op->Named.Data, Op->Named.Length);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }
            break;

        case AML_REGION_OP:
        case AML_CREATE_QWORD_FIELD_OP:
        case AML_CREATE_DWORD_FIELD_OP:
        case AML_CREATE_WORD_FIELD_OP:
        case AML_CREATE_BYTE_FIELD_OP:
        case AML_CREATE_BIT_FIELD_OP:
        case AML_CREATE_FIELD_OP:
        case AML_BANK_FIELD_OP:

            /* Nothing to do in these cases */

            break;

        default:
            ACPI_ERROR ((AE_INFO, "Unhandled deferred opcode [%s]",
                Op->Common.AmlOpName));
            break;
        }

        Op = AcpiPsGetDepthNext (Root, Op);
    }

    fprintf (stderr, "\n");
    return Status;
}
示例#2
0
static ACPI_STATUS
AcpiDbClassifyOneObject (
    ACPI_HANDLE             ObjHandle,
    UINT32                  NestingLevel,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    UINT32                  Type;


    AcpiGbl_NumNodes++;

    Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    ObjDesc = AcpiNsGetAttachedObject (Node);

    AcpiDbEnumerateObject (ObjDesc);

    Type = Node->Type;
    if (Type > ACPI_TYPE_NS_NODE_MAX)
    {
        AcpiGbl_NodeTypeCountMisc++;
    }
    else
    {
        AcpiGbl_NodeTypeCount [Type]++;
    }

    return AE_OK;


#ifdef ACPI_FUTURE_IMPLEMENTATION

    /* TBD: These need to be counted during the initial parsing phase */

    if (AcpiPsIsNamedOp (Op->Opcode))
    {
        NumNodes++;
    }

    if (IsMethod)
    {
        NumMethodElements++;
    }

    NumGrammarElements++;
    Op = AcpiPsGetDepthNext (Root, Op);

    SizeOfParseTree   = (NumGrammarElements - NumMethodElements) *
                            (UINT32) sizeof (ACPI_PARSE_OBJECT);
    SizeOfMethodTrees = NumMethodElements * (UINT32) sizeof (ACPI_PARSE_OBJECT);
    SizeOfNodeEntries = NumNodes * (UINT32) sizeof (ACPI_NAMESPACE_NODE);
    SizeOfAcpiObjects = NumNodes * (UINT32) sizeof (ACPI_OPERAND_OBJECT);
#endif
}
示例#3
0
void
AcpiDmFindResources (
    ACPI_PARSE_OBJECT       *Root)
{
    ACPI_PARSE_OBJECT       *Op = Root;
    ACPI_PARSE_OBJECT       *Parent;


    /* Walk the entire parse tree */

    while (Op)
    {
        /* We are interested in Buffer() declarations */

        if (Op->Common.AmlOpcode == AML_BUFFER_OP)
        {
            /* And only declarations of the form Name (XXXX, Buffer()... ) */

            Parent = Op->Common.Parent;
            if (Parent->Common.AmlOpcode == AML_NAME_OP)
            {
                /*
                 * If the buffer is a resource template, add the individual
                 * resource descriptors to the namespace, as children of the
                 * buffer node.
                 */
                if (ACPI_SUCCESS (AcpiDmIsResourceTemplate (NULL, Op)))
                {
                    Op->Common.DisasmOpcode = ACPI_DASM_RESOURCE;
                    AcpiDmAddResourcesToNamespace (Parent->Common.Node, Op);
                }
            }
        }

        Op = AcpiPsGetDepthNext (Root, Op);
    }
}
示例#4
0
void
AcpiDmMethodFlags (
    ACPI_PARSE_OBJECT       *Op)
{
    UINT32                  Flags;
    UINT32                  Args;


    /* The next Op contains the flags */

    Op = AcpiPsGetDepthNext (NULL, Op);
    Flags = (UINT8) Op->Common.Value.Integer;
    Args = Flags & 0x07;

    /* Mark the Op as completed */

    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;

    /* 1) Method argument count */

    AcpiOsPrintf (", %d, ", Args);

    /* 2) Serialize rule */

    if (!(Flags & 0x08))
    {
        AcpiOsPrintf ("Not");
    }

    AcpiOsPrintf ("Serialized");

    /* 3) SyncLevel */

    if (Flags & 0xF0)
    {
        AcpiOsPrintf (", %d", Flags >> 4);
    }
示例#5
0
void
AcpiDmCheckResourceReference (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status;
    ACPI_PARSE_OBJECT       *BufferNameOp;
    ACPI_PARSE_OBJECT       *IndexOp;
    ACPI_NAMESPACE_NODE     *BufferNode;
    ACPI_NAMESPACE_NODE     *ResourceNode;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  BitIndex;


    /* We are only interested in the CreateXxxxField opcodes */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    if (OpInfo->Type != AML_TYPE_CREATE_FIELD)
    {
        return;
    }

    /* Get the buffer term operand */

    BufferNameOp = AcpiPsGetDepthNext (NULL, Op);

    /* Must be a named buffer, not an arg or local or method call */

    if (BufferNameOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)
    {
        return;
    }

    /* Get the Index term, must be an integer constant to convert */

    IndexOp = BufferNameOp->Common.Next;

    /* Major cheat: The Node field is also used for the Tag ptr. Clear it now */

    IndexOp->Common.Node = NULL;

    OpInfo = AcpiPsGetOpcodeInfo (IndexOp->Common.AmlOpcode);
    if (OpInfo->ObjectType != ACPI_TYPE_INTEGER)
    {
        return;
    }

    /* Get the bit offset of the descriptor within the buffer */

    if ((Op->Common.AmlOpcode == AML_CREATE_BIT_FIELD_OP) ||
        (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP))
    {
        /* Index operand is a bit offset */

        BitIndex = (UINT32) IndexOp->Common.Value.Integer;
    }
    else
    {
        /* Index operand is a byte offset, convert to bits */

        BitIndex = (UINT32) ACPI_MUL_8 (IndexOp->Common.Value.Integer);
    }

    /* Lookup the buffer in the namespace */

    Status = AcpiNsLookup (WalkState->ScopeInfo,
        BufferNameOp->Common.Value.String, ACPI_TYPE_BUFFER,
        ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState,
        &BufferNode);
    if (ACPI_FAILURE (Status))
    {
        return;
    }

    /* Validate object type, we must have a buffer */

    if (BufferNode->Type != ACPI_TYPE_BUFFER)
    {
        return;
    }

    /* Find the resource descriptor node corresponding to the index */

    ResourceNode = AcpiDmGetResourceNode (BufferNode, BitIndex);
    if (!ResourceNode)
    {
        return;
    }

    /* Translate the Index to a resource tag pathname */

    AcpiGetTagPathname (IndexOp, BufferNode, ResourceNode, BitIndex);
}
示例#6
0
void
AcpiDbDisplayMethodInfo (
    ACPI_PARSE_OBJECT       *StartOp)
{
    ACPI_WALK_STATE         *WalkState;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_PARSE_OBJECT       *RootOp;
    ACPI_PARSE_OBJECT       *Op;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  NumOps = 0;
    UINT32                  NumOperands = 0;
    UINT32                  NumOperators = 0;
    UINT32                  NumRemainingOps = 0;
    UINT32                  NumRemainingOperands = 0;
    UINT32                  NumRemainingOperators = 0;
    BOOLEAN                 CountRemaining = FALSE;


    WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList);
    if (!WalkState)
    {
        AcpiOsPrintf ("There is no method currently executing\n");
        return;
    }

    ObjDesc = WalkState->MethodDesc;
    Node    = WalkState->MethodNode;

    AcpiOsPrintf ("Currently executing control method is [%4.4s]\n",
            AcpiUtGetNodeName (Node));
    AcpiOsPrintf ("%X Arguments, SyncLevel = %X\n",
            (UINT32) ObjDesc->Method.ParamCount,
            (UINT32) ObjDesc->Method.SyncLevel);


    RootOp = StartOp;
    while (RootOp->Common.Parent)
    {
        RootOp = RootOp->Common.Parent;
    }

    Op = RootOp;

    while (Op)
    {
        if (Op == StartOp)
        {
            CountRemaining = TRUE;
        }

        NumOps++;
        if (CountRemaining)
        {
            NumRemainingOps++;
        }

        /* Decode the opcode */

        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
        switch (OpInfo->Class)
        {
        case AML_CLASS_ARGUMENT:

            if (CountRemaining)
            {
                NumRemainingOperands++;
            }

            NumOperands++;
            break;

        case AML_CLASS_UNKNOWN:

            /* Bad opcode or ASCII character */

            continue;

        default:

            if (CountRemaining)
            {
                NumRemainingOperators++;
            }

            NumOperators++;
            break;
        }

        Op = AcpiPsGetDepthNext (StartOp, Op);
    }

    AcpiOsPrintf (
        "Method contains:       %X AML Opcodes - %X Operators, %X Operands\n",
        NumOps, NumOperators, NumOperands);

    AcpiOsPrintf (
        "Remaining to execute:  %X AML Opcodes - %X Operators, %X Operands\n",
        NumRemainingOps, NumRemainingOperators, NumRemainingOperands);
}
示例#7
0
ACPI_STATUS
AcpiDbSecondPassParse (
    ACPI_PARSE_OBJECT       *Root)
{
    ACPI_PARSE_OBJECT       *Op = Root;
    ACPI_PARSE_OBJECT       *Method;
    ACPI_PARSE_OBJECT       *SearchOp;
    ACPI_PARSE_OBJECT       *StartOp;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  BaseAmlOffset;
    ACPI_WALK_STATE         *WalkState;


    ACPI_FUNCTION_ENTRY ();


    AcpiOsPrintf ("Pass two parse ....\n");

    while (Op)
    {
        if (Op->Common.AmlOpcode == AML_METHOD_OP)
        {
            Method = Op;

            /* Create a new walk state for the parse */

            WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
            if (!WalkState)
            {
                return (AE_NO_MEMORY);
            }

            /* Init the Walk State */

            WalkState->ParserState.Aml          =
            WalkState->ParserState.AmlStart     = Method->Named.Data;
            WalkState->ParserState.AmlEnd       =
            WalkState->ParserState.PkgEnd       = Method->Named.Data +
                                                  Method->Named.Length;
            WalkState->ParserState.StartScope   = Op;

            WalkState->DescendingCallback       = AcpiDsLoad1BeginOp;
            WalkState->AscendingCallback        = AcpiDsLoad1EndOp;

            /* Perform the AML parse */

            Status = AcpiPsParseAml (WalkState);

            BaseAmlOffset = (Method->Common.Value.Arg)->Common.AmlOffset + 1;
            StartOp = (Method->Common.Value.Arg)->Common.Next;
            SearchOp = StartOp;

            while (SearchOp)
            {
                SearchOp->Common.AmlOffset += BaseAmlOffset;
                SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
            }
        }

        if (Op->Common.AmlOpcode == AML_REGION_OP)
        {
            /* TBD: [Investigate] this isn't quite the right thing to do! */
            /*
             *
             * Method = (ACPI_DEFERRED_OP *) Op;
             * Status = AcpiPsParseAml (Op, Method->Body, Method->BodyLength);
             */
        }

        if (ACPI_FAILURE (Status))
        {
            break;
        }

        Op = AcpiPsGetDepthNext (Root, Op);
    }

    return (Status);
}
示例#8
0
static ACPI_STATUS
AcpiDmDeferredParse (
    ACPI_PARSE_OBJECT       *Op,
    UINT8                   *Aml,
    UINT32                  AmlLength)
{
    ACPI_WALK_STATE         *WalkState;
    ACPI_STATUS             Status;
    ACPI_PARSE_OBJECT       *SearchOp;
    ACPI_PARSE_OBJECT       *StartOp;
    UINT32                  BaseAmlOffset;
    ACPI_PARSE_OBJECT       *NewRootOp;
    ACPI_PARSE_OBJECT       *ExtraOp;


    ACPI_FUNCTION_TRACE (DmDeferredParse);


    if (!Aml || !AmlLength)
    {
        return_ACPI_STATUS (AE_OK);
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing deferred opcode %s [%4.4s]\n",
        Op->Common.AmlOpName, (char *) &Op->Named.Name));

    /* Need a new walk state to parse the AML */

    WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
    if (!WalkState)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml,
        AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Parse the AML for this deferred opcode */

    WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
    WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
    Status = AcpiPsParseAml (WalkState);

    /*
     * We need to update all of the AML offsets, since the parser thought
     * that the method began at offset zero. In reality, it began somewhere
     * within the ACPI table, at the BaseAmlOffset. Walk the entire tree that
     * was just created and update the AmlOffset in each Op.
     */
    BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1;
    StartOp = (Op->Common.Value.Arg)->Common.Next;
    SearchOp = StartOp;

    while (SearchOp)
    {
        SearchOp->Common.AmlOffset += BaseAmlOffset;
        SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
    }

    /*
     * For Buffer and Package opcodes, link the newly parsed subtree
     * into the main parse tree
     */
    switch (Op->Common.AmlOpcode)
    {
    case AML_BUFFER_OP:
    case AML_PACKAGE_OP:
    case AML_VAR_PACKAGE_OP:

        switch (Op->Common.AmlOpcode)
        {
        case AML_PACKAGE_OP:

            ExtraOp = Op->Common.Value.Arg;
            NewRootOp = ExtraOp->Common.Next;
            ACPI_FREE (ExtraOp);
            break;

        case AML_VAR_PACKAGE_OP:
        case AML_BUFFER_OP:
        default:

            NewRootOp = Op->Common.Value.Arg;
            break;
        }

        Op->Common.Value.Arg = NewRootOp->Common.Value.Arg;

        /* Must point all parents to the main tree */

        StartOp = Op;
        SearchOp = StartOp;
        while (SearchOp)
        {
            if (SearchOp->Common.Parent == NewRootOp)
            {
                SearchOp->Common.Parent = Op;
            }

            SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
        }

        ACPI_FREE (NewRootOp);
        break;

    default:

        break;
    }

    return_ACPI_STATUS (AE_OK);
}
示例#9
0
ACPI_STATUS
AcpiDmParseDeferredOps (
    ACPI_PARSE_OBJECT       *Root)
{
    const ACPI_OPCODE_INFO  *OpInfo;
    ACPI_PARSE_OBJECT       *Op = Root;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_ENTRY ();


    /* Traverse the entire parse tree */

    while (Op)
    {
        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
        if (!(OpInfo->Flags & AML_DEFER))
        {
            Op = AcpiPsGetDepthNext (Root, Op);
            continue;
        }

        /* Now we know we have a deferred opcode */

        switch (Op->Common.AmlOpcode)
        {
        case AML_METHOD_OP:
        case AML_BUFFER_OP:
        case AML_PACKAGE_OP:
        case AML_VAR_PACKAGE_OP:

            Status = AcpiDmDeferredParse (Op, Op->Named.Data, Op->Named.Length);
            if (ACPI_FAILURE (Status))
            {
                return (Status);
            }
            break;

        /* We don't need to do anything for these deferred opcodes */

        case AML_REGION_OP:
        case AML_DATA_REGION_OP:
        case AML_CREATE_QWORD_FIELD_OP:
        case AML_CREATE_DWORD_FIELD_OP:
        case AML_CREATE_WORD_FIELD_OP:
        case AML_CREATE_BYTE_FIELD_OP:
        case AML_CREATE_BIT_FIELD_OP:
        case AML_CREATE_FIELD_OP:
        case AML_BANK_FIELD_OP:

            break;

        default:

            ACPI_ERROR ((AE_INFO, "Unhandled deferred AML opcode [0x%.4X]",
                 Op->Common.AmlOpcode));
            break;
        }

        Op = AcpiPsGetDepthNext (Root, Op);
    }

    return (AE_OK);
}
示例#10
0
static ACPI_STATUS
AcpiDmDescendingOp (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_OP_WALK_INFO       *Info = Context;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  Name;
    ACPI_PARSE_OBJECT       *NextOp;


    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
    {
        /* Ignore this op -- it was handled elsewhere */

        return (AE_CTRL_DEPTH);
    }

    /* Level 0 is at the Definition Block level */

    if (Level == 0)
    {
        /* In verbose mode, print the AML offset, opcode and depth count */

        if (Info->WalkState)
        {
            VERBOSE_PRINT ((DB_FULL_OP_INFO,
                (Info->WalkState->MethodNode ?
                    Info->WalkState->MethodNode->Name.Ascii : "   "),
                Op->Common.AmlOffset, (UINT32) Op->Common.AmlOpcode));
        }

        if (Op->Common.AmlOpcode == AML_SCOPE_OP)
        {
            /* This is the beginning of the Definition Block */

            AcpiOsPrintf ("{\n");

            /* Emit all External() declarations here */

            AcpiDmEmitExternals ();
            return (AE_OK);
        }
    }
    else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
             (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMLIST)) &&
             (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    {
            /*
             * This is a first-level element of a term list,
             * indent a new line
             */
            switch (Op->Common.AmlOpcode)
            {
            case AML_NOOP_OP:
                /*
                 * Optionally just ignore this opcode. Some tables use
                 * NoOp opcodes for "padding" out packages that the BIOS
                 * changes dynamically. This can leave hundreds or
                 * thousands of NoOp opcodes that if disassembled,
                 * cannot be compiled because they are syntactically
                 * incorrect.
                 */
                if (AcpiGbl_IgnoreNoopOperator)
                {
                    Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                    return (AE_OK);
                }

                /* Fallthrough */

            default:

                AcpiDmIndent (Level);
                break;
            }

            Info->LastLevel = Level;
            Info->Count = 0;
    }

    /*
     * This is an inexpensive mechanism to try and keep lines from getting
     * too long. When the limit is hit, start a new line at the previous
     * indent plus one. A better but more expensive mechanism would be to
     * keep track of the current column.
     */
    Info->Count++;
    if (Info->Count /* +Info->LastLevel */ > 12)
    {
        Info->Count = 0;
        AcpiOsPrintf ("\n");
        AcpiDmIndent (Info->LastLevel + 1);
    }

    /* If ASL+ is enabled, check for a C-style operator */

    if (AcpiDmCheckForSymbolicOpcode (Op, Info))
    {
        return (AE_OK);
    }

    /* Print the opcode name */

    AcpiDmDisassembleOneOp (NULL, Info, Op);

    if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
        (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
    {
        return (AE_OK);
    }

    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
        (Op->Common.AmlOpcode == AML_RETURN_OP))
    {
        Info->Level--;
    }

    /* Start the opcode argument list if necessary */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);

    if ((OpInfo->Flags & AML_HAS_ARGS) ||
        (Op->Common.AmlOpcode == AML_EVENT_OP))
    {
        /* This opcode has an argument list */

        if (AcpiDmBlockType (Op) & BLOCK_PAREN)
        {
            AcpiOsPrintf (" (");
        }

        /* If this is a named opcode, print the associated name value */

        if (OpInfo->Flags & AML_NAMED)
        {
            switch (Op->Common.AmlOpcode)
            {
            case AML_ALIAS_OP:

                NextOp = AcpiPsGetDepthNext (NULL, Op);
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                AcpiDmNamestring (NextOp->Common.Value.Name);
                AcpiOsPrintf (", ");

                /*lint -fallthrough */

            default:

                Name = AcpiPsGetName (Op);
                if (Op->Named.Path)
                {
                    AcpiDmNamestring ((char *) Op->Named.Path);
                }
                else
                {
                    AcpiDmDumpName (Name);
                }

                if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
                {
                    if (AcpiGbl_DbOpt_Verbose)
                    {
                        (void) AcpiPsDisplayObjectPathname (NULL, Op);
                    }
                }
                break;
            }

            switch (Op->Common.AmlOpcode)
            {
            case AML_METHOD_OP:

                AcpiDmMethodFlags (Op);
                AcpiOsPrintf (")");

                /* Emit description comment for Method() with a predefined ACPI name */

                AcpiDmPredefinedDescription (Op);
                break;

            case AML_NAME_OP:

                /* Check for _HID and related EISAID() */

                AcpiDmCheckForHardwareId (Op);
                AcpiOsPrintf (", ");
                break;

            case AML_REGION_OP:

                AcpiDmRegionFlags (Op);
                break;

            case AML_POWER_RES_OP:

                /* Mark the next two Ops as part of the parameter list */

                AcpiOsPrintf (", ");
                NextOp = AcpiPsGetDepthNext (NULL, Op);
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;

                NextOp = NextOp->Common.Next;
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
                return (AE_OK);

            case AML_PROCESSOR_OP:

                /* Mark the next three Ops as part of the parameter list */

                AcpiOsPrintf (", ");
                NextOp = AcpiPsGetDepthNext (NULL, Op);
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;

                NextOp = NextOp->Common.Next;
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;

                NextOp = NextOp->Common.Next;
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
                return (AE_OK);

            case AML_MUTEX_OP:
            case AML_DATA_REGION_OP:

                AcpiOsPrintf (", ");
                return (AE_OK);

            case AML_EVENT_OP:
            case AML_ALIAS_OP:

                return (AE_OK);

            case AML_SCOPE_OP:
            case AML_DEVICE_OP:
            case AML_THERMAL_ZONE_OP:

                AcpiOsPrintf (")");
                break;

            default:

                AcpiOsPrintf ("*** Unhandled named opcode %X\n",
                    Op->Common.AmlOpcode);
                break;
            }
        }

        else switch (Op->Common.AmlOpcode)
        {
        case AML_FIELD_OP:
        case AML_BANK_FIELD_OP:
        case AML_INDEX_FIELD_OP:

            Info->BitOffset = 0;

            /* Name of the parent OperationRegion */

            NextOp = AcpiPsGetDepthNext (NULL, Op);
            AcpiDmNamestring (NextOp->Common.Value.Name);
            AcpiOsPrintf (", ");
            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;

            switch (Op->Common.AmlOpcode)
            {
            case AML_BANK_FIELD_OP:

                /* Namestring - Bank Name */

                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
                AcpiDmNamestring (NextOp->Common.Value.Name);
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                AcpiOsPrintf (", ");

                /*
                 * Bank Value. This is a TermArg in the middle of the parameter
                 * list, must handle it here.
                 *
                 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMLIST
                 * eliminates newline in the output.
                 */
                NextOp = NextOp->Common.Next;

                Info->Flags = ACPI_PARSEOP_PARAMLIST;
                AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
                    AcpiDmAscendingOp, Info);
                Info->Flags = 0;
                Info->Level = Level;

                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                AcpiOsPrintf (", ");
                break;

            case AML_INDEX_FIELD_OP:

                /* Namestring - Data Name */

                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
                AcpiDmNamestring (NextOp->Common.Value.Name);
                AcpiOsPrintf (", ");
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                break;

            default:

                break;
            }

            AcpiDmFieldFlags (NextOp);
            break;

        case AML_BUFFER_OP:

            /* The next op is the size parameter */

            NextOp = AcpiPsGetDepthNext (NULL, Op);
            if (!NextOp)
            {
                /* Single-step support */

                return (AE_OK);
            }

            if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
            {
                /*
                 * We have a resource list. Don't need to output
                 * the buffer size Op. Open up a new block
                 */
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                NextOp = NextOp->Common.Next;
                AcpiOsPrintf (")");

                /* Emit description comment for Name() with a predefined ACPI name */

                AcpiDmPredefinedDescription (Op->Asl.Parent);

                AcpiOsPrintf ("\n");
                AcpiDmIndent (Info->Level);
                AcpiOsPrintf ("{\n");
                return (AE_OK);
            }

            /* Normal Buffer, mark size as in the parameter list */

            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
            return (AE_OK);

        case AML_VAR_PACKAGE_OP:
        case AML_IF_OP:
        case AML_WHILE_OP:

            /* The next op is the size or predicate parameter */

            NextOp = AcpiPsGetDepthNext (NULL, Op);
            if (NextOp)
            {
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
            }
            return (AE_OK);

        case AML_PACKAGE_OP:

            /* The next op is the size parameter */

            NextOp = AcpiPsGetDepthNext (NULL, Op);
            if (NextOp)
            {
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMLIST;
            }
            return (AE_OK);

        case AML_MATCH_OP:

            AcpiDmMatchOp (Op);
            break;

        default:

            break;
        }

        if (AcpiDmBlockType (Op) & BLOCK_BRACE)
        {
            AcpiOsPrintf ("\n");
            AcpiDmIndent (Level);
            AcpiOsPrintf ("{\n");
        }
    }

    return (AE_OK);
}
示例#11
0
static ACPI_STATUS
AcpiDmDescendingOp (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_OP_WALK_INFO       *Info = Context;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  Name;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_PARSE_OBJECT       *NextOp2;
    UINT32                  AmlOffset;


    /* Determine which file this parse node is contained in. */

    if (AcpiGbl_CaptureComments)
    {
        ASL_CV_LABEL_FILENODE (Op);

        if (Level != 0 && ASL_CV_FILE_HAS_SWITCHED (Op))
        {
            ASL_CV_SWITCH_FILES (Level, Op);
        }

        /* If this parse node has regular comments, print them here. */

        ASL_CV_PRINT_ONE_COMMENT (Op, AML_COMMENT_STANDARD, NULL, Level);
    }

    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);

    /* Listing support to dump the AML code after the ASL statement */

    if (AcpiGbl_DmOpt_Listing)
    {
        /* We only care about these classes of objects */

        if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) ||
            (OpInfo->Class == AML_CLASS_CONTROL) ||
            (OpInfo->Class == AML_CLASS_CREATE) ||
            ((OpInfo->Class == AML_CLASS_EXECUTE) && (!Op->Common.Next)))
        {
            if (AcpiGbl_DmOpt_Listing && Info->PreviousAml)
            {
                /* Dump the AML byte code for the previous Op */

                if (Op->Common.Aml > Info->PreviousAml)
                {
                    AcpiOsPrintf ("\n");
                    AcpiUtDumpBuffer (
                        (Info->StartAml + Info->AmlOffset),
                        (Op->Common.Aml - Info->PreviousAml),
                        DB_BYTE_DISPLAY, Info->AmlOffset);
                    AcpiOsPrintf ("\n");
                }

                Info->AmlOffset = (Op->Common.Aml - Info->StartAml);
            }

            Info->PreviousAml = Op->Common.Aml;
        }
    }

    if (Op->Common.DisasmFlags & ACPI_PARSEOP_IGNORE)
    {
        /* Ignore this op -- it was handled elsewhere */

        return (AE_CTRL_DEPTH);
    }

    if (Op->Common.DisasmOpcode == ACPI_DASM_IGNORE_SINGLE)
    {
        /* Ignore this op, but not it's children */

        return (AE_OK);
    }

    if (Op->Common.AmlOpcode == AML_IF_OP)
    {
        NextOp = AcpiPsGetDepthNext (NULL, Op);
        if (NextOp)
        {
            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;

            /* Don't emit the actual embedded externals unless asked */

            if (!AcpiGbl_DmEmitExternalOpcodes)
            {
                /*
                 * A Zero predicate indicates the possibility of one or more
                 * External() opcodes within the If() block.
                 */
                if (NextOp->Common.AmlOpcode == AML_ZERO_OP)
                {
                    NextOp2 = NextOp->Common.Next;

                    if (NextOp2 &&
                        (NextOp2->Common.AmlOpcode == AML_EXTERNAL_OP))
                    {
                        /* Ignore the If 0 block and all children */

                        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                        return (AE_CTRL_DEPTH);
                    }
                }
            }
        }
    }

    /* Level 0 is at the Definition Block level */

    if (Level == 0)
    {
        /* In verbose mode, print the AML offset, opcode and depth count */

        if (Info->WalkState)
        {
            AmlOffset = (UINT32) ACPI_PTR_DIFF (Op->Common.Aml,
                Info->WalkState->ParserState.AmlStart);
            if (AcpiGbl_DmOpt_Verbose)
            {
                if (AcpiGbl_CmSingleStep)
                {
                    AcpiOsPrintf ("%5.5X/%4.4X: ",
                        AmlOffset, (UINT32) Op->Common.AmlOpcode);
                }
                else
                {
                    AcpiOsPrintf ("AML Offset %5.5X, Opcode %4.4X: ",
                        AmlOffset, (UINT32) Op->Common.AmlOpcode);
                }
            }
        }

        if (Op->Common.AmlOpcode == AML_SCOPE_OP)
        {
            /* This is the beginning of the Definition Block */

            AcpiOsPrintf ("{\n");

            /* Emit all External() declarations here */

            if (!AcpiGbl_DmEmitExternalOpcodes)
            {
                AcpiDmEmitExternals ();
            }

            return (AE_OK);
        }
    }
    else if ((AcpiDmBlockType (Op->Common.Parent) & BLOCK_BRACE) &&
         (!(Op->Common.DisasmFlags & ACPI_PARSEOP_PARAMETER_LIST)) &&
         (!(Op->Common.DisasmFlags & ACPI_PARSEOP_ELSEIF)) &&
         (Op->Common.AmlOpcode != AML_INT_BYTELIST_OP))
    {
        /*
         * This is a first-level element of a term list,
         * indent a new line
         */
        switch (Op->Common.AmlOpcode)
        {
        case AML_NOOP_OP:
            /*
             * Optionally just ignore this opcode. Some tables use
             * NoOp opcodes for "padding" out packages that the BIOS
             * changes dynamically. This can leave hundreds or
             * thousands of NoOp opcodes that if disassembled,
             * cannot be compiled because they are syntactically
             * incorrect.
             */
            if (AcpiGbl_IgnoreNoopOperator)
            {
                Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                return (AE_OK);
            }

            /* Fallthrough */

        default:

            AcpiDmIndent (Level);
            break;
        }

        Info->LastLevel = Level;
        Info->Count = 0;
    }

    /*
     * This is an inexpensive mechanism to try and keep lines from getting
     * too long. When the limit is hit, start a new line at the previous
     * indent plus one. A better but more expensive mechanism would be to
     * keep track of the current column.
     */
    Info->Count++;
    if (Info->Count /* +Info->LastLevel */ > 12)
    {
        Info->Count = 0;
        AcpiOsPrintf ("\n");
        AcpiDmIndent (Info->LastLevel + 1);
    }

    /* If ASL+ is enabled, check for a C-style operator */

    if (AcpiDmCheckForSymbolicOpcode (Op, Info))
    {
        return (AE_OK);
    }

    /* Print the opcode name */

    AcpiDmDisassembleOneOp (NULL, Info, Op);

    if ((Op->Common.DisasmOpcode == ACPI_DASM_LNOT_PREFIX) ||
        (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP))
    {
        return (AE_OK);
    }

    if ((Op->Common.AmlOpcode == AML_NAME_OP) ||
        (Op->Common.AmlOpcode == AML_RETURN_OP))
    {
        Info->Level--;
    }

    if (Op->Common.AmlOpcode == AML_EXTERNAL_OP)
    {
        Op->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
        return (AE_CTRL_DEPTH);
    }

    /* Start the opcode argument list if necessary */

    if ((OpInfo->Flags & AML_HAS_ARGS) ||
        (Op->Common.AmlOpcode == AML_EVENT_OP))
    {
        /* This opcode has an argument list */

        if (AcpiDmBlockType (Op) & BLOCK_PAREN)
        {
            AcpiOsPrintf (" (");
            if (!(AcpiDmBlockType (Op) & BLOCK_BRACE))
            {
                ASL_CV_PRINT_ONE_COMMENT (Op, AMLCOMMENT_INLINE, " ", 0);
            }
        }

        /* If this is a named opcode, print the associated name value */

        if (OpInfo->Flags & AML_NAMED)
        {
            switch (Op->Common.AmlOpcode)
            {
            case AML_ALIAS_OP:

                NextOp = AcpiPsGetDepthNext (NULL, Op);
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                AcpiDmNamestring (NextOp->Common.Value.Name);
                AcpiOsPrintf (", ");

                /*lint -fallthrough */

            default:

                Name = AcpiPsGetName (Op);
                if (Op->Named.Path)
                {
                    AcpiDmNamestring (Op->Named.Path);
                }
                else
                {
                    AcpiDmDumpName (Name);
                }

                if (Op->Common.AmlOpcode != AML_INT_NAMEDFIELD_OP)
                {
                    if (AcpiGbl_DmOpt_Verbose)
                    {
                        (void) AcpiPsDisplayObjectPathname (NULL, Op);
                    }
                }
                break;
            }

            switch (Op->Common.AmlOpcode)
            {
            case AML_METHOD_OP:

                AcpiDmMethodFlags (Op);
                ASL_CV_CLOSE_PAREN (Op, Level);

                /* Emit description comment for Method() with a predefined ACPI name */

                AcpiDmPredefinedDescription (Op);
                break;

            case AML_NAME_OP:

                /* Check for _HID and related EISAID() */

                AcpiDmCheckForHardwareId (Op);
                AcpiOsPrintf (", ");
                ASL_CV_PRINT_ONE_COMMENT (Op, AML_NAMECOMMENT, NULL, 0);
                break;

            case AML_REGION_OP:

                AcpiDmRegionFlags (Op);
                break;

            case AML_POWER_RESOURCE_OP:

                /* Mark the next two Ops as part of the parameter list */

                AcpiOsPrintf (", ");
                NextOp = AcpiPsGetDepthNext (NULL, Op);
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;

                NextOp = NextOp->Common.Next;
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
                return (AE_OK);

            case AML_PROCESSOR_OP:

                /* Mark the next three Ops as part of the parameter list */

                AcpiOsPrintf (", ");
                NextOp = AcpiPsGetDepthNext (NULL, Op);
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;

                NextOp = NextOp->Common.Next;
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;

                NextOp = NextOp->Common.Next;
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
                return (AE_OK);

            case AML_MUTEX_OP:
            case AML_DATA_REGION_OP:

                AcpiOsPrintf (", ");
                return (AE_OK);

            case AML_EVENT_OP:
            case AML_ALIAS_OP:

                return (AE_OK);

            case AML_SCOPE_OP:
            case AML_DEVICE_OP:
            case AML_THERMAL_ZONE_OP:

                ASL_CV_CLOSE_PAREN (Op, Level);
                break;

            default:

                AcpiOsPrintf ("*** Unhandled named opcode %X\n",
                    Op->Common.AmlOpcode);
                break;
            }
        }

        else switch (Op->Common.AmlOpcode)
        {
        case AML_FIELD_OP:
        case AML_BANK_FIELD_OP:
        case AML_INDEX_FIELD_OP:

            Info->BitOffset = 0;

            /* Name of the parent OperationRegion */

            NextOp = AcpiPsGetDepthNext (NULL, Op);
            AcpiDmNamestring (NextOp->Common.Value.Name);
            AcpiOsPrintf (", ");
            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;

            switch (Op->Common.AmlOpcode)
            {
            case AML_BANK_FIELD_OP:

                /* Namestring - Bank Name */

                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
                AcpiDmNamestring (NextOp->Common.Value.Name);
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                AcpiOsPrintf (", ");

                /*
                 * Bank Value. This is a TermArg in the middle of the parameter
                 * list, must handle it here.
                 *
                 * Disassemble the TermArg parse tree. ACPI_PARSEOP_PARAMETER_LIST
                 * eliminates newline in the output.
                 */
                NextOp = NextOp->Common.Next;

                Info->Flags = ACPI_PARSEOP_PARAMETER_LIST;
                AcpiDmWalkParseTree (NextOp, AcpiDmDescendingOp,
                    AcpiDmAscendingOp, Info);
                Info->Flags = 0;
                Info->Level = Level;

                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                AcpiOsPrintf (", ");
                break;

            case AML_INDEX_FIELD_OP:

                /* Namestring - Data Name */

                NextOp = AcpiPsGetDepthNext (NULL, NextOp);
                AcpiDmNamestring (NextOp->Common.Value.Name);
                AcpiOsPrintf (", ");
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                break;

            default:

                break;
            }

            AcpiDmFieldFlags (NextOp);
            break;

        case AML_BUFFER_OP:

            /* The next op is the size parameter */

            NextOp = AcpiPsGetDepthNext (NULL, Op);
            if (!NextOp)
            {
                /* Single-step support */

                return (AE_OK);
            }

            if (Op->Common.DisasmOpcode == ACPI_DASM_RESOURCE)
            {
                /*
                 * We have a resource list. Don't need to output
                 * the buffer size Op. Open up a new block
                 */
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_IGNORE;
                NextOp = NextOp->Common.Next;
                ASL_CV_CLOSE_PAREN (Op, Level);

                /* Emit description comment for Name() with a predefined ACPI name */

                AcpiDmPredefinedDescription (Op->Asl.Parent);

                AcpiOsPrintf ("\n");
                AcpiDmIndent (Info->Level);
                AcpiOsPrintf ("{\n");
                return (AE_OK);
            }

            /* Normal Buffer, mark size as in the parameter list */

            NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
            return (AE_OK);

        case AML_IF_OP:
        case AML_VARIABLE_PACKAGE_OP:
        case AML_WHILE_OP:

            /* The next op is the size or predicate parameter */

            NextOp = AcpiPsGetDepthNext (NULL, Op);
            if (NextOp)
            {
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
            }
            return (AE_OK);

        case AML_PACKAGE_OP:

            /* The next op is the size parameter */

            NextOp = AcpiPsGetDepthNext (NULL, Op);
            if (NextOp)
            {
                NextOp->Common.DisasmFlags |= ACPI_PARSEOP_PARAMETER_LIST;
            }
            return (AE_OK);

        case AML_MATCH_OP:

            AcpiDmMatchOp (Op);
            break;

        default:

            break;
        }

        if (AcpiDmBlockType (Op) & BLOCK_BRACE)
        {
            AcpiOsPrintf ("\n");
            AcpiDmIndent (Level);
            AcpiOsPrintf ("{\n");
        }
    }

    return (AE_OK);
}