ACPI_PARSE_OBJECT *
AcpiPsGetArg (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Argn)
{
    ACPI_PARSE_OBJECT       *Arg = NULL;
    const ACPI_OPCODE_INFO  *OpInfo;


    ACPI_FUNCTION_ENTRY ();

/*
    if (Op->Common.AmlOpcode == AML_INT_CONNECTION_OP)
    {
        return (Op->Common.Value.Arg);
    }
*/
    /* Get the info structure for this opcode */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    if (OpInfo->Class == AML_CLASS_UNKNOWN)
    {
        /* Invalid opcode or ASCII character */

        return (NULL);
    }

    /* Check if this opcode requires argument sub-objects */

    if (!(OpInfo->Flags & AML_HAS_ARGS))
    {
        /* Has no linked argument objects */

        return (NULL);
    }

    /* Get the requested argument object */

    Arg = Op->Common.Value.Arg;
    while (Arg && Argn)
    {
        Argn--;
        Arg = Arg->Common.Next;
    }

    return (Arg);
}
Esempio n. 2
0
UINT32
AcpiDmListType (
    ACPI_PARSE_OBJECT       *Op)
{
    const ACPI_OPCODE_INFO  *OpInfo;


    if (!Op)
    {
        return (BLOCK_NONE);
    }

    switch (Op->Common.AmlOpcode)
    {

    case AML_ELSE_OP:
    case AML_METHOD_OP:
    case AML_DEVICE_OP:
    case AML_SCOPE_OP:
    case AML_POWER_RES_OP:
    case AML_PROCESSOR_OP:
    case AML_THERMAL_ZONE_OP:
    case AML_IF_OP:
    case AML_WHILE_OP:
    case AML_FIELD_OP:
    case AML_INDEX_FIELD_OP:
    case AML_BANK_FIELD_OP:

        return (BLOCK_NONE);

    case AML_BUFFER_OP:
    case AML_PACKAGE_OP:
    case AML_VAR_PACKAGE_OP:

        return (BLOCK_COMMA_LIST);

    default:

        OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
        if (OpInfo->Flags & AML_HAS_ARGS)
        {
            return (BLOCK_COMMA_LIST);
        }

        return (BLOCK_NONE);
    }
}
Esempio n. 3
0
static UINT32
AcpiDmInspectPossibleArgs (
    UINT32                  CurrentOpArgCount,
    UINT32                  TargetCount,
    ACPI_PARSE_OBJECT       *Op)
{
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  i;
    UINT32                  Last = 0;
    UINT32                  Lookahead;


    Lookahead = (ACPI_METHOD_NUM_ARGS + TargetCount) - CurrentOpArgCount;

    /* Lookahead for the maximum number of possible arguments */

    for (i = 0; i < Lookahead; i++)
    {
        if (!Op)
        {
            break;
        }

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

        /*
         * Any one of these operators is "very probably" not a method arg
         */
        if ((Op->Common.AmlOpcode == AML_STORE_OP) ||
            (Op->Common.AmlOpcode == AML_NOTIFY_OP))
        {
            break;
        }

        if ((OpInfo->Class != AML_CLASS_EXECUTE) &&
            (OpInfo->Class != AML_CLASS_CONTROL))
        {
            Last = i+1;
        }

        Op = Op->Common.Next;
    }

    return (Last);
}
Esempio n. 4
0
static ACPI_STATUS
XfNamespaceLocateEnd (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
    const ACPI_OPCODE_INFO  *OpInfo;


    ACPI_FUNCTION_TRACE (XfNamespaceLocateEnd);


    /* We are only interested in opcodes that have an associated name */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    if (!(OpInfo->Flags & AML_NAMED))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Not interested in name references, we did not open a scope for them */

    if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
        (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
        (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
        (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Pop the scope stack if necessary */

    if (AcpiNsOpensScope (AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode)))
    {

        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
            "%s: Popping scope for Op %p\n",
            AcpiUtGetTypeName (OpInfo->ObjectType), Op));

        (void) AcpiDsScopeStackPop (WalkState);
    }

    return_ACPI_STATUS (AE_OK);
}
Esempio n. 5
0
void
AcpiDbDumpParserDescriptor (
    ACPI_PARSE_OBJECT       *Op)
{
    const ACPI_OPCODE_INFO  *Info;


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

    AcpiOsPrintf ("Parser Op Descriptor:\n");
    AcpiOsPrintf ("%20.20s : %4.4X\n", "Opcode", Op->Common.AmlOpcode);

    ACPI_DEBUG_ONLY_MEMBERS (AcpiOsPrintf ("%20.20s : %s\n", "Opcode Name", Info->Name));

    AcpiOsPrintf ("%20.20s : %p\n", "Value/ArgList", Op->Common.Value.Arg);
    AcpiOsPrintf ("%20.20s : %p\n", "Parent", Op->Common.Parent);
    AcpiOsPrintf ("%20.20s : %p\n", "NextOp", Op->Common.Next);
}
Esempio n. 6
0
char *
AcpiPsGetOpcodeName (
    UINT16                  Opcode)
{
#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT)

    const ACPI_OPCODE_INFO  *Op;


    Op = AcpiPsGetOpcodeInfo (Opcode);

    /* Always guaranteed to return a valid pointer */

    return (Op->Name);

#else
    return ("OpcodeName unavailable");

#endif
}
Esempio n. 7
0
static ACPI_PARSE_OBJECT *
LkGetNameOp (
    ACPI_PARSE_OBJECT       *Op)
{
    const ACPI_OPCODE_INFO  *OpInfo;
    ACPI_PARSE_OBJECT       *NameOp = Op;


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


    /* Get the NamePath from the appropriate place */

    if (OpInfo->Flags & AML_NAMED)
    {
        /* For nearly all NAMED operators, the name reference is the first child */

        NameOp = Op->Asl.Child;
        if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
        {
            /*
             * ALIAS is the only oddball opcode, the name declaration
             * (alias name) is the second operand
             */
            NameOp = Op->Asl.Child->Asl.Next;
        }
    }
    else if (OpInfo->Flags & AML_CREATE)
    {
        /* Name must appear as the last parameter */

        NameOp = Op->Asl.Child;
        while (!(NameOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
        {
            NameOp = NameOp->Asl.Next;
        }
    }

    return (NameOp);
}
Esempio n. 8
0
static void
MtCheckNamedObjectInMethod (
    ACPI_PARSE_OBJECT       *Op,
    ASL_METHOD_INFO         *MethodInfo)
{
    const ACPI_OPCODE_INFO  *OpInfo;


    /* We don't care about actual method declarations or scopes */

    if ((Op->Asl.AmlOpcode == AML_METHOD_OP) ||
        (Op->Asl.AmlOpcode == AML_SCOPE_OP))
    {
        return;
    }

    /* Determine if we are creating a named object */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    if (OpInfo->Class == AML_CLASS_NAMED_OBJECT)
    {
        /*
         * If we have a named object created within a non-serialized method,
         * emit a remark that the method should be serialized.
         *
         * Reason: If a thread blocks within the method for any reason, and
         * another thread enters the method, the method will fail because an
         * attempt will be made to create the same object twice.
         */
        if (MethodInfo && !MethodInfo->ShouldBeSerialized)
        {
            AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op,
                "due to creation of named objects within");

            /* Emit message only ONCE per method */

            MethodInfo->ShouldBeSerialized = TRUE;
        }
    }
}
Esempio n. 9
0
static ACPI_STATUS
AcpiDmResourceDescendingOp (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_OP_WALK_INFO       *Info = Context;
    const ACPI_OPCODE_INFO  *OpInfo;
    ACPI_WALK_STATE         *WalkState;
    ACPI_OBJECT_TYPE        ObjectType;
    ACPI_STATUS             Status;


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

    /* Open new scope if necessary */

    ObjectType = OpInfo->ObjectType;
    if (AcpiNsOpensScope (ObjectType))
    {
        if (Op->Common.Node)
        {

            Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState);
            if (ACPI_FAILURE (Status))
            {
                return (Status);
            }
        }
    }

    /*
     * Check if this operator contains a reference to a resource descriptor.
     * If so, convert the reference into a symbolic reference.
     */
    AcpiDmCheckResourceReference (Op, WalkState);
    return (AE_OK);
}
Esempio n. 10
0
static ACPI_STATUS
AcpiDmCommonAscendingOp (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_OP_WALK_INFO       *Info = Context;
    const ACPI_OPCODE_INFO  *OpInfo;
    ACPI_OBJECT_TYPE        ObjectType;


    /* Close scope if necessary */

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

    if (AcpiNsOpensScope (ObjectType))
    {
        (void) AcpiDsScopeStackPop (Info->WalkState);
    }

    return (AE_OK);
}
Esempio n. 11
0
ACPI_STATUS
AcpiDsBuildInternalObject (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (DsBuildInternalObject);


    *ObjDescPtr = NULL;
    if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    {
        /*
         * This is a named object reference. If this name was
         * previously looked up in the namespace, it was stored in
         * this op. Otherwise, go ahead and look it up now
         */
        if (!Op->Common.Node)
        {
            /* Check if we are resolving a named reference within a package */

            if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
                (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
            {
                /*
                 * We won't resolve package elements here, we will do this
                 * after all ACPI tables are loaded into the namespace. This
                 * behavior supports both forward references to named objects
                 * and external references to objects in other tables.
                 */
                goto CreateNewObject;
            }
            else
            {
                Status = AcpiNsLookup (WalkState->ScopeInfo,
                    Op->Common.Value.String,
                    ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                    ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
                    ACPI_CAST_INDIRECT_PTR (
                        ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
                if (ACPI_FAILURE (Status))
                {
                    ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
                        Op->Common.Value.String, Status);
                    return_ACPI_STATUS (Status);
                }
            }
        }
    }

CreateNewObject:

    /* Create and init a new internal ACPI object */

    ObjDesc = AcpiUtCreateInternalObject (
        (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitObjectFromOp (
        WalkState, Op, Op->Common.AmlOpcode, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ObjDesc);
        return_ACPI_STATUS (Status);
    }

    /*
     * Handling for unresolved package reference elements.
     * These are elements that are namepaths.
     */
    if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
        (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
    {
        ObjDesc->Reference.Resolved = TRUE;

        if ((Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
            !ObjDesc->Reference.Node)
        {
            /*
             * Name was unresolved above.
             * Get the prefix node for later lookup
             */
            ObjDesc->Reference.Node = WalkState->ScopeInfo->Scope.Node;
            ObjDesc->Reference.Aml = Op->Common.Aml;
            ObjDesc->Reference.Resolved = FALSE;
        }
    }

    *ObjDescPtr = ObjDesc;
    return_ACPI_STATUS (Status);
}
Esempio n. 12
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);
}
Esempio n. 13
0
static ACPI_STATUS
OpcAmlCheckForConstant (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState = Context;


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

    DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ",
                Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName);

    /*
     * These opcodes do not appear in the OpcodeInfo table, but
     * they represent constants, so abort the constant walk now.
     */
    if ((WalkState->Opcode == AML_RAW_DATA_BYTE) ||
        (WalkState->Opcode == AML_RAW_DATA_WORD) ||
        (WalkState->Opcode == AML_RAW_DATA_DWORD) ||
        (WalkState->Opcode == AML_RAW_DATA_QWORD))
    {
        WalkState->WalkType = ACPI_WALK_CONST_OPTIONAL;
        return (AE_TYPE);
    }

    if (!(WalkState->OpInfo->Flags & AML_CONSTANT))
    {
        /* The opcode is not a Type 3/4/5 opcode */

        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
        {
            DbgPrint (ASL_PARSE_OUTPUT,
                "**** Valid Target, cannot reduce ****\n");
        }
        else
        {
            DbgPrint (ASL_PARSE_OUTPUT,
                "**** Not a Type 3/4/5 opcode ****\n");
        }

        if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL)
        {
            /*
             * We are looking at at normal expression to see if it can be
             * reduced. It can't. No error
             */
            return (AE_TYPE);
        }

        /*
         * This is an expression that MUST reduce to a constant, and it
         * can't be reduced. This is an error
         */
        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
        {
            AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op,
                Op->Asl.ParseOpName);
        }
        else
        {
            AslError (ASL_ERROR, ASL_MSG_INVALID_CONSTANT_OP, Op,
                Op->Asl.ParseOpName);
        }

        return (AE_TYPE);
    }

    /* Debug output */

    DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345");

    if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    {
        DbgPrint (ASL_PARSE_OUTPUT, " TARGET");
    }
    if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
    {
        DbgPrint (ASL_PARSE_OUTPUT, " TERMARG");
    }

    DbgPrint (ASL_PARSE_OUTPUT, "\n");
    return (AE_OK);
}
Esempio n. 14
0
static ACPI_STATUS
AcpiPsCompleteOp (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       **Op,
    ACPI_STATUS             Status)
{
    ACPI_STATUS             Status2;


    ACPI_FUNCTION_TRACE_PTR (PsCompleteOp, WalkState);


    /*
     * Finished one argument of the containing scope
     */
    WalkState->ParserState.Scope->ParseScope.ArgCount--;

    /* Close this Op (will result in parse subtree deletion) */

    Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
    if (ACPI_FAILURE (Status2))
    {
        return_ACPI_STATUS (Status2);
    }

    *Op = NULL;

    switch (Status)
    {
    case AE_OK:
        break;


    case AE_CTRL_TRANSFER:

        /* We are about to transfer to a called method */

        WalkState->PrevOp = NULL;
        WalkState->PrevArgTypes = WalkState->ArgTypes;
        return_ACPI_STATUS (Status);


    case AE_CTRL_END:

        AcpiPsPopScope (&(WalkState->ParserState), Op,
            &WalkState->ArgTypes, &WalkState->ArgCount);

        if (*Op)
        {
            WalkState->Op = *Op;
            WalkState->OpInfo = AcpiPsGetOpcodeInfo ((*Op)->Common.AmlOpcode);
            WalkState->Opcode = (*Op)->Common.AmlOpcode;

            Status = WalkState->AscendingCallback (WalkState);
            Status = AcpiPsNextParseState (WalkState, *Op, Status);

            Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
            if (ACPI_FAILURE (Status2))
            {
                return_ACPI_STATUS (Status2);
            }
        }

        Status = AE_OK;
        break;


    case AE_CTRL_BREAK:
    case AE_CTRL_CONTINUE:

        /* Pop off scopes until we find the While */

        while (!(*Op) || ((*Op)->Common.AmlOpcode != AML_WHILE_OP))
        {
            AcpiPsPopScope (&(WalkState->ParserState), Op,
                &WalkState->ArgTypes, &WalkState->ArgCount);
        }

        /* Close this iteration of the While loop */

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

        Status = WalkState->AscendingCallback (WalkState);
        Status = AcpiPsNextParseState (WalkState, *Op, Status);

        Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
        if (ACPI_FAILURE (Status2))
        {
            return_ACPI_STATUS (Status2);
        }

        Status = AE_OK;
        break;


    case AE_CTRL_TERMINATE:

        /* Clean up */
        do
        {
            if (*Op)
            {
                Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
                if (ACPI_FAILURE (Status2))
                {
                    return_ACPI_STATUS (Status2);
                }

                AcpiUtDeleteGenericState (
                    AcpiUtPopGenericState (&WalkState->ControlState));
            }

            AcpiPsPopScope (&(WalkState->ParserState), Op,
                &WalkState->ArgTypes, &WalkState->ArgCount);

        } while (*Op);

        return_ACPI_STATUS (AE_OK);


    default:  /* All other non-AE_OK status */

        do
        {
            if (*Op)
            {
                Status2 = AcpiPsCompleteThisOp (WalkState, *Op);
                if (ACPI_FAILURE (Status2))
                {
                    return_ACPI_STATUS (Status2);
                }
            }

            AcpiPsPopScope (&(WalkState->ParserState), Op,
                &WalkState->ArgTypes, &WalkState->ArgCount);

        } while (*Op);


#if 0
        /*
         * TBD: Cleanup parse ops on error
         */
        if (*Op == NULL)
        {
            AcpiPsPopScope (ParserState, Op,
                &WalkState->ArgTypes, &WalkState->ArgCount);
        }
#endif
        WalkState->PrevOp = NULL;
        WalkState->PrevArgTypes = WalkState->ArgTypes;
        return_ACPI_STATUS (Status);
    }

    /* This scope complete? */

    if (AcpiPsHasCompletedScope (&(WalkState->ParserState)))
    {
        AcpiPsPopScope (&(WalkState->ParserState), Op,
            &WalkState->ArgTypes, &WalkState->ArgCount);
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *Op));
    }
    else
    {
        *Op = NULL;
    }

    return_ACPI_STATUS (AE_OK);
}
Esempio n. 15
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);
}
Esempio n. 16
0
static ACPI_STATUS
AcpiPsCreateOp (
    ACPI_WALK_STATE         *WalkState,
    UINT8                   *AmlOpStart,
    ACPI_PARSE_OBJECT       **NewOp)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_PARSE_OBJECT       *Op;
    ACPI_PARSE_OBJECT       *NamedOp = NULL;
    ACPI_PARSE_OBJECT       *ParentScope;
    UINT8                   ArgumentCount;
    const ACPI_OPCODE_INFO  *OpInfo;


    ACPI_FUNCTION_TRACE_PTR (PsCreateOp, WalkState);


    Status = AcpiPsGetAmlOpcode (WalkState);
    if (Status == AE_CTRL_PARSE_CONTINUE)
    {
        return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);
    }

    /* Create Op structure and append to parent's argument list */

    WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);
    Op = AcpiPsAllocOp (WalkState->Opcode);
    if (!Op)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    if (WalkState->OpInfo->Flags & AML_NAMED)
    {
        Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp);
        AcpiPsFreeOp (Op);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

        *NewOp = NamedOp;
        return_ACPI_STATUS (AE_OK);
    }

    /* Not a named opcode, just allocate Op and append to parent */

    if (WalkState->OpInfo->Flags & AML_CREATE)
    {
        /*
         * Backup to beginning of CreateXXXfield declaration
         * BodyLength is unknown until we parse the body
         */
        Op->Named.Data = AmlOpStart;
        Op->Named.Length = 0;
    }

    if (WalkState->Opcode == AML_BANK_FIELD_OP)
    {
        /*
         * Backup to beginning of BankField declaration
         * BodyLength is unknown until we parse the body
         */
        Op->Named.Data = AmlOpStart;
        Op->Named.Length = 0;
    }

    ParentScope = AcpiPsGetParentScope (&(WalkState->ParserState));
    AcpiPsAppendArg (ParentScope, Op);

    if (ParentScope)
    {
        OpInfo = AcpiPsGetOpcodeInfo (ParentScope->Common.AmlOpcode);
        if (OpInfo->Flags & AML_HAS_TARGET)
        {
            ArgumentCount = AcpiPsGetArgumentCount (OpInfo->Type);
            if (ParentScope->Common.ArgListLength > ArgumentCount)
            {
                Op->Common.Flags |= ACPI_PARSEOP_TARGET;
            }
        }
        else if (ParentScope->Common.AmlOpcode == AML_INCREMENT_OP)
        {
            Op->Common.Flags |= ACPI_PARSEOP_TARGET;
        }
    }

    if (WalkState->DescendingCallback != NULL)
    {
        /*
         * Find the object. This will either insert the object into
         * the namespace or simply look it up
         */
        WalkState->Op = *NewOp = Op;

        Status = WalkState->DescendingCallback (WalkState, &Op);
        Status = AcpiPsNextParseState (WalkState, Op, Status);
        if (Status == AE_CTRL_PENDING)
        {
            Status = AE_CTRL_PARSE_PENDING;
        }
    }

    return_ACPI_STATUS (Status);
}
Esempio n. 17
0
static ACPI_STATUS
AcpiPsGetArguments (
    ACPI_WALK_STATE         *WalkState,
    UINT8                   *AmlOpStart,
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_PARSE_OBJECT       *Arg = NULL;
    const ACPI_OPCODE_INFO  *OpInfo;


    ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState);


    switch (Op->Common.AmlOpcode)
    {
    case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
    case AML_WORD_OP:       /* AML_WORDDATA_ARG */
    case AML_DWORD_OP:      /* AML_DWORDATA_ARG */
    case AML_QWORD_OP:      /* AML_QWORDATA_ARG */
    case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */

        /* Fill in constant or string argument directly */

        AcpiPsGetNextSimpleArg (&(WalkState->ParserState),
            GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), Op);
        break;

    case AML_INT_NAMEPATH_OP:   /* AML_NAMESTRING_ARG */

        Status = AcpiPsGetNextNamepath (WalkState, &(WalkState->ParserState), Op, 1);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

        WalkState->ArgTypes = 0;
        break;

    default:
        /*
         * Op is not a constant or string, append each argument to the Op
         */
        while (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) && !WalkState->ArgCount)
        {
            WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
                WalkState->ParserState.AmlStart);

            Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState),
                        GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }

            if (Arg)
            {
                Arg->Common.AmlOffset = WalkState->AmlOffset;
                AcpiPsAppendArg (Op, Arg);
            }

            INCREMENT_ARG_LIST (WalkState->ArgTypes);
        }


        /*
         * Handle executable code at "module-level". This refers to
         * executable opcodes that appear outside of any control method.
         */
        if ((WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2) &&
            ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) == 0))
        {
            /*
             * We want to skip If/Else/While constructs during Pass1 because we
             * want to actually conditionally execute the code during Pass2.
             *
             * Except for disassembly, where we always want to walk the
             * If/Else/While packages
             */
            switch (Op->Common.AmlOpcode)
            {
            case AML_IF_OP:
            case AML_ELSE_OP:
            case AML_WHILE_OP:

                /*
                 * Currently supported module-level opcodes are:
                 * IF/ELSE/WHILE. These appear to be the most common,
                 * and easiest to support since they open an AML
                 * package.
                 */
                if (WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1)
                {
                    AcpiPsLinkModuleCode (Op->Common.Parent, AmlOpStart,
                        (UINT32) (WalkState->ParserState.PkgEnd - AmlOpStart),
                        WalkState->OwnerId);
                }

                ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
                    "Pass1: Skipping an If/Else/While body\n"));

                /* Skip body of if/else/while in pass 1 */

                WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
                WalkState->ArgCount = 0;
                break;

            default:
                /*
                 * Check for an unsupported executable opcode at module
                 * level. We must be in PASS1, the parent must be a SCOPE,
                 * The opcode class must be EXECUTE, and the opcode must
                 * not be an argument to another opcode.
                 */
                if ((WalkState->PassNumber == ACPI_IMODE_LOAD_PASS1) &&
                    (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
                {
                    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
                    if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
                        (!Arg))
                    {
                        ACPI_WARNING ((AE_INFO,
                            "Unsupported module-level executable opcode "
                            "0x%.2X at table offset 0x%.4X",
                            Op->Common.AmlOpcode,
                            (UINT32) (ACPI_PTR_DIFF (AmlOpStart,
                                WalkState->ParserState.AmlStart) +
                                sizeof (ACPI_TABLE_HEADER))));
                    }
                }
                break;
            }
        }

        /* Special processing for certain opcodes */

        switch (Op->Common.AmlOpcode)
        {
        case AML_METHOD_OP:
            /*
             * Skip parsing of control method because we don't have enough
             * info in the first pass to parse it correctly.
             *
             * Save the length and address of the body
             */
            Op->Named.Data = WalkState->ParserState.Aml;
            Op->Named.Length = (UINT32)
                (WalkState->ParserState.PkgEnd - WalkState->ParserState.Aml);

            /* Skip body of method */

            WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
            WalkState->ArgCount = 0;
            break;

        case AML_BUFFER_OP:
        case AML_PACKAGE_OP:
        case AML_VAR_PACKAGE_OP:

            if ((Op->Common.Parent) &&
                (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
                (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
            {
                /*
                 * Skip parsing of Buffers and Packages because we don't have
                 * enough info in the first pass to parse them correctly.
                 */
                Op->Named.Data = AmlOpStart;
                Op->Named.Length = (UINT32)
                    (WalkState->ParserState.PkgEnd - AmlOpStart);

                /* Skip body */

                WalkState->ParserState.Aml = WalkState->ParserState.PkgEnd;
                WalkState->ArgCount = 0;
            }
            break;

        case AML_WHILE_OP:

            if (WalkState->ControlState)
            {
                WalkState->ControlState->Control.PackageEnd =
                    WalkState->ParserState.PkgEnd;
            }
            break;

        default:

            /* No action for all other opcodes */
            break;
        }

        break;
    }

    return_ACPI_STATUS (AE_OK);
}
Esempio n. 18
0
ACPI_STATUS
AcpiPsParseLoop (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_PARSE_OBJECT       *Op = NULL;     /* current op */
    ACPI_PARSE_STATE        *ParserState;
    UINT8                   *AmlOpStart = NULL;


    ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState);


    if (WalkState->DescendingCallback == NULL)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    ParserState = &WalkState->ParserState;
    WalkState->ArgTypes = 0;

#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))

    if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART)
    {
        /* We are restarting a preempted control method */

        if (AcpiPsHasCompletedScope (ParserState))
        {
            /*
             * We must check if a predicate to an IF or WHILE statement
             * was just completed
             */
            if ((ParserState->Scope->ParseScope.Op) &&
               ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) ||
                (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) &&
                (WalkState->ControlState) &&
                (WalkState->ControlState->Common.State ==
                    ACPI_CONTROL_PREDICATE_EXECUTING))
            {
                /*
                 * A predicate was just completed, get the value of the
                 * predicate and branch based on that value
                 */
                WalkState->Op = NULL;
                Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE));
                if (ACPI_FAILURE (Status) &&
                    ((Status & AE_CODE_MASK) != AE_CODE_CONTROL))
                {
                    if (Status == AE_AML_NO_RETURN_VALUE)
                    {
                        ACPI_EXCEPTION ((AE_INFO, Status,
                            "Invoked method did not return a value"));
                    }

                    ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed"));
                    return_ACPI_STATUS (Status);
                }

                Status = AcpiPsNextParseState (WalkState, Op, Status);
            }

            AcpiPsPopScope (ParserState, &Op,
                &WalkState->ArgTypes, &WalkState->ArgCount);
            ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op));
        }
        else if (WalkState->PrevOp)
        {
            /* We were in the middle of an op */

            Op = WalkState->PrevOp;
            WalkState->ArgTypes = WalkState->PrevArgTypes;
        }
    }
#endif

    /* Iterative parsing loop, while there is more AML to process: */

    while ((ParserState->Aml < ParserState->AmlEnd) || (Op))
    {
        AmlOpStart = ParserState->Aml;
        if (!Op)
        {
            Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op);
            if (ACPI_FAILURE (Status))
            {
                if (Status == AE_CTRL_PARSE_CONTINUE)
                {
                    continue;
                }

                if (Status == AE_CTRL_PARSE_PENDING)
                {
                    Status = AE_OK;
                }

                Status = AcpiPsCompleteOp (WalkState, &Op, Status);
                if (ACPI_FAILURE (Status))
                {
                    return_ACPI_STATUS (Status);
                }

                continue;
            }

            Op->Common.AmlOffset = WalkState->AmlOffset;

            if (WalkState->OpInfo)
            {
                ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
                    "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
                     (UINT32) Op->Common.AmlOpcode, WalkState->OpInfo->Name,
                     Op, ParserState->Aml, Op->Common.AmlOffset));
            }
        }


        /*
         * Start ArgCount at zero because we don't know if there are
         * any args yet
         */
        WalkState->ArgCount  = 0;

        /* Are there any arguments that must be processed? */

        if (WalkState->ArgTypes)
        {
            /* Get arguments */

            Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op);
            if (ACPI_FAILURE (Status))
            {
                Status = AcpiPsCompleteOp (WalkState, &Op, Status);
                if (ACPI_FAILURE (Status))
                {
                    return_ACPI_STATUS (Status);
                }

                continue;
            }
        }

        /* Check for arguments that need to be processed */

        if (WalkState->ArgCount)
        {
            /*
             * There are arguments (complex ones), push Op and
             * prepare for argument
             */
            Status = AcpiPsPushScope (ParserState, Op,
                        WalkState->ArgTypes, WalkState->ArgCount);
            if (ACPI_FAILURE (Status))
            {
                Status = AcpiPsCompleteOp (WalkState, &Op, Status);
                if (ACPI_FAILURE (Status))
                {
                    return_ACPI_STATUS (Status);
                }

                continue;
            }

            Op = NULL;
            continue;
        }

        /*
         * All arguments have been processed -- Op is complete,
         * prepare for next
         */
        WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
        if (WalkState->OpInfo->Flags & AML_NAMED)
        {
            if (AcpiGbl_Depth)
            {
                AcpiGbl_Depth--;
            }

            if (Op->Common.AmlOpcode == AML_REGION_OP ||
                Op->Common.AmlOpcode == AML_DATA_REGION_OP)
            {
                /*
                 * Skip parsing of control method or opregion body,
                 * because we don't have enough info in the first pass
                 * to parse them correctly.
                 *
                 * Completed parsing an OpRegion declaration, we now
                 * know the length.
                 */
                Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
            }
        }

        if (WalkState->OpInfo->Flags & AML_CREATE)
        {
            /*
             * Backup to beginning of CreateXXXfield declaration (1 for
             * Opcode)
             *
             * BodyLength is unknown until we parse the body
             */
            Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
        }

        if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
        {
            /*
             * Backup to beginning of BankField declaration
             *
             * BodyLength is unknown until we parse the body
             */
            Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data);
        }

        /* This op complete, notify the dispatcher */

        if (WalkState->AscendingCallback != NULL)
        {
            WalkState->Op = Op;
            WalkState->Opcode = Op->Common.AmlOpcode;

            Status = WalkState->AscendingCallback (WalkState);
            Status = AcpiPsNextParseState (WalkState, Op, Status);
            if (Status == AE_CTRL_PENDING)
            {
                Status = AE_OK;
            }
        }

        Status = AcpiPsCompleteOp (WalkState, &Op, Status);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

    } /* while ParserState->Aml */

    Status = AcpiPsCompleteFinalOp (WalkState, Op, Status);
    return_ACPI_STATUS (Status);
}
Esempio n. 19
0
static ACPI_STATUS
AcpiPsGetAmlOpcode (
    ACPI_WALK_STATE         *WalkState)
{

    ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState);


    WalkState->AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->ParserState.Aml,
                                WalkState->ParserState.AmlStart);
    WalkState->Opcode = AcpiPsPeekOpcode (&(WalkState->ParserState));

    /*
     * First cut to determine what we have found:
     * 1) A valid AML opcode
     * 2) A name string
     * 3) An unknown/invalid opcode
     */
    WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode);

    switch (WalkState->OpInfo->Class)
    {
    case AML_CLASS_ASCII:
    case AML_CLASS_PREFIX:
        /*
         * Starts with a valid prefix or ASCII char, this is a name
         * string. Convert the bare name string to a namepath.
         */
        WalkState->Opcode = AML_INT_NAMEPATH_OP;
        WalkState->ArgTypes = ARGP_NAMESTRING;
        break;

    case AML_CLASS_UNKNOWN:

        /* The opcode is unrecognized. Complain and skip unknown opcodes */

        if (WalkState->PassNumber == 2)
        {
            ACPI_ERROR ((AE_INFO,
                "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
                WalkState->Opcode,
                (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER))));

            ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48);

#ifdef ACPI_ASL_COMPILER
            /*
             * This is executed for the disassembler only. Output goes
             * to the disassembled ASL output file.
             */
            AcpiOsPrintf (
                "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
                WalkState->Opcode,
                (UINT32) (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER)));

            /* Dump the context surrounding the invalid opcode */

            AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16),
                48, DB_BYTE_DISPLAY,
                (WalkState->AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16));
            AcpiOsPrintf (" */\n");
#endif
        }

        /* Increment past one-byte or two-byte opcode */

        WalkState->ParserState.Aml++;
        if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */
        {
            WalkState->ParserState.Aml++;
        }

        return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE);

    default:

        /* Found opcode info, this is a normal opcode */

        WalkState->ParserState.Aml += AcpiPsGetOpcodeSize (WalkState->Opcode);
        WalkState->ArgTypes = WalkState->OpInfo->ParseArgs;
        break;
    }

    return_ACPI_STATUS (AE_OK);
}
Esempio n. 20
0
void
AcpiDmDisplayPath (
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_PARSE_OBJECT       *Prev;
    ACPI_PARSE_OBJECT       *Search;
    UINT32                  Name;
    BOOLEAN                 DoDot = FALSE;
    ACPI_PARSE_OBJECT       *NamePath;
    const ACPI_OPCODE_INFO  *OpInfo;


    /* We are only interested in named objects */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    if (!(OpInfo->Flags & AML_NSNODE))
    {
        return;
    }

    if (OpInfo->Flags & AML_CREATE)
    {
        /* Field creation - check for a fully qualified namepath */

        if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP)
        {
            NamePath = AcpiPsGetArg (Op, 3);
        }
        else
        {
            NamePath = AcpiPsGetArg (Op, 2);
        }

        if ((NamePath) &&
            (NamePath->Common.Value.String) &&
            (ACPI_IS_ROOT_PREFIX (NamePath->Common.Value.String[0])))
        {
            AcpiDmNamestring (NamePath->Common.Value.String);
            return;
        }
    }

    Prev = NULL;            /* Start with Root Node */

    while (Prev != Op)
    {
        /* Search upwards in the tree to find scope with "prev" as its parent */

        Search = Op;
        for (; ;)
        {
            if (Search->Common.Parent == Prev)
            {
                break;
            }

            /* Go up one level */

            Search = Search->Common.Parent;
        }

        if (Prev)
        {
            OpInfo = AcpiPsGetOpcodeInfo (Search->Common.AmlOpcode);
            if (!(OpInfo->Flags & AML_FIELD))
            {
                /* Below root scope, append scope name */

                if (DoDot)
                {
                    /* Append dot */

                    AcpiOsPrintf (".");
                }

                if (OpInfo->Flags & AML_CREATE)
                {
                    if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP)
                    {
                        NamePath = AcpiPsGetArg (Op, 3);
                    }
                    else
                    {
                        NamePath = AcpiPsGetArg (Op, 2);
                    }

                    if ((NamePath) &&
                        (NamePath->Common.Value.String))
                    {
                        AcpiDmDumpName (NamePath->Common.Value.String);
                    }
                }
                else
                {
                    Name = AcpiPsGetName (Search);
                    AcpiDmDumpName ((char *) &Name);
                }

                DoDot = TRUE;
            }
        }
        Prev = Search;
    }
}
Esempio n. 21
0
static ACPI_STATUS
AcpiPsCompleteFinalOp (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    ACPI_STATUS             Status)
{
    ACPI_STATUS             Status2;


    ACPI_FUNCTION_TRACE_PTR (PsCompleteFinalOp, WalkState);


    /*
     * Complete the last Op (if not completed), and clear the scope stack.
     * It is easily possible to end an AML "package" with an unbounded number
     * of open scopes (such as when several ASL blocks are closed with
     * sequential closing braces). We want to terminate each one cleanly.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", Op));
    do
    {
        if (Op)
        {
            if (WalkState->AscendingCallback != NULL)
            {
                WalkState->Op = Op;
                WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
                WalkState->Opcode = Op->Common.AmlOpcode;

                Status = WalkState->AscendingCallback (WalkState);
                Status = AcpiPsNextParseState (WalkState, Op, Status);
                if (Status == AE_CTRL_PENDING)
                {
                    Status = AcpiPsCompleteOp (WalkState, &Op, AE_OK);
                    if (ACPI_FAILURE (Status))
                    {
                        return_ACPI_STATUS (Status);
                    }
                }

                if (Status == AE_CTRL_TERMINATE)
                {
                    Status = AE_OK;

                    /* Clean up */
                    do
                    {
                        if (Op)
                        {
                            Status2 = AcpiPsCompleteThisOp (WalkState, Op);
                            if (ACPI_FAILURE (Status2))
                            {
                                return_ACPI_STATUS (Status2);
                            }
                        }

                        AcpiPsPopScope (&(WalkState->ParserState), &Op,
                            &WalkState->ArgTypes, &WalkState->ArgCount);

                    } while (Op);

                    return_ACPI_STATUS (Status);
                }

                else if (ACPI_FAILURE (Status))
                {
                    /* First error is most important */

                    (void) AcpiPsCompleteThisOp (WalkState, Op);
                    return_ACPI_STATUS (Status);
                }
            }

            Status2 = AcpiPsCompleteThisOp (WalkState, Op);
            if (ACPI_FAILURE (Status2))
            {
                return_ACPI_STATUS (Status2);
            }
        }

        AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes,
            &WalkState->ArgCount);

    } while (Op);

    return_ACPI_STATUS (Status);
}
Esempio n. 22
0
BOOLEAN
AcpiDsIsResultUsed (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState)
{
    const ACPI_OPCODE_INFO  *ParentInfo;

    ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op);


    /* Must have both an Op and a Result Object */

    if (!Op)
    {
        ACPI_ERROR ((AE_INFO, "Null Op"));
        return_UINT8 (TRUE);
    }

    /*
     * We know that this operator is not a
     * Return() operator (would not come here.) The following code is the
     * optional support for a so-called "implicit return". Some AML code
     * assumes that the last value of the method is "implicitly" returned
     * to the caller. Just save the last result as the return value.
     * NOTE: this is optional because the ASL language does not actually
     * support this behavior.
     */
    (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE);

    /*
     * Now determine if the parent will use the result
     *
     * If there is no parent, or the parent is a ScopeOp, we are executing
     * at the method level. An executing method typically has no parent,
     * since each method is parsed separately. A method invoked externally
     * via ExecuteControlMethod has a ScopeOp as the parent.
     */
    if ((!Op->Common.Parent) ||
        (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP))
    {
        /* No parent, the return value cannot possibly be used */

        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
            "At Method level, result of [%s] not used\n",
            AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
        return_UINT8 (FALSE);
    }

    /* Get info on the parent. The RootOp is AML_SCOPE */

    ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);
    if (ParentInfo->Class == AML_CLASS_UNKNOWN)
    {
        ACPI_ERROR ((AE_INFO,
            "Unknown parent opcode Op=%p", Op));
        return_UINT8 (FALSE);
    }

    /*
     * Decide what to do with the result based on the parent. If
     * the parent opcode will not use the result, delete the object.
     * Otherwise leave it as is, it will be deleted when it is used
     * as an operand later.
     */
    switch (ParentInfo->Class)
    {
    case AML_CLASS_CONTROL:

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

            /* Never delete the return value associated with a return opcode */

            goto ResultUsed;

        case AML_IF_OP:
        case AML_WHILE_OP:

            /*
             * If we are executing the predicate AND this is the predicate op,
             * we will use the return value
             */
            if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) &&
                (WalkState->ControlState->Control.PredicateOp == Op))
            {
                goto ResultUsed;
            }
            break;

        default:
            /* Ignore other control opcodes */
            break;
        }

        /* The general control opcode returns no result */

        goto ResultNotUsed;


    case AML_CLASS_CREATE:

        /*
         * These opcodes allow TermArg(s) as operands and therefore
         * the operands can be method calls. The result is used.
         */
        goto ResultUsed;


    case AML_CLASS_NAMED_OBJECT:

        if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
            (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
            (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
            (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)  ||
            (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
            (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) ||
            (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP))
        {
            /*
             * These opcodes allow TermArg(s) as operands and therefore
             * the operands can be method calls. The result is used.
             */
            goto ResultUsed;
        }

        goto ResultNotUsed;


    default:

        /*
         * In all other cases. the parent will actually use the return
         * object, so keep it.
         */
        goto ResultUsed;
    }


ResultUsed:
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "Result of [%s] used by Parent [%s] Op=%p\n",
        AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));

    return_UINT8 (TRUE);


ResultNotUsed:
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "Result of [%s] not used by Parent [%s] Op=%p\n",
        AcpiPsGetOpcodeName (Op->Common.AmlOpcode),
        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op));

    return_UINT8 (FALSE);
}
Esempio n. 23
0
ACPI_STATUS
AcpiDsInitObjectFromOp (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    UINT16                  Opcode,
    ACPI_OPERAND_OBJECT     **RetObjDesc)
{
    const ACPI_OPCODE_INFO  *OpInfo;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE (DsInitObjectFromOp);


    ObjDesc = *RetObjDesc;
    OpInfo = AcpiPsGetOpcodeInfo (Opcode);
    if (OpInfo->Class == AML_CLASS_UNKNOWN)
    {
        /* Unknown opcode */

        return_ACPI_STATUS (AE_TYPE);
    }

    /* Perform per-object initialization */

    switch (ObjDesc->Common.Type)
    {
    case ACPI_TYPE_BUFFER:

        /*
         * Defer evaluation of Buffer TermArg operand
         */
        ObjDesc->Buffer.Node      = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
                                        WalkState->Operands[0]);
        ObjDesc->Buffer.AmlStart  = Op->Named.Data;
        ObjDesc->Buffer.AmlLength = Op->Named.Length;
        break;


    case ACPI_TYPE_PACKAGE:

        /*
         * Defer evaluation of Package TermArg operand
         */
        ObjDesc->Package.Node      = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
                                        WalkState->Operands[0]);
        ObjDesc->Package.AmlStart  = Op->Named.Data;
        ObjDesc->Package.AmlLength = Op->Named.Length;
        break;


    case ACPI_TYPE_INTEGER:

        switch (OpInfo->Type)
        {
        case AML_TYPE_CONSTANT:
            /*
             * Resolve AML Constants here - AND ONLY HERE!
             * All constants are integers.
             * We mark the integer with a flag that indicates that it started
             * life as a constant -- so that stores to constants will perform
             * as expected (noop). ZeroOp is used as a placeholder for optional
             * target operands.
             */
            ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT;

            switch (Opcode)
            {
            case AML_ZERO_OP:

                ObjDesc->Integer.Value = 0;
                break;

            case AML_ONE_OP:

                ObjDesc->Integer.Value = 1;
                break;

            case AML_ONES_OP:

                ObjDesc->Integer.Value = ACPI_UINT64_MAX;

                /* Truncate value if we are executing from a 32-bit ACPI table */

#ifndef ACPI_NO_METHOD_EXECUTION
                (void) AcpiExTruncateFor32bitTable (ObjDesc);
#endif
                break;

            case AML_REVISION_OP:

                ObjDesc->Integer.Value = ACPI_CA_VERSION;
                break;

            default:

                ACPI_ERROR ((AE_INFO,
                    "Unknown constant opcode 0x%X", Opcode));
                Status = AE_AML_OPERAND_TYPE;
                break;
            }
            break;


        case AML_TYPE_LITERAL:

            ObjDesc->Integer.Value = Op->Common.Value.Integer;

#ifndef ACPI_NO_METHOD_EXECUTION
            if (AcpiExTruncateFor32bitTable (ObjDesc))
            {
                /* Warn if we found a 64-bit constant in a 32-bit table */

                ACPI_WARNING ((AE_INFO,
                    "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
                    ACPI_FORMAT_UINT64 (Op->Common.Value.Integer),
                    (UINT32) ObjDesc->Integer.Value));
            }
#endif
            break;


        default:
            ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X",
                OpInfo->Type));
            Status = AE_AML_OPERAND_TYPE;
            break;
        }
        break;


    case ACPI_TYPE_STRING:

        ObjDesc->String.Pointer = Op->Common.Value.String;
        ObjDesc->String.Length = (UINT32) ACPI_STRLEN (Op->Common.Value.String);

        /*
         * The string is contained in the ACPI table, don't ever try
         * to delete it
         */
        ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
        break;


    case ACPI_TYPE_METHOD:
        break;


    case ACPI_TYPE_LOCAL_REFERENCE:

        switch (OpInfo->Type)
        {
        case AML_TYPE_LOCAL_VARIABLE:

            /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */

            ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_LOCAL_OP;
            ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL;

#ifndef ACPI_NO_METHOD_EXECUTION
            Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL,
                        ObjDesc->Reference.Value, WalkState,
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
                            &ObjDesc->Reference.Object));
#endif
            break;


        case AML_TYPE_METHOD_ARGUMENT:

            /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */

            ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_ARG_OP;
            ObjDesc->Reference.Class = ACPI_REFCLASS_ARG;

#ifndef ACPI_NO_METHOD_EXECUTION
            Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG,
                        ObjDesc->Reference.Value, WalkState,
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE,
                            &ObjDesc->Reference.Object));
#endif
            break;

        default: /* Object name or Debug object */

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

                /* Node was saved in Op */

                ObjDesc->Reference.Node = Op->Common.Node;
                ObjDesc->Reference.Object = Op->Common.Node->Object;
                ObjDesc->Reference.Class = ACPI_REFCLASS_NAME;
                break;

            case AML_DEBUG_OP:

                ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG;
                break;

            default:

                ACPI_ERROR ((AE_INFO,
                    "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode));
                return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
            }
            break;
        }
        break;


    default:

        ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X",
            ObjDesc->Common.Type));

        Status = AE_AML_OPERAND_TYPE;
        break;
    }

    return_ACPI_STATUS (Status);
}
Esempio n. 24
0
ACPI_STATUS
AcpiPsCompleteThisOp (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_PARSE_OBJECT       *Prev;
    ACPI_PARSE_OBJECT       *Next;
    const ACPI_OPCODE_INFO  *ParentInfo;
    ACPI_PARSE_OBJECT       *ReplacementOp = NULL;
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE_PTR (PsCompleteThisOp, Op);


    /* Check for null Op, can happen if AML code is corrupt */

    if (!Op)
    {
        return_ACPI_STATUS (AE_OK);  /* OK for now */
    }

    AcpiExStopTraceOpcode (Op, WalkState);

    /* Delete this op and the subtree below it if asked to */

    if (((WalkState->ParseFlags & ACPI_PARSE_TREE_MASK) != ACPI_PARSE_DELETE_TREE) ||
         (WalkState->OpInfo->Class == AML_CLASS_ARGUMENT))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Make sure that we only delete this subtree */

    if (Op->Common.Parent)
    {
        Prev = Op->Common.Parent->Common.Value.Arg;
        if (!Prev)
        {
            /* Nothing more to do */

            goto Cleanup;
        }

        /*
         * Check if we need to replace the operator and its subtree
         * with a return value op (placeholder op)
         */
        ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode);

        switch (ParentInfo->Class)
        {
        case AML_CLASS_CONTROL:

            break;

        case AML_CLASS_CREATE:
            /*
             * These opcodes contain TermArg operands. The current
             * op must be replaced by a placeholder return op
             */
            ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP,
                                Op->Common.Aml);
            if (!ReplacementOp)
            {
                Status = AE_NO_MEMORY;
            }
            break;

        case AML_CLASS_NAMED_OBJECT:
            /*
             * These opcodes contain TermArg operands. The current
             * op must be replaced by a placeholder return op
             */
            if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP)       ||
                (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP)  ||
                (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP)       ||
                (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP)      ||
                (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)   ||
                (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
            {
                ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP,
                                    Op->Common.Aml);
                if (!ReplacementOp)
                {
                    Status = AE_NO_MEMORY;
                }
            }
            else if ((Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) &&
                     (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2))
            {
                if ((Op->Common.AmlOpcode == AML_BUFFER_OP) ||
                    (Op->Common.AmlOpcode == AML_PACKAGE_OP) ||
                    (Op->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
                {
                    ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode,
                                        Op->Common.Aml);
                    if (!ReplacementOp)
                    {
                        Status = AE_NO_MEMORY;
                    }
                    else
                    {
                        ReplacementOp->Named.Data = Op->Named.Data;
                        ReplacementOp->Named.Length = Op->Named.Length;
                    }
                }
            }
            break;

        default:

            ReplacementOp = AcpiPsAllocOp (AML_INT_RETURN_VALUE_OP,
                                Op->Common.Aml);
            if (!ReplacementOp)
            {
                Status = AE_NO_MEMORY;
            }
        }

        /* We must unlink this op from the parent tree */

        if (Prev == Op)
        {
            /* This op is the first in the list */

            if (ReplacementOp)
            {
                ReplacementOp->Common.Parent        = Op->Common.Parent;
                ReplacementOp->Common.Value.Arg     = NULL;
                ReplacementOp->Common.Node          = Op->Common.Node;
                Op->Common.Parent->Common.Value.Arg = ReplacementOp;
                ReplacementOp->Common.Next          = Op->Common.Next;
            }
            else
            {
                Op->Common.Parent->Common.Value.Arg = Op->Common.Next;
            }
        }

        /* Search the parent list */

        else while (Prev)
        {
            /* Traverse all siblings in the parent's argument list */

            Next = Prev->Common.Next;
            if (Next == Op)
            {
                if (ReplacementOp)
                {
                    ReplacementOp->Common.Parent    = Op->Common.Parent;
                    ReplacementOp->Common.Value.Arg = NULL;
                    ReplacementOp->Common.Node      = Op->Common.Node;
                    Prev->Common.Next               = ReplacementOp;
                    ReplacementOp->Common.Next      = Op->Common.Next;
                    Next = NULL;
                }
                else
                {
                    Prev->Common.Next = Op->Common.Next;
                    Next = NULL;
                }
            }
            Prev = Next;
        }
    }


Cleanup:

    /* Now we can actually delete the subtree rooted at Op */

    AcpiPsDeleteParseTree (Op);
    return_ACPI_STATUS (Status);
}
Esempio n. 25
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);
}
Esempio n. 26
0
static void
LsWriteNodeToListing (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  FileId)
{
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  OpClass;
    char                    *Pathname;
    UINT32                  Length;
    UINT32                  i;


    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    OpClass = OpInfo->Class;

    /* TBD: clean this up with a single flag that says:
     * I start a named output block
     */
    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
    {
        switch (Op->Asl.ParseOpcode)
        {
        case PARSEOP_DEFINITION_BLOCK:
        case PARSEOP_METHODCALL:
        case PARSEOP_INCLUDE:
        case PARSEOP_INCLUDE_END:
        case PARSEOP_DEFAULT_ARG:

            break;

        default:

            switch (OpClass)
            {
            case AML_CLASS_NAMED_OBJECT:

                switch (Op->Asl.AmlOpcode)
                {
                case AML_SCOPE_OP:
                case AML_ALIAS_OP:

                    break;

                default:

                    if (Op->Asl.ExternalName)
                    {
                        LsFlushListingBuffer (FileId);
                        FlPrintFile (FileId, "    };\n");
                    }
                    break;
                }
                break;

            default:

                /* Don't care about other objects */

                break;
            }
            break;
        }
    }

    /* These cases do not have a corresponding AML opcode */

    switch (Op->Asl.ParseOpcode)
    {
    case PARSEOP_DEFINITION_BLOCK:

        /* Always start a definition block at AML offset zero */

        Gbl_CurrentAmlOffset = 0;
        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);

        /* Use the table Signature and TableId to build a unique name */

        switch (FileId)
        {
        case ASL_FILE_ASM_SOURCE_OUTPUT:

            FlPrintFile (FileId,
                "%s_%s_Header \\\n",
                Gbl_TableSignature, Gbl_TableId);
            break;

        case ASL_FILE_C_SOURCE_OUTPUT:

            FlPrintFile (FileId,
                "    unsigned char    %s_%s_Header [] =\n    {\n",
                Gbl_TableSignature, Gbl_TableId);
            break;

        case ASL_FILE_ASM_INCLUDE_OUTPUT:

            FlPrintFile (FileId,
                "extrn %s_%s_Header : byte\n",
                Gbl_TableSignature, Gbl_TableId);
            break;

        case ASL_FILE_C_INCLUDE_OUTPUT:

            FlPrintFile (FileId,
                "extern unsigned char    %s_%s_Header [];\n",
                Gbl_TableSignature, Gbl_TableId);
            break;

        default:
            break;
        }

        return;


    case PARSEOP_METHODCALL:

        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
            FileId);
        return;


    case PARSEOP_INCLUDE:

        /* Flush everything up to and including the include source line */

        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
            FileId);

        /* Create a new listing node and push it */

        LsPushNode (Op->Asl.Value.String);
        return;


    case PARSEOP_INCLUDE_END:

        /* Flush out the rest of the include file */

        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
            FileId);

        /* Pop off this listing node and go back to the parent file */

        (void) LsPopNode ();
        return;


    case PARSEOP_DEFAULT_ARG:

        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
        {
            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
                FileId);
        }
        return;


    default:

        /* All other opcodes have an AML opcode */

        break;
    }

    /*
     * Otherwise, we look at the AML opcode because we can
     * switch on the opcode type, getting an entire class
     * at once
     */
    switch (OpClass)
    {
    case AML_CLASS_ARGUMENT:       /* argument type only */
    case AML_CLASS_INTERNAL:

        break;

    case AML_CLASS_NAMED_OBJECT:

        switch (Op->Asl.AmlOpcode)
        {
        case AML_FIELD_OP:
        case AML_INDEX_FIELD_OP:
        case AML_BANK_FIELD_OP:
            /*
             * For fields, we want to dump all the AML after the
             * entire definition
             */
            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
                FileId);
            break;

        case AML_NAME_OP:

            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
            {
                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
                    FileId);
            }
            else
            {
                /*
                 * For fields, we want to dump all the AML after the
                 * entire definition
                 */
                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
                    FileId);
            }
            break;

        default:

            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
                FileId);
            break;
        }

        switch (Op->Asl.AmlOpcode)
        {
        case AML_SCOPE_OP:
        case AML_ALIAS_OP:

            /* These opcodes do not declare a new object, ignore them */

            break;

        default:

            /* All other named object opcodes come here */

            switch (FileId)
            {
            case ASL_FILE_ASM_SOURCE_OUTPUT:
            case ASL_FILE_C_SOURCE_OUTPUT:
            case ASL_FILE_ASM_INCLUDE_OUTPUT:
            case ASL_FILE_C_INCLUDE_OUTPUT:
                /*
                 * For named objects, we will create a valid symbol so that the
                 * AML code can be referenced from C or ASM
                 */
                if (Op->Asl.ExternalName)
                {
                    /* Get the full pathname associated with this node */

                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
                    Length = strlen (Pathname);
                    if (Length >= 4)
                    {
                        /* Convert all dots in the path to underscores */

                        for (i = 0; i < Length; i++)
                        {
                            if (Pathname[i] == '.')
                            {
                                Pathname[i] = '_';
                            }
                        }

                        /* Create the appropriate symbol in the output file */

                        switch (FileId)
                        {
                        case ASL_FILE_ASM_SOURCE_OUTPUT:

                            FlPrintFile (FileId,
                                "%s_%s_%s  \\\n",
                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
                            break;

                        case ASL_FILE_C_SOURCE_OUTPUT:

                            FlPrintFile (FileId,
                                "    unsigned char    %s_%s_%s [] =\n    {\n",
                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
                            break;

                        case ASL_FILE_ASM_INCLUDE_OUTPUT:

                            FlPrintFile (FileId,
                                "extrn %s_%s_%s : byte\n",
                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
                            break;

                        case ASL_FILE_C_INCLUDE_OUTPUT:

                            FlPrintFile (FileId,
                                "extern unsigned char    %s_%s_%s [];\n",
                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
                            break;

                        default:
                            break;
                        }
                    }

                    ACPI_FREE (Pathname);
                }
                break;

            default:

                /* Nothing to do for listing file */

                break;
            }
        }
        break;

    case AML_CLASS_EXECUTE:
    case AML_CLASS_CREATE:
    default:

        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
        {
            return;
        }

        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
            FileId);
        break;

    case AML_CLASS_UNKNOWN:

        break;
    }
}
Esempio n. 27
0
static ACPI_STATUS
AcpiDsBuildInternalObject (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;
    ACPI_OBJECT_TYPE        Type;


    ACPI_FUNCTION_TRACE (DsBuildInternalObject);


    *ObjDescPtr = NULL;
    if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    {
        /*
         * This is a named object reference. If this name was
         * previously looked up in the namespace, it was stored in this op.
         * Otherwise, go ahead and look it up now
         */
        if (!Op->Common.Node)
        {
            Status = AcpiNsLookup (WalkState->ScopeInfo,
                        Op->Common.Value.String,
                        ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
            if (ACPI_FAILURE (Status))
            {
                /* Check if we are resolving a named reference within a package */

                if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) &&

                    ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
                     (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)))
                {
                    /*
                     * We didn't find the target and we are populating elements
                     * of a package - ignore if slack enabled. Some ASL code
                     * contains dangling invalid references in packages and
                     * expects that no exception will be issued. Leave the
                     * element as a null element. It cannot be used, but it
                     * can be overwritten by subsequent ASL code - this is
                     * typically the case.
                     */
                    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                        "Ignoring unresolved reference in package [%4.4s]\n",
                        WalkState->ScopeInfo->Scope.Node->Name.Ascii));

                    return_ACPI_STATUS (AE_OK);
                }
                else
                {
                    ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status);
                }

                return_ACPI_STATUS (Status);
            }
        }

        /* Special object resolution for elements of a package */

        if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
            (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
        {
            /*
             * Attempt to resolve the node to a value before we insert it into
             * the package. If this is a reference to a common data type,
             * resolve it immediately. According to the ACPI spec, package
             * elements can only be "data objects" or method references.
             * Attempt to resolve to an Integer, Buffer, String or Package.
             * If cannot, return the named reference (for things like Devices,
             * Methods, etc.) Buffer Fields and Fields will resolve to simple
             * objects (int/buf/str/pkg).
             *
             * NOTE: References to things like Devices, Methods, Mutexes, etc.
             * will remain as named references. This behavior is not described
             * in the ACPI spec, but it appears to be an oversight.
             */
            ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Op->Common.Node);

            Status = AcpiExResolveNodeToValue (
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc),
                        WalkState);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }

            /*
             * Special handling for Alias objects. We need to setup the type
             * and the Op->Common.Node to point to the Alias target. Note,
             * Alias has at most one level of indirection internally.
             */
            Type = Op->Common.Node->Type;
            if (Type == ACPI_TYPE_LOCAL_ALIAS)
            {
                Type = ObjDesc->Common.Type;
                Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
                    Op->Common.Node->Object);
            }

            switch (Type)
            {
            /*
             * For these types, we need the actual node, not the subobject.
             * However, the subobject did not get an extra reference count above.
             *
             * TBD: should ExResolveNodeToValue be changed to fix this?
             */
            case ACPI_TYPE_DEVICE:
            case ACPI_TYPE_THERMAL:

                AcpiUtAddReference (Op->Common.Node->Object);

                /*lint -fallthrough */
            /*
             * For these types, we need the actual node, not the subobject.
             * The subobject got an extra reference count in ExResolveNodeToValue.
             */
            case ACPI_TYPE_MUTEX:
            case ACPI_TYPE_METHOD:
            case ACPI_TYPE_POWER:
            case ACPI_TYPE_PROCESSOR:
            case ACPI_TYPE_EVENT:
            case ACPI_TYPE_REGION:

                /* We will create a reference object for these types below */
                break;

            default:
                /*
                 * All other types - the node was resolved to an actual
                 * object, we are done.
                 */
                goto Exit;
            }
        }
    }

    /* Create and init a new internal ACPI object */

    ObjDesc = AcpiUtCreateInternalObject (
                (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode,
                &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ObjDesc);
        return_ACPI_STATUS (Status);
    }

Exit:
    *ObjDescPtr = ObjDesc;
    return_ACPI_STATUS (Status);
}
Esempio n. 28
0
static ACPI_STATUS
XfNamespaceLocateBegin (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;
    ACPI_OBJECT_TYPE        ObjectType;
    char                    *Path;
    UINT8                   PassedArgs;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_PARSE_OBJECT       *OwningOp;
    ACPI_PARSE_OBJECT       *SpaceIdOp;
    UINT32                  MinimumLength;
    UINT32                  Offset;
    UINT32                  FieldBitLength;
    UINT32                  TagBitLength;
    UINT8                   Message = 0;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  Flags;
    ASL_METHOD_LOCAL        *MethodLocals = NULL;
    ASL_METHOD_LOCAL        *MethodArgs = NULL;
    int                     RegisterNumber;
    UINT32                  i;


    ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);


    if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node)
    {
        Node = Op->Asl.Node;

        /* Support for method LocalX/ArgX analysis */

        if (!Node->MethodLocals)
        {
            /* Create local/arg info blocks */

            MethodLocals = UtLocalCalloc (
                sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
            Node->MethodLocals = MethodLocals;

            MethodArgs = UtLocalCalloc (
                sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS);
            Node->MethodArgs = MethodArgs;

            /*
             * Get the method argument count
             * First, get the name node
             */
            NextOp = Op->Asl.Child;

            /* Get the NumArguments node */

            NextOp = NextOp->Asl.Next;
            Node->ArgCount = (UINT8)
                (((UINT8) NextOp->Asl.Value.Integer) & 0x07);

            /* We will track all possible ArgXs */

            for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
            {
                if (i < Node->ArgCount)
                {
                    /* Real Args are always "initialized" */

                    MethodArgs[i].Flags = ASL_ARG_INITIALIZED;
                }
                else
                {
                    /* Other ArgXs can be used as locals */

                    MethodArgs[i].Flags = ASL_ARG_IS_LOCAL;
                }

                MethodArgs[i].Op = Op;
            }
        }
    }

    /*
     * If this node is the actual declaration of a name
     * [such as the XXXX name in "Method (XXXX)"],
     * we are not interested in it here. We only care about names that are
     * references to other objects within the namespace and the parent objects
     * of name declarations
     */
    if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION)
    {
        return_ACPI_STATUS (AE_OK);
    }

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

    /* Check method LocalX variables */

    if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE)
    {
        /* Find parent method Op */

        NextOp = XfGetParentMethod (Op);
        if (!NextOp)
        {
            return_ACPI_STATUS (AE_OK);
        }

        /* Get method node */

        Node = NextOp->Asl.Node;

        RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */
        MethodLocals = Node->MethodLocals;

        if (Op->Asl.CompileFlags & OP_IS_TARGET)
        {
            /* Local is being initialized */

            MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED;
            MethodLocals[RegisterNumber].Op = Op;

            return_ACPI_STATUS (AE_OK);
        }

        /* Mark this Local as referenced */

        MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED;
        MethodLocals[RegisterNumber].Op = Op;

        return_ACPI_STATUS (AE_OK);
    }

    /* Check method ArgX variables */

    if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT)
    {
        /* Find parent method Op */

        NextOp = XfGetParentMethod (Op);
        if (!NextOp)
        {
            return_ACPI_STATUS (AE_OK);
        }

        /* Get method node */

        Node = NextOp->Asl.Node;

        /* Get Arg # */

        RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */
        MethodArgs = Node->MethodArgs;

        /* Mark this Arg as referenced */

        MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED;
        MethodArgs[RegisterNumber].Op = Op;

        if (Op->Asl.CompileFlags & OP_IS_TARGET)
        {
            /* Arg is being initialized */

            MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED;
        }

        return_ACPI_STATUS (AE_OK);
    }

    /*
     * After method ArgX and LocalX, we are only interested in opcodes
     * that have an associated name
     */
    if ((!(OpInfo->Flags & AML_NAMED)) &&
        (!(OpInfo->Flags & AML_CREATE)) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
        (Op->Asl.ParseOpcode != PARSEOP_METHODCALL) &&
        (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /*
     * One special case: CondRefOf operator - we don't care if the name exists
     * or not at this point, just ignore it, the point of the operator is to
     * determine if the name exists at runtime.
     */
    if ((Op->Asl.Parent) &&
        (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /*
     * We must enable the "search-to-root" for single NameSegs, but
     * we have to be very careful about opening up scopes
     */
    Flags = ACPI_NS_SEARCH_PARENT;
    if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
        (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
        (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
        (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
    {
        /*
         * These are name references, do not push the scope stack
         * for them.
         */
        Flags |= ACPI_NS_DONT_OPEN_SCOPE;
    }

    /* Get the NamePath from the appropriate place */

    if (OpInfo->Flags & AML_NAMED)
    {
        /* For nearly all NAMED operators, the name reference is the first child */

        Path = Op->Asl.Child->Asl.Value.String;
        if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
        {
            /*
             * ALIAS is the only oddball opcode, the name declaration
             * (alias name) is the second operand
             */
            Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
        }
    }
    else if (OpInfo->Flags & AML_CREATE)
    {
        /* Name must appear as the last parameter */

        NextOp = Op->Asl.Child;
        while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
        {
            NextOp = NextOp->Asl.Next;
        }

        Path = NextOp->Asl.Value.String;
    }
    else
    {
        Path = Op->Asl.Value.String;
    }

    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "Type=%s\n", AcpiUtGetTypeName (ObjectType)));

    /*
     * Lookup the name in the namespace. Name must exist at this point, or it
     * is an invalid reference.
     *
     * The namespace is also used as a lookup table for references to resource
     * descriptors and the fields within them.
     */
    AslGbl_NsLookupCount++;

    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
        ACPI_IMODE_EXECUTE, Flags, WalkState, &Node);
    if (ACPI_FAILURE (Status))
    {
        if (Status == AE_NOT_FOUND)
        {
            /*
             * We didn't find the name reference by path -- we can qualify this
             * a little better before we print an error message
             */
            if (strlen (Path) == ACPI_NAME_SIZE)
            {
                /* A simple, one-segment ACPI name */

                if (XfObjectExists (Path))
                {
                    /*
                     * There exists such a name, but we couldn't get to it
                     * from this scope
                     */
                    AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
                        Op->Asl.ExternalName);
                }
                else
                {
                    /* The name doesn't exist, period */

                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
                        Op, Op->Asl.ExternalName);
                }
            }
            else
            {
                /* The NamePath contains multiple NameSegs */

                if ((OpInfo->Flags & AML_CREATE) ||
                    (OpInfo->ObjectType == ACPI_TYPE_LOCAL_ALIAS))
                {
                    /*
                     * The new name is the last parameter. For the
                     * CreateXXXXField and Alias operators
                     */
                    NextOp = Op->Asl.Child;
                    while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
                    {
                        NextOp = NextOp->Asl.Next;
                    }

                    AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, NextOp,
                        NextOp->Asl.ExternalName);
                }
                else if (OpInfo->Flags & AML_NAMED)
                {
                    /* The new name is the first parameter */

                    AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, Op,
                        Op->Asl.ExternalName);
                }
                else if (Path[0] == AML_ROOT_PREFIX)
                {
                    /* Full namepath from root, the object does not exist */

                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
                        Op->Asl.ExternalName);
                }
                else
                {
                    /*
                     * Generic "not found" error. Cannot determine whether it
                     * doesn't exist or just can't be reached. However, we
                     * can differentiate between a NameSeg vs. NamePath.
                     */
                    if (strlen (Op->Asl.ExternalName) == ACPI_NAME_SIZE)
                    {
                        AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
                            Op->Asl.ExternalName);
                    }
                    else
                    {
                        AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op,
                            Op->Asl.ExternalName);
                    }
                }
            }

            Status = AE_OK;
        }

        return_ACPI_STATUS (Status);
    }

    /* Check for an attempt to access an object in another method */

    if (!XfValidateCrossReference (Op, OpInfo, Node))
    {
        AslError (ASL_ERROR, ASL_MSG_TEMPORARY_OBJECT, Op,
            Op->Asl.ExternalName);
        return_ACPI_STATUS (Status);
    }

    /* Object was found above, check for an illegal forward reference */

    if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD)
    {
        /*
         * During the load phase, this Op was flagged as a possible
         * illegal forward reference
         *
         * Note: Allow "forward references" from within a method to an
         * object that is not within any method (module-level code)
         */
        if (!WalkState->ScopeInfo || (UtGetParentMethod (Node) &&
            !UtNodeIsDescendantOf (WalkState->ScopeInfo->Scope.Node,
                UtGetParentMethod (Node))))
        {
            AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
                Op->Asl.ExternalName);
        }
    }

    /* Check for a reference vs. name declaration */

    if (!(OpInfo->Flags & AML_NAMED) &&
        !(OpInfo->Flags & AML_CREATE))
    {
        /* This node has been referenced, mark it for reference check */

        Node->Flags |= ANOBJ_IS_REFERENCED;
    }

    /* Attempt to optimize the NamePath */

    OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);

    /*
     * 1) Dereference an alias (A name reference that is an alias)
     *    Aliases are not nested, the alias always points to the final object
     */
    if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
        (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
    {
        /* This node points back to the original PARSEOP_ALIAS */

        NextOp = Node->Op;

        /* The first child is the alias target op */

        NextOp = NextOp->Asl.Child;

        /* That in turn points back to original target alias node */

        if (NextOp->Asl.Node)
        {
            Node = NextOp->Asl.Node;
        }

        /* Else - forward reference to alias, will be resolved later */
    }

    /* 2) Check for a reference to a resource descriptor */

    if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
        (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    {
        /*
         * This was a reference to a field within a resource descriptor.
         * Extract the associated field offset (either a bit or byte
         * offset depending on the field type) and change the named
         * reference into an integer for AML code generation
         */
        Offset = Node->Value;
        TagBitLength = Node->Length;

        /*
         * If a field is being created, generate the length (in bits) of
         * the field. Note: Opcodes other than CreateXxxField and Index
         * can come through here. For other opcodes, we just need to
         * convert the resource tag reference to an integer offset.
         */
        switch (Op->Asl.Parent->Asl.AmlOpcode)
        {
        case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
            /*
             * We know the length operand is an integer constant because
             * we know that it contains a reference to a resource
             * descriptor tag.
             */
            FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
            break;

        case AML_CREATE_BIT_FIELD_OP:

            FieldBitLength = 1;
            break;

        case AML_CREATE_BYTE_FIELD_OP:
        case AML_INDEX_OP:

            FieldBitLength = 8;
            break;

        case AML_CREATE_WORD_FIELD_OP:

            FieldBitLength = 16;
            break;

        case AML_CREATE_DWORD_FIELD_OP:

            FieldBitLength = 32;
            break;

        case AML_CREATE_QWORD_FIELD_OP:

            FieldBitLength = 64;
            break;

        default:

            FieldBitLength = 0;
            break;
        }

        /* Check the field length against the length of the resource tag */

        if (FieldBitLength)
        {
            if (TagBitLength < FieldBitLength)
            {
                Message = ASL_MSG_TAG_SMALLER;
            }
            else if (TagBitLength > FieldBitLength)
            {
                Message = ASL_MSG_TAG_LARGER;
            }

            if (Message)
            {
                sprintf (AslGbl_MsgBuffer,
                    "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
                    TagBitLength, (TagBitLength > 1) ? "s" : "",
                    FieldBitLength, (FieldBitLength > 1) ? "s" : "");

                AslError (ASL_WARNING, Message, Op, AslGbl_MsgBuffer);
            }
        }

        /* Convert the BitOffset to a ByteOffset for certain opcodes */

        switch (Op->Asl.Parent->Asl.AmlOpcode)
        {
        case AML_CREATE_BYTE_FIELD_OP:
        case AML_CREATE_WORD_FIELD_OP:
        case AML_CREATE_DWORD_FIELD_OP:
        case AML_CREATE_QWORD_FIELD_OP:
        case AML_INDEX_OP:

            Offset = ACPI_DIV_8 (Offset);
            break;

        default:

            break;
        }

        /* Now convert this node to an integer whose value is the field offset */

        Op->Asl.AmlLength = 0;
        Op->Asl.ParseOpcode = PARSEOP_INTEGER;
        Op->Asl.Value.Integer = (UINT64) Offset;
        Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD;

        OpcGenerateAmlOpcode (Op);
    }

    /* 3) Check for a method invocation */

    else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
                (Node->Type == ACPI_TYPE_METHOD) &&
                (Op->Asl.Parent) &&
                (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||

                (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
    {
        /*
         * A reference to a method within one of these opcodes is not an
         * invocation of the method, it is simply a reference to the method.
         *
         * September 2016: Removed DeRefOf from this list
         */
        if ((Op->Asl.Parent) &&
            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)     ||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE)    ||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
        {
            return_ACPI_STATUS (AE_OK);
        }

        /*
         * There are two types of method invocation:
         * 1) Invocation with arguments -- the parser recognizes this
         *    as a METHODCALL.
         * 2) Invocation with no arguments --the parser cannot determine that
         *    this is a method invocation, therefore we have to figure it out
         *    here.
         */
        if (Node->Type != ACPI_TYPE_METHOD)
        {
            sprintf (AslGbl_MsgBuffer, "%s is a %s",
                Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));

            AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, AslGbl_MsgBuffer);
            return_ACPI_STATUS (AE_OK);
        }

        /* Save the method node in the caller's op */

        Op->Asl.Node = Node;
        if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
        {
            return_ACPI_STATUS (AE_OK);
        }

        /*
         * This is a method invocation, with or without arguments.
         * Count the number of arguments, each appears as a child
         * under the parent node
         */
        Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
        UtSetParseOpName (Op);

        PassedArgs = 0;
        NextOp = Op->Asl.Child;

        while (NextOp)
        {
            PassedArgs++;
            NextOp = NextOp->Asl.Next;
        }

        if (Node->Value != ASL_EXTERNAL_METHOD &&
            Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
        {
            /*
             * Check the parsed arguments with the number expected by the
             * method declaration itself
             */
            if (PassedArgs != Node->Value)
            {
                sprintf (AslGbl_MsgBuffer, "%s requires %u", Op->Asl.ExternalName,
                    Node->Value);

                if (PassedArgs < Node->Value)
                {
                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, AslGbl_MsgBuffer);
                }
                else
                {
                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, AslGbl_MsgBuffer);
                }
            }
        }
    }

    /* 4) Check for an ASL Field definition */

    else if ((Op->Asl.Parent) &&
            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
    {
        /*
         * Offset checking for fields. If the parent operation region has a
         * constant length (known at compile time), we can check fields
         * defined in that region against the region length. This will catch
         * fields and field units that cannot possibly fit within the region.
         *
         * Note: Index fields do not directly reference an operation region,
         * thus they are not included in this check.
         */
        if (Op == Op->Asl.Parent->Asl.Child)
        {
            /*
             * This is the first child of the field node, which is
             * the name of the region. Get the parse node for the
             * region -- which contains the length of the region.
             */
            OwningOp = Node->Op;
            Op->Asl.Parent->Asl.ExtraValue =
                ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);

            /* Examine the field access width */

            switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
            {
            case AML_FIELD_ACCESS_ANY:
            case AML_FIELD_ACCESS_BYTE:
            case AML_FIELD_ACCESS_BUFFER:
            default:

                MinimumLength = 1;
                break;

            case AML_FIELD_ACCESS_WORD:

                MinimumLength = 2;
                break;

            case AML_FIELD_ACCESS_DWORD:

                MinimumLength = 4;
                break;

            case AML_FIELD_ACCESS_QWORD:

                MinimumLength = 8;
                break;
            }

            /*
             * Is the region at least as big as the access width?
             * Note: DataTableRegions have 0 length
             */
            if (((UINT32) OwningOp->Asl.Value.Integer) &&
                ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
            {
                AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
            }

            /*
             * Check EC/CMOS/SMBUS fields to make sure that the correct
             * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
             */
            SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
            switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
            {
            case ACPI_ADR_SPACE_EC:
            case ACPI_ADR_SPACE_CMOS:
            case ACPI_ADR_SPACE_GPIO:

                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
                    AML_FIELD_ACCESS_BYTE)
                {
                    AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
                }
                break;

            case ACPI_ADR_SPACE_SMBUS:
            case ACPI_ADR_SPACE_IPMI:
            case ACPI_ADR_SPACE_GSBUS:

                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
                    AML_FIELD_ACCESS_BUFFER)
                {
                    AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
                }
                break;

            default:

                /* Nothing to do for other address spaces */

                break;
            }
        }
        else
        {
            /*
             * This is one element of the field list. Check to make sure
             * that it does not go beyond the end of the parent operation region.
             *
             * In the code below:
             *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
             *    Op->Asl.ExtraValue                  - Field start offset (bits)
             *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
             *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
             */
            if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
            {
                XfCheckFieldRange (Op,
                    Op->Asl.Parent->Asl.ExtraValue,
                    Op->Asl.ExtraValue,
                    (UINT32) Op->Asl.Child->Asl.Value.Integer,
                    Op->Asl.Child->Asl.ExtraValue);
            }
        }
    }

    /* 5) Check for a connection object */
#if 0
    else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
    {
        return_ACPI_STATUS (Status);
    }
#endif

    Op->Asl.Node = Node;
    return_ACPI_STATUS (Status);
}
Esempio n. 29
0
ACPI_STATUS
AcpiDsCreateOperand (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Arg,
    UINT32                  ArgIndex)
{
    ACPI_STATUS             Status = AE_OK;
    char                    *NameString;
    UINT32                  NameLength;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PARSE_OBJECT       *ParentOp;
    UINT16                  Opcode;
    ACPI_INTERPRETER_MODE   InterpreterMode;
    const ACPI_OPCODE_INFO  *OpInfo;


    ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);


    /* A valid name must be looked up in the namespace */

    if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
        (Arg->Common.Value.String) &&
        !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));

        /* Get the entire name string from the AML stream */

        Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer,
                        &NameString, &NameLength);

        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

        /* All prefixes have been handled, and the name is in NameString */

        /*
         * Special handling for BufferField declarations. This is a deferred
         * opcode that unfortunately defines the field name as the last
         * parameter instead of the first. We get here when we are performing
         * the deferred execution, so the actual name of the field is already
         * in the namespace. We don't want to attempt to look it up again
         * because we may be executing in a different scope than where the
         * actual opcode exists.
         */
        if ((WalkState->DeferredNode) &&
            (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
            (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
        {
            ObjDesc = ACPI_CAST_PTR (
                        ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
            Status = AE_OK;
        }
        else    /* All other opcodes */
        {
            /*
             * Differentiate between a namespace "create" operation
             * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
             * IMODE_EXECUTE) in order to support the creation of
             * namespace objects during the execution of control methods.
             */
            ParentOp = Arg->Common.Parent;
            OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
            if ((OpInfo->Flags & AML_NSNODE) &&
                (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
                (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
                (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
            {
                /* Enter name into namespace if not found */

                InterpreterMode = ACPI_IMODE_LOAD_PASS2;
            }
            else
            {
                /* Return a failure if name not found */

                InterpreterMode = ACPI_IMODE_EXECUTE;
            }

            Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
                        ACPI_TYPE_ANY, InterpreterMode,
                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
                        WalkState,
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
            /*
             * The only case where we pass through (ignore) a NOT_FOUND
             * error is for the CondRefOf opcode.
             */
            if (Status == AE_NOT_FOUND)
            {
                if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP)
                {
                    /*
                     * For the Conditional Reference op, it's OK if
                     * the name is not found;  We just need a way to
                     * indicate this to the interpreter, set the
                     * object to the root
                     */
                    ObjDesc = ACPI_CAST_PTR (
                                ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
                    Status = AE_OK;
                }
                else
                {
                    /*
                     * We just plain didn't find it -- which is a
                     * very serious error at this point
                     */
                    Status = AE_AML_NAME_NOT_FOUND;
                }
            }

            if (ACPI_FAILURE (Status))
            {
                ACPI_ERROR_NAMESPACE (NameString, Status);
            }
        }

        /* Free the namestring created above */

        ACPI_FREE (NameString);

        /* Check status from the lookup */

        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

        /* Put the resulting object onto the current object stack */

        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }
        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
    }
    else
    {
        /* Check for null name case */

        if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
            !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
        {
            /*
             * If the name is null, this means that this is an
             * optional result parameter that was not specified
             * in the original ASL. Create a Zero Constant for a
             * placeholder. (Store to a constant is a Noop.)
             */
            Opcode = AML_ZERO_OP;       /* Has no arguments! */

            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                "Null namepath: Arg=%p\n", Arg));
        }
        else
        {
            Opcode = Arg->Common.AmlOpcode;
        }

        /* Get the object type of the argument */

        OpInfo = AcpiPsGetOpcodeInfo (Opcode);
        if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
        {
            return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
        }

        if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                "Argument previously created, already stacked\n"));

            ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (
                WalkState->Operands [WalkState->NumOperands - 1], WalkState));

            /*
             * Use value that was already previously returned
             * by the evaluation of this argument
             */
            Status = AcpiDsResultPop (&ObjDesc, WalkState);
            if (ACPI_FAILURE (Status))
            {
                /*
                 * Only error is underflow, and this indicates
                 * a missing or null operand!
                 */
                ACPI_EXCEPTION ((AE_INFO, Status,
                    "Missing or null operand"));
                return_ACPI_STATUS (Status);
            }
        }
        else
        {
            /* Create an ACPI_INTERNAL_OBJECT for the argument */

            ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
            if (!ObjDesc)
            {
                return_ACPI_STATUS (AE_NO_MEMORY);
            }

            /* Initialize the new object */

            Status = AcpiDsInitObjectFromOp (
                        WalkState, Arg, Opcode, &ObjDesc);
            if (ACPI_FAILURE (Status))
            {
                AcpiUtDeleteObjectDesc (ObjDesc);
                return_ACPI_STATUS (Status);
            }
        }

        /* Put the operand object on the object stack */

        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
    }

    return_ACPI_STATUS (AE_OK);
}
Esempio n. 30
0
ACPI_STATUS
AcpiDsLoad1EndOp (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_PARSE_OBJECT       *Op;
    ACPI_OBJECT_TYPE        ObjectType;
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE (DsLoad1EndOp);


    Op = WalkState->Op;
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState));

    /* We are only interested in opcodes that have an associated name */

    if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_FIELD)))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Get the object type to determine if we should pop the scope */

    ObjectType = WalkState->OpInfo->ObjectType;

#ifndef ACPI_NO_METHOD_EXECUTION
    if (WalkState->OpInfo->Flags & AML_FIELD)
    {
        /*
         * If we are executing a method, do not create any namespace objects
         * during the load phase, only during execution.
         */
        if (!WalkState->MethodNode)
        {
            if (WalkState->Opcode == AML_FIELD_OP          ||
                WalkState->Opcode == AML_BANK_FIELD_OP     ||
                WalkState->Opcode == AML_INDEX_FIELD_OP)
            {
                Status = AcpiDsInitFieldObjects (Op, WalkState);
            }
        }
        return_ACPI_STATUS (Status);
    }

    /*
     * If we are executing a method, do not create any namespace objects
     * during the load phase, only during execution.
     */
    if (!WalkState->MethodNode)
    {
        if (Op->Common.AmlOpcode == AML_REGION_OP)
        {
            Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length,
                        (ACPI_ADR_SPACE_TYPE) ((Op->Common.Value.Arg)->Common.Value.Integer),
                        WalkState);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }
        }
        else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP)
        {
            Status = AcpiExCreateRegion (Op->Named.Data, Op->Named.Length,
                        ACPI_ADR_SPACE_DATA_TABLE, WalkState);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }
        }
    }
#endif

    if (Op->Common.AmlOpcode == AML_NAME_OP)
    {
        /* For Name opcode, get the object type from the argument */

        if (Op->Common.Value.Arg)
        {
            ObjectType = (AcpiPsGetOpcodeInfo (
                (Op->Common.Value.Arg)->Common.AmlOpcode))->ObjectType;

            /* Set node type if we have a namespace node */

            if (Op->Common.Node)
            {
                Op->Common.Node->Type = (UINT8) ObjectType;
            }
        }
    }

    /*
     * If we are executing a method, do not create any namespace objects
     * during the load phase, only during execution.
     */
    if (!WalkState->MethodNode)
    {
        if (Op->Common.AmlOpcode == AML_METHOD_OP)
        {
            /*
             * MethodOp PkgLength NameString MethodFlags TermList
             *
             * Note: We must create the method node/object pair as soon as we
             * see the method declaration. This allows later pass1 parsing
             * of invocations of the method (need to know the number of
             * arguments.)
             */
            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
                WalkState, Op, Op->Named.Node));

            if (!AcpiNsGetAttachedObject (Op->Named.Node))
            {
                WalkState->Operands[0] = ACPI_CAST_PTR (void, Op->Named.Node);
                WalkState->NumOperands = 1;

                Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg);
                if (ACPI_SUCCESS (Status))
                {
                    Status = AcpiExCreateMethod (Op->Named.Data,
                                        Op->Named.Length, WalkState);
                }

                WalkState->Operands[0] = NULL;
                WalkState->NumOperands = 0;

                if (ACPI_FAILURE (Status))
                {
                    return_ACPI_STATUS (Status);
                }
            }
        }