Ejemplo n.º 1
0
ACPI_STATUS
AcpiDsMethodDataSetEntry (
    UINT16                  Opcode,
    UINT32                  Index,
    ACPI_OPERAND_OBJECT     *Object,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status;
    ACPI_OPERAND_OBJECT     **Entry;


    FUNCTION_TRACE ("DsMethodDataSetEntry");


    /* Get a pointer to the stack entry to set */

    Status = AcpiDsMethodDataGetEntry (Opcode, Index, WalkState, &Entry);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Increment ref count so object can't be deleted while installed */

    AcpiUtAddReference (Object);

    /* Install the object into the stack entry */

    *Entry = Object;

    return_ACPI_STATUS (AE_OK);
}
Ejemplo n.º 2
0
ACPI_STATUS
AcpiEvAttachRegion (
    ACPI_OPERAND_OBJECT     *HandlerObj,
    ACPI_OPERAND_OBJECT     *RegionObj,
    BOOLEAN                 AcpiNsIsLocked)
{

    ACPI_FUNCTION_TRACE (EvAttachRegion);


    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "Adding Region [%4.4s] %p to address handler %p [%s]\n",
        AcpiUtGetNodeName (RegionObj->Region.Node),
        RegionObj, HandlerObj,
        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));

    /* Link this region to the front of the handler's list */

    RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
    HandlerObj->AddressSpace.RegionList = RegionObj;

    /* Install the region's handler */

    if (RegionObj->Region.Handler)
    {
        return_ACPI_STATUS (AE_ALREADY_EXISTS);
    }

    RegionObj->Region.Handler = HandlerObj;
    AcpiUtAddReference (HandlerObj);

    return_ACPI_STATUS (AE_OK);
}
Ejemplo n.º 3
0
static void
AcpiNsResolveReferences (
    ACPI_EVALUATE_INFO      *Info)
{
    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    ACPI_NAMESPACE_NODE     *Node;


    /* We are interested in reference objects only */

    if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
    {
        return;
    }

    /*
     * Two types of references are supported - those created by Index and
     * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
     * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
     * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
     * an ACPI_OBJECT.
     */
    switch (Info->ReturnObject->Reference.Class)
    {
    case ACPI_REFCLASS_INDEX:

        ObjDesc = *(Info->ReturnObject->Reference.Where);
        break;

    case ACPI_REFCLASS_REFOF:

        Node = Info->ReturnObject->Reference.Object;
        if (Node)
        {
            ObjDesc = Node->Object;
        }
        break;

    default:

        return;
    }

    /* Replace the existing reference object */

    if (ObjDesc)
    {
        AcpiUtAddReference (ObjDesc);
        AcpiUtRemoveReference (Info->ReturnObject);
        Info->ReturnObject = ObjDesc;
    }

    return;
}
Ejemplo n.º 4
0
BOOLEAN
AcpiDsDoImplicitReturn (
    ACPI_OPERAND_OBJECT     *ReturnDesc,
    ACPI_WALK_STATE         *WalkState,
    BOOLEAN                 AddReference)
{
    ACPI_FUNCTION_NAME (DsDoImplicitReturn);


    /*
     * Slack must be enabled for this feature, and we must
     * have a valid return object
     */
    if ((!AcpiGbl_EnableInterpreterSlack) ||
        (!ReturnDesc))
    {
        return (FALSE);
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
            "Result %p will be implicitly returned; Prev=%p\n",
            ReturnDesc,
            WalkState->ImplicitReturnObj));

    /*
     * Delete any "stale" implicit return value first. However, in
     * complex statements, the implicit return value can be
     * bubbled up several levels, so we don't clear the value if it
     * is the same as the ReturnDesc.
     */
    if (WalkState->ImplicitReturnObj)
    {
        if (WalkState->ImplicitReturnObj == ReturnDesc)
        {
            return (TRUE);
        }
        AcpiDsClearImplicitReturn (WalkState);
    }

    /* Save the implicit return value, add a reference if requested */

    WalkState->ImplicitReturnObj = ReturnDesc;
    if (AddReference)
    {
        AcpiUtAddReference (ReturnDesc);
    }

    return (TRUE);
}
Ejemplo n.º 5
0
static ACPI_STATUS
AcpiDsMethodDataSetValue (
    UINT8                   Type,
    UINT32                  Index,
    ACPI_OPERAND_OBJECT     *Object,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;


    ACPI_FUNCTION_TRACE (DsMethodDataSetValue);


    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
        "NewObj %p Type %2.2X, Refs=%u [%s]\n", Object,
        Type, Object->Common.ReferenceCount,
        AcpiUtGetTypeName (Object->Common.Type)));

    /* Get the namespace node for the arg/local */

    Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * Increment ref count so object can't be deleted while installed.
     * NOTE: We do not copy the object in order to preserve the call by
     * reference semantics of ACPI Control Method invocation.
     * (See ACPI Specification 2.0C)
     */
    AcpiUtAddReference (Object);

    /* Install the object */

    Node->Object = Object;
    return_ACPI_STATUS (Status);
}
Ejemplo n.º 6
0
ACPI_STATUS
AcpiInstallNotifyHandler (
    ACPI_HANDLE             Device,
    UINT32                  HandlerType,
    ACPI_NOTIFY_HANDLER     Handler,
    void                    *Context)
{
    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_STATUS             Status;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);


    /* Parameter validation */

    if ((!Device) || (!Handler) || (!HandlerType) ||
        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * Root Object:
     * Registering a notify handler on the root object indicates that the
     * caller wishes to receive notifications for all objects. Note that
     * only one global handler can be registered per notify type.
     * Ensure that a handler is not already installed.
     */
    if (Device == ACPI_ROOT_OBJECT)
    {
        for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
        {
            if (HandlerType & (i+1))
            {
                if (AcpiGbl_GlobalNotify[i].Handler)
                {
                    Status = AE_ALREADY_EXISTS;
                    goto UnlockAndExit;
                }

                AcpiGbl_GlobalNotify[i].Handler = Handler;
                AcpiGbl_GlobalNotify[i].Context = Context;
            }
        }

        goto UnlockAndExit; /* Global notify handler installed, all done */
    }

    /*
     * All Other Objects:
     * Caller will only receive notifications specific to the target
     * object. Note that only certain object types are allowed to
     * receive notifications.
     */

    /* Are Notifies allowed on this object? */

    if (!AcpiEvIsNotifyObject (Node))
    {
        Status = AE_TYPE;
        goto UnlockAndExit;
    }

    /* Check for an existing internal object, might not exist */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (!ObjDesc)
    {
        /* Create a new object */

        ObjDesc = AcpiUtCreateInternalObject (Node->Type);
        if (!ObjDesc)
        {
            Status = AE_NO_MEMORY;
            goto UnlockAndExit;
        }

        /* Attach new object to the Node, remove local reference */

        Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
        AcpiUtRemoveReference (ObjDesc);
        if (ACPI_FAILURE (Status))
        {
            goto UnlockAndExit;
        }
    }

    /* Ensure that the handler is not already installed in the lists */

    for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
    {
        if (HandlerType & (i+1))
        {
            HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
            while (HandlerObj)
            {
                if (HandlerObj->Notify.Handler == Handler)
                {
                    Status = AE_ALREADY_EXISTS;
                    goto UnlockAndExit;
                }

                HandlerObj = HandlerObj->Notify.Next[i];
            }
        }
    }

    /* Create and populate a new notify handler object */

    HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
    if (!HandlerObj)
    {
        Status = AE_NO_MEMORY;
        goto UnlockAndExit;
    }

    HandlerObj->Notify.Node = Node;
    HandlerObj->Notify.HandlerType = HandlerType;
    HandlerObj->Notify.Handler = Handler;
    HandlerObj->Notify.Context = Context;

    /* Install the handler at the list head(s) */

    for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
    {
        if (HandlerType & (i+1))
        {
            HandlerObj->Notify.Next[i] =
                ObjDesc->CommonNotify.NotifyList[i];

            ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
        }
    }

    /* Add an extra reference if handler was installed in both lists */

    if (HandlerType == ACPI_ALL_NOTIFY)
    {
        AcpiUtAddReference (HandlerObj);
    }


UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_ACPI_STATUS (Status);
}
Ejemplo n.º 7
0
ACPI_STATUS
AcpiNsConvertToReference (
    ACPI_NAMESPACE_NODE     *Scope,
    ACPI_OPERAND_OBJECT     *OriginalObject,
    ACPI_OPERAND_OBJECT     **ReturnObject)
{
    ACPI_OPERAND_OBJECT     *NewObject = NULL;
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_GENERIC_STATE      ScopeInfo;
    char                    *Name;


    ACPI_FUNCTION_NAME (NsConvertToReference);


    /* Convert path into internal presentation */

    Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Find the namespace node */

    ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope);
    Status = AcpiNsLookup (&ScopeInfo, Name,
        ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node);
    if (ACPI_FAILURE (Status))
    {
        /* Check if we are resolving a named reference within a package */

        ACPI_ERROR_NAMESPACE (&ScopeInfo,
            OriginalObject->String.Pointer, Status);
        goto ErrorExit;
    }

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

    NewObject = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
    if (!NewObject)
    {
        Status = AE_NO_MEMORY;
        goto ErrorExit;
    }
    NewObject->Reference.Node = Node;
    NewObject->Reference.Object = Node->Object;
    NewObject->Reference.Class = ACPI_REFCLASS_NAME;

    /*
     * Increase reference of the object if needed (the object is likely a
     * null for device nodes).
     */
    AcpiUtAddReference (Node->Object);

ErrorExit:
    ACPI_FREE (Name);
    *ReturnObject = NewObject;
    return (AE_OK);
}
Ejemplo n.º 8
0
ACPI_STATUS
AcpiDsExecEndOp (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_PARSE_OBJECT       *Op;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  OpType;
    UINT32                  OpClass;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_PARSE_OBJECT       *FirstArg;


    ACPI_FUNCTION_TRACE_PTR (DsExecEndOp, WalkState);


    Op = WalkState->Op;
    OpType = WalkState->OpInfo->Type;
    OpClass = WalkState->OpInfo->Class;

    if (OpClass == AML_CLASS_UNKNOWN)
    {
        ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%X", Op->Common.AmlOpcode));
        return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
    }

    FirstArg = Op->Common.Value.Arg;

    /* Init the walk state */

    WalkState->NumOperands = 0;
    WalkState->OperandIndex = 0;
    WalkState->ReturnDesc = NULL;
    WalkState->ResultObj = NULL;

    /* Call debugger for single step support (DEBUG build only) */

    Status = AcpiDbSingleStep (WalkState, Op, OpClass);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Decode the Opcode Class */

    switch (OpClass)
    {
    case AML_CLASS_ARGUMENT:    /* Constants, literals, etc. */

        if (WalkState->Opcode == AML_INT_NAMEPATH_OP)
        {
            Status = AcpiDsEvaluateNamePath (WalkState);
            if (ACPI_FAILURE (Status))
            {
                goto Cleanup;
            }
        }
        break;

    case AML_CLASS_EXECUTE:     /* Most operators with arguments */

        /* Build resolved operand stack */

        Status = AcpiDsCreateOperands (WalkState, FirstArg);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }

        /*
         * All opcodes require operand resolution, with the only exceptions
         * being the ObjectType and SizeOf operators.
         */
        if (!(WalkState->OpInfo->Flags & AML_NO_OPERAND_RESOLVE))
        {
            /* Resolve all operands */

            Status = AcpiExResolveOperands (WalkState->Opcode,
                &(WalkState->Operands [WalkState->NumOperands -1]),
                WalkState);
        }

        if (ACPI_SUCCESS (Status))
        {
            /*
             * Dispatch the request to the appropriate interpreter handler
             * routine. There is one routine per opcode "type" based upon the
             * number of opcode arguments and return type.
             */
            Status = AcpiGbl_OpTypeDispatch[OpType] (WalkState);
        }
        else
        {
            /*
             * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the
             * Local is uninitialized.
             */
            if  ((Status == AE_AML_UNINITIALIZED_LOCAL) &&
                (WalkState->Opcode == AML_STORE_OP) &&
                (WalkState->Operands[0]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) &&
                (WalkState->Operands[1]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) &&
                (WalkState->Operands[0]->Reference.Class ==
                 WalkState->Operands[1]->Reference.Class) &&
                (WalkState->Operands[0]->Reference.Value ==
                 WalkState->Operands[1]->Reference.Value))
            {
                Status = AE_OK;
            }
            else
            {
                ACPI_EXCEPTION ((AE_INFO, Status,
                    "While resolving operands for [%s]",
                    AcpiPsGetOpcodeName (WalkState->Opcode)));
            }
        }

        /* Always delete the argument objects and clear the operand stack */

        AcpiDsClearOperands (WalkState);

        /*
         * If a result object was returned from above, push it on the
         * current result stack
         */
        if (ACPI_SUCCESS (Status) &&
            WalkState->ResultObj)
        {
            Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
        }
        break;

    default:

        switch (OpType)
        {
        case AML_TYPE_CONTROL:    /* Type 1 opcode, IF/ELSE/WHILE/NOOP */

            /* 1 Operand, 0 ExternalResult, 0 InternalResult */

            Status = AcpiDsExecEndControlOp (WalkState, Op);

            break;

        case AML_TYPE_METHOD_CALL:
            /*
             * If the method is referenced from within a package
             * declaration, it is not a invocation of the method, just
             * a reference to it.
             */
            if ((Op->Asl.Parent) &&
               ((Op->Asl.Parent->Asl.AmlOpcode == AML_PACKAGE_OP) ||
                (Op->Asl.Parent->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)))
            {
                ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                    "Method Reference in a Package, Op=%p\n", Op));

                Op->Common.Node = (ACPI_NAMESPACE_NODE *)
                    Op->Asl.Value.Arg->Asl.Node;
                AcpiUtAddReference (Op->Asl.Value.Arg->Asl.Node->Object);
                return_ACPI_STATUS (AE_OK);
            }

            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                "Method invocation, Op=%p\n", Op));

            /*
             * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
             * the method Node pointer
             */
            /* NextOp points to the op that holds the method name */

            NextOp = FirstArg;

            /* NextOp points to first argument op */

            NextOp = NextOp->Common.Next;

            /*
             * Get the method's arguments and put them on the operand stack
             */
            Status = AcpiDsCreateOperands (WalkState, NextOp);
            if (ACPI_FAILURE (Status))
            {
                break;
            }

            /*
             * Since the operands will be passed to another control method,
             * we must resolve all local references here (Local variables,
             * arguments to *this* method, etc.)
             */
            Status = AcpiDsResolveOperands (WalkState);
            if (ACPI_FAILURE (Status))
            {
                /* On error, clear all resolved operands */

                AcpiDsClearOperands (WalkState);
                break;
            }

            /*
             * Tell the walk loop to preempt this running method and
             * execute the new method
             */
            Status = AE_CTRL_TRANSFER;

            /*
             * Return now; we don't want to disturb anything,
             * especially the operand count!
             */
            return_ACPI_STATUS (Status);

        case AML_TYPE_CREATE_FIELD:

            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
                "Executing CreateField Buffer/Index Op=%p\n", Op));

            Status = AcpiDsLoad2EndOp (WalkState);
            if (ACPI_FAILURE (Status))
            {
                break;
            }

            Status = AcpiDsEvalBufferFieldOperands (WalkState, Op);
            break;


        case AML_TYPE_CREATE_OBJECT:

            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
                "Executing CreateObject (Buffer/Package) Op=%p\n", Op));

            switch (Op->Common.Parent->Common.AmlOpcode)
            {
            case AML_NAME_OP:
                /*
                 * Put the Node on the object stack (Contains the ACPI Name
                 * of this object)
                 */
                WalkState->Operands[0] = (void *)
                    Op->Common.Parent->Common.Node;
                WalkState->NumOperands = 1;

                Status = AcpiDsCreateNode (WalkState,
                    Op->Common.Parent->Common.Node, Op->Common.Parent);
                if (ACPI_FAILURE (Status))
                {
                    break;
                }

                /* Fall through */
                /*lint -fallthrough */

            case AML_INT_EVAL_SUBTREE_OP:

                Status = AcpiDsEvalDataObjectOperands (WalkState, Op,
                    AcpiNsGetAttachedObject (Op->Common.Parent->Common.Node));
                break;

            default:

                Status = AcpiDsEvalDataObjectOperands (WalkState, Op, NULL);
                break;
            }

            /*
             * If a result object was returned from above, push it on the
             * current result stack
             */
            if (WalkState->ResultObj)
            {
                Status = AcpiDsResultPush (WalkState->ResultObj, WalkState);
            }
            break;

        case AML_TYPE_NAMED_FIELD:
        case AML_TYPE_NAMED_COMPLEX:
        case AML_TYPE_NAMED_SIMPLE:
        case AML_TYPE_NAMED_NO_OBJ:

            Status = AcpiDsLoad2EndOp (WalkState);
            if (ACPI_FAILURE (Status))
            {
                break;
            }

            if (Op->Common.AmlOpcode == AML_REGION_OP)
            {
                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
                    "Executing OpRegion Address/Length Op=%p\n", Op));

                Status = AcpiDsEvalRegionOperands (WalkState, Op);
                if (ACPI_FAILURE (Status))
                {
                    break;
                }
            }
            else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP)
            {
                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
                    "Executing DataTableRegion Strings Op=%p\n", Op));

                Status = AcpiDsEvalTableRegionOperands (WalkState, Op);
                if (ACPI_FAILURE (Status))
                {
                    break;
                }
            }
            else if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP)
            {
                ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
                    "Executing BankField Op=%p\n", Op));

                Status = AcpiDsEvalBankFieldOperands (WalkState, Op);
                if (ACPI_FAILURE (Status))
                {
                    break;
                }
            }
            break;

        case AML_TYPE_UNDEFINED:

            ACPI_ERROR ((AE_INFO,
                "Undefined opcode type Op=%p", Op));
            return_ACPI_STATUS (AE_NOT_IMPLEMENTED);

        case AML_TYPE_BOGUS:

            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                "Internal opcode=%X type Op=%p\n",
                WalkState->Opcode, Op));
            break;

        default:

            ACPI_ERROR ((AE_INFO,
                "Unimplemented opcode, class=0x%X "
                "type=0x%X Opcode=0x%X Op=%p",
                OpClass, OpType, Op->Common.AmlOpcode, Op));

            Status = AE_NOT_IMPLEMENTED;
            break;
        }
    }

    /*
     * ACPI 2.0 support for 64-bit integers: Truncate numeric
     * result value if we are executing from a 32-bit ACPI table
     */
    (void) AcpiExTruncateFor32bitTable (WalkState->ResultObj);

    /*
     * Check if we just completed the evaluation of a
     * conditional predicate
     */
    if ((ACPI_SUCCESS (Status)) &&
        (WalkState->ControlState) &&
        (WalkState->ControlState->Common.State ==
            ACPI_CONTROL_PREDICATE_EXECUTING) &&
        (WalkState->ControlState->Control.PredicateOp == Op))
    {
        Status = AcpiDsGetPredicateValue (WalkState, WalkState->ResultObj);
        WalkState->ResultObj = NULL;
    }


Cleanup:

    if (WalkState->ResultObj)
    {
        /* Break to debugger to display result */

        AcpiDbDisplayResultObject (WalkState->ResultObj,WalkState);

        /*
         * Delete the result op if and only if:
         * Parent will not use the result -- such as any
         * non-nested type2 op in a method (parent will be method)
         */
        AcpiDsDeleteResultIfNotUsed (Op, WalkState->ResultObj, WalkState);
    }

#ifdef _UNDER_DEVELOPMENT

    if (WalkState->ParserState.Aml == WalkState->ParserState.AmlEnd)
    {
        AcpiDbMethodEnd (WalkState);
    }
#endif

    /* Invoke exception handler on error */

    if (ACPI_FAILURE (Status))
    {
        Status = AcpiDsMethodError (Status, WalkState);
    }

    /* Always clear the object stack */

    WalkState->NumOperands = 0;
    return_ACPI_STATUS (Status);
}
Ejemplo n.º 9
0
static ACPI_STATUS
AcpiUtCopySimpleObject (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     *DestDesc)
{
    UINT16                  ReferenceCount;
    ACPI_OPERAND_OBJECT     *NextObject;


    /* Save fields from destination that we don't want to overwrite */

    ReferenceCount = DestDesc->Common.ReferenceCount;
    NextObject = DestDesc->Common.NextObject;

    /* Copy the entire source object over the destination object*/

    ACPI_MEMCPY ((char *) DestDesc, (char *) SourceDesc,
                    sizeof (ACPI_OPERAND_OBJECT));

    /* Restore the saved fields */

    DestDesc->Common.ReferenceCount = ReferenceCount;
    DestDesc->Common.NextObject = NextObject;

    /* New object is not static, regardless of source */

    DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;

    /* Handle the objects with extra data */

    switch (ACPI_GET_OBJECT_TYPE (DestDesc))
    {
    case ACPI_TYPE_BUFFER:
        /*
         * Allocate and copy the actual buffer if and only if:
         * 1) There is a valid buffer pointer
         * 2) The buffer has a length > 0
         */
        if ((SourceDesc->Buffer.Pointer) &&
            (SourceDesc->Buffer.Length))
        {
            DestDesc->Buffer.Pointer =
                ACPI_ALLOCATE (SourceDesc->Buffer.Length);
            if (!DestDesc->Buffer.Pointer)
            {
                return (AE_NO_MEMORY);
            }

            /* Copy the actual buffer data */

            ACPI_MEMCPY (DestDesc->Buffer.Pointer,
                    SourceDesc->Buffer.Pointer,
                    SourceDesc->Buffer.Length);
        }
        break;

    case ACPI_TYPE_STRING:
        /*
         * Allocate and copy the actual string if and only if:
         * 1) There is a valid string pointer
         * (Pointer to a NULL string is allowed)
         */
        if (SourceDesc->String.Pointer)
        {
            DestDesc->String.Pointer =
                ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
            if (!DestDesc->String.Pointer)
            {
                return (AE_NO_MEMORY);
            }

            /* Copy the actual string data */

            ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
                         (ACPI_SIZE) SourceDesc->String.Length + 1);
        }
        break;

    case ACPI_TYPE_LOCAL_REFERENCE:
        /*
         * We copied the reference object, so we now must add a reference
         * to the object pointed to by the reference
         *
         * DDBHandle reference (from Load/LoadTable is a special reference,
         * it's Reference.Object is the table index, so does not need to
         * increase the reference count
         */
        if (SourceDesc->Reference.Opcode == AML_LOAD_OP)
        {
            break;
        }

        AcpiUtAddReference (SourceDesc->Reference.Object);
        break;

    case ACPI_TYPE_REGION:
        /*
         * We copied the Region Handler, so we now must add a reference
         */
        if (DestDesc->Region.Handler)
        {
            AcpiUtAddReference (DestDesc->Region.Handler);
        }
        break;

    default:
        /* Nothing to do for other simple objects */
        break;
    }

    return (AE_OK);
}
Ejemplo n.º 10
0
ACPI_STATUS
AcpiExResolveNodeToValue (
    ACPI_NAMESPACE_NODE     **ObjectPtr,
    ACPI_WALK_STATE         *WalkState)

{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *SourceDesc;
    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_OBJECT_TYPE        EntryType;


    ACPI_FUNCTION_TRACE (ExResolveNodeToValue);


    /*
     * The stack pointer points to a ACPI_NAMESPACE_NODE (Node). Get the
     * object that is attached to the Node.
     */
    Node       = *ObjectPtr;
    SourceDesc = AcpiNsGetAttachedObject (Node);
    EntryType  = AcpiNsGetType ((ACPI_HANDLE) Node);

    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n",
         Node, SourceDesc, AcpiUtGetTypeName (EntryType)));

    if ((EntryType == ACPI_TYPE_LOCAL_ALIAS) ||
        (EntryType == ACPI_TYPE_LOCAL_METHOD_ALIAS))
    {
        /* There is always exactly one level of indirection */

        Node       = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Node->Object);
        SourceDesc = AcpiNsGetAttachedObject (Node);
        EntryType  = AcpiNsGetType ((ACPI_HANDLE) Node);
        *ObjectPtr = Node;
    }

    /*
     * Several object types require no further processing:
     * 1) Device/Thermal objects don't have a "real" subobject, return the Node
     * 2) Method locals and arguments have a pseudo-Node
     * 3) 10/2007: Added method type to assist with Package construction.
     */
    if ((EntryType == ACPI_TYPE_DEVICE)  ||
        (EntryType == ACPI_TYPE_THERMAL) ||
        (EntryType == ACPI_TYPE_METHOD)  ||
        (Node->Flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL)))
    {
        return_ACPI_STATUS (AE_OK);
    }

    if (!SourceDesc)
    {
        ACPI_ERROR ((AE_INFO, "No object attached to node %p",
            Node));
        return_ACPI_STATUS (AE_AML_NO_OPERAND);
    }

    /*
     * Action is based on the type of the Node, which indicates the type
     * of the attached object or pointer
     */
    switch (EntryType)
    {
    case ACPI_TYPE_PACKAGE:

        if (SourceDesc->Common.Type != ACPI_TYPE_PACKAGE)
        {
            ACPI_ERROR ((AE_INFO, "Object not a Package, type %s",
                AcpiUtGetObjectTypeName (SourceDesc)));
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        Status = AcpiDsGetPackageArguments (SourceDesc);
        if (ACPI_SUCCESS (Status))
        {
            /* Return an additional reference to the object */

            ObjDesc = SourceDesc;
            AcpiUtAddReference (ObjDesc);
        }
        break;


    case ACPI_TYPE_BUFFER:

        if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER)
        {
            ACPI_ERROR ((AE_INFO, "Object not a Buffer, type %s",
                AcpiUtGetObjectTypeName (SourceDesc)));
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        Status = AcpiDsGetBufferArguments (SourceDesc);
        if (ACPI_SUCCESS (Status))
        {
            /* Return an additional reference to the object */

            ObjDesc = SourceDesc;
            AcpiUtAddReference (ObjDesc);
        }
        break;


    case ACPI_TYPE_STRING:

        if (SourceDesc->Common.Type != ACPI_TYPE_STRING)
        {
            ACPI_ERROR ((AE_INFO, "Object not a String, type %s",
                AcpiUtGetObjectTypeName (SourceDesc)));
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        /* Return an additional reference to the object */

        ObjDesc = SourceDesc;
        AcpiUtAddReference (ObjDesc);
        break;


    case ACPI_TYPE_INTEGER:

        if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER)
        {
            ACPI_ERROR ((AE_INFO, "Object not a Integer, type %s",
                AcpiUtGetObjectTypeName (SourceDesc)));
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        /* Return an additional reference to the object */

        ObjDesc = SourceDesc;
        AcpiUtAddReference (ObjDesc);
        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 Node=%p SourceDesc=%p Type=%X\n",
            Node, SourceDesc, EntryType));

        Status = AcpiExReadDataFromField (WalkState, SourceDesc, &ObjDesc);
        break;

    /* For these objects, just return the object attached to the Node */

    case ACPI_TYPE_MUTEX:
    case ACPI_TYPE_POWER:
    case ACPI_TYPE_PROCESSOR:
    case ACPI_TYPE_EVENT:
    case ACPI_TYPE_REGION:

        /* Return an additional reference to the object */

        ObjDesc = SourceDesc;
        AcpiUtAddReference (ObjDesc);
        break;

    /* TYPE_ANY is untyped, and thus there is no object associated with it */

    case ACPI_TYPE_ANY:

        ACPI_ERROR ((AE_INFO,
            "Untyped entry %p, no attached object!", Node));

        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);  /* Cannot be AE_TYPE */


    case ACPI_TYPE_LOCAL_REFERENCE:

        switch (SourceDesc->Reference.Class)
        {
        case ACPI_REFCLASS_TABLE:   /* This is a DdbHandle */
        case ACPI_REFCLASS_REFOF:
        case ACPI_REFCLASS_INDEX:

            /* Return an additional reference to the object */

            ObjDesc = SourceDesc;
            AcpiUtAddReference (ObjDesc);
            break;

        default:
            /* No named references are allowed here */

            ACPI_ERROR ((AE_INFO,
                "Unsupported Reference type 0x%X",
                SourceDesc->Reference.Class));

            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }
        break;


    default:

        /* Default case is for unknown types */

        ACPI_ERROR ((AE_INFO,
            "Node %p - Unknown object type 0x%X",
            Node, EntryType));

        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);

    } /* switch (EntryType) */


    /* Return the object descriptor */

    *ObjectPtr = (void *) ObjDesc;
    return_ACPI_STATUS (Status);
}
Ejemplo n.º 11
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);
}
Ejemplo n.º 12
0
ACPI_STATUS
AcpiPsxExecute (
    ACPI_NAMESPACE_NODE     *MethodNode,
    ACPI_OPERAND_OBJECT     **Params,
    ACPI_OPERAND_OBJECT     **ReturnObjDesc)
{
    ACPI_STATUS             Status;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    UINT32                  i;
    ACPI_PARSE_OBJECT       *Op;
    ACPI_WALK_STATE         *WalkState;


    ACPI_FUNCTION_TRACE ("PsxExecute");


    /* Validate the Node and get the attached object */

    if (!MethodNode)
    {
        return_ACPI_STATUS (AE_NULL_ENTRY);
    }

    ObjDesc = AcpiNsGetAttachedObject (MethodNode);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NULL_OBJECT);
    }

    /* Init for new method, wait on concurrency semaphore */

    Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc, NULL);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    if (Params)
    {
        /*
         * The caller "owns" the parameters, so give each one an extra
         * reference
         */
        for (i = 0; Params[i]; i++)
        {
            AcpiUtAddReference (Params[i]);
        }
    }

    /*
     * 1) Perform the first pass parse of the method to enter any
     * named objects that it creates into the namespace
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
        "**** Begin Method Parse **** Entry=%p obj=%p\n",
        MethodNode, ObjDesc));

    /* Create and init a Root Node */

    Op = AcpiPsCreateScopeOp ();
    if (!Op)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /*
     * Get a new OwnerId for objects created by this method.  Namespace
     * objects (such as Operation Regions) can be created during the
     * first pass parse.
     */
    ObjDesc->Method.OwningId = AcpiUtAllocateOwnerId (ACPI_OWNER_TYPE_METHOD);

    /* Create and initialize a new walk state */

    WalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwningId,
                                    NULL, NULL, NULL);
    if (!WalkState)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitAmlWalk (WalkState, Op, MethodNode, ObjDesc->Method.AmlStart,
                    ObjDesc->Method.AmlLength, NULL, NULL, 1);
    if (ACPI_FAILURE (Status))
    {
        AcpiDsDeleteWalkState (WalkState);
        return_ACPI_STATUS (Status);
    }

    /* Parse the AML */

    Status = AcpiPsParseAml (WalkState);
    AcpiPsDeleteParseTree (Op);

    /*
     * 2) Execute the method.  Performs second pass parse simultaneously
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
        "**** Begin Method Execution **** Entry=%p obj=%p\n",
        MethodNode, ObjDesc));

    /* Create and init a Root Node */

    Op = AcpiPsCreateScopeOp ();
    if (!Op)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Init new op with the method name and pointer back to the NS node */

    AcpiPsSetName (Op, MethodNode->Name.Integer);
    Op->Common.Node = MethodNode;

    /* Create and initialize a new walk state */

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

    Status = AcpiDsInitAmlWalk (WalkState, Op, MethodNode, ObjDesc->Method.AmlStart,
                    ObjDesc->Method.AmlLength, Params, ReturnObjDesc, 3);
    if (ACPI_FAILURE (Status))
    {
        AcpiDsDeleteWalkState (WalkState);
        return_ACPI_STATUS (Status);
    }

    /*
     * The walk of the parse tree is where we actually execute the method
     */
    Status = AcpiPsParseAml (WalkState);
    AcpiPsDeleteParseTree (Op);

    if (Params)
    {
        /* Take away the extra reference that we gave the parameters above */

        for (i = 0; Params[i]; i++)
        {
            /* Ignore errors, just do them all */

            (void) AcpiUtUpdateObjectReference (Params[i], REF_DECREMENT);
        }
    }

    /*
     * If the method has returned an object, signal this to the caller with
     * a control exception code
     */
    if (*ReturnObjDesc)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
            *ReturnObjDesc));
        ACPI_DUMP_STACK_ENTRY (*ReturnObjDesc);

        Status = AE_CTRL_RETURN_VALUE;
    }

    return_ACPI_STATUS (Status);
}
Ejemplo n.º 13
0
ACPI_STATUS
AcpiDsMethodDataGetValue (
    UINT16                  Opcode,
    UINT32                  Index,
    ACPI_WALK_STATE         *WalkState,
    ACPI_OPERAND_OBJECT     **DestDesc)
{
    ACPI_STATUS             Status;
    ACPI_OPERAND_OBJECT     **Entry;
    ACPI_OPERAND_OBJECT     *Object;


    FUNCTION_TRACE ("DsMethodDataGetValue");


    /* Validate the object descriptor */

    if (!DestDesc)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null object descriptor pointer\n"));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }


    /* Get a pointer to the requested method stack entry */

    Status = AcpiDsMethodDataGetEntry (Opcode, Index, WalkState, &Entry);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the object from the method stack */

    Object = *Entry;


    /* Examine the returned object, it must be valid. */

    if (!Object)
    {
        /*
         * Index points to uninitialized object stack value.
         * This means that either 1) The expected argument was
         * not passed to the method, or 2) A local variable
         * was referenced by the method (via the ASL)
         * before it was initialized.  Either case is an error.
         */
        switch (Opcode)
        {
        case AML_ARG_OP:

            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at entry %p\n",
                               Index, Entry));

            return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG);
            break;

        case AML_LOCAL_OP:

            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Local[%d] at entry %p\n",
                               Index, Entry));

            return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
            break;
        }
    }


    /*
     * Index points to initialized and valid object stack value.
     * Return an additional reference to the object
     */
    *DestDesc = Object;
    AcpiUtAddReference (Object);

    return_ACPI_STATUS (AE_OK);
}
Ejemplo n.º 14
0
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);
}
Ejemplo n.º 15
0
ACPI_STATUS
AcpiExOpcode_2A_1T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
    UINT64                  Index;
    ACPI_STATUS             Status = AE_OK;
    ACPI_SIZE               Length = 0;


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


    /* Execute the opcode */

    if (WalkState->OpInfo->Flags & AML_MATH)
    {
        /* All simple math opcodes (add, etc.) */

        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        ReturnDesc->Integer.Value = AcpiExDoMathOp (WalkState->Opcode,
                                                Operand[0]->Integer.Value,
                                                Operand[1]->Integer.Value);
        goto StoreResultToTarget;
    }

    switch (WalkState->Opcode)
    {
    case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */

        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /* ReturnDesc will contain the remainder */

        Status = AcpiUtDivide (Operand[0]->Integer.Value,
                               Operand[1]->Integer.Value,
                               NULL,
                               &ReturnDesc->Integer.Value);
        break;

    case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */

        Status = AcpiExDoConcatenate (Operand[0], Operand[1],
                    &ReturnDesc, WalkState);
        break;

    case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */
        /*
         * Input object is guaranteed to be a buffer at this point (it may have
         * been converted.)  Copy the raw buffer data to a new object of
         * type String.
         */

        /*
         * Get the length of the new string. It is the smallest of:
         * 1) Length of the input buffer
         * 2) Max length as specified in the ToString operator
         * 3) Length of input buffer up to a zero byte (null terminator)
         *
         * NOTE: A length of zero is ok, and will create a zero-length, null
         *       terminated string.
         */
        while ((Length < Operand[0]->Buffer.Length) &&
               (Length < Operand[1]->Integer.Value) &&
               (Operand[0]->Buffer.Pointer[Length]))
        {
            Length++;
        }

        /* Allocate a new string object */

        ReturnDesc = AcpiUtCreateStringObject (Length);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /*
         * Copy the raw buffer data with no transform.
         * (NULL terminated already)
         */
        ACPI_MEMCPY (ReturnDesc->String.Pointer,
            Operand[0]->Buffer.Pointer, Length);
        break;

    case AML_CONCAT_RES_OP:

        /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */

        Status = AcpiExConcatTemplate (Operand[0], Operand[1],
                    &ReturnDesc, WalkState);
        break;

    case AML_INDEX_OP:              /* Index (Source Index Result) */

        /* Create the internal return object */

        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /* Initialize the Index reference object */

        Index = Operand[1]->Integer.Value;
        ReturnDesc->Reference.Value = (UINT32) Index;
        ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX;

        /*
         * At this point, the Source operand is a String, Buffer, or Package.
         * Verify that the index is within range.
         */
        switch ((Operand[0])->Common.Type)
        {
        case ACPI_TYPE_STRING:

            if (Index >= Operand[0]->String.Length)
            {
                Length = Operand[0]->String.Length;
                Status = AE_AML_STRING_LIMIT;
            }

            ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD;
            break;

        case ACPI_TYPE_BUFFER:

            if (Index >= Operand[0]->Buffer.Length)
            {
                Length = Operand[0]->Buffer.Length;
                Status = AE_AML_BUFFER_LIMIT;
            }

            ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD;
            break;

        case ACPI_TYPE_PACKAGE:

            if (Index >= Operand[0]->Package.Count)
            {
                Length = Operand[0]->Package.Count;
                Status = AE_AML_PACKAGE_LIMIT;
            }

            ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE;
            ReturnDesc->Reference.Where = &Operand[0]->Package.Elements [Index];
            break;

        default:

            Status = AE_AML_INTERNAL;
            goto Cleanup;
        }

        /* Failure means that the Index was beyond the end of the object */

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
                ACPI_FORMAT_UINT64 (Index), (UINT32) Length));
            goto Cleanup;
        }

        /*
         * Save the target object and add a reference to it for the life
         * of the index
         */
        ReturnDesc->Reference.Object = Operand[0];
        AcpiUtAddReference (Operand[0]);

        /* Store the reference to the Target */

        Status = AcpiExStore (ReturnDesc, Operand[2], WalkState);

        /* Return the reference */

        WalkState->ResultObj = ReturnDesc;
        goto Cleanup;

    default:

        ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
            WalkState->Opcode));
        Status = AE_AML_BAD_OPCODE;
        break;
    }


StoreResultToTarget:

    if (ACPI_SUCCESS (Status))
    {
        /*
         * Store the result of the operation (which is now in ReturnDesc) into
         * the Target descriptor.
         */
        Status = AcpiExStore (ReturnDesc, Operand[2], WalkState);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }

        if (!WalkState->ResultObj)
        {
            WalkState->ResultObj = ReturnDesc;
        }
    }


Cleanup:

    /* Delete return object on error */

    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ReturnDesc);
        WalkState->ResultObj = NULL;
    }

    return_ACPI_STATUS (Status);
}
Ejemplo n.º 16
0
ACPI_STATUS
AcpiExPrepFieldValue (
    ACPI_CREATE_FIELD_INFO  *Info)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *SecondDesc = NULL;
    ACPI_STATUS             Status;
    UINT32                  AccessByteWidth;
    UINT32                  Type;


    ACPI_FUNCTION_TRACE (ExPrepFieldValue);


    /* Parameter validation */

    if (Info->FieldType != ACPI_TYPE_LOCAL_INDEX_FIELD)
    {
        if (!Info->RegionNode)
        {
            ACPI_ERROR ((AE_INFO, "Null RegionNode"));
            return_ACPI_STATUS (AE_AML_NO_OPERAND);
        }

        Type = AcpiNsGetType (Info->RegionNode);
        if (Type != ACPI_TYPE_REGION)
        {
            ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)",
                Type, AcpiUtGetTypeName (Type)));

            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }
    }

    /* Allocate a new field object */

    ObjDesc = AcpiUtCreateInternalObject (Info->FieldType);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Initialize areas of the object that are common to all fields */

    ObjDesc->CommonField.Node = Info->FieldNode;
    Status = AcpiExPrepCommonFieldObject (ObjDesc,
                Info->FieldFlags, Info->Attribute,
                Info->FieldBitPosition, Info->FieldBitLength);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtDeleteObjectDesc (ObjDesc);
        return_ACPI_STATUS (Status);
    }

    /* Initialize areas of the object that are specific to the field type */

    switch (Info->FieldType)
    {
    case ACPI_TYPE_LOCAL_REGION_FIELD:

        ObjDesc->Field.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode);

        /* Fields specific to GenericSerialBus fields */

        ObjDesc->Field.AccessLength = Info->AccessLength;

        if (Info->ConnectionNode)
        {
            SecondDesc = Info->ConnectionNode->Object;
            if (!(SecondDesc->Common.Flags & AOPOBJ_DATA_VALID))
            {
                Status = AcpiDsGetBufferArguments (SecondDesc);
                if (ACPI_FAILURE (Status))
                {
                    AcpiUtDeleteObjectDesc (ObjDesc);
                    return_ACPI_STATUS (Status);
                }
            }

            ObjDesc->Field.ResourceBuffer = SecondDesc->Buffer.Pointer;
            ObjDesc->Field.ResourceLength = (UINT16) SecondDesc->Buffer.Length;
        }
        else if (Info->ResourceBuffer)
        {
            ObjDesc->Field.ResourceBuffer = Info->ResourceBuffer;
            ObjDesc->Field.ResourceLength = Info->ResourceLength;
        }

        /* Allow full data read from EC address space */

        if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
            (ObjDesc->CommonField.BitLength > 8))
        {
            AccessByteWidth = ACPI_ROUND_BITS_UP_TO_BYTES (
                ObjDesc->CommonField.BitLength);

            /* Maximum byte width supported is 255 */

            if (AccessByteWidth < 256)
            {
                ObjDesc->CommonField.AccessByteWidth = (UINT8) AccessByteWidth;
            }
        }

        /* An additional reference for the container */

        AcpiUtAddReference (ObjDesc->Field.RegionObj);

        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
            "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
            ObjDesc->Field.StartFieldBitOffset, ObjDesc->Field.BaseByteOffset,
            ObjDesc->Field.AccessByteWidth, ObjDesc->Field.RegionObj));
        break;

    case ACPI_TYPE_LOCAL_BANK_FIELD:

        ObjDesc->BankField.Value = Info->BankValue;
        ObjDesc->BankField.RegionObj =
            AcpiNsGetAttachedObject (Info->RegionNode);
        ObjDesc->BankField.BankObj =
            AcpiNsGetAttachedObject (Info->RegisterNode);

        /* An additional reference for the attached objects */

        AcpiUtAddReference (ObjDesc->BankField.RegionObj);
        AcpiUtAddReference (ObjDesc->BankField.BankObj);

        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
            "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
            ObjDesc->BankField.StartFieldBitOffset,
            ObjDesc->BankField.BaseByteOffset,
            ObjDesc->Field.AccessByteWidth,
            ObjDesc->BankField.RegionObj,
            ObjDesc->BankField.BankObj));

        /*
         * Remember location in AML stream of the field unit
         * opcode and operands -- since the BankValue
         * operands must be evaluated.
         */
        SecondDesc = ObjDesc->Common.NextObject;
        SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT,
            Info->DataRegisterNode)->Named.Data;
        SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT,
            Info->DataRegisterNode)->Named.Length;

        break;

    case ACPI_TYPE_LOCAL_INDEX_FIELD:

        /* Get the Index and Data registers */

        ObjDesc->IndexField.IndexObj =
            AcpiNsGetAttachedObject (Info->RegisterNode);
        ObjDesc->IndexField.DataObj =
            AcpiNsGetAttachedObject (Info->DataRegisterNode);

        if (!ObjDesc->IndexField.DataObj || !ObjDesc->IndexField.IndexObj)
        {
            ACPI_ERROR ((AE_INFO, "Null Index Object during field prep"));
            AcpiUtDeleteObjectDesc (ObjDesc);
            return_ACPI_STATUS (AE_AML_INTERNAL);
        }

        /* An additional reference for the attached objects */

        AcpiUtAddReference (ObjDesc->IndexField.DataObj);
        AcpiUtAddReference (ObjDesc->IndexField.IndexObj);

        /*
         * April 2006: Changed to match MS behavior
         *
         * The value written to the Index register is the byte offset of the
         * target field in units of the granularity of the IndexField
         *
         * Previously, the value was calculated as an index in terms of the
         * width of the Data register, as below:
         *
         *      ObjDesc->IndexField.Value = (UINT32)
         *          (Info->FieldBitPosition / ACPI_MUL_8 (
         *              ObjDesc->Field.AccessByteWidth));
         *
         * February 2006: Tried value as a byte offset:
         *      ObjDesc->IndexField.Value = (UINT32)
         *          ACPI_DIV_8 (Info->FieldBitPosition);
         */
        ObjDesc->IndexField.Value = (UINT32) ACPI_ROUND_DOWN (
            ACPI_DIV_8 (Info->FieldBitPosition),
            ObjDesc->IndexField.AccessByteWidth);

        ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
            "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
            ObjDesc->IndexField.StartFieldBitOffset,
            ObjDesc->IndexField.BaseByteOffset,
            ObjDesc->IndexField.Value,
            ObjDesc->Field.AccessByteWidth,
            ObjDesc->IndexField.IndexObj,
            ObjDesc->IndexField.DataObj));
        break;

    default:

        /* No other types should get here */

        break;
    }

    /*
     * Store the constructed descriptor (ObjDesc) into the parent Node,
     * preserving the current type of that NamedObj.
     */
    Status = AcpiNsAttachObject (Info->FieldNode, ObjDesc,
                AcpiNsGetType (Info->FieldNode));

    ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set NamedObj %p [%4.4s], ObjDesc %p\n",
        Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc));

    /* Remove local reference to the object */

    AcpiUtRemoveReference (ObjDesc);
    return_ACPI_STATUS (Status);
}
Ejemplo n.º 17
0
static ACPI_STATUS
AcpiUtCopySimpleObject (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     *DestDesc)
{
    UINT16                  ReferenceCount;
    ACPI_OPERAND_OBJECT     *NextObject;
    ACPI_STATUS             Status;
    ACPI_SIZE               CopySize;


    /* Save fields from destination that we don't want to overwrite */

    ReferenceCount = DestDesc->Common.ReferenceCount;
    NextObject = DestDesc->Common.NextObject;

    /*
     * Copy the entire source object over the destination object.
     * Note: Source can be either an operand object or namespace node.
     */
    CopySize = sizeof (ACPI_OPERAND_OBJECT);
    if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
    {
        CopySize = sizeof (ACPI_NAMESPACE_NODE);
    }

    ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc),
                 ACPI_CAST_PTR (char, SourceDesc), CopySize);

    /* Restore the saved fields */

    DestDesc->Common.ReferenceCount = ReferenceCount;
    DestDesc->Common.NextObject = NextObject;

    /* New object is not static, regardless of source */

    DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;

    /* Handle the objects with extra data */

    switch (DestDesc->Common.Type)
    {
    case ACPI_TYPE_BUFFER:
        /*
         * Allocate and copy the actual buffer if and only if:
         * 1) There is a valid buffer pointer
         * 2) The buffer has a length > 0
         */
        if ((SourceDesc->Buffer.Pointer) &&
                (SourceDesc->Buffer.Length))
        {
            DestDesc->Buffer.Pointer =
                ACPI_ALLOCATE (SourceDesc->Buffer.Length);
            if (!DestDesc->Buffer.Pointer)
            {
                return (AE_NO_MEMORY);
            }

            /* Copy the actual buffer data */

            ACPI_MEMCPY (DestDesc->Buffer.Pointer,
                         SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
        }
        break;

    case ACPI_TYPE_STRING:
        /*
         * Allocate and copy the actual string if and only if:
         * 1) There is a valid string pointer
         * (Pointer to a NULL string is allowed)
         */
        if (SourceDesc->String.Pointer)
        {
            DestDesc->String.Pointer =
                ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
            if (!DestDesc->String.Pointer)
            {
                return (AE_NO_MEMORY);
            }

            /* Copy the actual string data */

            ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
                         (ACPI_SIZE) SourceDesc->String.Length + 1);
        }
        break;

    case ACPI_TYPE_LOCAL_REFERENCE:
        /*
         * We copied the reference object, so we now must add a reference
         * to the object pointed to by the reference
         *
         * DDBHandle reference (from Load/LoadTable) is a special reference,
         * it does not have a Reference.Object, so does not need to
         * increase the reference count
         */
        if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
        {
            break;
        }

        AcpiUtAddReference (SourceDesc->Reference.Object);
        break;

    case ACPI_TYPE_REGION:
        /*
         * We copied the Region Handler, so we now must add a reference
         */
        if (DestDesc->Region.Handler)
        {
            AcpiUtAddReference (DestDesc->Region.Handler);
        }
        break;

    /*
     * For Mutex and Event objects, we cannot simply copy the underlying
     * OS object. We must create a new one.
     */
    case ACPI_TYPE_MUTEX:

        Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }
        break;

    case ACPI_TYPE_EVENT:

        Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
                                        &DestDesc->Event.OsSemaphore);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }
        break;

    default:
        /* Nothing to do for other simple objects */
        break;
    }

    return (AE_OK);
}
Ejemplo n.º 18
0
ACPI_STATUS
AcpiDsMethodDataGetValue (
    UINT8                   Type,
    UINT32                  Index,
    ACPI_WALK_STATE         *WalkState,
    ACPI_OPERAND_OBJECT     **DestDesc)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_OPERAND_OBJECT     *Object;


    ACPI_FUNCTION_TRACE (DsMethodDataGetValue);


    /* Validate the object descriptor */

    if (!DestDesc)
    {
        ACPI_ERROR ((AE_INFO, "Null object descriptor pointer"));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Get the namespace node for the arg/local */

    Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Get the object from the node */

    Object = Node->Object;

    /* Examine the returned object, it must be valid. */

    if (!Object)
    {
        /*
         * Index points to uninitialized object.
         * This means that either 1) The expected argument was
         * not passed to the method, or 2) A local variable
         * was referenced by the method (via the ASL)
         * before it was initialized.  Either case is an error.
         */

        /* If slack enabled, init the LocalX/ArgX to an Integer of value zero */

        if (AcpiGbl_EnableInterpreterSlack)
        {
            Object = AcpiUtCreateIntegerObject ((UINT64) 0);
            if (!Object)
            {
                return_ACPI_STATUS (AE_NO_MEMORY);
            }

            Node->Object = Object;
        }

        /* Otherwise, return the error */

        else switch (Type)
        {
        case ACPI_REFCLASS_ARG:

            ACPI_ERROR ((AE_INFO,
                "Uninitialized Arg[%u] at node %p",
                Index, Node));

            return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG);

        case ACPI_REFCLASS_LOCAL:

            /*
             * No error message for this case, will be trapped again later to
             * detect and ignore cases of Store(LocalX,LocalX)
             */
            return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);

        default:

            ACPI_ERROR ((AE_INFO, "Not a Arg/Local opcode: 0x%X", Type));
            return_ACPI_STATUS (AE_AML_INTERNAL);
        }
    }

    /*
     * The Index points to an initialized and valid object.
     * Return an additional reference to the object
     */
    *DestDesc = Object;
    AcpiUtAddReference (Object);

    return_ACPI_STATUS (AE_OK);
}
Ejemplo n.º 19
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);
}
Ejemplo n.º 20
0
static void
AcpiNsExecModuleCode (
    ACPI_OPERAND_OBJECT     *MethodObj,
    ACPI_EVALUATE_INFO      *Info)
{
    ACPI_OPERAND_OBJECT     *ParentObj;
    ACPI_NAMESPACE_NODE     *ParentNode;
    ACPI_OBJECT_TYPE        Type;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsExecModuleCode);


    /*
     * Get the parent node. We cheat by using the NextObject field
     * of the method object descriptor.
     */
    ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
                    MethodObj->Method.NextObject);
    Type = AcpiNsGetType (ParentNode);

    /*
     * Get the region handler and save it in the method object. We may need
     * this if an operation region declaration causes a _REG method to be run.
     *
     * We can't do this in AcpiPsLinkModuleCode because
     * AcpiGbl_RootNode->Object is NULL at PASS1.
     */
    if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object)
    {
        MethodObj->Method.Dispatch.Handler =
            ParentNode->Object->Device.Handler;
    }

    /* Must clear NextObject (AcpiNsAttachObject needs the field) */

    MethodObj->Method.NextObject = NULL;

    /* Initialize the evaluation information block */

    ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO));
    Info->PrefixNode = ParentNode;

    /*
     * Get the currently attached parent object. Add a reference, because the
     * ref count will be decreased when the method object is installed to
     * the parent node.
     */
    ParentObj = AcpiNsGetAttachedObject (ParentNode);
    if (ParentObj)
    {
        AcpiUtAddReference (ParentObj);
    }

    /* Install the method (module-level code) in the parent node */

    Status = AcpiNsAttachObject (ParentNode, MethodObj,
                ACPI_TYPE_METHOD);
    if (ACPI_FAILURE (Status))
    {
        goto Exit;
    }

    /* Execute the parent node as a control method */

    Status = AcpiNsEvaluate (Info);

    ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n",
        MethodObj->Method.AmlStart));

    /* Delete a possible implicit return value (in slack mode) */

    if (Info->ReturnObject)
    {
        AcpiUtRemoveReference (Info->ReturnObject);
    }

    /* Detach the temporary method object */

    AcpiNsDetachObject (ParentNode);

    /* Restore the original parent object */

    if (ParentObj)
    {
        Status = AcpiNsAttachObject (ParentNode, ParentObj, Type);
    }
    else
    {
        ParentNode->Type = (UINT8) Type;
    }

Exit:
    if (ParentObj)
    {
        AcpiUtRemoveReference (ParentObj);
    }
    return_VOID;
}
Ejemplo n.º 21
0
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);
}
Ejemplo n.º 22
0
ACPI_STATUS
AcpiExOpcode_1A_1T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
    ACPI_OPERAND_OBJECT     *ReturnDesc2 = NULL;
    UINT32                  Temp32;
    UINT32                  i;
    UINT64                  PowerOfTen;
    UINT64                  Digit;


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


    /* Examine the AML opcode */

    switch (WalkState->Opcode)
    {
    case AML_BIT_NOT_OP:
    case AML_FIND_SET_LEFT_BIT_OP:
    case AML_FIND_SET_RIGHT_BIT_OP:
    case AML_FROM_BCD_OP:
    case AML_TO_BCD_OP:
    case AML_COND_REF_OF_OP:

        /* Create a return object of type Integer for these opcodes */

        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        switch (WalkState->Opcode)
        {
        case AML_BIT_NOT_OP:            /* Not (Operand, Result)  */

            ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value;
            break;

        case AML_FIND_SET_LEFT_BIT_OP:  /* FindSetLeftBit (Operand, Result) */

            ReturnDesc->Integer.Value = Operand[0]->Integer.Value;

            /*
             * Acpi specification describes Integer type as a little
             * endian unsigned value, so this boundary condition is valid.
             */
            for (Temp32 = 0; ReturnDesc->Integer.Value &&
                    Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32)
            {
                ReturnDesc->Integer.Value >>= 1;
            }

            ReturnDesc->Integer.Value = Temp32;
            break;

        case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */

            ReturnDesc->Integer.Value = Operand[0]->Integer.Value;

            /*
             * The Acpi specification describes Integer type as a little
             * endian unsigned value, so this boundary condition is valid.
             */
            for (Temp32 = 0; ReturnDesc->Integer.Value &&
                     Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32)
            {
                ReturnDesc->Integer.Value <<= 1;
            }

            /* Since the bit position is one-based, subtract from 33 (65) */

            ReturnDesc->Integer.Value =
                Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32;
            break;

        case AML_FROM_BCD_OP:           /* FromBcd (BCDValue, Result)  */
            /*
             * The 64-bit ACPI integer can hold 16 4-bit BCD characters
             * (if table is 32-bit, integer can hold 8 BCD characters)
             * Convert each 4-bit BCD value
             */
            PowerOfTen = 1;
            ReturnDesc->Integer.Value = 0;
            Digit = Operand[0]->Integer.Value;

            /* Convert each BCD digit (each is one nybble wide) */

            for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)
            {
                /* Get the least significant 4-bit BCD digit */

                Temp32 = ((UINT32) Digit) & 0xF;

                /* Check the range of the digit */

                if (Temp32 > 9)
                {
                    ACPI_ERROR ((AE_INFO,
                        "BCD digit too large (not decimal): 0x%X",
                        Temp32));

                    Status = AE_AML_NUMERIC_OVERFLOW;
                    goto Cleanup;
                }

                /* Sum the digit into the result with the current power of 10 */

                ReturnDesc->Integer.Value +=
                    (((UINT64) Temp32) * PowerOfTen);

                /* Shift to next BCD digit */

                Digit >>= 4;

                /* Next power of 10 */

                PowerOfTen *= 10;
            }
            break;

        case AML_TO_BCD_OP:             /* ToBcd (Operand, Result)  */

            ReturnDesc->Integer.Value = 0;
            Digit = Operand[0]->Integer.Value;

            /* Each BCD digit is one nybble wide */

            for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)
            {
                (void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32);

                /*
                 * Insert the BCD digit that resides in the
                 * remainder from above
                 */
                ReturnDesc->Integer.Value |=
                    (((UINT64) Temp32) << ACPI_MUL_4 (i));
            }

            /* Overflow if there is any data left in Digit */

            if (Digit > 0)
            {
                ACPI_ERROR ((AE_INFO,
                    "Integer too large to convert to BCD: 0x%8.8X%8.8X",
                    ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value)));
                Status = AE_AML_NUMERIC_OVERFLOW;
                goto Cleanup;
            }
            break;

        case AML_COND_REF_OF_OP:        /* CondRefOf (SourceObject, Result)  */
            /*
             * This op is a little strange because the internal return value is
             * different than the return value stored in the result descriptor
             * (There are really two return values)
             */
            if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode)
            {
                /*
                 * This means that the object does not exist in the namespace,
                 * return FALSE
                 */
                ReturnDesc->Integer.Value = 0;
                goto Cleanup;
            }

            /* Get the object reference, store it, and remove our reference */

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

            Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState);
            AcpiUtRemoveReference (ReturnDesc2);

            /* The object exists in the namespace, return TRUE */

            ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
            goto Cleanup;


        default:

            /* No other opcodes get here */

            break;
        }
        break;

    case AML_STORE_OP:              /* Store (Source, Target) */
        /*
         * A store operand is typically a number, string, buffer or lvalue
         * Be careful about deleting the source object,
         * since the object itself may have been stored.
         */
        Status = AcpiExStore (Operand[0], Operand[1], WalkState);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

        /* It is possible that the Store already produced a return object */

        if (!WalkState->ResultObj)
        {
            /*
             * Normally, we would remove a reference on the Operand[0]
             * parameter; But since it is being used as the internal return
             * object (meaning we would normally increment it), the two
             * cancel out, and we simply don't do anything.
             */
            WalkState->ResultObj = Operand[0];
            WalkState->Operands[0] = NULL;  /* Prevent deletion */
        }
        return_ACPI_STATUS (Status);

    /*
     * ACPI 2.0 Opcodes
     */
    case AML_COPY_OP:               /* Copy (Source, Target) */

        Status = AcpiUtCopyIobjectToIobject (
            Operand[0], &ReturnDesc, WalkState);
        break;

    case AML_TO_DECSTRING_OP:       /* ToDecimalString (Data, Result) */

        Status = AcpiExConvertToString (
            Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_DECIMAL);
        if (ReturnDesc == Operand[0])
        {
            /* No conversion performed, add ref to handle return value */

            AcpiUtAddReference (ReturnDesc);
        }
        break;

    case AML_TO_HEXSTRING_OP:       /* ToHexString (Data, Result) */

        Status = AcpiExConvertToString (
            Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_HEX);
        if (ReturnDesc == Operand[0])
        {
            /* No conversion performed, add ref to handle return value */

            AcpiUtAddReference (ReturnDesc);
        }
        break;

    case AML_TO_BUFFER_OP:          /* ToBuffer (Data, Result) */

        Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc);
        if (ReturnDesc == Operand[0])
        {
            /* No conversion performed, add ref to handle return value */

            AcpiUtAddReference (ReturnDesc);
        }
        break;

    case AML_TO_INTEGER_OP:         /* ToInteger (Data, Result) */

        /* Perform "explicit" conversion */

        Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc, 0);
        if (ReturnDesc == Operand[0])
        {
            /* No conversion performed, add ref to handle return value */

            AcpiUtAddReference (ReturnDesc);
        }
        break;

    case AML_SHIFT_LEFT_BIT_OP:     /* ShiftLeftBit (Source, BitNum)  */
    case AML_SHIFT_RIGHT_BIT_OP:    /* ShiftRightBit (Source, BitNum) */

        /* These are two obsolete opcodes */

        ACPI_ERROR ((AE_INFO,
            "%s is obsolete and not implemented",
            AcpiPsGetOpcodeName (WalkState->Opcode)));
        Status = AE_SUPPORT;
        goto Cleanup;

    default:                        /* Unknown opcode */

        ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
            WalkState->Opcode));
        Status = AE_AML_BAD_OPCODE;
        goto Cleanup;
    }

    if (ACPI_SUCCESS (Status))
    {
        /* Store the return value computed above into the target object */

        Status = AcpiExStore (ReturnDesc, Operand[1], WalkState);
    }


Cleanup:

    /* Delete return object on error */

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

    /* Save return object on success */

    else if (!WalkState->ResultObj)
    {
        WalkState->ResultObj = ReturnDesc;
    }

    return_ACPI_STATUS (Status);
}
Ejemplo n.º 23
0
ACPI_STATUS
AcpiNsAttachObject (
    ACPI_NAMESPACE_NODE     *Node,
    ACPI_OPERAND_OBJECT     *Object,
    ACPI_OBJECT_TYPE        Type)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *LastObjDesc;
    ACPI_OBJECT_TYPE        ObjectType = ACPI_TYPE_ANY;


    ACPI_FUNCTION_TRACE (NsAttachObject);


    /*
     * Parameter validation
     */
    if (!Node)
    {
        /* Invalid handle */

        ACPI_ERROR ((AE_INFO, "Null NamedObj handle"));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    if (!Object && (ACPI_TYPE_ANY != Type))
    {
        /* Null object */

        ACPI_ERROR ((AE_INFO,
            "Null object, but type not ACPI_TYPE_ANY"));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED)
    {
        /* Not a name handle */

        ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]",
            Node, AcpiUtGetDescriptorName (Node)));
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Check if this object is already attached */

    if (Node->Object == Object)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "Obj %p already installed in NameObj %p\n",
            Object, Node));

        return_ACPI_STATUS (AE_OK);
    }

    /* If null object, we will just install it */

    if (!Object)
    {
        ObjDesc    = NULL;
        ObjectType = ACPI_TYPE_ANY;
    }

    /*
     * If the source object is a namespace Node with an attached object,
     * we will use that (attached) object
     */
    else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) &&
            ((ACPI_NAMESPACE_NODE *) Object)->Object)
    {
        /*
         * Value passed is a name handle and that name has a
         * non-null value. Use that name's value and type.
         */
        ObjDesc = ((ACPI_NAMESPACE_NODE *) Object)->Object;
        ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type;
    }

    /*
     * Otherwise, we will use the parameter object, but we must type
     * it first
     */
    else
    {
        ObjDesc = (ACPI_OPERAND_OBJECT  *) Object;

        /* Use the given type */

        ObjectType = Type;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n",
        ObjDesc, Node, AcpiUtGetNodeName (Node)));

    /* Detach an existing attached object if present */

    if (Node->Object)
    {
        AcpiNsDetachObject (Node);
    }

    if (ObjDesc)
    {
        /*
         * Must increment the new value's reference count
         * (if it is an internal object)
         */
        AcpiUtAddReference (ObjDesc);

        /*
         * Handle objects with multiple descriptors - walk
         * to the end of the descriptor list
         */
        LastObjDesc = ObjDesc;
        while (LastObjDesc->Common.NextObject)
        {
            LastObjDesc = LastObjDesc->Common.NextObject;
        }

        /* Install the object at the front of the object list */

        LastObjDesc->Common.NextObject = Node->Object;
    }

    Node->Type = (UINT8) ObjectType;
    Node->Object = ObjDesc;

    return_ACPI_STATUS (AE_OK);
}
Ejemplo n.º 24
0
ACPI_STATUS
AcpiDsBuildInternalPackageObj (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  ElementCount,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_PARSE_OBJECT       *Arg;
    ACPI_PARSE_OBJECT       *Parent;
    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  i;
    UINT16                  Index;
    UINT16                  ReferenceCount;


    ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj);


    /* Find the parent of a possibly nested package */

    Parent = Op->Common.Parent;
    while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
           (Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
    {
        Parent = Parent->Common.Parent;
    }

    /*
     * If we are evaluating a Named package object "Name (xxxx, Package)",
     * the package object already exists, otherwise it must be created.
     */
    ObjDesc = *ObjDescPtr;
    if (!ObjDesc)
    {
        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE);
        *ObjDescPtr = ObjDesc;
        if (!ObjDesc)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        ObjDesc->Package.Node = Parent->Common.Node;
    }

    /*
     * Allocate the element array (array of pointers to the individual
     * objects) based on the NumElements parameter. Add an extra pointer slot
     * so that the list is always null terminated.
     */
    ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED (
        ((ACPI_SIZE) ElementCount + 1) * sizeof (void *));

    if (!ObjDesc->Package.Elements)
    {
        AcpiUtDeleteObjectDesc (ObjDesc);
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    ObjDesc->Package.Count = ElementCount;

    /*
     * Initialize the elements of the package, up to the NumElements count.
     * Package is automatically padded with uninitialized (NULL) elements
     * if NumElements is greater than the package list length. Likewise,
     * Package is truncated if NumElements is less than the list length.
     */
    Arg = Op->Common.Value.Arg;
    Arg = Arg->Common.Next;
    for (i = 0; Arg && (i < ElementCount); i++)
    {
        if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP)
        {
            if (Arg->Common.Node->Type == ACPI_TYPE_METHOD)
            {
                /*
                 * A method reference "looks" to the parser to be a method
                 * invocation, so we special case it here
                 */
                Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
                Status = AcpiDsBuildInternalObject (WalkState, Arg,
                            &ObjDesc->Package.Elements[i]);
            }
            else
            {
                /* This package element is already built, just get it */

                ObjDesc->Package.Elements[i] =
                    ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node);
            }
        }
        else
        {
            Status = AcpiDsBuildInternalObject (WalkState, Arg,
                        &ObjDesc->Package.Elements[i]);
        }

        if (*ObjDescPtr)
        {
            /* Existing package, get existing reference count */

            ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount;
            if (ReferenceCount > 1)
            {
                /* Make new element ref count match original ref count */

                for (Index = 0; Index < (ReferenceCount - 1); Index++)
                {
                    AcpiUtAddReference ((ObjDesc->Package.Elements[i]));
                }
            }
        }

        Arg = Arg->Common.Next;
    }

    /* Check for match between NumElements and actual length of PackageList */

    if (Arg)
    {
        /*
         * NumElements was exhausted, but there are remaining elements in the
         * PackageList. Truncate the package to NumElements.
         *
         * Note: technically, this is an error, from ACPI spec: "It is an error
         * for NumElements to be less than the number of elements in the
         * PackageList". However, we just print a message and
         * no exception is returned. This provides Windows compatibility. Some
         * BIOSs will alter the NumElements on the fly, creating this type
         * of ill-formed package object.
         */
        while (Arg)
        {
            /*
             * We must delete any package elements that were created earlier
             * and are not going to be used because of the package truncation.
             */
            if (Arg->Common.Node)
            {
                AcpiUtRemoveReference (
                    ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node));
                Arg->Common.Node = NULL;
            }

            /* Find out how many elements there really are */

            i++;
            Arg = Arg->Common.Next;
        }

        ACPI_INFO ((AE_INFO,
            "Actual Package length (%u) is larger than NumElements field (%u), truncated",
            i, ElementCount));
    }
    else if (i < ElementCount)
    {
        /*
         * Arg list (elements) was exhausted, but we did not reach NumElements count.
         * Note: this is not an error, the package is padded out with NULLs.
         */
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
            "Package List length (%u) smaller than NumElements count (%u), padded with null elements\n",
            i, ElementCount));
    }

    ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
    Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
    return_ACPI_STATUS (Status);
}
Ejemplo n.º 25
0
ACPI_STATUS
AcpiInstallNotifyHandler (
    ACPI_HANDLE             Device,
    UINT32                  HandlerType,
    ACPI_NOTIFY_HANDLER     Handler,
    void                    *Context)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *NotifyObj;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);


    /* Parameter validation */

    if ((!Device)  ||
        (!Handler) ||
        (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Convert and validate the device handle */

    Node = AcpiNsMapHandleToNode (Device);
    if (!Node)
    {
        Status = AE_BAD_PARAMETER;
        goto UnlockAndExit;
    }

    /*
     * Root Object:
     * Registering a notify handler on the root object indicates that the
     * caller wishes to receive notifications for all objects.  Note that
     * only one <external> global handler can be regsitered (per notify type).
     */
    if (Device == ACPI_ROOT_OBJECT)
    {
        /* Make sure the handler is not already installed */

        if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
                AcpiGbl_SystemNotify.Handler)       ||
            ((HandlerType & ACPI_DEVICE_NOTIFY) &&
                AcpiGbl_DeviceNotify.Handler))
        {
            Status = AE_ALREADY_EXISTS;
            goto UnlockAndExit;
        }

        if (HandlerType & ACPI_SYSTEM_NOTIFY)
        {
            AcpiGbl_SystemNotify.Node    = Node;
            AcpiGbl_SystemNotify.Handler = Handler;
            AcpiGbl_SystemNotify.Context = Context;
        }

        if (HandlerType & ACPI_DEVICE_NOTIFY)
        {
            AcpiGbl_DeviceNotify.Node    = Node;
            AcpiGbl_DeviceNotify.Handler = Handler;
            AcpiGbl_DeviceNotify.Context = Context;
        }

        /* Global notify handler installed */
    }

    /*
     * All Other Objects:
     * Caller will only receive notifications specific to the target object.
     * Note that only certain object types can receive notifications.
     */
    else
    {
        /* Notifies allowed on this object? */

        if (!AcpiEvIsNotifyObject (Node))
        {
            Status = AE_TYPE;
            goto UnlockAndExit;
        }

        /* Check for an existing internal object */

        ObjDesc = AcpiNsGetAttachedObject (Node);
        if (ObjDesc)
        {
            /* Object exists - make sure there's no handler */

            if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
                    ObjDesc->CommonNotify.SystemNotify)   ||
                ((HandlerType & ACPI_DEVICE_NOTIFY) &&
                    ObjDesc->CommonNotify.DeviceNotify))
            {
                Status = AE_ALREADY_EXISTS;
                goto UnlockAndExit;
            }
        }
        else
        {
            /* Create a new object */

            ObjDesc = AcpiUtCreateInternalObject (Node->Type);
            if (!ObjDesc)
            {
                Status = AE_NO_MEMORY;
                goto UnlockAndExit;
            }

            /* Attach new object to the Node */

            Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);

            /* Remove local reference to the object */

            AcpiUtRemoveReference (ObjDesc);
            if (ACPI_FAILURE (Status))
            {
                goto UnlockAndExit;
            }
        }

        /* Install the handler */

        NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
        if (!NotifyObj)
        {
            Status = AE_NO_MEMORY;
            goto UnlockAndExit;
        }

        NotifyObj->Notify.Node    = Node;
        NotifyObj->Notify.Handler = Handler;
        NotifyObj->Notify.Context = Context;

        if (HandlerType & ACPI_SYSTEM_NOTIFY)
        {
            ObjDesc->CommonNotify.SystemNotify = NotifyObj;
        }

        if (HandlerType & ACPI_DEVICE_NOTIFY)
        {
            ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
        }

        if (HandlerType == ACPI_ALL_NOTIFY)
        {
            /* Extra ref if installed in both */

            AcpiUtAddReference (NotifyObj);
        }
    }


UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_ACPI_STATUS (Status);
}
Ejemplo n.º 26
0
static ACPI_STATUS
AcpiExStoreObjectToIndex (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     *IndexDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *NewDesc;
    UINT8                   Value = 0;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (ExStoreObjectToIndex);


    /*
     * Destination must be a reference pointer, and
     * must point to either a buffer or a package
     */
    switch (IndexDesc->Reference.TargetType)
    {
    case ACPI_TYPE_PACKAGE:
        /*
         * Storing to a package element. Copy the object and replace
         * any existing object with the new object. No implicit
         * conversion is performed.
         *
         * The object at *(IndexDesc->Reference.Where) is the
         * element within the package that is to be modified.
         * The parent package object is at IndexDesc->Reference.Object
         */
        ObjDesc = *(IndexDesc->Reference.Where);

        if (SourceDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE &&
            SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
        {
            /* This is a DDBHandle, just add a reference to it */

            AcpiUtAddReference (SourceDesc);
            NewDesc = SourceDesc;
        }
        else
        {
            /* Normal object, copy it */

            Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }
        }

        if (ObjDesc)
        {
            /* Decrement reference count by the ref count of the parent package */

            for (i = 0;
                 i < ((ACPI_OPERAND_OBJECT *)
                        IndexDesc->Reference.Object)->Common.ReferenceCount;
                 i++)
            {
                AcpiUtRemoveReference (ObjDesc);
            }
        }

        *(IndexDesc->Reference.Where) = NewDesc;

        /* Increment ref count by the ref count of the parent package-1 */

        for (i = 1;
             i < ((ACPI_OPERAND_OBJECT *)
                    IndexDesc->Reference.Object)->Common.ReferenceCount;
             i++)
        {
            AcpiUtAddReference (NewDesc);
        }

        break;

    case ACPI_TYPE_BUFFER_FIELD:
        /*
         * Store into a Buffer or String (not actually a real BufferField)
         * at a location defined by an Index.
         *
         * The first 8-bit element of the source object is written to the
         * 8-bit Buffer location defined by the Index destination object,
         * according to the ACPI 2.0 specification.
         */

        /*
         * Make sure the target is a Buffer or String. An error should
         * not happen here, since the ReferenceObject was constructed
         * by the INDEX_OP code.
         */
        ObjDesc = IndexDesc->Reference.Object;
        if ((ObjDesc->Common.Type != ACPI_TYPE_BUFFER) &&
            (ObjDesc->Common.Type != ACPI_TYPE_STRING))
        {
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        /*
         * The assignment of the individual elements will be slightly
         * different for each source type.
         */
        switch (SourceDesc->Common.Type)
        {
        case ACPI_TYPE_INTEGER:

            /* Use the least-significant byte of the integer */

            Value = (UINT8) (SourceDesc->Integer.Value);
            break;

        case ACPI_TYPE_BUFFER:
        case ACPI_TYPE_STRING:

            /* Note: Takes advantage of common string/buffer fields */

            Value = SourceDesc->Buffer.Pointer[0];
            break;

        default:

            /* All other types are invalid */

            ACPI_ERROR ((AE_INFO,
                "Source must be Integer/Buffer/String type, not %s",
                AcpiUtGetObjectTypeName (SourceDesc)));
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        /* Store the source value into the target buffer byte */

        ObjDesc->Buffer.Pointer[IndexDesc->Reference.Value] = Value;
        break;

    default:
        ACPI_ERROR ((AE_INFO,
            "Target is not a Package or BufferField"));
        Status = AE_AML_OPERAND_TYPE;
        break;
    }

    return_ACPI_STATUS (Status);
}
Ejemplo n.º 27
0
ACPI_STATUS
AcpiDsBuildInternalPackageObj (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  ElementCount,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_PARSE_OBJECT       *Arg;
    ACPI_PARSE_OBJECT       *Parent;
    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    ACPI_STATUS             Status = AE_OK;
    ACPI_NATIVE_UINT        i;
    UINT16                  Index;
    UINT16                  ReferenceCount;


    ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj);


    /* Find the parent of a possibly nested package */

    Parent = Op->Common.Parent;
    while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
           (Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
    {
        Parent = Parent->Common.Parent;
    }

    /*
     * If we are evaluating a Named package object "Name (xxxx, Package)",
     * the package object already exists, otherwise it must be created.
     */
    ObjDesc = *ObjDescPtr;
    if (!ObjDesc)
    {
        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE);
        *ObjDescPtr = ObjDesc;
        if (!ObjDesc)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        ObjDesc->Package.Node = Parent->Common.Node;
    }

    /*
     * Allocate the element array (array of pointers to the individual
     * objects) based on the NumElements parameter. Add an extra pointer slot
     * so that the list is always null terminated.
     */
    ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED (
        ((ACPI_SIZE) ElementCount + 1) * sizeof (void *));

    if (!ObjDesc->Package.Elements)
    {
        AcpiUtDeleteObjectDesc (ObjDesc);
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    ObjDesc->Package.Count = ElementCount;

    /*
     * Initialize the elements of the package, up to the NumElements count.
     * Package is automatically padded with uninitialized (NULL) elements
     * if NumElements is greater than the package list length. Likewise,
     * Package is truncated if NumElements is less than the list length.
     */
    Arg = Op->Common.Value.Arg;
    Arg = Arg->Common.Next;
    for (i = 0; Arg && (i < ElementCount); i++)
    {
        if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP)
        {
            /* This package element is already built, just get it */

            ObjDesc->Package.Elements[i] =
                ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node);
        }
        else
        {
            Status = AcpiDsBuildInternalObject (WalkState, Arg,
                        &ObjDesc->Package.Elements[i]);
        }

        if (*ObjDescPtr)
        {
            /* Existing package, get existing reference count */

            ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount;
            if (ReferenceCount > 1)
            {
                /* Make new element ref count match original ref count */

                for (Index = 0; Index < (ReferenceCount - 1); Index++)
                {
                    AcpiUtAddReference ((ObjDesc->Package.Elements[i]));
                }
            }
        }

        Arg = Arg->Common.Next;
    }

    if (!Arg)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
            "Package List length larger than NumElements count (%X), truncated\n",
            ElementCount));
    }

    ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
    Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
    return_ACPI_STATUS (Status);
}