예제 #1
0
ACPI_STATUS
AcpiExOpcode_1A_0T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_OPERAND_OBJECT     *TempDesc;
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  Type;
    UINT64                  Value;


    ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R,
        AcpiPsGetOpcodeName (WalkState->Opcode));


    /* Examine the AML opcode */

    switch (WalkState->Opcode)
    {
    case AML_LNOT_OP:               /* LNot (Operand) */

        ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /*
         * Set result to ONES (TRUE) if Value == 0. Note:
         * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above.
         */
        if (!Operand[0]->Integer.Value)
        {
            ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
        }
        break;

    case AML_DECREMENT_OP:          /* Decrement (Operand)  */
    case AML_INCREMENT_OP:          /* Increment (Operand)  */
        /*
         * Create a new integer. Can't just get the base integer and
         * increment it because it may be an Arg or Field.
         */
        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /*
         * Since we are expecting a Reference operand, it can be either a
         * NS Node or an internal object.
         */
        TempDesc = Operand[0];
        if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND)
        {
            /* Internal reference object - prevent deletion */

            AcpiUtAddReference (TempDesc);
        }

        /*
         * Convert the Reference operand to an Integer (This removes a
         * reference on the Operand[0] object)
         *
         * NOTE:  We use LNOT_OP here in order to force resolution of the
         * reference operand to an actual integer.
         */
        Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState);
        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "While resolving operands for [%s]",
                AcpiPsGetOpcodeName (WalkState->Opcode)));

            goto Cleanup;
        }

        /*
         * TempDesc is now guaranteed to be an Integer object --
         * Perform the actual increment or decrement
         */
        if (WalkState->Opcode == AML_INCREMENT_OP)
        {
            ReturnDesc->Integer.Value = TempDesc->Integer.Value + 1;
        }
        else
        {
            ReturnDesc->Integer.Value = TempDesc->Integer.Value - 1;
        }

        /* Finished with this Integer object */

        AcpiUtRemoveReference (TempDesc);

        /*
         * Store the result back (indirectly) through the original
         * Reference object
         */
        Status = AcpiExStore (ReturnDesc, Operand[0], WalkState);
        break;

    case AML_OBJECT_TYPE_OP:            /* ObjectType (SourceObject) */
        /*
         * Note: The operand is not resolved at this point because we want to
         * get the associated object, not its value. For example, we don't
         * want to resolve a FieldUnit to its value, we want the actual
         * FieldUnit object.
         */

        /* Get the type of the base object */

        Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }

        /* Allocate a descriptor to hold the type. */

        ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }
        break;

    case AML_SIZE_OF_OP:            /* SizeOf (SourceObject)  */
        /*
         * Note: The operand is not resolved at this point because we want to
         * get the associated object, not its value.
         */

        /* Get the base object */

        Status = AcpiExResolveMultiple (
            WalkState, Operand[0], &Type, &TempDesc);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }

        /*
         * The type of the base object must be integer, buffer, string, or
         * package. All others are not supported.
         *
         * NOTE: Integer is not specifically supported by the ACPI spec,
         * but is supported implicitly via implicit operand conversion.
         * rather than bother with conversion, we just use the byte width
         * global (4 or 8 bytes).
         */
        switch (Type)
        {
        case ACPI_TYPE_INTEGER:

            Value = AcpiGbl_IntegerByteWidth;
            break;

        case ACPI_TYPE_STRING:

            Value = TempDesc->String.Length;
            break;

        case ACPI_TYPE_BUFFER:

            /* Buffer arguments may not be evaluated at this point */

            Status = AcpiDsGetBufferArguments (TempDesc);
            Value = TempDesc->Buffer.Length;
            break;

        case ACPI_TYPE_PACKAGE:

            /* Package arguments may not be evaluated at this point */

            Status = AcpiDsGetPackageArguments (TempDesc);
            Value = TempDesc->Package.Count;
            break;

        default:

            ACPI_ERROR ((AE_INFO,
                "Operand must be Buffer/Integer/String/Package"
                " - found type %s",
                AcpiUtGetTypeName (Type)));

            Status = AE_AML_OPERAND_TYPE;
            goto Cleanup;
        }

        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }

        /*
         * Now that we have the size of the object, create a result
         * object to hold the value
         */
        ReturnDesc = AcpiUtCreateIntegerObject (Value);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }
        break;


    case AML_REF_OF_OP:             /* RefOf (SourceObject) */

        Status = AcpiExGetObjectReference (
            Operand[0], &ReturnDesc, WalkState);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }
        break;


    case AML_DEREF_OF_OP:           /* DerefOf (ObjReference | String) */

        /* Check for a method local or argument, or standalone String */

        if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)
        {
            TempDesc = AcpiNsGetAttachedObject (
                           (ACPI_NAMESPACE_NODE *) Operand[0]);
            if (TempDesc &&
                 ((TempDesc->Common.Type == ACPI_TYPE_STRING) ||
                  (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)))
            {
                Operand[0] = TempDesc;
                AcpiUtAddReference (TempDesc);
            }
            else
            {
                Status = AE_AML_OPERAND_TYPE;
                goto Cleanup;
            }
        }
        else
        {
            switch ((Operand[0])->Common.Type)
            {
            case ACPI_TYPE_LOCAL_REFERENCE:
                /*
                 * This is a DerefOf (LocalX | ArgX)
                 *
                 * Must resolve/dereference the local/arg reference first
                 */
                switch (Operand[0]->Reference.Class)
                {
                case ACPI_REFCLASS_LOCAL:
                case ACPI_REFCLASS_ARG:

                    /* Set Operand[0] to the value of the local/arg */

                    Status = AcpiDsMethodDataGetValue (
                        Operand[0]->Reference.Class,
                        Operand[0]->Reference.Value,
                        WalkState, &TempDesc);
                    if (ACPI_FAILURE (Status))
                    {
                        goto Cleanup;
                    }

                    /*
                     * Delete our reference to the input object and
                     * point to the object just retrieved
                     */
                    AcpiUtRemoveReference (Operand[0]);
                    Operand[0] = TempDesc;
                    break;

                case ACPI_REFCLASS_REFOF:

                    /* Get the object to which the reference refers */

                    TempDesc = Operand[0]->Reference.Object;
                    AcpiUtRemoveReference (Operand[0]);
                    Operand[0] = TempDesc;
                    break;

                default:

                    /* Must be an Index op - handled below */
                    break;
                }
                break;

            case ACPI_TYPE_STRING:

                break;

            default:

                Status = AE_AML_OPERAND_TYPE;
                goto Cleanup;
            }
        }

        if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED)
        {
            if ((Operand[0])->Common.Type == ACPI_TYPE_STRING)
            {
                /*
                 * This is a DerefOf (String). The string is a reference
                 * to a named ACPI object.
                 *
                 * 1) Find the owning Node
                 * 2) Dereference the node to an actual object. Could be a
                 *    Field, so we need to resolve the node to a value.
                 */
                Status = AcpiNsGetNodeUnlocked (WalkState->ScopeInfo->Scope.Node,
                    Operand[0]->String.Pointer,
                    ACPI_NS_SEARCH_PARENT,
                    ACPI_CAST_INDIRECT_PTR (
                        ACPI_NAMESPACE_NODE, &ReturnDesc));
                if (ACPI_FAILURE (Status))
                {
                    goto Cleanup;
                }

                Status = AcpiExResolveNodeToValue (
                    ACPI_CAST_INDIRECT_PTR (
                        ACPI_NAMESPACE_NODE, &ReturnDesc),
                    WalkState);
                goto Cleanup;
            }
        }

        /* Operand[0] may have changed from the code above */

        if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)
        {
            /*
             * This is a DerefOf (ObjectReference)
             * Get the actual object from the Node (This is the dereference).
             * This case may only happen when a LocalX or ArgX is
             * dereferenced above.
             */
            ReturnDesc = AcpiNsGetAttachedObject (
                (ACPI_NAMESPACE_NODE *) Operand[0]);
            AcpiUtAddReference (ReturnDesc);
        }
        else
        {
            /*
             * This must be a reference object produced by either the
             * Index() or RefOf() operator
             */
            switch (Operand[0]->Reference.Class)
            {
            case ACPI_REFCLASS_INDEX:
                /*
                 * The target type for the Index operator must be
                 * either a Buffer or a Package
                 */
                switch (Operand[0]->Reference.TargetType)
                {
                case ACPI_TYPE_BUFFER_FIELD:

                    TempDesc = Operand[0]->Reference.Object;

                    /*
                     * Create a new object that contains one element of the
                     * buffer -- the element pointed to by the index.
                     *
                     * NOTE: index into a buffer is NOT a pointer to a
                     * sub-buffer of the main buffer, it is only a pointer to a
                     * single element (byte) of the buffer!
                     *
                     * Since we are returning the value of the buffer at the
                     * indexed location, we don't need to add an additional
                     * reference to the buffer itself.
                     */
                    ReturnDesc = AcpiUtCreateIntegerObject ((UINT64)
                        TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]);
                    if (!ReturnDesc)
                    {
                        Status = AE_NO_MEMORY;
                        goto Cleanup;
                    }
                    break;

                case ACPI_TYPE_PACKAGE:
                    /*
                     * Return the referenced element of the package. We must
                     * add another reference to the referenced object, however.
                     */
                    ReturnDesc = *(Operand[0]->Reference.Where);
                    if (!ReturnDesc)
                    {
                        /*
                         * Element is NULL, do not allow the dereference.
                         * This provides compatibility with other ACPI
                         * implementations.
                         */
                        return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT);
                    }

                    AcpiUtAddReference (ReturnDesc);
                    break;

                default:

                    ACPI_ERROR ((AE_INFO,
                        "Unknown Index TargetType 0x%X in reference object %p",
                        Operand[0]->Reference.TargetType, Operand[0]));

                    Status = AE_AML_OPERAND_TYPE;
                    goto Cleanup;
                }
                break;

            case ACPI_REFCLASS_REFOF:

                ReturnDesc = Operand[0]->Reference.Object;

                if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) ==
                    ACPI_DESC_TYPE_NAMED)
                {
                    ReturnDesc = AcpiNsGetAttachedObject (
                        (ACPI_NAMESPACE_NODE *) ReturnDesc);
                    if (!ReturnDesc)
                    {
                        break;
                    }

                   /*
                    * June 2013:
                    * BufferFields/FieldUnits require additional resolution
                    */
                    switch (ReturnDesc->Common.Type)
                    {
                    case ACPI_TYPE_BUFFER_FIELD:
                    case ACPI_TYPE_LOCAL_REGION_FIELD:
                    case ACPI_TYPE_LOCAL_BANK_FIELD:
                    case ACPI_TYPE_LOCAL_INDEX_FIELD:

                        Status = AcpiExReadDataFromField (
                            WalkState, ReturnDesc, &TempDesc);
                        if (ACPI_FAILURE (Status))
                        {
                            goto Cleanup;
                        }

                        ReturnDesc = TempDesc;
                        break;

                    default:

                        /* Add another reference to the object */

                        AcpiUtAddReference (ReturnDesc);
                        break;
                    }
                }
                break;

            default:

                ACPI_ERROR ((AE_INFO,
                    "Unknown class in reference(%p) - 0x%2.2X",
                    Operand[0], Operand[0]->Reference.Class));

                Status = AE_TYPE;
                goto Cleanup;
            }
        }
        break;

    default:

        ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
            WalkState->Opcode));

        Status = AE_AML_BAD_OPCODE;
        goto Cleanup;
    }


Cleanup:

    /* Delete return object on error */

    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ReturnDesc);
    }

    /* Save return object on success */

    else
    {
        WalkState->ResultObj = ReturnDesc;
    }

    return_ACPI_STATUS (Status);
}
예제 #2
0
파일: exresolv.c 프로젝트: MarginC/kame
ACPI_STATUS
AcpiExResolveObjectToValue (
    ACPI_OPERAND_OBJECT     **StackPtr,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *StackDesc;
    void                    *TempNode;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    UINT16                  Opcode;


    FUNCTION_TRACE ("ExResolveObjectToValue");


    StackDesc = *StackPtr;

    /* This is an ACPI_OPERAND_OBJECT  */

    switch (StackDesc->Common.Type)
    {

    case INTERNAL_TYPE_REFERENCE:

        Opcode = StackDesc->Reference.Opcode;

        switch (Opcode)
        {

        case AML_NAME_OP:

            /*
             * Convert indirect name ptr to a direct name ptr.
             * Then, AcpiExResolveNodeToValue can be used to get the value
             */
            TempNode = StackDesc->Reference.Object;

            /* Delete the Reference Object */

            AcpiUtRemoveReference (StackDesc);

            /* Put direct name pointer onto stack and exit */

            (*StackPtr) = TempNode;
            break;


        case AML_LOCAL_OP:
        case AML_ARG_OP:

            /*
             * Get the local from the method's state info
             * Note: this increments the local's object reference count
             */
            Status = AcpiDsMethodDataGetValue (Opcode,
                            StackDesc->Reference.Offset, WalkState, &ObjDesc);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }

            /*
             * Now we can delete the original Reference Object and
             * replace it with the resolve value
             */
            AcpiUtRemoveReference (StackDesc);
            *StackPtr = ObjDesc;

            ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[Arg/Local %d] ValueObj is %p\n",
                StackDesc->Reference.Offset, ObjDesc));
            break;


        /*
         * TBD: [Restructure] These next three opcodes change the type of
         * the object, which is actually a no-no.
         */
        case AML_ZERO_OP:

            StackDesc->Common.Type = (UINT8) ACPI_TYPE_INTEGER;
            StackDesc->Integer.Value = 0;
            break;


        case AML_ONE_OP:

            StackDesc->Common.Type = (UINT8) ACPI_TYPE_INTEGER;
            StackDesc->Integer.Value = 1;
            break;


        case AML_ONES_OP:

            StackDesc->Common.Type = (UINT8) ACPI_TYPE_INTEGER;
            StackDesc->Integer.Value = ACPI_INTEGER_MAX;

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

            AcpiExTruncateFor32bitTable (StackDesc, WalkState);
            break;


        case AML_INDEX_OP:

            switch (StackDesc->Reference.TargetType)
            {
            case ACPI_TYPE_BUFFER_FIELD:

                /* Just return - leave the Reference on the stack */
                break;


            case ACPI_TYPE_PACKAGE:
                ObjDesc = *StackDesc->Reference.Where;
                if (ObjDesc)
                {
                    /*
                     * Valid obj descriptor, copy pointer to return value
                     * (i.e., dereference the package index)
                     * Delete the ref object, increment the returned object
                     */
                    AcpiUtRemoveReference (StackDesc);
                    AcpiUtAddReference (ObjDesc);
                    *StackPtr = ObjDesc;
                }

                else
                {
                    /*
                     * A NULL object descriptor means an unitialized element of
                     * the package, can't dereference it
                     */
                    ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
                        "Attempt to deref an Index to NULL pkg element Idx=%p\n",
                        StackDesc));
                    Status = AE_AML_UNINITIALIZED_ELEMENT;
                }
                break;

            default:
                /* Invalid reference object */

                ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
                    "Unknown TargetType %X in Index/Reference obj %p\n",
                    StackDesc->Reference.TargetType, StackDesc));
                Status = AE_AML_INTERNAL;
                break;
            }

            break;


        case AML_DEBUG_OP:

            /* Just leave the object as-is */
            break;


        default:

            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference object subtype %02X in %p\n",
                Opcode, StackDesc));
            Status = AE_AML_INTERNAL;
            break;

        }   /* switch (Opcode) */

        break; /* case INTERNAL_TYPE_REFERENCE */


    case ACPI_TYPE_BUFFER_FIELD:

        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_ANY);
        if (!ObjDesc)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        Status = AcpiExGetBufferFieldValue (StackDesc, ObjDesc);
        if (ACPI_FAILURE (Status))
        {
            AcpiUtRemoveReference (ObjDesc);
            ObjDesc = NULL;
        }

        *StackPtr = (void *) ObjDesc;
        break;


    case INTERNAL_TYPE_BANK_FIELD:

        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_ANY);
        if (!ObjDesc)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        /* TBD: WRONG! */

        Status = AcpiExGetBufferFieldValue (StackDesc, ObjDesc);
        if (ACPI_FAILURE (Status))
        {
            AcpiUtRemoveReference (ObjDesc);
            ObjDesc = NULL;
        }

        *StackPtr = (void *) ObjDesc;
        break;


    /* TBD: [Future] - may need to handle IndexField, and DefField someday */

    default:

        break;

    }   /* switch (StackDesc->Common.Type) */


    return_ACPI_STATUS (Status);
}
예제 #3
0
파일: exresolv.c 프로젝트: ChaiSoft/ChaiOS
static ACPI_STATUS
AcpiExResolveObjectToValue (
    ACPI_OPERAND_OBJECT     **StackPtr,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *StackDesc;
    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    UINT8                   RefType;


    ACPI_FUNCTION_TRACE (ExResolveObjectToValue);


    StackDesc = *StackPtr;

    /* This is an object of type ACPI_OPERAND_OBJECT */

    switch (StackDesc->Common.Type)
    {
    case ACPI_TYPE_LOCAL_REFERENCE:

        RefType = StackDesc->Reference.Class;

        switch (RefType)
        {
        case ACPI_REFCLASS_LOCAL:
        case ACPI_REFCLASS_ARG:
            /*
             * Get the local from the method's state info
             * Note: this increments the local's object reference count
             */
            Status = AcpiDsMethodDataGetValue (RefType,
                StackDesc->Reference.Value, WalkState, &ObjDesc);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }

            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] ValueObj is %p\n",
                StackDesc->Reference.Value, ObjDesc));

            /*
             * Now we can delete the original Reference Object and
             * replace it with the resolved value
             */
            AcpiUtRemoveReference (StackDesc);
            *StackPtr = ObjDesc;
            break;

        case ACPI_REFCLASS_INDEX:

            switch (StackDesc->Reference.TargetType)
            {
            case ACPI_TYPE_BUFFER_FIELD:

                /* Just return - do not dereference */
                break;

            case ACPI_TYPE_PACKAGE:

                /* If method call or CopyObject - do not dereference */

                if ((WalkState->Opcode == AML_INT_METHODCALL_OP) ||
                    (WalkState->Opcode == AML_COPY_OBJECT_OP))
                {
                    break;
                }

                /* Otherwise, dereference the PackageIndex to a package element */

                ObjDesc = *StackDesc->Reference.Where;
                if (ObjDesc)
                {
                    /*
                     * Valid object descriptor, copy pointer to return value
                     * (i.e., dereference the package index)
                     * Delete the ref object, increment the returned object
                     */
                    AcpiUtAddReference (ObjDesc);
                    *StackPtr = ObjDesc;
                }
                else
                {
                    /*
                     * A NULL object descriptor means an uninitialized element of
                     * the package, can't dereference it
                     */
                    ACPI_ERROR ((AE_INFO,
                        "Attempt to dereference an Index to "
                        "NULL package element Idx=%p",
                        StackDesc));
                    Status = AE_AML_UNINITIALIZED_ELEMENT;
                }
                break;

            default:

                /* Invalid reference object */

                ACPI_ERROR ((AE_INFO,
                    "Unknown TargetType 0x%X in Index/Reference object %p",
                    StackDesc->Reference.TargetType, StackDesc));
                Status = AE_AML_INTERNAL;
                break;
            }
            break;

        case ACPI_REFCLASS_REFOF:
        case ACPI_REFCLASS_DEBUG:
        case ACPI_REFCLASS_TABLE:

            /* Just leave the object as-is, do not dereference */

            break;

        case ACPI_REFCLASS_NAME:   /* Reference to a named object */

            /* Dereference the name */

            if ((StackDesc->Reference.Node->Type == ACPI_TYPE_DEVICE) ||
                (StackDesc->Reference.Node->Type == ACPI_TYPE_THERMAL))
            {
                /* These node types do not have 'real' subobjects */

                *StackPtr = (void *) StackDesc->Reference.Node;
            }
            else
            {
                /* Get the object pointed to by the namespace node */

                *StackPtr = (StackDesc->Reference.Node)->Object;
                AcpiUtAddReference (*StackPtr);
            }

            AcpiUtRemoveReference (StackDesc);
            break;

        default:

            ACPI_ERROR ((AE_INFO,
                "Unknown Reference type 0x%X in %p",
                RefType, StackDesc));
            Status = AE_AML_INTERNAL;
            break;
        }
        break;

    case ACPI_TYPE_BUFFER:

        Status = AcpiDsGetBufferArguments (StackDesc);
        break;

    case ACPI_TYPE_PACKAGE:

        Status = AcpiDsGetPackageArguments (StackDesc);
        break;

    case ACPI_TYPE_BUFFER_FIELD:
    case ACPI_TYPE_LOCAL_REGION_FIELD:
    case ACPI_TYPE_LOCAL_BANK_FIELD:
    case ACPI_TYPE_LOCAL_INDEX_FIELD:

        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "FieldRead SourceDesc=%p Type=%X\n",
            StackDesc, StackDesc->Common.Type));

        Status = AcpiExReadDataFromField (WalkState, StackDesc, &ObjDesc);

        /* Remove a reference to the original operand, then override */

        AcpiUtRemoveReference (*StackPtr);
        *StackPtr = (void *) ObjDesc;
        break;

    default:

        break;
    }

    return_ACPI_STATUS (Status);
}
예제 #4
0
ACPI_STATUS
AcpiExResolveMultiple (
    ACPI_WALK_STATE         *WalkState,
    ACPI_OPERAND_OBJECT     *Operand,
    ACPI_OBJECT_TYPE        *ReturnType,
    ACPI_OPERAND_OBJECT     **ReturnDesc)
{
    ACPI_OPERAND_OBJECT     *ObjDesc = (void *) Operand;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_OBJECT_TYPE        Type;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (AcpiExResolveMultiple);


    /* Operand can be either a namespace node or an operand descriptor */

    switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
    {
    case ACPI_DESC_TYPE_OPERAND:
        Type = ObjDesc->Common.Type;
        break;

    case ACPI_DESC_TYPE_NAMED:
        Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type;
        ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc);

        /* If we had an Alias node, use the attached object for type info */

        if (Type == ACPI_TYPE_LOCAL_ALIAS)
        {
            Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type;
            ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc);
        }
        break;

    default:
        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
    }

    /* If type is anything other than a reference, we are done */

    if (Type != ACPI_TYPE_LOCAL_REFERENCE)
    {
        goto Exit;
    }

    /*
     * For reference objects created via the RefOf, Index, or Load/LoadTable
     * operators, we need to get to the base object (as per the ACPI
     * specification of the ObjectType and SizeOf operators). This means
     * traversing the list of possibly many nested references.
     */
    while (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)
    {
        switch (ObjDesc->Reference.Class)
        {
        case ACPI_REFCLASS_REFOF:
        case ACPI_REFCLASS_NAME:

            /* Dereference the reference pointer */

            if (ObjDesc->Reference.Class == ACPI_REFCLASS_REFOF)
            {
                Node = ObjDesc->Reference.Object;
            }
            else /* AML_INT_NAMEPATH_OP */
            {
                Node = ObjDesc->Reference.Node;
            }

            /* All "References" point to a NS node */

            if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
            {
                ACPI_ERROR ((AE_INFO,
                    "Not a namespace node %p [%s]",
                    Node, AcpiUtGetDescriptorName (Node)));
                return_ACPI_STATUS (AE_AML_INTERNAL);
            }

            /* Get the attached object */

            ObjDesc = AcpiNsGetAttachedObject (Node);
            if (!ObjDesc)
            {
                /* No object, use the NS node type */

                Type = AcpiNsGetType (Node);
                goto Exit;
            }

            /* Check for circular references */

            if (ObjDesc == Operand)
            {
                return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
            }
            break;


        case ACPI_REFCLASS_INDEX:

            /* Get the type of this reference (index into another object) */

            Type = ObjDesc->Reference.TargetType;
            if (Type != ACPI_TYPE_PACKAGE)
            {
                goto Exit;
            }

            /*
             * The main object is a package, we want to get the type
             * of the individual package element that is referenced by
             * the index.
             *
             * This could of course in turn be another reference object.
             */
            ObjDesc = *(ObjDesc->Reference.Where);
            if (!ObjDesc)
            {
                /* NULL package elements are allowed */

                Type = 0; /* Uninitialized */
                goto Exit;
            }
            break;


        case ACPI_REFCLASS_TABLE:

            Type = ACPI_TYPE_DDB_HANDLE;
            goto Exit;


        case ACPI_REFCLASS_LOCAL:
        case ACPI_REFCLASS_ARG:

            if (ReturnDesc)
            {
                Status = AcpiDsMethodDataGetValue (ObjDesc->Reference.Class,
                            ObjDesc->Reference.Value, WalkState, &ObjDesc);
                if (ACPI_FAILURE (Status))
                {
                    return_ACPI_STATUS (Status);
                }
                AcpiUtRemoveReference (ObjDesc);
            }
            else
            {
                Status = AcpiDsMethodDataGetNode (ObjDesc->Reference.Class,
                            ObjDesc->Reference.Value, WalkState, &Node);
                if (ACPI_FAILURE (Status))
                {
                    return_ACPI_STATUS (Status);
                }

                ObjDesc = AcpiNsGetAttachedObject (Node);
                if (!ObjDesc)
                {
                    Type = ACPI_TYPE_ANY;
                    goto Exit;
                }
            }
            break;


        case ACPI_REFCLASS_DEBUG:

            /* The Debug Object is of type "DebugObject" */

            Type = ACPI_TYPE_DEBUG_OBJECT;
            goto Exit;


        default:

            ACPI_ERROR ((AE_INFO,
                "Unknown Reference Class 0x%2.2X", ObjDesc->Reference.Class));
            return_ACPI_STATUS (AE_AML_INTERNAL);
        }
    }

    /*
     * Now we are guaranteed to have an object that has not been created
     * via the RefOf or Index operators.
     */
    Type = ObjDesc->Common.Type;


Exit:
    /* Convert internal types to external types */

    switch (Type)
    {
    case ACPI_TYPE_LOCAL_REGION_FIELD:
    case ACPI_TYPE_LOCAL_BANK_FIELD:
    case ACPI_TYPE_LOCAL_INDEX_FIELD:

        Type = ACPI_TYPE_FIELD_UNIT;
        break;

    case ACPI_TYPE_LOCAL_SCOPE:

        /* Per ACPI Specification, Scope is untyped */

        Type = ACPI_TYPE_ANY;
        break;

    default:
        /* No change to Type required */
        break;
    }

    *ReturnType = Type;
    if (ReturnDesc)
    {
        *ReturnDesc = ObjDesc;
    }
    return_ACPI_STATUS (AE_OK);
}