Beispiel #1
0
char *
MpGetDdnValue (
    char                    *DeviceName)
{
    ACPI_NAMESPACE_NODE     *DeviceNode;
    ACPI_NAMESPACE_NODE     *DdnNode;
    ACPI_STATUS             Status;


    Status = AcpiNsGetNode (NULL, DeviceName, ACPI_NS_NO_UPSEARCH,
        &DeviceNode);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit;
    }

    Status = AcpiNsGetNode (DeviceNode, METHOD_NAME__DDN, ACPI_NS_NO_UPSEARCH,
        &DdnNode);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit;
    }

    if ((DdnNode->Type != ACPI_TYPE_STRING) ||
        !DdnNode->Object)
    {
        goto ErrorExit;
    }

    return (DdnNode->Object->String.Pointer);


ErrorExit:
    return (NULL);
}
Beispiel #2
0
void
AcpiDbSetScope (
    char                    *Name)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;


    if (!Name || Name[0] == 0)
    {
        AcpiOsPrintf ("Current scope: %s\n", AcpiGbl_DbScopeBuf);
        return;
    }

    AcpiDbPrepNamestring (Name);

    if (Name[0] == '\\')
    {
        /* Validate new scope from the root */

        Status = AcpiNsGetNode (AcpiGbl_RootNode, Name, ACPI_NS_NO_UPSEARCH,
                    &Node);
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }

        ACPI_STRCPY (AcpiGbl_DbScopeBuf, Name);
        ACPI_STRCAT (AcpiGbl_DbScopeBuf, "\\");
    }
    else
    {
        /* Validate new scope relative to old scope */

        Status = AcpiNsGetNode (AcpiGbl_DbScopeNode, Name, ACPI_NS_NO_UPSEARCH,
                    &Node);
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }

        ACPI_STRCAT (AcpiGbl_DbScopeBuf, Name);
        ACPI_STRCAT (AcpiGbl_DbScopeBuf, "\\");
    }

    AcpiGbl_DbScopeNode = Node;
    AcpiOsPrintf ("New scope: %s\n", AcpiGbl_DbScopeBuf);
    return;

ErrorExit:

    AcpiOsPrintf ("Could not attach scope: %s, %s\n",
        Name, AcpiFormatException (Status));
}
void
AcpiNsReportMethodError (
    const char              *ModuleName,
    UINT32                  LineNumber,
    const char              *Message,
    ACPI_NAMESPACE_NODE     *PrefixNode,
    const char              *Path,
    ACPI_STATUS             MethodStatus)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node = PrefixNode;


    AcpiOsPrintf ("ACPI Error (%s-%04d): ", ModuleName, LineNumber);

    if (Path)
    {
        Status = AcpiNsGetNode (PrefixNode, Path, ACPI_NS_NO_UPSEARCH,
                    &Node);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("[Could not get node by pathname]");
        }
    }

    AcpiNsPrintNodePathname (Node, Message);
    AcpiOsPrintf (", %s\n", AcpiFormatException (MethodStatus));
}
Beispiel #4
0
void
AcpiUtMethodError (
    const char              *ModuleName,
    UINT32                  LineNumber,
    const char              *Message,
    ACPI_NAMESPACE_NODE     *PrefixNode,
    const char              *Path,
    ACPI_STATUS             MethodStatus)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node = PrefixNode;


    ACPI_MSG_REDIRECT_BEGIN;
    AcpiOsPrintf (ACPI_MSG_ERROR);

    if (Path)
    {
        Status = AcpiNsGetNode (PrefixNode, Path,
            ACPI_NS_NO_UPSEARCH, &Node);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("[Could not get node by pathname]");
        }
    }

    AcpiNsPrintNodePathname (Node, Message);
    AcpiOsPrintf (", %s", AcpiFormatException (MethodStatus));

    ACPI_MSG_SUFFIX;
    ACPI_MSG_REDIRECT_END;
}
Beispiel #5
0
static ACPI_STATUS
AcpiNsRepair_TSS (
    ACPI_EVALUATE_INFO      *Info,
    ACPI_OPERAND_OBJECT     **ReturnObjectPtr)
{
    ACPI_OPERAND_OBJECT     *ReturnObject = *ReturnObjectPtr;
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;


    /*
     * We can only sort the _TSS return package if there is no _PSS in the
     * same scope. This is because if _PSS is present, the ACPI specification
     * dictates that the _TSS Power Dissipation field is to be ignored, and
     * therefore some BIOSs leave garbage values in the _TSS Power field(s).
     * In this case, it is best to just return the _TSS package as-is.
     * (May, 2011)
     */
    Status = AcpiNsGetNode (Info->Node, "^_PSS",
        ACPI_NS_NO_UPSEARCH, &Node);
    if (ACPI_SUCCESS (Status))
    {
        return (AE_OK);
    }

    Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1,
                ACPI_SORT_DESCENDING, "PowerDissipation");

    return (Status);
}
Beispiel #6
0
char *
MpGetHidValue (
    ACPI_NAMESPACE_NODE     *DeviceNode)
{
    ACPI_NAMESPACE_NODE     *HidNode;
    char                    *HidString;
    ACPI_STATUS             Status;


    Status = AcpiNsGetNode (DeviceNode, METHOD_NAME__HID,
        ACPI_NS_NO_UPSEARCH, &HidNode);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit;
    }

    /* If only partial namespace, get the _HID from the parse tree */

    if (!HidNode->Object)
    {
        return (MpGetHidFromParseTree (HidNode));
    }

    /* Handle the different _HID flavors */

    switch (HidNode->Type)
    {
    case ACPI_TYPE_STRING:

        return (HidNode->Object->String.Pointer);

    case ACPI_TYPE_INTEGER:

        /* Convert EISAID to a string */

        HidString = UtLocalCacheCalloc (ACPI_EISAID_STRING_SIZE);
        AcpiExEisaIdToString (HidString, HidNode->Object->Integer.Value);
        return (HidString);

    case ACPI_TYPE_METHOD:

        return ("-Method-");

    default:

        FlPrintFile (ASL_FILE_MAP_OUTPUT, "BAD HID TYPE: %u", HidNode->Type);
        break;
    }


ErrorExit:
    return ("-No HID-");
}
Beispiel #7
0
char *
MpGetHidViaNamestring (
    char                    *DeviceName)
{
    ACPI_NAMESPACE_NODE     *DeviceNode;
    ACPI_STATUS             Status;


    Status = AcpiNsGetNode (NULL, DeviceName, ACPI_NS_NO_UPSEARCH,
        &DeviceNode);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit;
    }

    return (MpGetHidValue (DeviceNode));


ErrorExit:
    return ("-No HID-");
}
Beispiel #8
0
ACPI_STATUS
AcpiExOpcode_1A_0T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_OPERAND_OBJECT     *TempDesc;
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  Type;
    UINT64                  Value;


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


    /* Examine the AML opcode */

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

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

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


    case AML_DECREMENT_OP:          /* Decrement (Operand)  */
    case AML_INCREMENT_OP:          /* Increment (Operand)  */

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

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

            AcpiUtAddReference (TempDesc);
        }

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

            goto Cleanup;
        }

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

        /* Finished with this Integer object */

        AcpiUtRemoveReference (TempDesc);

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


    case AML_TYPE_OP:               /* ObjectType (SourceObject) */

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

        /* Get the type of the base object */

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

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

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


    case AML_SIZE_OF_OP:            /* SizeOf (SourceObject)  */

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

        /* Get the base object */

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

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

        case ACPI_TYPE_STRING:
            Value = TempDesc->String.Length;
            break;

        case ACPI_TYPE_BUFFER:

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

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

        case ACPI_TYPE_PACKAGE:

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

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

        default:
            ACPI_ERROR ((AE_INFO,
                "Operand must be Buffer/Integer/String/Package - found type %s",
                AcpiUtGetTypeName (Type)));
            Status = AE_AML_OPERAND_TYPE;
            goto Cleanup;
        }

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

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


    case AML_REF_OF_OP:             /* RefOf (SourceObject) */

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


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

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

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

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

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

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

                case ACPI_REFCLASS_REFOF:

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

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

                default:

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

            case ACPI_TYPE_STRING:
                break;

            default:
                Status = AE_AML_OPERAND_TYPE;
                goto Cleanup;
            }
        }

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

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

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

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

                /*
                 * The target type for the Index operator must be
                 * either a Buffer or a Package
                 */
                switch (Operand[0]->Reference.TargetType)
                {
                case ACPI_TYPE_BUFFER_FIELD:

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

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


                case ACPI_TYPE_PACKAGE:

                    /*
                     * Return the referenced element of the package.  We must
                     * add another reference to the referenced object, however.
                     */
                    ReturnDesc = *(Operand[0]->Reference.Where);
                    if (ReturnDesc)
                    {
                        AcpiUtAddReference (ReturnDesc);
                    }
                    break;


                default:

                    ACPI_ERROR ((AE_INFO,
                        "Unknown Index TargetType 0x%X in reference object %p",
                        Operand[0]->Reference.TargetType, Operand[0]));
                    Status = AE_AML_OPERAND_TYPE;
                    goto Cleanup;
                }
                break;


            case ACPI_REFCLASS_REFOF:

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

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

                /* Add another reference to the object! */

                AcpiUtAddReference (ReturnDesc);
                break;


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

                Status = AE_TYPE;
                goto Cleanup;
            }
        }
        break;


    default:

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


Cleanup:

    /* Delete return object on error */

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

    /* Save return object on success */

    else
    {
        WalkState->ResultObj = ReturnDesc;
    }

    return_ACPI_STATUS (Status);
}
Beispiel #9
0
ACPI_STATUS
AcpiNsRootInitialize (
    void)
{
    ACPI_STATUS                 Status;
    const ACPI_PREDEFINED_NAMES *InitVal = NULL;
    ACPI_NAMESPACE_NODE         *NewNode;
    ACPI_OPERAND_OBJECT         *ObjDesc;
    ACPI_STRING                 Val = NULL;


    ACPI_FUNCTION_TRACE (NsRootInitialize);


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

    /*
     * The global root ptr is initially NULL, so a non-NULL value indicates
     * that AcpiNsRootInitialize() has already been called; just return.
     */
    if (AcpiGbl_RootNode)
    {
        Status = AE_OK;
        goto UnlockAndExit;
    }

    /*
     * Tell the rest of the subsystem that the root is initialized
     * (This is OK because the namespace is locked)
     */
    AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct;

    /* Enter the pre-defined names in the name table */

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "Entering predefined entries into namespace\n"));

    for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++)
    {
        /* _OSI is optional for now, will be permanent later */

        if (!strcmp (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod)
        {
            continue;
        }

        Status = AcpiNsLookup (NULL, ACPI_CAST_PTR (char, InitVal->Name),
            InitVal->Type, ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
            NULL, &NewNode);
        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "Could not create predefined name %s",
                InitVal->Name));
            continue;
        }

        /*
         * Name entered successfully. If entry in PreDefinedNames[] specifies
         * an initial value, create the initial value.
         */
        if (InitVal->Val)
        {
            Status = AcpiOsPredefinedOverride (InitVal, &Val);
            if (ACPI_FAILURE (Status))
            {
                ACPI_ERROR ((AE_INFO,
                    "Could not override predefined %s",
                    InitVal->Name));
            }

            if (!Val)
            {
                Val = InitVal->Val;
            }

            /*
             * Entry requests an initial value, allocate a
             * descriptor for it.
             */
            ObjDesc = AcpiUtCreateInternalObject (InitVal->Type);
            if (!ObjDesc)
            {
                Status = AE_NO_MEMORY;
                goto UnlockAndExit;
            }

            /*
             * Convert value string from table entry to
             * internal representation. Only types actually
             * used for initial values are implemented here.
             */
            switch (InitVal->Type)
            {
            case ACPI_TYPE_METHOD:

                ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val);
                ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;

#if defined (ACPI_ASL_COMPILER)

                /* Save the parameter count for the iASL compiler */

                NewNode->Value = ObjDesc->Method.ParamCount;
#else
                /* Mark this as a very SPECIAL method */

                ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY;
                ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation;
#endif
                break;

            case ACPI_TYPE_INTEGER:

                ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val);
                break;

            case ACPI_TYPE_STRING:

                /* Build an object around the static string */

                ObjDesc->String.Length = (UINT32) strlen (Val);
                ObjDesc->String.Pointer = Val;
                ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER;
                break;

            case ACPI_TYPE_MUTEX:

                ObjDesc->Mutex.Node = NewNode;
                ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1);

                /* Create a mutex */

                Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex);
                if (ACPI_FAILURE (Status))
                {
                    AcpiUtRemoveReference (ObjDesc);
                    goto UnlockAndExit;
                }

                /* Special case for ACPI Global Lock */

                if (strcmp (InitVal->Name, "_GL_") == 0)
                {
                    AcpiGbl_GlobalLockMutex = ObjDesc;

                    /* Create additional counting semaphore for global lock */

                    Status = AcpiOsCreateSemaphore (
                        1, 0, &AcpiGbl_GlobalLockSemaphore);
                    if (ACPI_FAILURE (Status))
                    {
                        AcpiUtRemoveReference (ObjDesc);
                        goto UnlockAndExit;
                    }
                }
                break;

            default:

                ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X",
                    InitVal->Type));
                AcpiUtRemoveReference (ObjDesc);
                ObjDesc = NULL;
                continue;
            }

            /* Store pointer to value descriptor in the Node */

            Status = AcpiNsAttachObject (NewNode, ObjDesc,
                ObjDesc->Common.Type);

            /* Remove local reference to the object */

            AcpiUtRemoveReference (ObjDesc);
        }
    }


UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);

    /* Save a handle to "_GPE", it is always present */

    if (ACPI_SUCCESS (Status))
    {
        Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH,
            &AcpiGbl_FadtGpeDevice);
    }

    return_ACPI_STATUS (Status);
}
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;
    ACPI_TABLE_HEADER       *Table;
    UINT32                  TableIndex;


    ACPI_FUNCTION_TRACE (ExLoadTableOp);


    /* Validate lengths for the SignatureString, OEMIDString, OEMTableID */

    if ((Operand[0]->String.Length > ACPI_NAME_SIZE) ||
        (Operand[1]->String.Length > ACPI_OEM_ID_SIZE) ||
        (Operand[2]->String.Length > ACPI_OEM_TABLE_ID_SIZE))
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

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

    Status = AcpiTbFindTable (Operand[0]->String.Pointer,
                              Operand[1]->String.Pointer,
                              Operand[2]->String.Pointer, &TableIndex);
    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 = AcpiNsGetNode (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] != '\\') &&
            (Operand[4]->String.Pointer[0] != '^'))
        {
            /*
             * 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 = AcpiNsGetNode (StartNode, Operand[4]->String.Pointer,
                    ACPI_NS_SEARCH_PARENT, &ParameterNode);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }
    }

    /* Load the table into the namespace */

    Status = AcpiExAddTable (TableIndex, ParentNode, &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);
        }
    }

    Status = AcpiGetTableByIndex (TableIndex, &Table);
    if (ACPI_SUCCESS (Status))
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dynamic OEM Table Load:"));
        AcpiTbPrintTableHeader (0, Table);
    }

    /* Invoke table handler if present */

    if (AcpiGbl_TableHandler)
    {
        (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table,
                    AcpiGbl_TableHandlerContext);
    }

    *ReturnDesc = DdbHandle;
    return_ACPI_STATUS  (Status);
}
Beispiel #11
0
ACPI_STATUS
AcpiEvMatchPrwAndGpe (
    ACPI_HANDLE             ObjHandle,
    UINT32                  Level,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_GPE_WALK_INFO      *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context);
    ACPI_NAMESPACE_NODE     *GpeDevice;
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
    ACPI_NAMESPACE_NODE     *TargetGpeDevice;
    ACPI_NAMESPACE_NODE     *PrwNode;
    ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    ACPI_OPERAND_OBJECT     *PkgDesc;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    UINT32                  GpeNumber;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe);


    /* Check for a _PRW method under this device */

    Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW,
                ACPI_NS_NO_UPSEARCH, &PrwNode);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Check if requested OwnerId matches this OwnerId */

    if ((WalkInfo->ExecuteByOwnerId) &&
        (PrwNode->OwnerId != WalkInfo->OwnerId))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Execute the _PRW */

    Status = AcpiUtEvaluateObject (PrwNode, NULL,
                ACPI_BTYPE_PACKAGE, &PkgDesc);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* The returned _PRW package must have at least two elements */

    if (PkgDesc->Package.Count < 2)
    {
        goto Cleanup;
    }

    /* Extract pointers from the input context */

    GpeDevice = WalkInfo->GpeDevice;
    GpeBlock = WalkInfo->GpeBlock;

    /*
     * The _PRW object must return a package, we are only interested
     * in the first element
     */
    ObjDesc = PkgDesc->Package.Elements[0];

    if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER)
    {
        /* Use FADT-defined GPE device (from definition of _PRW) */

        TargetGpeDevice = NULL;
        if (GpeDevice)
        {
            TargetGpeDevice = AcpiGbl_FadtGpeDevice;
        }

        /* Integer is the GPE number in the FADT described GPE blocks */

        GpeNumber = (UINT32) ObjDesc->Integer.Value;
    }
    else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE)
    {
        /* Package contains a GPE reference and GPE number within a GPE block */

        if ((ObjDesc->Package.Count < 2) ||
            ((ObjDesc->Package.Elements[0])->Common.Type !=
                ACPI_TYPE_LOCAL_REFERENCE) ||
            ((ObjDesc->Package.Elements[1])->Common.Type !=
                ACPI_TYPE_INTEGER))
        {
            goto Cleanup;
        }

        /* Get GPE block reference and decode */

        TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node;
        GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value;
    }
    else
    {
        /* Unknown type, just ignore it */

        goto Cleanup;
    }

    /* Get the GpeEventInfo for this GPE */

    if (GpeDevice)
    {
        /*
         * Is this GPE within this block?
         *
         * TRUE if and only if these conditions are true:
         *     1) The GPE devices match.
         *     2) The GPE index(number) is within the range of the Gpe Block
         *          associated with the GPE device.
         */
        if (GpeDevice != TargetGpeDevice)
        {
            goto Cleanup;
        }

        GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock);
    }
    else
    {
        /* GpeDevice is NULL, just match the TargetDevice and GpeNumber */

        GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber);
    }

    if (GpeEventInfo)
    {
        if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
        {
            /* This GPE can wake the system */

            GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
            WalkInfo->Count++;
        }
    }

Cleanup:
    AcpiUtRemoveReference (PkgDesc);
    return_ACPI_STATUS (AE_OK);
}
Beispiel #12
0
ACPI_STATUS
AcpiGetHandle (
    ACPI_HANDLE             Parent,
    ACPI_STRING             Pathname,
    ACPI_HANDLE             *RetHandle)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node = NULL;
    ACPI_NAMESPACE_NODE     *PrefixNode = NULL;


    FUNCTION_ENTRY ();


    /* Ensure that ACPI has been initialized */

    ACPI_IS_INITIALIZATION_COMPLETE (Status);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    /* Parameter Validation */

    if (!RetHandle || !Pathname)
    {
        return (AE_BAD_PARAMETER);
    }

    /* Convert a parent handle to a prefix node */

    if (Parent)
    {
        AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);

        PrefixNode = AcpiNsConvertHandleToEntry (Parent);
        if (!PrefixNode)
        {
            AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
            return (AE_BAD_PARAMETER);
        }

        AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    }

    /* Special case for root, since we can't search for it */

    if (STRCMP (Pathname, NS_ROOT_PATH) == 0)
    {
        *RetHandle = AcpiNsConvertEntryToHandle (AcpiGbl_RootNode);
        return (AE_OK);
    }

    /*
     *  Find the Node and convert to a handle
     */
    Status = AcpiNsGetNode (Pathname, PrefixNode, &Node);

    *RetHandle = NULL;
    if (ACPI_SUCCESS (Status))
    {
        *RetHandle = AcpiNsConvertEntryToHandle (Node);
    }

    return (Status);
}
Beispiel #13
0
ACPI_STATUS
AcpiGetHandle (
    ACPI_HANDLE             Parent,
    ACPI_STRING             Pathname,
    ACPI_HANDLE             *RetHandle)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node = NULL;
    ACPI_NAMESPACE_NODE     *PrefixNode = NULL;


    ACPI_FUNCTION_ENTRY ();


    /* Parameter Validation */

    if (!RetHandle || !Pathname)
    {
        return (AE_BAD_PARAMETER);
    }

    /* Convert a parent handle to a prefix node */

    if (Parent)
    {
        PrefixNode = AcpiNsMapHandleToNode (Parent);
        if (!PrefixNode)
        {
            return (AE_BAD_PARAMETER);
        }
    }

    /*
     * Valid cases are:
     * 1) Fully qualified pathname
     * 2) Parent + Relative pathname
     *
     * Error for <null Parent + relative path>
     */
    if (AcpiNsValidRootPrefix (Pathname[0]))
    {
        /* Pathname is fully qualified (starts with '\') */

        /* Special case for root-only, since we can't search for it */

        if (!ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH))
        {
            *RetHandle = AcpiNsConvertEntryToHandle (AcpiGbl_RootNode);
            return (AE_OK);
        }
    }
    else if (!PrefixNode)
    {
        /* Relative path with null prefix is disallowed */

        return (AE_BAD_PARAMETER);
    }

    /* Find the Node and convert to a handle */

    Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH, &Node);
    if (ACPI_SUCCESS (Status))
    {
        *RetHandle = AcpiNsConvertEntryToHandle (Node);
    }

    return (Status);
}
Beispiel #14
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);
}
Beispiel #15
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);
}
Beispiel #16
0
void
AcpiDbSetScope (
    char                    *Name)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;


    if (!Name || Name[0] == 0)
    {
        AcpiOsPrintf ("Current scope: %s\n", AcpiGbl_DbScopeBuf);
        return;
    }

    AcpiDbPrepNamestring (Name);

    if (ACPI_IS_ROOT_PREFIX (Name[0]))
    {
        /* Validate new scope from the root */

        Status = AcpiNsGetNode (AcpiGbl_RootNode, Name, ACPI_NS_NO_UPSEARCH,
                    &Node);
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }

        AcpiGbl_DbScopeBuf[0] = 0;
    }
    else
    {
        /* Validate new scope relative to old scope */

        Status = AcpiNsGetNode (AcpiGbl_DbScopeNode, Name, ACPI_NS_NO_UPSEARCH,
                    &Node);
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }
    }

    /* Build the final pathname */

    if (AcpiUtSafeStrcat (AcpiGbl_DbScopeBuf, sizeof (AcpiGbl_DbScopeBuf),
        Name))
    {
        Status = AE_BUFFER_OVERFLOW;
        goto ErrorExit;
    }

    if (AcpiUtSafeStrcat (AcpiGbl_DbScopeBuf, sizeof (AcpiGbl_DbScopeBuf),
        "\\"))
    {
        Status = AE_BUFFER_OVERFLOW;
        goto ErrorExit;
    }

    AcpiGbl_DbScopeNode = Node;
    AcpiOsPrintf ("New scope: %s\n", AcpiGbl_DbScopeBuf);
    return;

ErrorExit:

    AcpiOsPrintf ("Could not attach scope: %s, %s\n",
        Name, AcpiFormatException (Status));
}
Beispiel #17
0
ACPI_STATUS
AcpiGetHandle (
    ACPI_HANDLE             Parent,
    ACPI_STRING             Pathname,
    ACPI_HANDLE             *RetHandle)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node = NULL;
    ACPI_NAMESPACE_NODE     *PrefixNode = NULL;


    ACPI_FUNCTION_ENTRY ();


    /* Parameter Validation */

    if (!RetHandle || !Pathname)
    {
        return (AE_BAD_PARAMETER);
    }

    /* Convert a parent handle to a prefix node */

    if (Parent)
    {
        Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }

        PrefixNode = AcpiNsMapHandleToNode (Parent);
        if (!PrefixNode)
        {
            (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
            return (AE_BAD_PARAMETER);
        }

        Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }
    }

    /* Special case for root, since we can't search for it */

    if (ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH) == 0)
    {
        *RetHandle = AcpiNsConvertEntryToHandle (AcpiGbl_RootNode);
        return (AE_OK);
    }

    /*
     *  Find the Node and convert to a handle
     */
    Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH,
                &Node);

    *RetHandle = NULL;
    if (ACPI_SUCCESS (Status))
    {
        *RetHandle = AcpiNsConvertEntryToHandle (Node);
    }

    return (Status);
}