Example #1
0
ACPI_STATUS
AcpiNsInitializeDevices (
    void)
{
    ACPI_STATUS             Status;
    ACPI_DEVICE_WALK_INFO   Info;


    ACPI_FUNCTION_TRACE (NsInitializeDevices);


    /* Init counters */

    Info.DeviceCount = 0;
    Info.Num_STA = 0;
    Info.Num_INI = 0;

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "Initializing Device/Processor/Thermal objects "
        "and executing _INI/_STA methods:\n"));

    /* Tree analysis: find all subtrees that contain _INI methods */

    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
                ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit;
    }

    /* Allocate the evaluation information block */

    Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    if (!Info.EvaluateInfo)
    {
        Status = AE_NO_MEMORY;
        goto ErrorExit;
    }

    /*
     * Execute the "global" _INI method that may appear at the root. This
     * support is provided for Windows compatibility (Vista+) and is not
     * part of the ACPI specification.
     */
    Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
    Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
    Info.EvaluateInfo->Parameters = NULL;
    Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;

    Status = AcpiNsEvaluate (Info.EvaluateInfo);
    if (ACPI_SUCCESS (Status))
    {
        Info.Num_INI++;
    }

    /* Walk namespace to execute all _INIs on present devices */

    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
                ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);

    /*
     * Any _OSI requests should be completed by now. If the BIOS has
     * requested any Windows OSI strings, we will always truncate
     * I/O addresses to 16 bits -- for Windows compatibility.
     */
    if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
    {
        AcpiGbl_TruncateIoAddresses = TRUE;
    }

    ACPI_FREE (Info.EvaluateInfo);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit;
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "    Executed %u _INI methods requiring %u _STA executions "
        "(examined %u objects)\n",
        Info.Num_INI, Info.Num_STA, Info.DeviceCount));

    return_ACPI_STATUS (Status);


ErrorExit:
    ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
    return_ACPI_STATUS (Status);
}
Example #2
0
static ACPI_STATUS
AcpiNsInitOneDevice (
    ACPI_HANDLE             ObjHandle,
    UINT32                  NestingLevel,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
    ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
    UINT32                  Flags;
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *DeviceNode;


    ACPI_FUNCTION_TRACE (NsInitOneDevice);


    /* We are interested in Devices, Processors and ThermalZones only */

    DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
    if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
        (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
        (DeviceNode->Type != ACPI_TYPE_THERMAL))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /*
     * Because of an earlier namespace analysis, all subtrees that contain an
     * _INI method are tagged.
     *
     * If this device subtree does not contain any _INI methods, we
     * can exit now and stop traversing this entire subtree.
     */
    if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
    {
        return_ACPI_STATUS (AE_CTRL_DEPTH);
    }

    /*
     * Run _STA to determine if this device is present and functioning. We
     * must know this information for two important reasons (from ACPI spec):
     *
     * 1) We can only run _INI if the device is present.
     * 2) We must abort the device tree walk on this subtree if the device is
     *    not present and is not functional (we will not examine the children)
     *
     * The _STA method is not required to be present under the device, we
     * assume the device is present if _STA does not exist.
     */
    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));

    Status = AcpiUtExecute_STA (DeviceNode, &Flags);
    if (ACPI_FAILURE (Status))
    {
        /* Ignore error and move on to next device */

        return_ACPI_STATUS (AE_OK);
    }

    /*
     * Flags == -1 means that _STA was not found. In this case, we assume that
     * the device is both present and functional.
     *
     * From the ACPI spec, description of _STA:
     *
     * "If a device object (including the processor object) does not have an
     * _STA object, then OSPM assumes that all of the above bits are set (in
     * other words, the device is present, ..., and functioning)"
     */
    if (Flags != ACPI_UINT32_MAX)
    {
        WalkInfo->Num_STA++;
    }

    /*
     * Examine the PRESENT and FUNCTIONING status bits
     *
     * Note: ACPI spec does not seem to specify behavior for the present but
     * not functioning case, so we assume functioning if present.
     */
    if (!(Flags & ACPI_STA_DEVICE_PRESENT))
    {
        /* Device is not present, we must examine the Functioning bit */

        if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
        {
            /*
             * Device is not present but is "functioning". In this case,
             * we will not run _INI, but we continue to examine the children
             * of this device.
             *
             * From the ACPI spec, description of _STA: (Note - no mention
             * of whether to run _INI or not on the device in question)
             *
             * "_STA may return bit 0 clear (not present) with bit 3 set
             * (device is functional). This case is used to indicate a valid
             * device for which no device driver should be loaded (for example,
             * a bridge device.) Children of this device may be present and
             * valid. OSPM should continue enumeration below a device whose
             * _STA returns this bit combination"
             */
            return_ACPI_STATUS (AE_OK);
        }
        else
        {
            /*
             * Device is not present and is not functioning. We must abort the
             * walk of this subtree immediately -- don't look at the children
             * of such a device.
             *
             * From the ACPI spec, description of _INI:
             *
             * "If the _STA method indicates that the device is not present,
             * OSPM will not run the _INI and will not examine the children
             * of the device for _INI methods"
             */
            return_ACPI_STATUS (AE_CTRL_DEPTH);
        }
    }

    /*
     * The device is present or is assumed present if no _STA exists.
     * Run the _INI if it exists (not required to exist)
     *
     * Note: We know there is an _INI within this subtree, but it may not be
     * under this particular device, it may be lower in the branch.
     */
    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));

    ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO));
    Info->PrefixNode = DeviceNode;
    Info->RelativePathname = METHOD_NAME__INI;
    Info->Parameters = NULL;
    Info->Flags = ACPI_IGNORE_RETURN_VALUE;

    Status = AcpiNsEvaluate (Info);
    if (ACPI_SUCCESS (Status))
    {
        WalkInfo->Num_INI++;
    }

#ifdef ACPI_DEBUG_OUTPUT
    else if (Status != AE_NOT_FOUND)
    {
        /* Ignore error and move on to next device */

        char *ScopeName = AcpiNsGetExternalPathname (Info->Node);

        ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
            ScopeName));
        ACPI_FREE (ScopeName);
    }
#endif

    /* Ignore errors from above */

    Status = AE_OK;

    /*
     * The _INI method has been run if present; call the Global Initialization
     * Handler for this device.
     */
    if (AcpiGbl_InitHandler)
    {
        Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
    }

    return_ACPI_STATUS (Status);
}
Example #3
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);
}
Example #4
0
static void ACPI_SYSTEM_XFACE
AcpiEvAsynchExecuteGpeMethod (
    void                    *Context)
{
    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    ACPI_STATUS             Status = AE_OK;
    ACPI_EVALUATE_INFO      *Info;
    ACPI_GPE_NOTIFY_INFO    *Notify;


    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);


    /* Do the correct dispatch - normal method or implicit notify */

    switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
    {
    case ACPI_GPE_DISPATCH_NOTIFY:
        /*
         * Implicit notify.
         * Dispatch a DEVICE_WAKE notify to the appropriate handler.
         * NOTE: the request is queued for execution after this method
         * completes. The notify handlers are NOT invoked synchronously
         * from this thread -- because handlers may in turn run other
         * control methods.
         *
         * June 2012: Expand implicit notify mechanism to support
         * notifies on multiple device objects.
         */
        Notify = GpeEventInfo->Dispatch.NotifyList;
        while (ACPI_SUCCESS (Status) && Notify)
        {
            Status = AcpiEvQueueNotifyRequest (
                Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);

            Notify = Notify->Next;
        }
        break;

    case ACPI_GPE_DISPATCH_METHOD:

        /* Allocate the evaluation information block */

        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
        if (!Info)
        {
            Status = AE_NO_MEMORY;
        }
        else
        {
            /*
             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
             * _Lxx/_Exx control method that corresponds to this GPE
             */
            Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
            Info->Flags = ACPI_IGNORE_RETURN_VALUE;

            Status = AcpiNsEvaluate (Info);
            ACPI_FREE (Info);
        }

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "while evaluating GPE method [%4.4s]",
                AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
        }
        break;

    default:

        goto ErrorExit; /* Should never happen */
    }

    /* Defer enabling of GPE until all notify handlers are done */

    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
        AcpiEvAsynchEnableGpe, GpeEventInfo);
    if (ACPI_SUCCESS (Status))
    {
        return_VOID;
    }

ErrorExit:
    AcpiEvAsynchEnableGpe (GpeEventInfo);
    return_VOID;
}
Example #5
0
ACPI_STATUS
AcpiNsInitializeDevices (
    UINT32                  Flags)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_DEVICE_WALK_INFO   Info;
    ACPI_HANDLE             Handle;


    ACPI_FUNCTION_TRACE (NsInitializeDevices);


    if (!(Flags & ACPI_NO_DEVICE_INIT))
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "[Init] Initializing ACPI Devices\n"));

        /* Init counters */

        Info.DeviceCount = 0;
        Info.Num_STA = 0;
        Info.Num_INI = 0;

        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
            "Initializing Device/Processor/Thermal objects "
            "and executing _INI/_STA methods:\n"));

        /* Tree analysis: find all subtrees that contain _INI methods */

        Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
            ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }

        /* Allocate the evaluation information block */

        Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
        if (!Info.EvaluateInfo)
        {
            Status = AE_NO_MEMORY;
            goto ErrorExit;
        }

        /*
         * Execute the "global" _INI method that may appear at the root.
         * This support is provided for Windows compatibility (Vista+) and
         * is not part of the ACPI specification.
         */
        Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
        Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
        Info.EvaluateInfo->Parameters = NULL;
        Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;

        Status = AcpiNsEvaluate (Info.EvaluateInfo);
        if (ACPI_SUCCESS (Status))
        {
            Info.Num_INI++;
        }

        /*
         * Execute \_SB._INI.
         * There appears to be a strict order requirement for \_SB._INI,
         * which should be evaluated before any _REG evaluations.
         */
        Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
        if (ACPI_SUCCESS (Status))
        {
            memset (Info.EvaluateInfo, 0, sizeof (ACPI_EVALUATE_INFO));
            Info.EvaluateInfo->PrefixNode = Handle;
            Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
            Info.EvaluateInfo->Parameters = NULL;
            Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;

            Status = AcpiNsEvaluate (Info.EvaluateInfo);
            if (ACPI_SUCCESS (Status))
            {
                Info.Num_INI++;
            }
        }
    }

    /*
     * Run all _REG methods
     *
     * Note: Any objects accessed by the _REG methods will be automatically
     * initialized, even if they contain executable AML (see the call to
     * AcpiNsInitializeObjects below).
     *
     * Note: According to the ACPI specification, we actually needn't execute
     * _REG for SystemMemory/SystemIo operation regions, but for PCI_Config
     * operation regions, it is required to evaluate _REG for those on a PCI
     * root bus that doesn't contain _BBN object. So this code is kept here
     * in order not to break things.
     */
    if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT))
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "[Init] Executing _REG OpRegion methods\n"));

        Status = AcpiEvInitializeOpRegions ();
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }
    }

    if (!(Flags & ACPI_NO_DEVICE_INIT))
    {
        /* Walk namespace to execute all _INIs on present devices */

        Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
            ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);

        /*
         * Any _OSI requests should be completed by now. If the BIOS has
         * requested any Windows OSI strings, we will always truncate
         * I/O addresses to 16 bits -- for Windows compatibility.
         */
        if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
        {
            AcpiGbl_TruncateIoAddresses = TRUE;
        }

        ACPI_FREE (Info.EvaluateInfo);
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }

        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
            "    Executed %u _INI methods requiring %u _STA executions "
            "(examined %u objects)\n",
            Info.Num_INI, Info.Num_STA, Info.DeviceCount));
    }

    return_ACPI_STATUS (Status);


ErrorExit:
    ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
    return_ACPI_STATUS (Status);
}
Example #6
0
ACPI_STATUS
AcpiEvExecuteRegMethod (
    ACPI_OPERAND_OBJECT     *RegionObj,
    UINT32                  Function)
{
    ACPI_EVALUATE_INFO      *Info;
    ACPI_OPERAND_OBJECT     *Args[3];
    ACPI_OPERAND_OBJECT     *RegionObj2;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (EvExecuteRegMethod);


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

    if (RegionObj2->Extra.Method_REG == NULL)
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Allocate and initialize the evaluation information block */

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

    Info->PrefixNode = RegionObj2->Extra.Method_REG;
    Info->RelativePathname = NULL;
    Info->Parameters = Args;
    Info->Flags = ACPI_IGNORE_RETURN_VALUE;

    /*
     * The _REG method has two arguments:
     *
     * Arg0 - Integer:
     *  Operation region space ID Same value as RegionObj->Region.SpaceId
     *
     * Arg1 - Integer:
     *  connection status 1 for connecting the handler, 0 for disconnecting
     *  the handler (Passed as a parameter)
     */
    Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
    if (!Args[0])
    {
        Status = AE_NO_MEMORY;
        goto Cleanup1;
    }

    Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
    if (!Args[1])
    {
        Status = AE_NO_MEMORY;
        goto Cleanup2;
    }

    Args[2] = NULL; /* Terminate list */

    /* Execute the method, no return value */

    ACPI_DEBUG_EXEC (
        AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));

    Status = AcpiNsEvaluate (Info);
    AcpiUtRemoveReference (Args[1]);

Cleanup2:
    AcpiUtRemoveReference (Args[0]);

Cleanup1:
    ACPI_FREE (Info);
    return_ACPI_STATUS (Status);
}
Example #7
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);
}
Example #8
0
static void
AcpiNsExecModuleCode (
    ACPI_OPERAND_OBJECT     *MethodObj,
    ACPI_EVALUATE_INFO      *Info)
{
    ACPI_OPERAND_OBJECT     *ParentObj;
    ACPI_NAMESPACE_NODE     *ParentNode;
    ACPI_OBJECT_TYPE        Type;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsExecModuleCode);


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

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

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

    MethodObj->Method.NextObject = NULL;

    /* Initialize the evaluation information block */

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

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

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

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

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

    Status = AcpiNsEvaluate (Info);

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

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

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

    /* Detach the temporary method object */

    AcpiNsDetachObject (ParentNode);

    /* Restore the original parent object */

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

Exit:
    if (ParentObj)
    {
        AcpiUtRemoveReference (ParentObj);
    }
    return_VOID;
}
Example #9
0
ACPI_STATUS
AcpiEvExecuteRegMethod (
    ACPI_OPERAND_OBJECT     *RegionObj,
    UINT32                  Function)
{
    ACPI_EVALUATE_INFO      *Info;
    ACPI_OPERAND_OBJECT     *Args[3];
    ACPI_OPERAND_OBJECT     *RegionObj2;
    const ACPI_NAME         *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG);
    ACPI_NAMESPACE_NODE     *MethodNode;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (EvExecuteRegMethod);


    if (!AcpiGbl_NamespaceInitialized ||
        RegionObj->Region.Handler == NULL)
    {
        return_ACPI_STATUS (AE_OK);
    }

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

    /*
     * Find any "_REG" method associated with this region definition.
     * The method should always be updated as this function may be
     * invoked after a namespace change.
     */
    Node = RegionObj->Region.Node->Parent;
    Status = AcpiNsSearchOneScope (
        *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);
    if (ACPI_SUCCESS (Status))
    {
        /*
         * The _REG method is optional and there can be only one per
         * region definition. This will be executed when the handler is
         * attached or removed.
         */
        RegionObj2->Extra.Method_REG = MethodNode;
    }
    if (RegionObj2->Extra.Method_REG == NULL)
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */

    if ((Function == ACPI_REG_CONNECT &&
        RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) ||
        (Function == ACPI_REG_DISCONNECT &&
         !(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED)))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Allocate and initialize the evaluation information block */

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

    Info->PrefixNode = RegionObj2->Extra.Method_REG;
    Info->RelativePathname = NULL;
    Info->Parameters = Args;
    Info->Flags = ACPI_IGNORE_RETURN_VALUE;

    /*
     * The _REG method has two arguments:
     *
     * Arg0 - Integer:
     *  Operation region space ID Same value as RegionObj->Region.SpaceId
     *
     * Arg1 - Integer:
     *  connection status 1 for connecting the handler, 0 for disconnecting
     *  the handler (Passed as a parameter)
     */
    Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
    if (!Args[0])
    {
        Status = AE_NO_MEMORY;
        goto Cleanup1;
    }

    Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
    if (!Args[1])
    {
        Status = AE_NO_MEMORY;
        goto Cleanup2;
    }

    Args[2] = NULL; /* Terminate list */

    /* Execute the method, no return value */

    ACPI_DEBUG_EXEC (
        AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));

    Status = AcpiNsEvaluate (Info);
    AcpiUtRemoveReference (Args[1]);

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

    if (Function == ACPI_REG_CONNECT)
    {
        RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED;
    }
    else
    {
        RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED;
    }

Cleanup2:
    AcpiUtRemoveReference (Args[0]);

Cleanup1:
    ACPI_FREE (Info);
    return_ACPI_STATUS (Status);
}
Example #10
0
static void ACPI_SYSTEM_XFACE
AcpiEvAsynchExecuteGpeMethod (
    void                    *Context)
{
    ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    ACPI_STATUS             Status;
    ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
    ACPI_EVALUATE_INFO      *Info;
    ACPI_GPE_NOTIFY_INFO    *Notify;


    ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);


    /* Allocate a local GPE block */

    LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
    if (!LocalGpeEventInfo)
    {
        ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
            "while handling a GPE"));
        return_VOID;
    }

    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (LocalGpeEventInfo);
        return_VOID;
    }

    /* Must revalidate the GpeNumber/GpeBlock */

    if (!AcpiEvValidGpeEvent (GpeEventInfo))
    {
        Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
        ACPI_FREE (LocalGpeEventInfo);
        return_VOID;
    }

    /*
     * Take a snapshot of the GPE info for this level - we copy the info to
     * prevent a race condition with RemoveHandler/RemoveBlock.
     */
    ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
        sizeof (ACPI_GPE_EVENT_INFO));

    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (LocalGpeEventInfo);
        return_VOID;
    }

    /* Do the correct dispatch - normal method or implicit notify */

    switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
    {
    case ACPI_GPE_DISPATCH_NOTIFY:
        /*
         * Implicit notify.
         * Dispatch a DEVICE_WAKE notify to the appropriate handler.
         * NOTE: the request is queued for execution after this method
         * completes. The notify handlers are NOT invoked synchronously
         * from this thread -- because handlers may in turn run other
         * control methods.
         *
         * June 2012: Expand implicit notify mechanism to support
         * notifies on multiple device objects.
         */
        Notify = LocalGpeEventInfo->Dispatch.NotifyList;
        while (ACPI_SUCCESS (Status) && Notify)
        {
            Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode,
                        ACPI_NOTIFY_DEVICE_WAKE);

            Notify = Notify->Next;
        }
        break;

    case ACPI_GPE_DISPATCH_METHOD:

        /* Allocate the evaluation information block */

        Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
        if (!Info)
        {
            Status = AE_NO_MEMORY;
        }
        else
        {
            /*
             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
             * _Lxx/_Exx control method that corresponds to this GPE
             */
            Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
            Info->Flags = ACPI_IGNORE_RETURN_VALUE;

            Status = AcpiNsEvaluate (Info);
            ACPI_FREE (Info);
        }

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "while evaluating GPE method [%4.4s]",
                AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
        }
        break;

    default:

        return_VOID; /* Should never happen */
    }

    /* Defer enabling of GPE until all notify handlers are done */

    Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
                AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (LocalGpeEventInfo);
    }
    return_VOID;
}
Example #11
0
ACPI_STATUS
AcpiUtEvaluateObject (
    ACPI_NAMESPACE_NODE     *PrefixNode,
    char                    *Path,
    UINT32                  ExpectedReturnBtypes,
    ACPI_OPERAND_OBJECT     **ReturnDesc)
{
    ACPI_EVALUATE_INFO      *Info;
    ACPI_STATUS             Status;
    UINT32                  ReturnBtype;


    ACPI_FUNCTION_TRACE (UtEvaluateObject);


    /* Allocate the evaluation information block */

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

    Info->PrefixNode = PrefixNode;
    Info->Pathname = Path;

    /* Evaluate the object/method */

    Status = AcpiNsEvaluate (Info);
    if (ACPI_FAILURE (Status))
    {
        if (Status == AE_NOT_FOUND)
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n",
                AcpiUtGetNodeName (PrefixNode), Path));
        }
        else
        {
            ACPI_ERROR_METHOD ("Method execution failed",
                PrefixNode, Path, Status);
        }

        goto Cleanup;
    }

    /* Did we get a return object? */

    if (!Info->ReturnObject)
    {
        if (ExpectedReturnBtypes)
        {
            ACPI_ERROR_METHOD ("No object was returned from",
                PrefixNode, Path, AE_NOT_EXIST);

            Status = AE_NOT_EXIST;
        }

        goto Cleanup;
    }

    /* Map the return object type to the bitmapped type */

    switch ((Info->ReturnObject)->Common.Type)
    {
    case ACPI_TYPE_INTEGER:
        ReturnBtype = ACPI_BTYPE_INTEGER;
        break;

    case ACPI_TYPE_BUFFER:
        ReturnBtype = ACPI_BTYPE_BUFFER;
        break;

    case ACPI_TYPE_STRING:
        ReturnBtype = ACPI_BTYPE_STRING;
        break;

    case ACPI_TYPE_PACKAGE:
        ReturnBtype = ACPI_BTYPE_PACKAGE;
        break;

    default:
        ReturnBtype = 0;
        break;
    }

    if ((AcpiGbl_EnableInterpreterSlack) &&
        (!ExpectedReturnBtypes))
    {
        /*
         * We received a return object, but one was not expected.  This can
         * happen frequently if the "implicit return" feature is enabled.
         * Just delete the return object and return AE_OK.
         */
        AcpiUtRemoveReference (Info->ReturnObject);
        goto Cleanup;
    }

    /* Is the return object one of the expected types? */

    if (!(ExpectedReturnBtypes & ReturnBtype))
    {
        ACPI_ERROR_METHOD ("Return object type is incorrect",
            PrefixNode, Path, AE_TYPE);

        ACPI_ERROR ((AE_INFO,
            "Type returned from %s was incorrect: %s, expected Btypes: %X",
            Path, AcpiUtGetObjectTypeName (Info->ReturnObject),
            ExpectedReturnBtypes));

        /* On error exit, we must delete the return object */

        AcpiUtRemoveReference (Info->ReturnObject);
        Status = AE_TYPE;
        goto Cleanup;
    }

    /* Object type is OK, return it */

    *ReturnDesc = Info->ReturnObject;

Cleanup:
    ACPI_FREE (Info);
    return_ACPI_STATUS (Status);
}