ACPI_STATUS
AcpiDsMethodError (
    ACPI_STATUS             Status,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_FUNCTION_ENTRY ();


    /* Ignore AE_OK and control exception codes */

    if (ACPI_SUCCESS (Status) ||
        (Status & AE_CODE_CONTROL))
    {
        return (Status);
    }

    /* Invoke the global exception handler */

    if (AcpiGbl_ExceptionHandler)
    {
        /* Exit the interpreter, allow handler to execute methods */

        AcpiExExitInterpreter ();

        /*
         * Handler can map the exception code to anything it wants, including
         * AE_OK, in which case the executing method will not be aborted.
         */
        Status = AcpiGbl_ExceptionHandler (Status,
                    WalkState->MethodNode ?
                        WalkState->MethodNode->Name.Integer : 0,
                    WalkState->Opcode, WalkState->AmlOffset, NULL);
        AcpiExEnterInterpreter ();
    }

    AcpiDsClearImplicitReturn (WalkState);

#ifdef ACPI_DISASSEMBLER
    if (ACPI_FAILURE (Status))
    {
        /* Display method locals/args if disassembler is present */

        AcpiDmDumpMethodInfo (Status, WalkState, WalkState->Op);
    }
#endif

    return (Status);
}
Exemple #2
0
ACPI_STATUS
AcpiExSystemWaitMutex (
    ACPI_MUTEX              Mutex,
    UINT16                  Timeout)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (ExSystemWaitMutex);


    Status = AcpiOsAcquireMutex (Mutex, ACPI_DO_NOT_WAIT);
    if (ACPI_SUCCESS (Status))
    {
        return_ACPI_STATUS (Status);
    }

    if (Status == AE_TIME)
    {
        /* We must wait, so unlock the interpreter */

        AcpiExExitInterpreter ();

        Status = AcpiOsAcquireMutex (Mutex, Timeout);

        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "*** Thread awake after blocking, %s\n",
            AcpiFormatException (Status)));

        /* Reacquire the interpreter */

        AcpiExEnterInterpreter ();
    }

    return_ACPI_STATUS (Status);
}
Exemple #3
0
ACPI_STATUS
AcpiNsEvaluate (
    ACPI_EVALUATE_INFO      *Info)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsEvaluate);


    if (!Info)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    if (!Info->Node)
    {
        /*
         * Get the actual namespace node for the target object if we
         * need to. Handles these cases:
         *
         * 1) Null node, valid pathname from root (absolute path)
         * 2) Node and valid pathname (path relative to Node)
         * 3) Node, Null pathname
         */
        Status = AcpiNsGetNode (Info->PrefixNode, Info->RelativePathname,
            ACPI_NS_NO_UPSEARCH, &Info->Node);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }
    }

    /*
     * For a method alias, we must grab the actual method node so that
     * proper scoping context will be established before execution.
     */
    if (AcpiNsGetType (Info->Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS)
    {
        Info->Node = ACPI_CAST_PTR (
            ACPI_NAMESPACE_NODE, Info->Node->Object);
    }

    /* Complete the info block initialization */

    Info->ReturnObject = NULL;
    Info->NodeFlags = Info->Node->Flags;
    Info->ObjDesc = AcpiNsGetAttachedObject (Info->Node);

    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
        Info->RelativePathname, Info->Node,
        AcpiNsGetAttachedObject (Info->Node)));

    /* Get info if we have a predefined name (_HID, etc.) */

    Info->Predefined = AcpiUtMatchPredefinedMethod (Info->Node->Name.Ascii);

    /* Get the full pathname to the object, for use in warning messages */

    Info->FullPathname = AcpiNsGetExternalPathname (Info->Node);
    if (!Info->FullPathname)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Count the number of arguments being passed in */

    Info->ParamCount = 0;
    if (Info->Parameters)
    {
        while (Info->Parameters[Info->ParamCount])
        {
            Info->ParamCount++;
        }

        /* Warn on impossible argument count */

        if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
        {
            ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS,
                "Excess arguments (%u) - using only %u",
                Info->ParamCount, ACPI_METHOD_NUM_ARGS));

            Info->ParamCount = ACPI_METHOD_NUM_ARGS;
        }
    }

    /*
     * For predefined names: Check that the declared argument count
     * matches the ACPI spec -- otherwise this is a BIOS error.
     */
    AcpiNsCheckAcpiCompliance (Info->FullPathname, Info->Node,
        Info->Predefined);

    /*
     * For all names: Check that the incoming argument count for
     * this method/object matches the actual ASL/AML definition.
     */
    AcpiNsCheckArgumentCount (Info->FullPathname, Info->Node,
        Info->ParamCount, Info->Predefined);

    /* For predefined names: Typecheck all incoming arguments */

    AcpiNsCheckArgumentTypes (Info);

    /*
     * Three major evaluation cases:
     *
     * 1) Object types that cannot be evaluated by definition
     * 2) The object is a control method -- execute it
     * 3) The object is not a method -- just return it's current value
     */
    switch (AcpiNsGetType (Info->Node))
    {
    case ACPI_TYPE_DEVICE:
    case ACPI_TYPE_EVENT:
    case ACPI_TYPE_MUTEX:
    case ACPI_TYPE_REGION:
    case ACPI_TYPE_THERMAL:
    case ACPI_TYPE_LOCAL_SCOPE:
        /*
         * 1) Disallow evaluation of certain object types. For these,
         *    object evaluation is undefined and not supported.
         */
        ACPI_ERROR ((AE_INFO,
            "%s: Evaluation of object type [%s] is not supported",
            Info->FullPathname,
            AcpiUtGetTypeName (Info->Node->Type)));

        Status = AE_TYPE;
        goto Cleanup;

    case ACPI_TYPE_METHOD:
        /*
         * 2) Object is a control method - execute it
         */

        /* Verify that there is a method object associated with this node */

        if (!Info->ObjDesc)
        {
            ACPI_ERROR ((AE_INFO, "%s: Method has no attached sub-object",
                Info->FullPathname));
            Status = AE_NULL_OBJECT;
            goto Cleanup;
        }

        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "**** Execute method [%s] at AML address %p length %X\n",
            Info->FullPathname,
            Info->ObjDesc->Method.AmlStart + 1,
            Info->ObjDesc->Method.AmlLength - 1));

        /*
         * Any namespace deletion must acquire both the namespace and
         * interpreter locks to ensure that no thread is using the portion of
         * the namespace that is being deleted.
         *
         * Execute the method via the interpreter. The interpreter is locked
         * here before calling into the AML parser
         */
        AcpiExEnterInterpreter ();
        Status = AcpiPsExecuteMethod (Info);
        AcpiExExitInterpreter ();
        break;

    default:
        /*
         * 3) All other non-method objects -- get the current object value
         */

        /*
         * Some objects require additional resolution steps (e.g., the Node
         * may be a field that must be read, etc.) -- we can't just grab
         * the object out of the node.
         *
         * Use ResolveNodeToValue() to get the associated value.
         *
         * NOTE: we can get away with passing in NULL for a walk state because
         * the Node is guaranteed to not be a reference to either a method
         * local or a method argument (because this interface is never called
         * from a running method.)
         *
         * Even though we do not directly invoke the interpreter for object
         * resolution, we must lock it because we could access an OpRegion.
         * The OpRegion access code assumes that the interpreter is locked.
         */
        AcpiExEnterInterpreter ();

        /* TBD: ResolveNodeToValue has a strange interface, fix */

        Info->ReturnObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->Node);

        Status = AcpiExResolveNodeToValue (ACPI_CAST_INDIRECT_PTR (
            ACPI_NAMESPACE_NODE, &Info->ReturnObject), NULL);
        AcpiExExitInterpreter ();

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

        ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returned object %p [%s]\n",
            Info->ReturnObject,
            AcpiUtGetObjectTypeName (Info->ReturnObject)));

        Status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */
        break;
    }

    /*
     * For predefined names, check the return value against the ACPI
     * specification. Some incorrect return value types are repaired.
     */
    (void) AcpiNsCheckReturnValue (Info->Node, Info, Info->ParamCount,
        Status, &Info->ReturnObject);

    /* Check if there is a return value that must be dealt with */

    if (Status == AE_CTRL_RETURN_VALUE)
    {
        /* If caller does not want the return value, delete it */

        if (Info->Flags & ACPI_IGNORE_RETURN_VALUE)
        {
            AcpiUtRemoveReference (Info->ReturnObject);
            Info->ReturnObject = NULL;
        }

        /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */

        Status = AE_OK;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
        "*** Completed evaluation of object %s ***\n",
        Info->RelativePathname));

Cleanup:
    /*
     * Namespace was unlocked by the handling AcpiNs* function, so we
     * just free the pathname and return
     */
    ACPI_FREE (Info->FullPathname);
    Info->FullPathname = NULL;
    return_ACPI_STATUS (Status);
}
Exemple #4
0
ACPI_STATUS
AcpiNsLoadTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *Node)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsLoadTable);


    /* If table already loaded into namespace, just return */

    if (AcpiTbIsTableLoaded (TableIndex))
    {
        Status = AE_ALREADY_EXISTS;
        goto Unlock;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Loading table into namespace ****\n"));

    Status = AcpiTbAllocateOwnerId (TableIndex);
    if (ACPI_FAILURE (Status))
    {
        goto Unlock;
    }

    /*
     * Parse the table and load the namespace with all named
     * objects found within. Control methods are NOT parsed
     * at this time. In fact, the control methods cannot be
     * parsed until the entire namespace is loaded, because
     * if a control method makes a forward reference (call)
     * to another control method, we can't continue parsing
     * because we don't know how many arguments to parse next!
     */
    Status = AcpiNsParseTable (TableIndex, Node);
    if (ACPI_SUCCESS (Status))
    {
        AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
    }
    else
    {
        /*
         * On error, delete any namespace objects created by this table.
         * We cannot initialize these objects, so delete them. There are
         * a couple of expecially bad cases:
         * AE_ALREADY_EXISTS - namespace collision.
         * AE_NOT_FOUND - the target of a Scope operator does not
         * exist. This target of Scope must already exist in the
         * namespace, as per the ACPI specification.
         */
        AcpiNsDeleteNamespaceByOwner (
            AcpiGbl_RootTableList.Tables[TableIndex].OwnerId);

        AcpiTbReleaseOwnerId (TableIndex);
        return_ACPI_STATUS (Status);
    }

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

    /*
     * Now we can parse the control methods. We always parse
     * them here for a sanity check, and if configured for
     * just-in-time parsing, we delete the control method
     * parse trees.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Begin Table Object Initialization\n"));

    AcpiExEnterInterpreter ();
    Status = AcpiDsInitializeObjects (TableIndex, Node);
    AcpiExExitInterpreter ();

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Completed Table Object Initialization\n"));

    /*
     * Execute any module-level code that was detected during the table load
     * phase. Although illegal since ACPI 2.0, there are many machines that
     * contain this type of code. Each block of detected executable AML code
     * outside of any control method is wrapped with a temporary control
     * method object and placed on a global list. The methods on this list
     * are executed below.
     *
     * This case executes the module-level code for each table immediately
     * after the table has been loaded. This provides compatibility with
     * other ACPI implementations. Optionally, the execution can be deferred
     * until later, see AcpiInitializeObjects.
     */
    if (!AcpiGbl_ParseTableAsTermList && !AcpiGbl_GroupModuleLevelCode)
    {
        AcpiNsExecModuleCodeList ();
    }

    return_ACPI_STATUS (Status);
}
Exemple #5
0
ACPI_STATUS
AcpiEvAddressSpaceDispatch (
    ACPI_OPERAND_OBJECT     *RegionObj,
    UINT32                  Function,
    UINT32                  RegionOffset,
    UINT32                  BitWidth,
    UINT64                  *Value)
{
    ACPI_STATUS             Status;
    ACPI_ADR_SPACE_HANDLER  Handler;
    ACPI_ADR_SPACE_SETUP    RegionSetup;
    ACPI_OPERAND_OBJECT     *HandlerDesc;
    ACPI_OPERAND_OBJECT     *RegionObj2;
    void                    *RegionContext = NULL;


    ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);


    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
    if (!RegionObj2)
    {
        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /* Ensure that there is a handler associated with this region */

    HandlerDesc = RegionObj->Region.Handler;
    if (!HandlerDesc)
    {
        ACPI_ERROR ((AE_INFO,
            "No handler for Region [%4.4s] (%p) [%s]",
            AcpiUtGetNodeName (RegionObj->Region.Node),
            RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));

        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /*
     * It may be the case that the region has never been initialized.
     * Some types of regions require special init code
     */
    if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
    {
        /* This region has not been initialized yet, do it */

        RegionSetup = HandlerDesc->AddressSpace.Setup;
        if (!RegionSetup)
        {
            /* No initialization routine, exit with error */

            ACPI_ERROR ((AE_INFO,
                "No init routine for region(%p) [%s]",
                RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
            return_ACPI_STATUS (AE_NOT_EXIST);
        }

        /*
         * We must exit the interpreter because the region setup will
         * potentially execute control methods (for example, the _REG method
         * for this region)
         */
        AcpiExExitInterpreter ();

        Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
                    HandlerDesc->AddressSpace.Context, &RegionContext);

        /* Re-enter the interpreter */

        AcpiExEnterInterpreter ();

        /* Check for failure of the Region Setup */

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "During region initialization: [%s]",
                AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
            return_ACPI_STATUS (Status);
        }

        /* Region initialization may have been completed by RegionSetup */

        if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
        {
            RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;

            if (RegionObj2->Extra.RegionContext)
            {
                /* The handler for this region was already installed */

                ACPI_FREE (RegionContext);
            }
            else
            {
                /*
                 * Save the returned context for use in all accesses to
                 * this particular region
                 */
                RegionObj2->Extra.RegionContext = RegionContext;
            }
        }
    }

    /* We have everything we need, we can invoke the address space handler */

    Handler = HandlerDesc->AddressSpace.Handler;

    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
        &RegionObj->Region.Handler->AddressSpace, Handler,
        ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset),
        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));

    if (!(HandlerDesc->AddressSpace.HandlerFlags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    {
        /*
         * For handlers other than the default (supplied) handlers, we must
         * exit the interpreter because the handler *might* block -- we don't
         * know what it will do, so we can't hold the lock on the intepreter.
         */
        AcpiExExitInterpreter();
    }

    /* Call the handler */

    Status = Handler (Function,
        (RegionObj->Region.Address + RegionOffset), BitWidth, Value,
        HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext);

    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
            AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    }

    if (!(HandlerDesc->AddressSpace.HandlerFlags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    {
        /*
         * We just returned from a non-default handler, we must re-enter the
         * interpreter
         */
       AcpiExEnterInterpreter ();
    }

    return_ACPI_STATUS (Status);
}
Exemple #6
0
ACPI_STATUS
AcpiEvaluateObject (
    ACPI_HANDLE             Handle,
    ACPI_STRING             Pathname,
    ACPI_OBJECT_LIST        *ExternalParams,
    ACPI_BUFFER             *ReturnBuffer)
{
    ACPI_STATUS             Status;
    ACPI_EVALUATE_INFO      *Info;
    ACPI_SIZE               BufferSpaceNeeded;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);


    /* Allocate and initialize the evaluation information block */

    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    if (!Info)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Convert and validate the device handle */

    Info->PrefixNode = AcpiNsValidateHandle (Handle);
    if (!Info->PrefixNode)
    {
        Status = AE_BAD_PARAMETER;
        goto Cleanup;
    }

    /*
     * Get the actual namespace node for the target object.
     * Handles these cases:
     *
     * 1) Null node, valid pathname from root (absolute path)
     * 2) Node and valid pathname (path relative to Node)
     * 3) Node, Null pathname
     */
    if ((Pathname) &&
        (ACPI_IS_ROOT_PREFIX (Pathname[0])))
    {
        /* The path is fully qualified, just evaluate by name */

        Info->PrefixNode = NULL;
    }
    else if (!Handle)
    {
        /*
         * A handle is optional iff a fully qualified pathname is specified.
         * Since we've already handled fully qualified names above, this is
         * an error.
         */
        if (!Pathname)
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Both Handle and Pathname are NULL"));
        }
        else
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Null Handle with relative pathname [%s]", Pathname));
        }

        Status = AE_BAD_PARAMETER;
        goto Cleanup;
    }

    Info->RelativePathname = Pathname;

    /*
     * Convert all external objects passed as arguments to the
     * internal version(s).
     */
    if (ExternalParams && ExternalParams->Count)
    {
        Info->ParamCount = (UINT16) ExternalParams->Count;

        /* Warn on impossible argument count */

        if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
        {
            ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
                "Excess arguments (%u) - using only %u",
                Info->ParamCount, ACPI_METHOD_NUM_ARGS));

            Info->ParamCount = ACPI_METHOD_NUM_ARGS;
        }

        /*
         * Allocate a new parameter block for the internal objects
         * Add 1 to count to allow for null terminated internal list
         */
        Info->Parameters = ACPI_ALLOCATE_ZEROED (
            ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
        if (!Info->Parameters)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /* Convert each external object in the list to an internal object */

        for (i = 0; i < Info->ParamCount; i++)
        {
            Status = AcpiUtCopyEobjectToIobject (
                &ExternalParams->Pointer[i], &Info->Parameters[i]);
            if (ACPI_FAILURE (Status))
            {
                goto Cleanup;
            }
        }

        Info->Parameters[Info->ParamCount] = NULL;
    }


#if 0

    /*
     * Begin incoming argument count analysis. Check for too few args
     * and too many args.
     */

    switch (AcpiNsGetType (Info->Node))
    {
    case ACPI_TYPE_METHOD:

        /* Check incoming argument count against the method definition */

        if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
        {
            ACPI_ERROR ((AE_INFO,
                "Insufficient arguments (%u) - %u are required",
                Info->ParamCount,
                Info->ObjDesc->Method.ParamCount));

            Status = AE_MISSING_ARGUMENTS;
            goto Cleanup;
        }

        else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
        {
            ACPI_WARNING ((AE_INFO,
                "Excess arguments (%u) - only %u are required",
                Info->ParamCount,
                Info->ObjDesc->Method.ParamCount));

            /* Just pass the required number of arguments */

            Info->ParamCount = Info->ObjDesc->Method.ParamCount;
        }

        /*
         * Any incoming external objects to be passed as arguments to the
         * method must be converted to internal objects
         */
        if (Info->ParamCount)
        {
            /*
             * Allocate a new parameter block for the internal objects
             * Add 1 to count to allow for null terminated internal list
             */
            Info->Parameters = ACPI_ALLOCATE_ZEROED (
                ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
            if (!Info->Parameters)
            {
                Status = AE_NO_MEMORY;
                goto Cleanup;
            }

            /* Convert each external object in the list to an internal object */

            for (i = 0; i < Info->ParamCount; i++)
            {
                Status = AcpiUtCopyEobjectToIobject (
                    &ExternalParams->Pointer[i], &Info->Parameters[i]);
                if (ACPI_FAILURE (Status))
                {
                    goto Cleanup;
                }
            }

            Info->Parameters[Info->ParamCount] = NULL;
        }
        break;

    default:

        /* Warn if arguments passed to an object that is not a method */

        if (Info->ParamCount)
        {
            ACPI_WARNING ((AE_INFO,
                "%u arguments were passed to a non-method ACPI object",
                Info->ParamCount));
        }
        break;
    }

#endif


    /* Now we can evaluate the object */

    Status = AcpiNsEvaluate (Info);

    /*
     * If we are expecting a return value, and all went well above,
     * copy the return value to an external object.
     */
    if (ReturnBuffer)
    {
        if (!Info->ReturnObject)
        {
            ReturnBuffer->Length = 0;
        }
        else
        {
            if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
                ACPI_DESC_TYPE_NAMED)
            {
                /*
                 * If we received a NS Node as a return object, this means that
                 * the object we are evaluating has nothing interesting to
                 * return (such as a mutex, etc.)  We return an error because
                 * these types are essentially unsupported by this interface.
                 * We don't check up front because this makes it easier to add
                 * support for various types at a later date if necessary.
                 */
                Status = AE_TYPE;
                Info->ReturnObject = NULL;   /* No need to delete a NS Node */
                ReturnBuffer->Length = 0;
            }

            if (ACPI_SUCCESS (Status))
            {
                /* Dereference Index and RefOf references */

                AcpiNsResolveReferences (Info);

                /* Get the size of the returned object */

                Status = AcpiUtGetObjectSize (Info->ReturnObject,
                    &BufferSpaceNeeded);
                if (ACPI_SUCCESS (Status))
                {
                    /* Validate/Allocate/Clear caller buffer */

                    Status = AcpiUtInitializeBuffer (ReturnBuffer,
                        BufferSpaceNeeded);
                    if (ACPI_FAILURE (Status))
                    {
                        /*
                         * Caller's buffer is too small or a new one can't
                         * be allocated
                         */
                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                            "Needed buffer size %X, %s\n",
                            (UINT32) BufferSpaceNeeded,
                            AcpiFormatException (Status)));
                    }
                    else
                    {
                        /* We have enough space for the object, build it */

                        Status = AcpiUtCopyIobjectToEobject (
                            Info->ReturnObject, ReturnBuffer);
                    }
                }
            }
        }
    }

    if (Info->ReturnObject)
    {
        /*
         * Delete the internal return object. NOTE: Interpreter must be
         * locked to avoid race condition.
         */
        AcpiExEnterInterpreter ();

        /* Remove one reference on the return object (should delete it) */

        AcpiUtRemoveReference (Info->ReturnObject);
        AcpiExExitInterpreter ();
    }


Cleanup:

    /* Free the input parameter list (if we created one) */

    if (Info->Parameters)
    {
        /* Free the allocated parameter block */

        AcpiUtDeleteInternalObjectList (Info->Parameters);
    }

    ACPI_FREE (Info);
    return_ACPI_STATUS (Status);
}
Exemple #7
0
ACPI_STATUS
AcpiNsLoadTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *Node)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsLoadTable);


    /* If table already loaded into namespace, just return */

    if (AcpiTbIsTableLoaded (TableIndex))
    {
        Status = AE_ALREADY_EXISTS;
        goto Unlock;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Loading table into namespace ****\n"));

    Status = AcpiTbAllocateOwnerId (TableIndex);
    if (ACPI_FAILURE (Status))
    {
        goto Unlock;
    }

    /*
     * Parse the table and load the namespace with all named
     * objects found within. Control methods are NOT parsed
     * at this time. In fact, the control methods cannot be
     * parsed until the entire namespace is loaded, because
     * if a control method makes a forward reference (call)
     * to another control method, we can't continue parsing
     * because we don't know how many arguments to parse next!
     */
    Status = AcpiNsParseTable (TableIndex, Node);
    if (ACPI_SUCCESS (Status))
    {
        AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
    }
    else
    {
        /*
         * On error, delete any namespace objects created by this table.
         * We cannot initialize these objects, so delete them. There are
         * a couple of expecially bad cases:
         * AE_ALREADY_EXISTS - namespace collision.
         * AE_NOT_FOUND - the target of a Scope operator does not
         * exist. This target of Scope must already exist in the
         * namespace, as per the ACPI specification.
         */
        AcpiNsDeleteNamespaceByOwner (
            AcpiGbl_RootTableList.Tables[TableIndex].OwnerId);

        AcpiTbReleaseOwnerId (TableIndex);
        return_ACPI_STATUS (Status);
    }

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

    /*
     * Now we can parse the control methods. We always parse
     * them here for a sanity check, and if configured for
     * just-in-time parsing, we delete the control method
     * parse trees.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Begin Table Object Initialization\n"));

    AcpiExEnterInterpreter ();
    Status = AcpiDsInitializeObjects (TableIndex, Node);
    AcpiExExitInterpreter ();

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Completed Table Object Initialization\n"));

    /*
     * This case handles the legacy option that groups all module-level
     * code blocks together and defers execution until all of the tables
     * are loaded. Execute all of these blocks at this time.
     * Execute any module-level code that was detected during the table
     * load phase.
     *
     * Note: this option is deprecated and will be eliminated in the
     * future. Use of this option can cause problems with AML code that
     * depends upon in-order immediate execution of module-level code.
     */
    AcpiNsExecModuleCodeList ();
    return_ACPI_STATUS (Status);
}
Exemple #8
0
ACPI_STATUS
AcpiEvAddressSpaceDispatch (
    ACPI_OPERAND_OBJECT     *RegionObj,
    ACPI_OPERAND_OBJECT     *FieldObj,
    UINT32                  Function,
    UINT32                  RegionOffset,
    UINT32                  BitWidth,
    UINT64                  *Value)
{
    ACPI_STATUS             Status;
    ACPI_ADR_SPACE_HANDLER  Handler;
    ACPI_ADR_SPACE_SETUP    RegionSetup;
    ACPI_OPERAND_OBJECT     *HandlerDesc;
    ACPI_OPERAND_OBJECT     *RegionObj2;
    void                    *RegionContext = NULL;
    ACPI_CONNECTION_INFO    *Context;
    ACPI_PHYSICAL_ADDRESS   Address;


    ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);


    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
    if (!RegionObj2)
    {
        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /* Ensure that there is a handler associated with this region */

    HandlerDesc = RegionObj->Region.Handler;
    if (!HandlerDesc)
    {
        ACPI_ERROR ((AE_INFO,
            "No handler for Region [%4.4s] (%p) [%s]",
            AcpiUtGetNodeName (RegionObj->Region.Node),
            RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));

        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    Context = HandlerDesc->AddressSpace.Context;

    /*
     * It may be the case that the region has never been initialized.
     * Some types of regions require special init code
     */
    if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
    {
        /* This region has not been initialized yet, do it */

        RegionSetup = HandlerDesc->AddressSpace.Setup;
        if (!RegionSetup)
        {
            /* No initialization routine, exit with error */

            ACPI_ERROR ((AE_INFO,
                "No init routine for region(%p) [%s]",
                RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
            return_ACPI_STATUS (AE_NOT_EXIST);
        }

        /*
         * We must exit the interpreter because the region setup will
         * potentially execute control methods (for example, the _REG method
         * for this region)
         */
        AcpiExExitInterpreter ();

        Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
                    Context, &RegionContext);

        /* Re-enter the interpreter */

        AcpiExEnterInterpreter ();

        /* Check for failure of the Region Setup */

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "During region initialization: [%s]",
                AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
            return_ACPI_STATUS (Status);
        }

        /* Region initialization may have been completed by RegionSetup */

        if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
        {
            RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;

            /*
             * Save the returned context for use in all accesses to
             * the handler for this particular region
             */
            if (!(RegionObj2->Extra.RegionContext))
            {
                RegionObj2->Extra.RegionContext = RegionContext;
            }
        }
    }

    /* We have everything we need, we can invoke the address space handler */

    Handler = HandlerDesc->AddressSpace.Handler;
    Address = (RegionObj->Region.Address + RegionOffset);

    /*
     * Special handling for GenericSerialBus and GeneralPurposeIo:
     * There are three extra parameters that must be passed to the
     * handler via the context:
     *   1) Connection buffer, a resource template from Connection() op
     *   2) Length of the above buffer
     *   3) Actual access length from the AccessAs() op
     *
     * In addition, for GeneralPurposeIo, the Address and BitWidth fields
     * are defined as follows:
     *   1) Address is the pin number index of the field (bit offset from
     *      the previous Connection)
     *   2) BitWidth is the actual bit length of the field (number of pins)
     */
    if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) &&
        Context &&
        FieldObj)
    {
        /* Get the Connection (ResourceTemplate) buffer */

        Context->Connection = FieldObj->Field.ResourceBuffer;
        Context->Length = FieldObj->Field.ResourceLength;
        Context->AccessLength = FieldObj->Field.AccessLength;
    }
    if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) &&
        Context &&
        FieldObj)
    {
        /* Get the Connection (ResourceTemplate) buffer */

        Context->Connection = FieldObj->Field.ResourceBuffer;
        Context->Length = FieldObj->Field.ResourceLength;
        Context->AccessLength = FieldObj->Field.AccessLength;
        Address = FieldObj->Field.PinNumberIndex;
        BitWidth = FieldObj->Field.BitLength;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
        &RegionObj->Region.Handler->AddressSpace, Handler,
        ACPI_FORMAT_UINT64 (Address),
        AcpiUtGetRegionName (RegionObj->Region.SpaceId)));

    if (!(HandlerDesc->AddressSpace.HandlerFlags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    {
        /*
         * For handlers other than the default (supplied) handlers, we must
         * exit the interpreter because the handler *might* block -- we don't
         * know what it will do, so we can't hold the lock on the intepreter.
         */
        AcpiExExitInterpreter();
    }

    /* Call the handler */

    Status = Handler (Function, Address, BitWidth, Value, Context,
        RegionObj2->Extra.RegionContext);

    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
            AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
    }

    if (!(HandlerDesc->AddressSpace.HandlerFlags &
            ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    {
        /*
         * We just returned from a non-default handler, we must re-enter the
         * interpreter
         */
       AcpiExEnterInterpreter ();
    }

    return_ACPI_STATUS (Status);
}
Exemple #9
0
ACPI_STATUS
AcpiEvInitializeRegion (
    ACPI_OPERAND_OBJECT     *RegionObj)
{
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_ADR_SPACE_TYPE     SpaceId;
    ACPI_NAMESPACE_NODE     *Node;


    ACPI_FUNCTION_TRACE (EvInitializeRegion);


    if (!RegionObj)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED)
    {
        return_ACPI_STATUS (AE_OK);
    }

    RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED;

    Node = RegionObj->Region.Node->Parent;
    SpaceId = RegionObj->Region.SpaceId;

    /*
     * The following loop depends upon the root Node having no parent
     * ie: AcpiGbl_RootNode->Parent being set to NULL
     */
    while (Node)
    {
        /* Check to see if a handler exists */

        HandlerObj = NULL;
        ObjDesc = AcpiNsGetAttachedObject (Node);
        if (ObjDesc)
        {
            /* Can only be a handler if the object exists */

            switch (Node->Type)
            {
            case ACPI_TYPE_DEVICE:
            case ACPI_TYPE_PROCESSOR:
            case ACPI_TYPE_THERMAL:

                HandlerObj = ObjDesc->CommonNotify.Handler;
                break;

            case ACPI_TYPE_METHOD:
                /*
                 * If we are executing module level code, the original
                 * Node's object was replaced by this Method object and we
                 * saved the handler in the method object.
                 *
                 * See AcpiNsExecModuleCode
                 */
                if (!AcpiGbl_ParseTableAsTermList &&
                    ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)
                {
                    HandlerObj = ObjDesc->Method.Dispatch.Handler;
                }
                break;

            default:

                /* Ignore other objects */

                break;
            }

            HandlerObj = AcpiEvFindRegionHandler (SpaceId, HandlerObj);
            if (HandlerObj)
            {
                /* Found correct handler */

                ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
                    "Found handler %p for region %p in obj %p\n",
                    HandlerObj, RegionObj, ObjDesc));

                (void) AcpiEvAttachRegion (HandlerObj, RegionObj, FALSE);

                /*
                 * Tell all users that this region is usable by
                 * running the _REG method
                 */
                AcpiExExitInterpreter ();
                (void) AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT);
                AcpiExEnterInterpreter ();
                return_ACPI_STATUS (AE_OK);
            }
        }

        /* This node does not have the handler we need; Pop up one level */

        Node = Node->Parent;
    }

    /*
     * If we get here, there is no handler for this region. This is not
     * fatal because many regions get created before a handler is installed
     * for said region.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "No handler for RegionType %s(%X) (RegionObj %p)\n",
        AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj));

    return_ACPI_STATUS (AE_OK);
}
Exemple #10
0
ACPI_STATUS
AcpiDsMethodError (
    ACPI_STATUS             Status,
    ACPI_WALK_STATE         *WalkState)
{
    UINT32                  AmlOffset;
    ACPI_NAME               Name = 0;


    ACPI_FUNCTION_ENTRY ();


    /* Ignore AE_OK and control exception codes */

    if (ACPI_SUCCESS (Status) ||
        (Status & AE_CODE_CONTROL))
    {
        return (Status);
    }

    /* Invoke the global exception handler */

    if (AcpiGbl_ExceptionHandler)
    {
        /* Exit the interpreter, allow handler to execute methods */

        AcpiExExitInterpreter ();

        /*
         * Handler can map the exception code to anything it wants, including
         * AE_OK, in which case the executing method will not be aborted.
         */
        AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml,
            WalkState->ParserState.AmlStart);

        if (WalkState->MethodNode)
        {
            Name = WalkState->MethodNode->Name.Integer;
        }
        else if (WalkState->DeferredNode)
        {
            Name = WalkState->DeferredNode->Name.Integer;
        }

        Status = AcpiGbl_ExceptionHandler (Status, Name,
            WalkState->Opcode, AmlOffset, NULL);
        AcpiExEnterInterpreter ();
    }

    AcpiDsClearImplicitReturn (WalkState);

    if (ACPI_FAILURE (Status))
    {
        AcpiDsDumpMethodStack (Status, WalkState, WalkState->Op);

        /* Display method locals/args if debugger is present */

#ifdef ACPI_DEBUGGER
        AcpiDbDumpMethodInfo (Status, WalkState);
#endif
    }

    return (Status);
}
Exemple #11
0
ACPI_STATUS
AcpiExLoadOp (
    ACPI_OPERAND_OBJECT     *ObjDesc,
    ACPI_OPERAND_OBJECT     *Target,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_OPERAND_OBJECT     *DdbHandle;
    ACPI_TABLE_HEADER       *TableHeader;
    ACPI_TABLE_HEADER       *Table;
    UINT32                  TableIndex;
    ACPI_STATUS             Status;
    UINT32                  Length;


    ACPI_FUNCTION_TRACE (ExLoadOp);


    /* Source Object can be either an OpRegion or a Buffer/Field */

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

        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "Load table from Region %p\n", ObjDesc));

        /* Region must be SystemMemory (from ACPI spec) */

        if (ObjDesc->Region.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY)
        {
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        /*
         * If the Region Address and Length have not been previously
         * evaluated, evaluate them now and save the results.
         */
        if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID))
        {
            Status = AcpiDsGetRegionArguments (ObjDesc);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }
        }

        /* Get the table header first so we can get the table length */

        TableHeader = ACPI_ALLOCATE (sizeof (ACPI_TABLE_HEADER));
        if (!TableHeader)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        Status = AcpiExRegionRead (ObjDesc, sizeof (ACPI_TABLE_HEADER),
            ACPI_CAST_PTR (UINT8, TableHeader));
        Length = TableHeader->Length;
        ACPI_FREE (TableHeader);

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

        /* Must have at least an ACPI table header */

        if (Length < sizeof (ACPI_TABLE_HEADER))
        {
            return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
        }

        /*
         * The original implementation simply mapped the table, with no copy.
         * However, the memory region is not guaranteed to remain stable and
         * we must copy the table to a local buffer. For example, the memory
         * region is corrupted after suspend on some machines. Dynamically
         * loaded tables are usually small, so this overhead is minimal.
         *
         * The latest implementation (5/2009) does not use a mapping at all.
         * We use the low-level operation region interface to read the table
         * instead of the obvious optimization of using a direct mapping.
         * This maintains a consistent use of operation regions across the
         * entire subsystem. This is important if additional processing must
         * be performed in the (possibly user-installed) operation region
         * handler. For example, AcpiExec and ASLTS depend on this.
         */

        /* Allocate a buffer for the table */

        Table = ACPI_ALLOCATE (Length);
        if (!Table)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        /* Read the entire table */

        Status = AcpiExRegionRead (ObjDesc, Length,
            ACPI_CAST_PTR (UINT8, Table));
        if (ACPI_FAILURE (Status))
        {
            ACPI_FREE (Table);
            return_ACPI_STATUS (Status);
        }
        break;

    case ACPI_TYPE_BUFFER: /* Buffer or resolved RegionField */

        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "Load table from Buffer or Field %p\n", ObjDesc));

        /* Must have at least an ACPI table header */

        if (ObjDesc->Buffer.Length < sizeof (ACPI_TABLE_HEADER))
        {
            return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
        }

        /* Get the actual table length from the table header */

        TableHeader = ACPI_CAST_PTR (
            ACPI_TABLE_HEADER, ObjDesc->Buffer.Pointer);
        Length = TableHeader->Length;

        /* Table cannot extend beyond the buffer */

        if (Length > ObjDesc->Buffer.Length)
        {
            return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
        }
        if (Length < sizeof (ACPI_TABLE_HEADER))
        {
            return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH);
        }

        /*
         * Copy the table from the buffer because the buffer could be
         * modified or even deleted in the future
         */
        Table = ACPI_ALLOCATE (Length);
        if (!Table)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        memcpy (Table, TableHeader, Length);
        break;

    default:

        return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
    }

    /* Install the new table into the local data structures */

    ACPI_INFO (("Dynamic OEM Table Load:"));
    AcpiExExitInterpreter ();
    Status = AcpiTbInstallAndLoadTable (ACPI_PTR_TO_PHYSADDR (Table),
        ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, TRUE, &TableIndex);
    AcpiExEnterInterpreter ();
    if (ACPI_FAILURE (Status))
    {
        /* Delete allocated table buffer */

        ACPI_FREE (Table);
        return_ACPI_STATUS (Status);
    }

    /*
     * Add the table to the namespace.
     *
     * Note: Load the table objects relative to the root of the namespace.
     * This appears to go against the ACPI specification, but we do it for
     * compatibility with other ACPI implementations.
     */
    Status = AcpiExAddTable (TableIndex, &DdbHandle);
    if (ACPI_FAILURE (Status))
    {
        /* On error, TablePtr was deallocated above */

        return_ACPI_STATUS (Status);
    }

    /* Store the DdbHandle into the Target operand */

    Status = AcpiExStore (DdbHandle, Target, WalkState);
    if (ACPI_FAILURE (Status))
    {
        (void) AcpiExUnloadTable (DdbHandle);

        /* TablePtr was deallocated above */

        AcpiUtRemoveReference (DdbHandle);
        return_ACPI_STATUS (Status);
    }

    /* Remove the reference by added by AcpiExStore above */

    AcpiUtRemoveReference (DdbHandle);
    return_ACPI_STATUS (Status);
}
Exemple #12
0
ACPI_STATUS
AcpiExLoadTableOp (
    ACPI_WALK_STATE         *WalkState,
    ACPI_OPERAND_OBJECT     **ReturnDesc)
{
    ACPI_STATUS             Status;
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_NAMESPACE_NODE     *ParentNode;
    ACPI_NAMESPACE_NODE     *StartNode;
    ACPI_NAMESPACE_NODE     *ParameterNode = NULL;
    ACPI_OPERAND_OBJECT     *DdbHandle;
    UINT32                  TableIndex;


    ACPI_FUNCTION_TRACE (ExLoadTableOp);


    /* Find the ACPI table in the RSDT/XSDT */

    AcpiExExitInterpreter ();
    Status = AcpiTbFindTable (
        Operand[0]->String.Pointer,
        Operand[1]->String.Pointer,
        Operand[2]->String.Pointer, &TableIndex);
    AcpiExEnterInterpreter ();
    if (ACPI_FAILURE (Status))
    {
        if (Status != AE_NOT_FOUND)
        {
            return_ACPI_STATUS (Status);
        }

        /* Table not found, return an Integer=0 and AE_OK */

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

        *ReturnDesc = DdbHandle;
        return_ACPI_STATUS (AE_OK);
    }

    /* Default nodes */

    StartNode = WalkState->ScopeInfo->Scope.Node;
    ParentNode = AcpiGbl_RootNode;

    /* RootPath (optional parameter) */

    if (Operand[3]->String.Length > 0)
    {
        /*
         * Find the node referenced by the RootPathString. This is the
         * location within the namespace where the table will be loaded.
         */
        Status = AcpiNsGetNodeUnlocked (StartNode,
            Operand[3]->String.Pointer, ACPI_NS_SEARCH_PARENT,
            &ParentNode);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }
    }

    /* ParameterPath (optional parameter) */

    if (Operand[4]->String.Length > 0)
    {
        if ((Operand[4]->String.Pointer[0] != AML_ROOT_PREFIX) &&
            (Operand[4]->String.Pointer[0] != AML_PARENT_PREFIX))
        {
            /*
             * Path is not absolute, so it will be relative to the node
             * referenced by the RootPathString (or the NS root if omitted)
             */
            StartNode = ParentNode;
        }

        /* Find the node referenced by the ParameterPathString */

        Status = AcpiNsGetNodeUnlocked (StartNode,
            Operand[4]->String.Pointer, ACPI_NS_SEARCH_PARENT,
            &ParameterNode);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }
    }

    /* Load the table into the namespace */

    ACPI_INFO (("Dynamic OEM Table Load:"));
    AcpiExExitInterpreter ();
    Status = AcpiTbLoadTable (TableIndex, ParentNode);
    AcpiExEnterInterpreter ();
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    Status = AcpiExAddTable (TableIndex, &DdbHandle);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Parameter Data (optional) */

    if (ParameterNode)
    {
        /* Store the parameter data into the optional parameter object */

        Status = AcpiExStore (Operand[5],
            ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParameterNode), WalkState);
        if (ACPI_FAILURE (Status))
        {
            (void) AcpiExUnloadTable (DdbHandle);

            AcpiUtRemoveReference (DdbHandle);
            return_ACPI_STATUS (Status);
        }
    }

    *ReturnDesc = DdbHandle;
    return_ACPI_STATUS (Status);
}
Exemple #13
0
ACPI_STATUS
AcpiNsEvaluate (
    ACPI_EVALUATE_INFO      *Info)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;


    ACPI_FUNCTION_TRACE (NsEvaluate);


    if (!Info)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Initialize the return value to an invalid object */

    Info->ReturnObject = NULL;
    Info->ParamCount = 0;

    /*
     * Get the actual namespace node for the target object. Handles these cases:
     *
     * 1) Null node, Pathname (absolute path)
     * 2) Node, Pathname (path relative to Node)
     * 3) Node, Null Pathname
     */
    Status = AcpiNsGetNode (Info->PrefixNode, Info->Pathname,
                ACPI_NS_NO_UPSEARCH, &Info->ResolvedNode);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * For a method alias, we must grab the actual method node so that proper
     * scoping context will be established before execution.
     */
    if (AcpiNsGetType (Info->ResolvedNode) == ACPI_TYPE_LOCAL_METHOD_ALIAS)
    {
        Info->ResolvedNode =
            ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Info->ResolvedNode->Object);
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", Info->Pathname,
        Info->ResolvedNode, AcpiNsGetAttachedObject (Info->ResolvedNode)));

    Node = Info->ResolvedNode;

    /*
     * Two major cases here:
     *
     * 1) The object is a control method -- execute it
     * 2) The object is not a method -- just return it's current value
     */
    if (AcpiNsGetType (Info->ResolvedNode) == ACPI_TYPE_METHOD)
    {
        /*
         * 1) Object is a control method - execute it
         */

        /* Verify that there is a method object associated with this node */

        Info->ObjDesc = AcpiNsGetAttachedObject (Info->ResolvedNode);
        if (!Info->ObjDesc)
        {
            ACPI_ERROR ((AE_INFO, "Control method has no attached sub-object"));
            return_ACPI_STATUS (AE_NULL_OBJECT);
        }

        /* Count the number of arguments being passed to the method */

        if (Info->Parameters)
        {
            while (Info->Parameters[Info->ParamCount])
            {
                if (Info->ParamCount > ACPI_METHOD_MAX_ARG)
                {
                    return_ACPI_STATUS (AE_LIMIT);
                }
                Info->ParamCount++;
            }
        }

        ACPI_DUMP_PATHNAME (Info->ResolvedNode, "ACPI: Execute Method",
            ACPI_LV_INFO, _COMPONENT);

        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "Method at AML address %p Length %X\n",
            Info->ObjDesc->Method.AmlStart + 1,
            Info->ObjDesc->Method.AmlLength - 1));

        /*
         * Any namespace deletion must acquire both the namespace and
         * interpreter locks to ensure that no thread is using the portion of
         * the namespace that is being deleted.
         *
         * Execute the method via the interpreter. The interpreter is locked
         * here before calling into the AML parser
         */
        AcpiExEnterInterpreter ();
        Status = AcpiPsExecuteMethod (Info);
        AcpiExExitInterpreter ();
    }
    else
    {
        /*
         * 2) Object is not a method, return its current value
         *
         * Disallow certain object types. For these, "evaluation" is undefined.
         */
        switch (Info->ResolvedNode->Type)
        {
        case ACPI_TYPE_DEVICE:
        case ACPI_TYPE_EVENT:
        case ACPI_TYPE_MUTEX:
        case ACPI_TYPE_REGION:
        case ACPI_TYPE_THERMAL:
        case ACPI_TYPE_LOCAL_SCOPE:

            ACPI_ERROR ((AE_INFO,
                "[%4.4s] Evaluation of object type [%s] is not supported",
                Info->ResolvedNode->Name.Ascii,
                AcpiUtGetTypeName (Info->ResolvedNode->Type)));

            return_ACPI_STATUS (AE_TYPE);

        default:
            break;
        }

        /*
         * Objects require additional resolution steps (e.g., the Node may be
         * a field that must be read, etc.) -- we can't just grab the object
         * out of the node.
         *
         * Use ResolveNodeToValue() to get the associated value.
         *
         * NOTE: we can get away with passing in NULL for a walk state because
         * ResolvedNode is guaranteed to not be a reference to either a method
         * local or a method argument (because this interface is never called
         * from a running method.)
         *
         * Even though we do not directly invoke the interpreter for object
         * resolution, we must lock it because we could access an opregion.
         * The opregion access code assumes that the interpreter is locked.
         */
        AcpiExEnterInterpreter ();

        /* Function has a strange interface */

        Status = AcpiExResolveNodeToValue (&Info->ResolvedNode, NULL);
        AcpiExExitInterpreter ();

        /*
         * If AcpiExResolveNodeToValue() succeeded, the return value was placed
         * in ResolvedNode.
         */
        if (ACPI_SUCCESS (Status))
        {
            Status = AE_CTRL_RETURN_VALUE;
            Info->ReturnObject =
                ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->ResolvedNode);

            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
                Info->ReturnObject,
                AcpiUtGetObjectTypeName (Info->ReturnObject)));
        }
    }

    /*
     * Check input argument count against the ASL-defined count for a method.
     * Also check predefined names: argument count and return value against
     * the ACPI specification. Some incorrect return value types are repaired.
     */
    (void) AcpiNsCheckPredefinedNames (Node, Info->ParamCount,
                Status, &Info->ReturnObject);

    /* Check if there is a return value that must be dealt with */

    if (Status == AE_CTRL_RETURN_VALUE)
    {
        /* If caller does not want the return value, delete it */

        if (Info->Flags & ACPI_IGNORE_RETURN_VALUE)
        {
            AcpiUtRemoveReference (Info->ReturnObject);
            Info->ReturnObject = NULL;
        }

        /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */

        Status = AE_OK;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
        "*** Completed evaluation of object %s ***\n", Info->Pathname));

    /*
     * Namespace was unlocked by the handling AcpiNs* function, so we
     * just return
     */
    return_ACPI_STATUS (Status);
}
Exemple #14
0
ACPI_STATUS
AcpiEvAddressSpaceDispatch (
    ACPI_OPERAND_OBJECT     *RegionObj,
    UINT32                  Function,
    ACPI_PHYSICAL_ADDRESS   Address,
    UINT32                  BitWidth,
    void                    *Value)
{
    ACPI_STATUS             Status;
    ACPI_STATUS             Status2;
    ACPI_ADR_SPACE_HANDLER  Handler;
    ACPI_ADR_SPACE_SETUP    RegionSetup;
    ACPI_OPERAND_OBJECT     *HandlerDesc;
    ACPI_OPERAND_OBJECT     *RegionObj2;
    void                    *RegionContext = NULL;


    ACPI_FUNCTION_TRACE ("EvAddressSpaceDispatch");


    RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
    if (!RegionObj2)
    {
        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /*
     * Ensure that there is a handler associated with this region
     */
    HandlerDesc = RegionObj->Region.AddrHandler;
    if (!HandlerDesc)
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n",
            RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));

        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /*
     * It may be the case that the region has never been initialized
     * Some types of regions require special init code
     */
    if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
    {
        /*
         * This region has not been initialized yet, do it
         */
        RegionSetup = HandlerDesc->AddrHandler.Setup;
        if (!RegionSetup)
        {
            /*
             *  Bad news, no init routine and not init'd
             */
            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n",
                RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
            return_ACPI_STATUS (AE_UNKNOWN_STATUS);
        }

        /*
         * We must exit the interpreter because the region setup will potentially
         * execute control methods
         */
        AcpiExExitInterpreter ();

        Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
                        HandlerDesc->AddrHandler.Context, &RegionContext);

        /* Re-enter the interpreter */

        Status2 = AcpiExEnterInterpreter ();
        if (ACPI_FAILURE (Status2))
        {
            return_ACPI_STATUS (Status2);
        }

        /*
         *  Init routine may fail
         */
        if (ACPI_FAILURE (Status))
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n",
                AcpiFormatException (Status),
                AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
            return_ACPI_STATUS (Status);
        }

        RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;

        /*
         *  Save the returned context for use in all accesses to
         *  this particular region.
         */
        RegionObj2->Extra.RegionContext = RegionContext;
    }

    /*
     *  We have everything we need, begin the process
     */
    Handler = HandlerDesc->AddrHandler.Handler;

    ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
        "Addrhandler %p (%p), Address %8.8X%8.8X\n",
        &RegionObj->Region.AddrHandler->AddrHandler, Handler,
        ACPI_HIDWORD (Address), ACPI_LODWORD (Address)));

    if (!(HandlerDesc->AddrHandler.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    {
        /*
         *  For handlers other than the default (supplied) handlers, we must
         *  exit the interpreter because the handler *might* block -- we don't
         *  know what it will do, so we can't hold the lock on the intepreter.
         */
        AcpiExExitInterpreter();
    }

    /*
     *  Invoke the handler.
     */
    Status = Handler (Function, Address, BitWidth, Value,
                      HandlerDesc->AddrHandler.Context,
                      RegionObj2->Extra.RegionContext);

    if (ACPI_FAILURE (Status))
    {
        ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n",
            AcpiUtGetRegionName (RegionObj->Region.SpaceId),
            AcpiFormatException (Status)));
    }

    if (!(HandlerDesc->AddrHandler.Flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
    {
        /*
         * We just returned from a non-default handler, we must re-enter the
         * interpreter
         */
        Status2 = AcpiExEnterInterpreter ();
        if (ACPI_FAILURE (Status2))
        {
            return_ACPI_STATUS (Status2);
        }
    }

    return_ACPI_STATUS (Status);
}
Exemple #15
0
ACPI_STATUS
AcpiPsParseAml (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status;
    ACPI_THREAD_STATE       *Thread;
    ACPI_THREAD_STATE       *PrevWalkList = AcpiGbl_CurrentWalkList;
    ACPI_WALK_STATE         *PreviousWalkState;


    ACPI_FUNCTION_TRACE (PsParseAml);

    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
        "Entered with WalkState=%p Aml=%p size=%X\n",
        WalkState, WalkState->ParserState.Aml,
        WalkState->ParserState.AmlSize));

    if (!WalkState->ParserState.Aml)
    {
        return_ACPI_STATUS (AE_NULL_OBJECT);
    }

    /* Create and initialize a new thread state */

    Thread = AcpiUtCreateThreadState ();
    if (!Thread)
    {
        if (WalkState->MethodDesc)
        {
            /* Executing a control method - additional cleanup */

            AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);
        }

        AcpiDsDeleteWalkState (WalkState);
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    WalkState->Thread = Thread;

    /*
     * If executing a method, the starting SyncLevel is this method's
     * SyncLevel
     */
    if (WalkState->MethodDesc)
    {
        WalkState->Thread->CurrentSyncLevel =
            WalkState->MethodDesc->Method.SyncLevel;
    }

    AcpiDsPushWalkState (WalkState, Thread);

    /*
     * This global allows the AML debugger to get a handle to the currently
     * executing control method.
     */
    AcpiGbl_CurrentWalkList = Thread;

    /*
     * Execute the walk loop as long as there is a valid Walk State. This
     * handles nested control method invocations without recursion.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState));

    Status = AE_OK;
    while (WalkState)
    {
        if (ACPI_SUCCESS (Status))
        {
            /*
             * The ParseLoop executes AML until the method terminates
             * or calls another method.
             */
            Status = AcpiPsParseLoop (WalkState);
        }

        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
            "Completed one call to walk loop, %s State=%p\n",
            AcpiFormatException (Status), WalkState));

        if (Status == AE_CTRL_TRANSFER)
        {
            /*
             * A method call was detected.
             * Transfer control to the called control method
             */
            Status = AcpiDsCallControlMethod (Thread, WalkState, NULL);
            if (ACPI_FAILURE (Status))
            {
                Status = AcpiDsMethodError (Status, WalkState);
            }

            /*
             * If the transfer to the new method method call worked
             *, a new walk state was created -- get it
             */
            WalkState = AcpiDsGetCurrentWalkState (Thread);
            continue;
        }
        else if (Status == AE_CTRL_TERMINATE)
        {
            Status = AE_OK;
        }
        else if ((Status != AE_OK) && (WalkState->MethodDesc))
        {
            /* Either the method parse or actual execution failed */

            AcpiExExitInterpreter ();
            ACPI_ERROR_METHOD ("Method parse/execution failed",
                WalkState->MethodNode, NULL, Status);
            AcpiExEnterInterpreter ();

            /* Check for possible multi-thread reentrancy problem */

            if ((Status == AE_ALREADY_EXISTS) &&
                (!(WalkState->MethodDesc->Method.InfoFlags &
                    ACPI_METHOD_SERIALIZED)))
            {
                /*
                 * Method is not serialized and tried to create an object
                 * twice. The probable cause is that the method cannot
                 * handle reentrancy. Mark as "pending serialized" now, and
                 * then mark "serialized" when the last thread exits.
                 */
                WalkState->MethodDesc->Method.InfoFlags |=
                    ACPI_METHOD_SERIALIZED_PENDING;
            }
        }

        /* We are done with this walk, move on to the parent if any */

        WalkState = AcpiDsPopWalkState (Thread);

        /* Reset the current scope to the beginning of scope stack */

        AcpiDsScopeStackClear (WalkState);

        /*
         * If we just returned from the execution of a control method or if we
         * encountered an error during the method parse phase, there's lots of
         * cleanup to do
         */
        if (((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) ==
            ACPI_PARSE_EXECUTE &&
            !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) ||
            (ACPI_FAILURE (Status)))
        {
            AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);
        }

        /* Delete this walk state and all linked control states */

        AcpiPsCleanupScope (&WalkState->ParserState);
        PreviousWalkState = WalkState;

        ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
            "ReturnValue=%p, ImplicitValue=%p State=%p\n",
            WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState));

        /* Check if we have restarted a preempted walk */

        WalkState = AcpiDsGetCurrentWalkState (Thread);
        if (WalkState)
        {
            if (ACPI_SUCCESS (Status))
            {
                /*
                 * There is another walk state, restart it.
                 * If the method return value is not used by the parent,
                 * The object is deleted
                 */
                if (!PreviousWalkState->ReturnDesc)
                {
                    /*
                     * In slack mode execution, if there is no return value
                     * we should implicitly return zero (0) as a default value.
                     */
                    if (AcpiGbl_EnableInterpreterSlack &&
                        !PreviousWalkState->ImplicitReturnObj)
                    {
                        PreviousWalkState->ImplicitReturnObj =
                            AcpiUtCreateIntegerObject ((UINT64) 0);
                        if (!PreviousWalkState->ImplicitReturnObj)
                        {
                            return_ACPI_STATUS (AE_NO_MEMORY);
                        }
                    }

                    /* Restart the calling control method */

                    Status = AcpiDsRestartControlMethod (WalkState,
                        PreviousWalkState->ImplicitReturnObj);
                }
                else
                {
                    /*
                     * We have a valid return value, delete any implicit
                     * return value.
                     */
                    AcpiDsClearImplicitReturn (PreviousWalkState);

                    Status = AcpiDsRestartControlMethod (WalkState,
                        PreviousWalkState->ReturnDesc);
                }
                if (ACPI_SUCCESS (Status))
                {
                    WalkState->WalkType |= ACPI_WALK_METHOD_RESTART;
                }
            }
            else
            {
                /* On error, delete any return object or implicit return */

                AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
                AcpiDsClearImplicitReturn (PreviousWalkState);
            }
        }

        /*
         * Just completed a 1st-level method, save the final internal return
         * value (if any)
         */
        else if (PreviousWalkState->CallerReturnDesc)
        {
            if (PreviousWalkState->ImplicitReturnObj)
            {
                *(PreviousWalkState->CallerReturnDesc) =
                    PreviousWalkState->ImplicitReturnObj;
            }
            else
            {
                 /* NULL if no return value */

                *(PreviousWalkState->CallerReturnDesc) =
                    PreviousWalkState->ReturnDesc;
            }
        }
        else
        {
            if (PreviousWalkState->ReturnDesc)
            {
                /* Caller doesn't want it, must delete it */

                AcpiUtRemoveReference (PreviousWalkState->ReturnDesc);
            }
            if (PreviousWalkState->ImplicitReturnObj)
            {
                /* Caller doesn't want it, must delete it */

                AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj);
            }
        }

        AcpiDsDeleteWalkState (PreviousWalkState);
    }

    /* Normal exit */

    AcpiExReleaseAllMutexes (Thread);
    AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread));
    AcpiGbl_CurrentWalkList = PrevWalkList;
    return_ACPI_STATUS (Status);
}
Exemple #16
0
void
AcpiEvUpdateGpes (
    ACPI_OWNER_ID           TableOwnerId)
{
    ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
    ACPI_GPE_WALK_INFO      WalkInfo;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  NewWakeGpeCount = 0;


    /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */

    WalkInfo.OwnerId = TableOwnerId;
    WalkInfo.ExecuteByOwnerId = TRUE;
    WalkInfo.Count = 0;

    if (AcpiGbl_LeaveWakeGpesDisabled)
    {
        /*
         * 1) Run any newly-loaded _PRW methods to find any GPEs that
         * can now be marked as CAN_WAKE GPEs. Note: We must run the
         * _PRW methods before we process the _Lxx/_Exx methods because
         * we will enable all runtime GPEs associated with the new
         * _Lxx/_Exx methods at the time we process those methods.
         *
         * Unlock interpreter so that we can run the _PRW methods.
         */
        WalkInfo.GpeBlock = NULL;
        WalkInfo.GpeDevice = NULL;

        AcpiExExitInterpreter ();

        Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
                    ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
                    AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL);
        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "While executing _PRW methods"));
        }

        AcpiExEnterInterpreter ();
        NewWakeGpeCount = WalkInfo.Count;
    }

    /*
     * 2) Find any _Lxx/_Exx GPE methods that have just been loaded.
     *
     * Any GPEs that correspond to new _Lxx/_Exx methods and are not
     * marked as CAN_WAKE are immediately enabled.
     *
     * Examine the namespace underneath each GpeDevice within the
     * GpeBlock lists.
     */
    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    if (ACPI_FAILURE (Status))
    {
        return;
    }

    WalkInfo.Count = 0;
    WalkInfo.EnableThisGpe = TRUE;

    /* Walk the interrupt level descriptor list */

    GpeXruptInfo = AcpiGbl_GpeXruptListHead;
    while (GpeXruptInfo)
    {
        /* Walk all Gpe Blocks attached to this interrupt level */

        GpeBlock = GpeXruptInfo->GpeBlockListHead;
        while (GpeBlock)
        {
            WalkInfo.GpeBlock = GpeBlock;
            WalkInfo.GpeDevice = GpeBlock->Node;

            Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD,
                        WalkInfo.GpeDevice, ACPI_UINT32_MAX,
                        ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod,
                        NULL, &WalkInfo, NULL);
            if (ACPI_FAILURE (Status))
            {
                ACPI_EXCEPTION ((AE_INFO, Status,
                    "While decoding _Lxx/_Exx methods"));
            }

            GpeBlock = GpeBlock->Next;
        }

        GpeXruptInfo = GpeXruptInfo->Next;
    }

    if (WalkInfo.Count || NewWakeGpeCount)
    {
        ACPI_INFO ((AE_INFO,
            "Enabled %u new runtime GPEs, added %u new wakeup GPEs",
            WalkInfo.Count, NewWakeGpeCount));
    }

    (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    return;
}
Exemple #17
0
ACPI_STATUS
AcpiEvaluateObject (
    ACPI_HANDLE             Handle,
    ACPI_STRING             Pathname,
    ACPI_OBJECT_LIST        *ExternalParams,
    ACPI_BUFFER             *ReturnBuffer)
{
    ACPI_STATUS             Status;
    ACPI_EVALUATE_INFO      *Info;
    ACPI_SIZE               BufferSpaceNeeded;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);


    /* Allocate and initialize the evaluation information block */

    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    if (!Info)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Info->Pathname = Pathname;

    /* Convert and validate the device handle */

    Info->PrefixNode = AcpiNsValidateHandle (Handle);
    if (!Info->PrefixNode)
    {
        Status = AE_BAD_PARAMETER;
        goto Cleanup;
    }

    /*
     * If there are parameters to be passed to a control method, the external
     * objects must all be converted to internal objects
     */
    if (ExternalParams && ExternalParams->Count)
    {
        /*
         * Allocate a new parameter block for the internal objects
         * Add 1 to count to allow for null terminated internal list
         */
        Info->Parameters = ACPI_ALLOCATE_ZEROED (
            ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *));
        if (!Info->Parameters)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /* Convert each external object in the list to an internal object */

        for (i = 0; i < ExternalParams->Count; i++)
        {
            Status = AcpiUtCopyEobjectToIobject (
                        &ExternalParams->Pointer[i], &Info->Parameters[i]);
            if (ACPI_FAILURE (Status))
            {
                goto Cleanup;
            }
        }
        Info->Parameters[ExternalParams->Count] = NULL;
    }

    /*
     * Three major cases:
     * 1) Fully qualified pathname
     * 2) No handle, not fully qualified pathname (error)
     * 3) Valid handle
     */
    if ((Pathname) &&
        (AcpiNsValidRootPrefix (Pathname[0])))
    {
        /* The path is fully qualified, just evaluate by name */

        Info->PrefixNode = NULL;
        Status = AcpiNsEvaluate (Info);
    }
    else if (!Handle)
    {
        /*
         * A handle is optional iff a fully qualified pathname is specified.
         * Since we've already handled fully qualified names above, this is
         * an error
         */
        if (!Pathname)
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Both Handle and Pathname are NULL"));
        }
        else
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Null Handle with relative pathname [%s]", Pathname));
        }

        Status = AE_BAD_PARAMETER;
    }
    else
    {
        /* We have a namespace a node and a possible relative path */

        Status = AcpiNsEvaluate (Info);
    }

    /*
     * If we are expecting a return value, and all went well above,
     * copy the return value to an external object.
     */
    if (ReturnBuffer)
    {
        if (!Info->ReturnObject)
        {
            ReturnBuffer->Length = 0;
        }
        else
        {
            if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
                ACPI_DESC_TYPE_NAMED)
            {
                /*
                 * If we received a NS Node as a return object, this means that
                 * the object we are evaluating has nothing interesting to
                 * return (such as a mutex, etc.)  We return an error because
                 * these types are essentially unsupported by this interface.
                 * We don't check up front because this makes it easier to add
                 * support for various types at a later date if necessary.
                 */
                Status = AE_TYPE;
                Info->ReturnObject = NULL;   /* No need to delete a NS Node */
                ReturnBuffer->Length = 0;
            }

            if (ACPI_SUCCESS (Status))
            {
                /* Dereference Index and RefOf references */

                AcpiNsResolveReferences (Info);

                /* Get the size of the returned object */

                Status = AcpiUtGetObjectSize (Info->ReturnObject,
                            &BufferSpaceNeeded);
                if (ACPI_SUCCESS (Status))
                {
                    /* Validate/Allocate/Clear caller buffer */

                    Status = AcpiUtInitializeBuffer (ReturnBuffer,
                                BufferSpaceNeeded);
                    if (ACPI_FAILURE (Status))
                    {
                        /*
                         * Caller's buffer is too small or a new one can't
                         * be allocated
                         */
                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                            "Needed buffer size %X, %s\n",
                            (UINT32) BufferSpaceNeeded,
                            AcpiFormatException (Status)));
                    }
                    else
                    {
                        /* We have enough space for the object, build it */

                        Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
                                    ReturnBuffer);
                    }
                }
            }
        }
    }

    if (Info->ReturnObject)
    {
        /*
         * Delete the internal return object. NOTE: Interpreter must be
         * locked to avoid race condition.
         */
        AcpiExEnterInterpreter ();

        /* Remove one reference on the return object (should delete it) */

        AcpiUtRemoveReference (Info->ReturnObject);
        AcpiExExitInterpreter ();
    }


Cleanup:

    /* Free the input parameter list (if we created one) */

    if (Info->Parameters)
    {
        /* Free the allocated parameter block */

        AcpiUtDeleteInternalObjectList (Info->Parameters);
    }

    ACPI_FREE (Info);
    return_ACPI_STATUS (Status);
}
Exemple #18
0
ACPI_STATUS
AcpiNsOneCompleteParse (
    UINT32                  PassNumber,
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *StartNode)
{
    ACPI_PARSE_OBJECT       *ParseRoot;
    ACPI_STATUS             Status;
    UINT32                  AmlLength;
    UINT8                   *AmlStart;
    ACPI_WALK_STATE         *WalkState;
    ACPI_TABLE_HEADER       *Table;
    ACPI_OWNER_ID           OwnerId;


    ACPI_FUNCTION_TRACE (NsOneCompleteParse);


    Status = AcpiGetTableByIndex (TableIndex, &Table);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Table must consist of at least a complete header */

    if (Table->Length < sizeof (ACPI_TABLE_HEADER))
    {
        return_ACPI_STATUS (AE_BAD_HEADER);
    }

    AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER);
    AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);

    Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Create and init a Root Node */

    ParseRoot = AcpiPsCreateScopeOp (AmlStart);
    if (!ParseRoot)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Create and initialize a new walk state */

    WalkState = AcpiDsCreateWalkState (OwnerId, NULL, NULL, NULL);
    if (!WalkState)
    {
        AcpiPsFreeOp (ParseRoot);
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL,
        AmlStart, AmlLength, NULL, (UINT8) PassNumber);
    if (ACPI_FAILURE (Status))
    {
        AcpiDsDeleteWalkState (WalkState);
        goto Cleanup;
    }

    /* Found OSDT table, enable the namespace override feature */

    if (ACPI_COMPARE_NAME(Table->Signature, ACPI_SIG_OSDT) &&
        PassNumber == ACPI_IMODE_LOAD_PASS1)
    {
        WalkState->NamespaceOverride = TRUE;
    }

    /* StartNode is the default location to load the table  */

    if (StartNode && StartNode != AcpiGbl_RootNode)
    {
        Status = AcpiDsScopeStackPush (
            StartNode, ACPI_TYPE_METHOD, WalkState);
        if (ACPI_FAILURE (Status))
        {
            AcpiDsDeleteWalkState (WalkState);
            goto Cleanup;
        }
    }

    /* Parse the AML */

    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
        "*PARSE* pass %u parse\n", PassNumber));
    AcpiExEnterInterpreter ();
    Status = AcpiPsParseAml (WalkState);
    AcpiExExitInterpreter ();

Cleanup:
    AcpiPsDeleteParseTree (ParseRoot);
    return_ACPI_STATUS (Status);
}
Exemple #19
0
ACPI_STATUS
AcpiPsExecuteTable (
    ACPI_EVALUATE_INFO      *Info)
{
    ACPI_STATUS             Status;
    ACPI_PARSE_OBJECT       *Op = NULL;
    ACPI_WALK_STATE         *WalkState = NULL;


    ACPI_FUNCTION_TRACE (PsExecuteTable);


    /* Create and init a Root Node */

    Op = AcpiPsCreateScopeOp (Info->ObjDesc->Method.AmlStart);
    if (!Op)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    /* Create and initialize a new walk state */

    WalkState = AcpiDsCreateWalkState (
        Info->ObjDesc->Method.OwnerId, NULL, NULL, NULL);
    if (!WalkState)
    {
        Status = AE_NO_MEMORY;
        goto Cleanup;
    }

    Status = AcpiDsInitAmlWalk (WalkState, Op, Info->Node,
        Info->ObjDesc->Method.AmlStart,
        Info->ObjDesc->Method.AmlLength, Info, Info->PassNumber);
    if (ACPI_FAILURE (Status))
    {
        goto Cleanup;
    }

    if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)
    {
        WalkState->ParseFlags |= ACPI_PARSE_MODULE_LEVEL;
    }

    /* Info->Node is the default location to load the table  */

    if (Info->Node && Info->Node != AcpiGbl_RootNode)
    {
        Status = AcpiDsScopeStackPush (
            Info->Node, ACPI_TYPE_METHOD, WalkState);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }
    }

    /*
     * Parse the AML, WalkState will be deleted by ParseAml
     */
    AcpiExEnterInterpreter ();
    Status = AcpiPsParseAml (WalkState);
    AcpiExExitInterpreter ();
    WalkState = NULL;

Cleanup:
    if (WalkState)
    {
        AcpiDsDeleteWalkState (WalkState);
    }
    if (Op)
    {
        AcpiPsDeleteParseTree (Op);
    }
    return_ACPI_STATUS (Status);
}
Exemple #20
0
void
AcpiDsTerminateControlMethod (
    ACPI_OPERAND_OBJECT     *MethodDesc,
    ACPI_WALK_STATE         *WalkState)
{

    ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState);


    /* MethodDesc is required, WalkState is optional */

    if (!MethodDesc)
    {
        return_VOID;
    }

    if (WalkState)
    {
        /* Delete all arguments and locals */

        AcpiDsMethodDataDeleteAll (WalkState);

        /*
         * If method is serialized, release the mutex and restore the
         * current sync level for this thread
         */
        if (MethodDesc->Method.Mutex)
        {
            /* Acquisition Depth handles recursive calls */

            MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--;
            if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth)
            {
                WalkState->Thread->CurrentSyncLevel =
                    MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel;

                AcpiOsReleaseMutex (
                    MethodDesc->Method.Mutex->Mutex.OsMutex);
                MethodDesc->Method.Mutex->Mutex.ThreadId = 0;
            }
        }

        /*
         * Delete any namespace objects created anywhere within the
         * namespace by the execution of this method. Unless:
         * 1) This method is a module-level executable code method, in which
         *    case we want make the objects permanent.
         * 2) There are other threads executing the method, in which case we
         *    will wait until the last thread has completed.
         */
        if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) &&
             (MethodDesc->Method.ThreadCount == 1))
        {
            /* Delete any direct children of (created by) this method */

            (void) AcpiExExitInterpreter ();
            AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode);
            (void) AcpiExEnterInterpreter ();

            /*
             * Delete any objects that were created by this method
             * elsewhere in the namespace (if any were created).
             * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the
             * deletion such that we don't have to perform an entire
             * namespace walk for every control method execution.
             */
            if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE)
            {
                (void) AcpiExExitInterpreter ();
                AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId);
                (void) AcpiExEnterInterpreter ();
                MethodDesc->Method.InfoFlags &=
                    ~ACPI_METHOD_MODIFIED_NAMESPACE;
            }
        }
    }

    /* Decrement the thread count on the method */

    if (MethodDesc->Method.ThreadCount)
    {
        MethodDesc->Method.ThreadCount--;
    }
    else
    {
        ACPI_ERROR ((AE_INFO,
            "Invalid zero thread count in method"));
    }

    /* Are there any other threads currently executing this method? */

    if (MethodDesc->Method.ThreadCount)
    {
        /*
         * Additional threads. Do not release the OwnerId in this case,
         * we immediately reuse it for the next thread executing this method
         */
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
            "*** Completed execution of one thread, %u threads remaining\n",
            MethodDesc->Method.ThreadCount));
    }
    else
    {
        /* This is the only executing thread for this method */

        /*
         * Support to dynamically change a method from NotSerialized to
         * Serialized if it appears that the method is incorrectly written and
         * does not support multiple thread execution. The best example of this
         * is if such a method creates namespace objects and blocks. A second
         * thread will fail with an AE_ALREADY_EXISTS exception.
         *
         * This code is here because we must wait until the last thread exits
         * before marking the method as serialized.
         */
        if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING)
        {
            if (WalkState)
            {
                ACPI_INFO ((
                    "Marking method %4.4s as Serialized "
                    "because of AE_ALREADY_EXISTS error",
                    WalkState->MethodNode->Name.Ascii));
            }

            /*
             * Method tried to create an object twice and was marked as
             * "pending serialized". The probable cause is that the method
             * cannot handle reentrancy.
             *
             * The method was created as NotSerialized, but it tried to create
             * a named object and then blocked, causing the second thread
             * entrance to begin and then fail. Workaround this problem by
             * marking the method permanently as Serialized when the last
             * thread exits here.
             */
            MethodDesc->Method.InfoFlags &=
                ~ACPI_METHOD_SERIALIZED_PENDING;

            MethodDesc->Method.InfoFlags |=
                (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL);
            MethodDesc->Method.SyncLevel = 0;
        }

        /* No more threads, we can free the OwnerId */

        if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL))
        {
            AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId);
        }
    }

    AcpiExStopTraceMethod ((ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node,
        MethodDesc, WalkState);

    return_VOID;
}
static ACPI_STATUS
AcpiExAddTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *ParentNode,
    ACPI_OPERAND_OBJECT     **DdbHandle)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;
    ACPI_OWNER_ID           OwnerId;


    ACPI_FUNCTION_TRACE (ExAddTable);


    /* Create an object to be the table handle */

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

    /* Init the table handle */

    ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
    ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE;
    *DdbHandle = ObjDesc;

    /* Install the new table into the local data structures */

    ObjDesc->Reference.Value = TableIndex;

    /* Add the table to the namespace */

    Status = AcpiNsLoadTable (TableIndex, ParentNode);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ObjDesc);
        *DdbHandle = NULL;
        return_ACPI_STATUS (Status);
    }

    /* Execute any module-level code that was found in the table */

    AcpiExExitInterpreter ();
    AcpiNsExecModuleCodeList ();
    AcpiExEnterInterpreter ();

    /*
     * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
     * responsible for discovering any new wake GPEs by running _PRW methods
     * that may have been loaded by this table.
     */
    Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
    if (ACPI_SUCCESS (Status))
    {
        AcpiEvUpdateGpes (OwnerId);
    }

    return_ACPI_STATUS (AE_OK);
}
Exemple #22
0
ACPI_STATUS
AcpiDsAutoSerializeMethod (
    ACPI_NAMESPACE_NODE     *Node,
    ACPI_OPERAND_OBJECT     *ObjDesc)
{
    ACPI_STATUS             Status;
    ACPI_PARSE_OBJECT       *Op = NULL;
    ACPI_WALK_STATE         *WalkState;


    ACPI_FUNCTION_TRACE_PTR (DsAutoSerializeMethod, Node);


    ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
        "Method auto-serialization parse [%4.4s] %p\n",
        AcpiUtGetNodeName (Node), Node));

    AcpiExEnterInterpreter ();

    /* Create/Init a root op for the method parse tree */

    Op = AcpiPsAllocOp (AML_METHOD_OP, ObjDesc->Method.AmlStart);
    if (!Op)
    {
        Status = AE_NO_MEMORY;
        goto Unlock;
    }

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

    /* Create and initialize a new walk state */

    WalkState = AcpiDsCreateWalkState (Node->OwnerId, NULL, NULL, NULL);
    if (!WalkState)
    {
        AcpiPsFreeOp (Op);
        Status = AE_NO_MEMORY;
        goto Unlock;
    }

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

    WalkState->DescendingCallback = AcpiDsDetectNamedOpcodes;

    /* Parse the method, scan for creation of named objects */

    Status = AcpiPsParseAml (WalkState);

    AcpiPsDeleteParseTree (Op);
Unlock:
    AcpiExExitInterpreter ();
    return_ACPI_STATUS (Status);
}
Exemple #23
0
static ACPI_STATUS
AcpiNsInitOneObject (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_OBJECT_TYPE        Type;
    ACPI_STATUS             Status = AE_OK;
    ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    ACPI_OPERAND_OBJECT     *ObjDesc;


    ACPI_FUNCTION_NAME (NsInitOneObject);


    Info->ObjectCount++;

    /* And even then, we are only interested in a few object types */

    Type = AcpiNsGetType (ObjHandle);
    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (!ObjDesc)
    {
        return (AE_OK);
    }

    /* Increment counters for object types we are looking for */

    switch (Type)
    {
    case ACPI_TYPE_REGION:

        Info->OpRegionCount++;
        break;

    case ACPI_TYPE_BUFFER_FIELD:

        Info->FieldCount++;
        break;

    case ACPI_TYPE_LOCAL_BANK_FIELD:

        Info->FieldCount++;
        break;

    case ACPI_TYPE_BUFFER:

        Info->BufferCount++;
        break;

    case ACPI_TYPE_PACKAGE:

        Info->PackageCount++;
        break;

    default:

        /* No init required, just exit now */

        return (AE_OK);
    }

    /* If the object is already initialized, nothing else to do */

    if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
    {
        return (AE_OK);
    }

    /* Must lock the interpreter before executing AML code */

    AcpiExEnterInterpreter ();

    /*
     * Each of these types can contain executable AML code within the
     * declaration.
     */
    switch (Type)
    {
    case ACPI_TYPE_REGION:

        Info->OpRegionInit++;
        Status = AcpiDsGetRegionArguments (ObjDesc);
        break;

    case ACPI_TYPE_BUFFER_FIELD:

        Info->FieldInit++;
        Status = AcpiDsGetBufferFieldArguments (ObjDesc);
        break;

    case ACPI_TYPE_LOCAL_BANK_FIELD:

        Info->FieldInit++;
        Status = AcpiDsGetBankFieldArguments (ObjDesc);
        break;

    case ACPI_TYPE_BUFFER:

        Info->BufferInit++;
        Status = AcpiDsGetBufferArguments (ObjDesc);
        break;

    case ACPI_TYPE_PACKAGE:

        Info->PackageInit++;
        Status = AcpiDsGetPackageArguments (ObjDesc);
        break;

    default:

        /* No other types can get here */

        break;
    }

    if (ACPI_FAILURE (Status))
    {
        ACPI_EXCEPTION ((AE_INFO, Status,
            "Could not execute arguments for [%4.4s] (%s)",
            AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
    }

    /*
     * We ignore errors from above, and always return OK, since we don't want
     * to abort the walk on any single error.
     */
    AcpiExExitInterpreter ();
    return (AE_OK);
}
Exemple #24
0
ACPI_STATUS
AcpiNsGetObjectValue (
    ACPI_NAMESPACE_NODE     *Node,
    ACPI_OPERAND_OBJECT     **ReturnObjDesc)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_NAMESPACE_NODE     *ResolvedNode = Node;


    ACPI_FUNCTION_TRACE ("NsGetObjectValue");


    /*
     * Objects require additional resolution steps (e.g., the
     * Node may be a field that must be read, etc.) -- we can't just grab
     * the object out of the node.
     */

    /*
     * Use ResolveNodeToValue() to get the associated value.  This call
     * always deletes ObjDesc (allocated above).
     *
     * NOTE: we can get away with passing in NULL for a walk state
     * because ObjDesc is guaranteed to not be a reference to either
     * a method local or a method argument (because this interface can only be
     * called from the AcpiEvaluate external interface, never called from
     * a running control method.)
     *
     * Even though we do not directly invoke the interpreter
     * for this, we must enter it because we could access an opregion.
     * The opregion access code assumes that the interpreter
     * is locked.
     *
     * We must release the namespace lock before entering the
     * intepreter.
     */
    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    Status = AcpiExEnterInterpreter ();
    if (ACPI_SUCCESS (Status))
    {
        Status = AcpiExResolveNodeToValue (&ResolvedNode, NULL);
        /*
         * If AcpiExResolveNodeToValue() succeeded, the return value was
         * placed in ResolvedNode.
         */
        AcpiExExitInterpreter ();

        if (ACPI_SUCCESS (Status))
        {
            Status = AE_CTRL_RETURN_VALUE;
            *ReturnObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ResolvedNode);
            ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
                *ReturnObjDesc, AcpiUtGetObjectTypeName (*ReturnObjDesc)));
        }
    }

    /* Namespace is unlocked */

    return_ACPI_STATUS (Status);
}