Пример #1
0
ACPI_STATUS
AcpiUtCopyIobjectToIobject (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     **DestDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject);


    /* Create the top level object */

    *DestDesc = AcpiUtCreateInternalObject (ACPI_GET_OBJECT_TYPE (SourceDesc));
    if (!*DestDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Copy the object and possible subobjects */

    if (ACPI_GET_OBJECT_TYPE (SourceDesc) == ACPI_TYPE_PACKAGE)
    {
        Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc,
                        WalkState);
    }
    else
    {
        Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc);
    }

    return_ACPI_STATUS (Status);
}
Пример #2
0
static ACPI_STATUS
AcpiExAddTable (
    UINT32                  TableIndex,
    ACPI_OPERAND_OBJECT     **DdbHandle)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;


    ACPI_FUNCTION_TRACE (ExAddTable);


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

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

    /* Init the table handle */

    ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID;
    ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE;
    ObjDesc->Reference.Value = TableIndex;
    *DdbHandle = ObjDesc;
    return_ACPI_STATUS (AE_OK);
}
Пример #3
0
static ACPI_STATUS
AcpiDsCreateMethodMutex (
    ACPI_OPERAND_OBJECT     *MethodDesc)
{
    ACPI_OPERAND_OBJECT     *MutexDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (DsCreateMethodMutex);


    /* Create the new mutex object */

    MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX);
    if (!MutexDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Create the actual OS Mutex */

    Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtDeleteObjectDesc (MutexDesc);
        return_ACPI_STATUS (Status);
    }

    MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel;
    MethodDesc->Method.Mutex = MutexDesc;
    return_ACPI_STATUS (AE_OK);
}
Пример #4
0
ACPI_OPERAND_OBJECT *
AcpiUtCreatePackageObject (
    UINT32                  Count)
{
    ACPI_OPERAND_OBJECT     *PackageDesc;
    ACPI_OPERAND_OBJECT     **PackageElements;


    ACPI_FUNCTION_TRACE_U32 (UtCreatePackageObject, Count);


    /* Create a new Package object */

    PackageDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE);
    if (!PackageDesc)
    {
        return_PTR (NULL);
    }

    /*
     * Create the element array. Count+1 allows the array to be null
     * terminated.
     */
    PackageElements = ACPI_ALLOCATE_ZEROED (
                        ((ACPI_SIZE) Count + 1) * sizeof (void *));
    if (!PackageElements)
    {
        ACPI_FREE (PackageDesc);
        return_PTR (NULL);
    }

    PackageDesc->Package.Count = Count;
    PackageDesc->Package.Elements = PackageElements;
    return_PTR (PackageDesc);
}
Пример #5
0
ACPI_STATUS
AcpiExOpcode_0A_0T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;


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


    /* Examine the AML opcode */

    switch (WalkState->Opcode)
    {
    case AML_TIMER_OP:      /*  Timer () */

        /* Create a return object of type Integer */

        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }
#if ACPI_MACHINE_WIDTH != 16
        ReturnDesc->Integer.Value = AcpiOsGetTimer ();
#endif
        break;

    default:                /*  Unknown opcode  */

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

Cleanup:

    /* Delete return object on error */

    if ((ACPI_FAILURE (Status)) || WalkState->ResultObj)
    {
        AcpiUtRemoveReference (ReturnDesc);
    }
    else
    {
        /* Save the return value */

        WalkState->ResultObj = ReturnDesc;
    }

    return_ACPI_STATUS (Status);
}
Пример #6
0
ACPI_STATUS
AcpiDsBuildInternalObject (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE ("DsBuildInternalObject");


    *ObjDescPtr = NULL;
    if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    {
        /*
         * This is an named object reference.  If this name was
         * previously looked up in the namespace, it was stored in this op.
         * Otherwise, go ahead and look it up now
         */
        if (!Op->Common.Node)
        {
            Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Common.Value.String,
                            ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                            ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
                            (ACPI_NAMESPACE_NODE **) &(Op->Common.Node));

            if (ACPI_FAILURE (Status))
            {
                ACPI_REPORT_NSERROR (Op->Common.Value.String, Status);
                return_ACPI_STATUS (Status);
            }
        }
    }

    /* Create and init the internal ACPI object */

    ObjDesc = AcpiUtCreateInternalObject ((AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ObjDesc);
        return_ACPI_STATUS (Status);
    }

    *ObjDescPtr = ObjDesc;
    return_ACPI_STATUS (AE_OK);
}
Пример #7
0
static void
AcpiPsLinkModuleCode (
    UINT8                   *AmlStart,
    UINT32                  AmlLength,
    ACPI_OWNER_ID           OwnerId)
{
    ACPI_OPERAND_OBJECT     *Prev;
    ACPI_OPERAND_OBJECT     *Next;
    ACPI_OPERAND_OBJECT     *MethodObj;


    /* Get the tail of the list */

    Prev = Next = AcpiGbl_ModuleCodeList;
    while (Next)
    {
        Prev = Next;
        Next = Next->Method.Mutex;
    }

    /*
     * Insert the module level code into the list. Merge it if it is
     * adjacent to the previous element.
     */
    if (!Prev ||
       ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart))
    {
        /* Create, initialize, and link a new temporary method object */

        MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
        if (!MethodObj)
        {
            return;
        }

        MethodObj->Method.AmlStart = AmlStart;
        MethodObj->Method.AmlLength = AmlLength;
        MethodObj->Method.OwnerId = OwnerId;
        MethodObj->Method.Flags |= AOPOBJ_MODULE_LEVEL;

        if (!Prev)
        {
            AcpiGbl_ModuleCodeList = MethodObj;
        }
        else
        {
            Prev->Method.Mutex = MethodObj;
        }
    }
    else
    {
        Prev->Method.AmlLength += AmlLength;
    }
}
Пример #8
0
ACPI_STATUS
AcpiNsAttachData (
    ACPI_NAMESPACE_NODE     *Node,
    ACPI_OBJECT_HANDLER     Handler,
    void                    *Data)
{
    ACPI_OPERAND_OBJECT     *PrevObjDesc;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *DataDesc;


    /* We only allow one attachment per handler */

    PrevObjDesc = NULL;
    ObjDesc = Node->Object;
    while (ObjDesc)
    {
        if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) &&
            (ObjDesc->Data.Handler == Handler))
        {
            return (AE_ALREADY_EXISTS);
        }

        PrevObjDesc = ObjDesc;
        ObjDesc = ObjDesc->Common.NextObject;
    }

    /* Create an internal object for the data */

    DataDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_DATA);
    if (!DataDesc)
    {
        return (AE_NO_MEMORY);
    }

    DataDesc->Data.Handler = Handler;
    DataDesc->Data.Pointer = Data;

    /* Install the data object */

    if (PrevObjDesc)
    {
        PrevObjDesc->Common.NextObject = DataDesc;
    }
    else
    {
        Node->Object = DataDesc;
    }

    return (AE_OK);
}
Пример #9
0
static ACPI_STATUS
AcpiExAddTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *ParentNode,
    ACPI_OPERAND_OBJECT     **DdbHandle)
{
    ACPI_STATUS             Status;
    ACPI_OPERAND_OBJECT     *ObjDesc;


    ACPI_FUNCTION_TRACE (ExAddTable);


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

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

    /* Init the table handle */

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

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

    ObjDesc->Reference.Value = TableIndex;

    /* Add the table to the namespace */

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

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

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

    return_ACPI_STATUS (Status);
}
Пример #10
0
ACPI_OPERAND_OBJECT *
AcpiUtCreateBufferObject (
    ACPI_SIZE               BufferSize)
{
    ACPI_OPERAND_OBJECT     *BufferDesc;
    UINT8                   *Buffer = NULL;


    ACPI_FUNCTION_TRACE_U32 (UtCreateBufferObject, BufferSize);


    /* Create a new Buffer object */

    BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER);
    if (!BufferDesc)
    {
        return_PTR (NULL);
    }

    /* Create an actual buffer only if size > 0 */

    if (BufferSize > 0)
    {
        /* Allocate the actual buffer */

        Buffer = ACPI_ALLOCATE_ZEROED (BufferSize);
        if (!Buffer)
        {
            ACPI_ERROR ((AE_INFO, "Could not allocate size %u",
                (UINT32) BufferSize));

            AcpiUtRemoveReference (BufferDesc);
            return_PTR (NULL);
        }
    }

    /* Complete buffer object initialization */

    BufferDesc->Buffer.Flags |= AOPOBJ_DATA_VALID;
    BufferDesc->Buffer.Pointer = Buffer;
    BufferDesc->Buffer.Length = (UINT32) BufferSize;

    /* Return the new buffer descriptor */

    return_PTR (BufferDesc);
}
Пример #11
0
ACPI_OPERAND_OBJECT *
AcpiUtCreateStringObject (
    ACPI_SIZE               StringSize)
{
    ACPI_OPERAND_OBJECT     *StringDesc;
    char                    *String;


    ACPI_FUNCTION_TRACE_U32 (UtCreateStringObject, StringSize);


    /* Create a new String object */

    StringDesc = AcpiUtCreateInternalObject (ACPI_TYPE_STRING);
    if (!StringDesc)
    {
        return_PTR (NULL);
    }

    /*
     * Allocate the actual string buffer -- (Size + 1) for NULL terminator.
     * NOTE: Zero-length strings are NULL terminated
     */
    String = ACPI_ALLOCATE_ZEROED (StringSize + 1);
    if (!String)
    {
        ACPI_ERROR ((AE_INFO, "Could not allocate size %u",
            (UINT32) StringSize));

        AcpiUtRemoveReference (StringDesc);
        return_PTR (NULL);
    }

    /* Complete string object initialization */

    StringDesc->String.Pointer = String;
    StringDesc->String.Length = (UINT32) StringSize;

    /* Return the new string descriptor */

    return_PTR (StringDesc);
}
Пример #12
0
ACPI_STATUS
AcpiUtCopyIobjectToIobject (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     **DestDesc,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject);


    /* Create the top level object */

    *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type);
    if (!*DestDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Copy the object and possible subobjects */

    if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE)
    {
        Status = AcpiUtCopyIpackageToIpackage (
            SourceDesc, *DestDesc, WalkState);
    }
    else
    {
        Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc);
    }

    /* Delete the allocated object if copy failed */

    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (*DestDesc);
    }

    return_ACPI_STATUS (Status);
}
Пример #13
0
ACPI_OPERAND_OBJECT *
AcpiUtCreateBufferObject (
    ACPI_SIZE               BufferSize)
{
    ACPI_OPERAND_OBJECT     *BufferDesc;
    UINT8                   *Buffer;


    ACPI_FUNCTION_TRACE_U32 ("UtCreateBufferObject", BufferSize);


    /*
     * Create a new Buffer object
     */
    BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER);
    if (!BufferDesc)
    {
        return_PTR (NULL);
    }

    /* Allocate the actual buffer */

    Buffer = ACPI_MEM_CALLOCATE (BufferSize);
    if (!Buffer)
    {
        ACPI_REPORT_ERROR (("CreateBuffer: could not allocate size %X\n", 
            (UINT32) BufferSize));
        AcpiUtRemoveReference (BufferDesc);
        return_PTR (NULL);
    }

    /* Complete buffer object initialization */

    BufferDesc->Buffer.Flags |= AOPOBJ_DATA_VALID;
    BufferDesc->Buffer.Pointer = Buffer;
    BufferDesc->Buffer.Length = (UINT32) BufferSize;

    /* Return the new buffer descriptor */

    return_PTR (BufferDesc);
}
Пример #14
0
ACPI_OPERAND_OBJECT *
AcpiUtCreateIntegerObject (
    UINT64                  InitialValue)
{
    ACPI_OPERAND_OBJECT     *IntegerDesc;


    ACPI_FUNCTION_TRACE (UtCreateIntegerObject);


    /* Create and initialize a new integer object */

    IntegerDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
    if (!IntegerDesc)
    {
        return_PTR (NULL);
    }

    IntegerDesc->Integer.Value = InitialValue;
    return_PTR (IntegerDesc);
}
Пример #15
0
void
AcpiDmAddExternalsToNamespace (
    void)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_OPERAND_OBJECT     *MethodDesc;
    ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;


    while (External)
    {
        /* Add the external name (object) into the namespace */

        Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
                   ACPI_IMODE_LOAD_PASS1,
                   ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
                   NULL, &Node);

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "while adding external to namespace [%s]",
                External->Path));
        }
        else if (External->Type == ACPI_TYPE_METHOD)
        {
            /* For methods, we need to save the argument count */

            MethodDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
            MethodDesc->Method.ParamCount = (UINT8) External->Value;
            Node->Object = MethodDesc;
        }

        External = External->Next;
    }
}
Пример #16
0
ACPI_STATUS
AcpiDsBuildInternalPackageObj (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  ElementCount,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_PARSE_OBJECT       *Arg;
    ACPI_PARSE_OBJECT       *Parent;
    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  i;
    UINT16                  Index;
    UINT16                  ReferenceCount;


    ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj);


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

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

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

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

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

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

    ObjDesc->Package.Count = ElementCount;

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

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

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

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

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

        Arg = Arg->Common.Next;
    }

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

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

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

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

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

    ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
    Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
    return_ACPI_STATUS (Status);
}
Пример #17
0
ACPI_STATUS
AcpiDsBuildInternalBufferObj (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  BufferLength,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_PARSE_OBJECT       *Arg;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PARSE_OBJECT       *ByteList;
    UINT32                  ByteListLength = 0;


    ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj);


    /*
     * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
     * The buffer object already exists (from the NS node), otherwise it must
     * be created.
     */
    ObjDesc = *ObjDescPtr;
    if (!ObjDesc)
    {
        /* Create a new buffer object */

        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER);
        *ObjDescPtr = ObjDesc;
        if (!ObjDesc)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }
    }

    /*
     * Second arg is the buffer data (optional) ByteList can be either
     * individual bytes or a string initializer. In either case, a
     * ByteList appears in the AML.
     */
    Arg = Op->Common.Value.Arg;         /* skip first arg */

    ByteList = Arg->Named.Next;
    if (ByteList)
    {
        if (ByteList->Common.AmlOpcode != AML_INT_BYTELIST_OP)
        {
            ACPI_ERROR ((AE_INFO,
                "Expecting bytelist, found AML opcode 0x%X in op %p",
                ByteList->Common.AmlOpcode, ByteList));

            AcpiUtRemoveReference (ObjDesc);
            return (AE_TYPE);
        }

        ByteListLength = (UINT32) ByteList->Common.Value.Integer;
    }

    /*
     * The buffer length (number of bytes) will be the larger of:
     * 1) The specified buffer length and
     * 2) The length of the initializer byte list
     */
    ObjDesc->Buffer.Length = BufferLength;
    if (ByteListLength > BufferLength)
    {
        ObjDesc->Buffer.Length = ByteListLength;
    }

    /* Allocate the buffer */

    if (ObjDesc->Buffer.Length == 0)
    {
        ObjDesc->Buffer.Pointer = NULL;
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "Buffer defined with zero length in AML, creating\n"));
    }
    else
    {
        ObjDesc->Buffer.Pointer = ACPI_ALLOCATE_ZEROED (
                                        ObjDesc->Buffer.Length);
        if (!ObjDesc->Buffer.Pointer)
        {
            AcpiUtDeleteObjectDesc (ObjDesc);
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        /* Initialize buffer from the ByteList (if present) */

        if (ByteList)
        {
            ACPI_MEMCPY (ObjDesc->Buffer.Pointer, ByteList->Named.Data,
                         ByteListLength);
        }
    }

    ObjDesc->Buffer.Flags |= AOPOBJ_DATA_VALID;
    Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
    return_ACPI_STATUS (AE_OK);
}
Пример #18
0
ACPI_STATUS
AcpiDsBuildInternalObject (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (DsBuildInternalObject);


    *ObjDescPtr = NULL;
    if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    {
        /*
         * This is a named object reference. If this name was
         * previously looked up in the namespace, it was stored in
         * this op. Otherwise, go ahead and look it up now
         */
        if (!Op->Common.Node)
        {
            /* Check if we are resolving a named reference within a package */

            if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
                (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
            {
                /*
                 * We won't resolve package elements here, we will do this
                 * after all ACPI tables are loaded into the namespace. This
                 * behavior supports both forward references to named objects
                 * and external references to objects in other tables.
                 */
                goto CreateNewObject;
            }
            else
            {
                Status = AcpiNsLookup (WalkState->ScopeInfo,
                    Op->Common.Value.String,
                    ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                    ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
                    ACPI_CAST_INDIRECT_PTR (
                        ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
                if (ACPI_FAILURE (Status))
                {
                    ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo,
                        Op->Common.Value.String, Status);
                    return_ACPI_STATUS (Status);
                }
            }
        }
    }

CreateNewObject:

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

    ObjDesc = AcpiUtCreateInternalObject (
        (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitObjectFromOp (
        WalkState, Op, Op->Common.AmlOpcode, &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ObjDesc);
        return_ACPI_STATUS (Status);
    }

    /*
     * Handling for unresolved package reference elements.
     * These are elements that are namepaths.
     */
    if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
        (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP))
    {
        ObjDesc->Reference.Resolved = TRUE;

        if ((Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
            !ObjDesc->Reference.Node)
        {
            /*
             * Name was unresolved above.
             * Get the prefix node for later lookup
             */
            ObjDesc->Reference.Node = WalkState->ScopeInfo->Scope.Node;
            ObjDesc->Reference.Aml = Op->Common.Aml;
            ObjDesc->Reference.Resolved = FALSE;
        }
    }

    *ObjDescPtr = ObjDesc;
    return_ACPI_STATUS (Status);
}
Пример #19
0
ACPI_STATUS
AcpiExOpcode_1A_0T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_OPERAND_OBJECT     *TempDesc;
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  Type;
    UINT64                  Value;


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


    /* Examine the AML opcode */

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

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

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

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

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

            AcpiUtAddReference (TempDesc);
        }

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

            goto Cleanup;
        }

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

        /* Finished with this Integer object */

        AcpiUtRemoveReference (TempDesc);

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

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

        /* Get the type of the base object */

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

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

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

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

        /* Get the base object */

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

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

            Value = AcpiGbl_IntegerByteWidth;
            break;

        case ACPI_TYPE_STRING:

            Value = TempDesc->String.Length;
            break;

        case ACPI_TYPE_BUFFER:

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

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

        case ACPI_TYPE_PACKAGE:

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

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

        default:

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

            Status = AE_AML_OPERAND_TYPE;
            goto Cleanup;
        }

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

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


    case AML_REF_OF_OP:             /* RefOf (SourceObject) */

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


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

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

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

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

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

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

                case ACPI_REFCLASS_REFOF:

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

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

                default:

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

            case ACPI_TYPE_STRING:

                break;

            default:

                Status = AE_AML_OPERAND_TYPE;
                goto Cleanup;
            }
        }

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

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

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

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

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

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

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

                    AcpiUtAddReference (ReturnDesc);
                    break;

                default:

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

                    Status = AE_AML_OPERAND_TYPE;
                    goto Cleanup;
                }
                break;

            case ACPI_REFCLASS_REFOF:

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

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

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

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

                        ReturnDesc = TempDesc;
                        break;

                    default:

                        /* Add another reference to the object */

                        AcpiUtAddReference (ReturnDesc);
                        break;
                    }
                }
                break;

            default:

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

                Status = AE_TYPE;
                goto Cleanup;
            }
        }
        break;

    default:

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

        Status = AE_AML_BAD_OPCODE;
        goto Cleanup;
    }


Cleanup:

    /* Delete return object on error */

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

    /* Save return object on success */

    else
    {
        WalkState->ResultObj = ReturnDesc;
    }

    return_ACPI_STATUS (Status);
}
Пример #20
0
ACPI_STATUS
AcpiExOpcode_1A_1T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
    ACPI_OPERAND_OBJECT     *ReturnDesc2 = NULL;
    UINT32                  Temp32;
    UINT32                  i;
    UINT64                  PowerOfTen;
    UINT64                  Digit;


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


    /* Examine the AML opcode */

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

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

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

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

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

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

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

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

            ReturnDesc->Integer.Value = Temp32;
            break;

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

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

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

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

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

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

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

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

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

                /* Check the range of the digit */

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

                    Status = AE_AML_NUMERIC_OVERFLOW;
                    goto Cleanup;
                }

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

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

                /* Shift to next BCD digit */

                Digit >>= 4;

                /* Next power of 10 */

                PowerOfTen *= 10;
            }
            break;

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

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

            /* Each BCD digit is one nybble wide */

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

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

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

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

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

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

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

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

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

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


        default:

            /* No other opcodes get here */

            break;
        }
        break;

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

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

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

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

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

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

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

            AcpiUtAddReference (ReturnDesc);
        }
        break;

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

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

            AcpiUtAddReference (ReturnDesc);
        }
        break;

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

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

            AcpiUtAddReference (ReturnDesc);
        }
        break;

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

        /* Perform "explicit" conversion */

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

            AcpiUtAddReference (ReturnDesc);
        }
        break;

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

        /* These are two obsolete opcodes */

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

    default:                        /* Unknown opcode */

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

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

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


Cleanup:

    /* Delete return object on error */

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

    /* Save return object on success */

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

    return_ACPI_STATUS (Status);
}
Пример #21
0
ACPI_STATUS
AcpiExOpcode_3A_1T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
    char                    *Buffer = NULL;
    ACPI_STATUS             Status = AE_OK;
    UINT64                  Index;
    ACPI_SIZE               Length;


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


    switch (WalkState->Opcode)
    {
    case AML_MID_OP:    /* Mid (Source[0], Index[1], Length[2], Result[3]) */

        /*
         * Create the return object.  The Source operand is guaranteed to be
         * either a String or a Buffer, so just use its type.
         */
        ReturnDesc = AcpiUtCreateInternalObject (
                        (Operand[0])->Common.Type);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /* Get the Integer values from the objects */

        Index = Operand[1]->Integer.Value;
        Length = (ACPI_SIZE) Operand[2]->Integer.Value;

        /*
         * If the index is beyond the length of the String/Buffer, or if the
         * requested length is zero, return a zero-length String/Buffer
         */
        if (Index >= Operand[0]->String.Length)
        {
            Length = 0;
        }

        /* Truncate request if larger than the actual String/Buffer */

        else if ((Index + Length) > Operand[0]->String.Length)
        {
            Length = (ACPI_SIZE) Operand[0]->String.Length -
                        (ACPI_SIZE) Index;
        }

        /* Strings always have a sub-pointer, not so for buffers */

        switch ((Operand[0])->Common.Type)
        {
        case ACPI_TYPE_STRING:

            /* Always allocate a new buffer for the String */

            Buffer = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) Length + 1);
            if (!Buffer)
            {
                Status = AE_NO_MEMORY;
                goto Cleanup;
            }
            break;

        case ACPI_TYPE_BUFFER:

            /* If the requested length is zero, don't allocate a buffer */

            if (Length > 0)
            {
                /* Allocate a new buffer for the Buffer */

                Buffer = ACPI_ALLOCATE_ZEROED (Length);
                if (!Buffer)
                {
                    Status = AE_NO_MEMORY;
                    goto Cleanup;
                }
            }
            break;

        default:                        /* Should not happen */

            Status = AE_AML_OPERAND_TYPE;
            goto Cleanup;
        }

        if (Buffer)
        {
            /* We have a buffer, copy the portion requested */

            ACPI_MEMCPY (Buffer, Operand[0]->String.Pointer + Index,
                         Length);
        }

        /* Set the length of the new String/Buffer */

        ReturnDesc->String.Pointer = Buffer;
        ReturnDesc->String.Length = (UINT32) Length;

        /* Mark buffer initialized */

        ReturnDesc->Buffer.Flags |= AOPOBJ_DATA_VALID;
        break;


    default:

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

    /* Store the result in the target */

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

Cleanup:

    /* Delete return object on error */

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

    /* Set the return object and exit */

    else
    {
        WalkState->ResultObj = ReturnDesc;
    }
    return_ACPI_STATUS (Status);
}
Пример #22
0
static void
AcpiPsLinkModuleCode (
    ACPI_PARSE_OBJECT       *ParentOp,
    UINT8                   *AmlStart,
    UINT32                  AmlLength,
    ACPI_OWNER_ID           OwnerId)
{
    ACPI_OPERAND_OBJECT     *Prev;
    ACPI_OPERAND_OBJECT     *Next;
    ACPI_OPERAND_OBJECT     *MethodObj;
    ACPI_NAMESPACE_NODE     *ParentNode;


    /* Get the tail of the list */

    Prev = Next = AcpiGbl_ModuleCodeList;
    while (Next)
    {
        Prev = Next;
        Next = Next->Method.Mutex;
    }

    /*
     * Insert the module level code into the list. Merge it if it is
     * adjacent to the previous element.
     */
    if (!Prev ||
       ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart))
    {
        /* Create, initialize, and link a new temporary method object */

        MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
        if (!MethodObj)
        {
            return;
        }

        if (ParentOp->Common.Node)
        {
            ParentNode = ParentOp->Common.Node;
        }
        else
        {
            ParentNode = AcpiGbl_RootNode;
        }

        MethodObj->Method.AmlStart = AmlStart;
        MethodObj->Method.AmlLength = AmlLength;
        MethodObj->Method.OwnerId = OwnerId;
        MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL;

        /*
         * Save the parent node in NextObject. This is cheating, but we
         * don't want to expand the method object.
         */
        MethodObj->Method.NextObject =
            ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParentNode);

        if (!Prev)
        {
            AcpiGbl_ModuleCodeList = MethodObj;
        }
        else
        {
            Prev->Method.Mutex = MethodObj;
        }
    }
    else
    {
        Prev->Method.AmlLength += AmlLength;
    }
}
Пример #23
0
ACPI_STATUS
AcpiInstallGpeBlock (
    ACPI_HANDLE             GpeDevice,
    ACPI_GENERIC_ADDRESS    *GpeBlockAddress,
    UINT32                  RegisterCount,
    UINT32                  InterruptNumber)
{
    ACPI_STATUS             Status;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_GPE_BLOCK_INFO     *GpeBlock;


    ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);


    if ((!GpeDevice)       ||
        (!GpeBlockAddress) ||
        (!RegisterCount))
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

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

    Node = AcpiNsValidateHandle (GpeDevice);
    if (!Node)
    {
        Status = AE_BAD_PARAMETER;
        goto UnlockAndExit;
    }

    /* Validate the parent device */

    if (Node->Type != ACPI_TYPE_DEVICE)
    {
        Status = AE_TYPE;
        goto UnlockAndExit;
    }

    if (Node->Object)
    {
        Status = AE_ALREADY_EXISTS;
        goto UnlockAndExit;
    }

    /*
     * For user-installed GPE Block Devices, the GpeBlockBaseNumber
     * is always zero
     */
    Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,
        GpeBlockAddress->SpaceId, RegisterCount,
        0, InterruptNumber, &GpeBlock);
    if (ACPI_FAILURE (Status))
    {
        goto UnlockAndExit;
    }

    /* Install block in the DeviceObject attached to the node */

    ObjDesc = AcpiNsGetAttachedObject (Node);
    if (!ObjDesc)
    {
        /*
         * No object, create a new one (Device nodes do not always have
         * an attached object)
         */
        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);
        if (!ObjDesc)
        {
            Status = AE_NO_MEMORY;
            goto UnlockAndExit;
        }

        Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);

        /* Remove local reference to the object */

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

    /* Now install the GPE block in the DeviceObject */

    ObjDesc->Device.GpeBlock = GpeBlock;


UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_ACPI_STATUS (Status);
}
Пример #24
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);
}
Пример #25
0
static ACPI_STATUS
AcpiExAddTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *ParentNode,
    ACPI_OPERAND_OBJECT     **DdbHandle)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;
    ACPI_OWNER_ID           OwnerId;


    ACPI_FUNCTION_TRACE (ExAddTable);


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

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

    /* Init the table handle */

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

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

    ObjDesc->Reference.Value = TableIndex;

    /* Add the table to the namespace */

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

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

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

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

    return_ACPI_STATUS (AE_OK);
}
Пример #26
0
ACPI_STATUS
AcpiInstallNotifyHandler (
    ACPI_HANDLE             Device,
    UINT32                  HandlerType,
    ACPI_NOTIFY_HANDLER     Handler,
    void                    *Context)
{
    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_OPERAND_OBJECT     *HandlerObj;
    ACPI_STATUS             Status;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);


    /* Parameter validation */

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

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

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

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

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

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

    /* Are Notifies allowed on this object? */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


UnlockAndExit:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_ACPI_STATUS (Status);
}
Пример #27
0
ACPI_STATUS
AcpiDsBuildInternalPackageObj (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  ElementCount,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_PARSE_OBJECT       *Arg;
    ACPI_PARSE_OBJECT       *Parent;
    ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
    ACPI_STATUS             Status = AE_OK;
    ACPI_NATIVE_UINT        i;


    ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj);


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

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

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

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

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

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

    ObjDesc->Package.Count = ElementCount;

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

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

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

    ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
    Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
    return_ACPI_STATUS (Status);
}
Пример #28
0
static ACPI_STATUS
AcpiDsBuildInternalObject (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;
    ACPI_OBJECT_TYPE        Type;


    ACPI_FUNCTION_TRACE (DsBuildInternalObject);


    *ObjDescPtr = NULL;
    if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    {
        /*
         * This is a named object reference. If this name was
         * previously looked up in the namespace, it was stored in this op.
         * Otherwise, go ahead and look it up now
         */
        if (!Op->Common.Node)
        {
            Status = AcpiNsLookup (WalkState->ScopeInfo,
                        Op->Common.Value.String,
                        ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
            if (ACPI_FAILURE (Status))
            {
                /* Check if we are resolving a named reference within a package */

                if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) &&

                    ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
                     (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)))
                {
                    /*
                     * We didn't find the target and we are populating elements
                     * of a package - ignore if slack enabled. Some ASL code
                     * contains dangling invalid references in packages and
                     * expects that no exception will be issued. Leave the
                     * element as a null element. It cannot be used, but it
                     * can be overwritten by subsequent ASL code - this is
                     * typically the case.
                     */
                    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                        "Ignoring unresolved reference in package [%4.4s]\n",
                        WalkState->ScopeInfo->Scope.Node->Name.Ascii));

                    return_ACPI_STATUS (AE_OK);
                }
                else
                {
                    ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status);
                }

                return_ACPI_STATUS (Status);
            }
        }

        /* Special object resolution for elements of a package */

        if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
            (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))
        {
            /*
             * Attempt to resolve the node to a value before we insert it into
             * the package. If this is a reference to a common data type,
             * resolve it immediately. According to the ACPI spec, package
             * elements can only be "data objects" or method references.
             * Attempt to resolve to an Integer, Buffer, String or Package.
             * If cannot, return the named reference (for things like Devices,
             * Methods, etc.) Buffer Fields and Fields will resolve to simple
             * objects (int/buf/str/pkg).
             *
             * NOTE: References to things like Devices, Methods, Mutexes, etc.
             * will remain as named references. This behavior is not described
             * in the ACPI spec, but it appears to be an oversight.
             */
            ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Op->Common.Node);

            Status = AcpiExResolveNodeToValue (
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc),
                        WalkState);
            if (ACPI_FAILURE (Status))
            {
                return_ACPI_STATUS (Status);
            }

            /*
             * Special handling for Alias objects. We need to setup the type
             * and the Op->Common.Node to point to the Alias target. Note,
             * Alias has at most one level of indirection internally.
             */
            Type = Op->Common.Node->Type;
            if (Type == ACPI_TYPE_LOCAL_ALIAS)
            {
                Type = ObjDesc->Common.Type;
                Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
                    Op->Common.Node->Object);
            }

            switch (Type)
            {
            /*
             * For these types, we need the actual node, not the subobject.
             * However, the subobject did not get an extra reference count above.
             *
             * TBD: should ExResolveNodeToValue be changed to fix this?
             */
            case ACPI_TYPE_DEVICE:
            case ACPI_TYPE_THERMAL:

                AcpiUtAddReference (Op->Common.Node->Object);

                /*lint -fallthrough */
            /*
             * For these types, we need the actual node, not the subobject.
             * The subobject got an extra reference count in ExResolveNodeToValue.
             */
            case ACPI_TYPE_MUTEX:
            case ACPI_TYPE_METHOD:
            case ACPI_TYPE_POWER:
            case ACPI_TYPE_PROCESSOR:
            case ACPI_TYPE_EVENT:
            case ACPI_TYPE_REGION:

                /* We will create a reference object for these types below */
                break;

            default:
                /*
                 * All other types - the node was resolved to an actual
                 * object, we are done.
                 */
                goto Exit;
            }
        }
    }

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

    ObjDesc = AcpiUtCreateInternalObject (
                (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode,
                &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ObjDesc);
        return_ACPI_STATUS (Status);
    }

Exit:
    *ObjDescPtr = ObjDesc;
    return_ACPI_STATUS (Status);
}
Пример #29
0
ACPI_STATUS
AcpiDsCreateOperand (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Arg,
    UINT32                  ArgIndex)
{
    ACPI_STATUS             Status = AE_OK;
    char                    *NameString;
    UINT32                  NameLength;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PARSE_OBJECT       *ParentOp;
    UINT16                  Opcode;
    ACPI_INTERPRETER_MODE   InterpreterMode;
    const ACPI_OPCODE_INFO  *OpInfo;


    ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg);


    /* A valid name must be looked up in the namespace */

    if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
        (Arg->Common.Value.String) &&
        !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg));

        /* Get the entire name string from the AML stream */

        Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer,
                        &NameString, &NameLength);

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

        /* All prefixes have been handled, and the name is in NameString */

        /*
         * Special handling for BufferField declarations. This is a deferred
         * opcode that unfortunately defines the field name as the last
         * parameter instead of the first. We get here when we are performing
         * the deferred execution, so the actual name of the field is already
         * in the namespace. We don't want to attempt to look it up again
         * because we may be executing in a different scope than where the
         * actual opcode exists.
         */
        if ((WalkState->DeferredNode) &&
            (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) &&
            (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2)))
        {
            ObjDesc = ACPI_CAST_PTR (
                        ACPI_OPERAND_OBJECT, WalkState->DeferredNode);
            Status = AE_OK;
        }
        else    /* All other opcodes */
        {
            /*
             * Differentiate between a namespace "create" operation
             * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
             * IMODE_EXECUTE) in order to support the creation of
             * namespace objects during the execution of control methods.
             */
            ParentOp = Arg->Common.Parent;
            OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode);
            if ((OpInfo->Flags & AML_NSNODE) &&
                (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) &&
                (ParentOp->Common.AmlOpcode != AML_REGION_OP) &&
                (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP))
            {
                /* Enter name into namespace if not found */

                InterpreterMode = ACPI_IMODE_LOAD_PASS2;
            }
            else
            {
                /* Return a failure if name not found */

                InterpreterMode = ACPI_IMODE_EXECUTE;
            }

            Status = AcpiNsLookup (WalkState->ScopeInfo, NameString,
                        ACPI_TYPE_ANY, InterpreterMode,
                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
                        WalkState,
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc));
            /*
             * The only case where we pass through (ignore) a NOT_FOUND
             * error is for the CondRefOf opcode.
             */
            if (Status == AE_NOT_FOUND)
            {
                if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP)
                {
                    /*
                     * For the Conditional Reference op, it's OK if
                     * the name is not found;  We just need a way to
                     * indicate this to the interpreter, set the
                     * object to the root
                     */
                    ObjDesc = ACPI_CAST_PTR (
                                ACPI_OPERAND_OBJECT, AcpiGbl_RootNode);
                    Status = AE_OK;
                }
                else
                {
                    /*
                     * We just plain didn't find it -- which is a
                     * very serious error at this point
                     */
                    Status = AE_AML_NAME_NOT_FOUND;
                }
            }

            if (ACPI_FAILURE (Status))
            {
                ACPI_ERROR_NAMESPACE (NameString, Status);
            }
        }

        /* Free the namestring created above */

        ACPI_FREE (NameString);

        /* Check status from the lookup */

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

        /* Put the resulting object onto the current object stack */

        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }
        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
    }
    else
    {
        /* Check for null name case */

        if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) &&
            !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
        {
            /*
             * If the name is null, this means that this is an
             * optional result parameter that was not specified
             * in the original ASL. Create a Zero Constant for a
             * placeholder. (Store to a constant is a Noop.)
             */
            Opcode = AML_ZERO_OP;       /* Has no arguments! */

            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                "Null namepath: Arg=%p\n", Arg));
        }
        else
        {
            Opcode = Arg->Common.AmlOpcode;
        }

        /* Get the object type of the argument */

        OpInfo = AcpiPsGetOpcodeInfo (Opcode);
        if (OpInfo->ObjectType == ACPI_TYPE_INVALID)
        {
            return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
        }

        if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK))
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
                "Argument previously created, already stacked\n"));

            ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (
                WalkState->Operands [WalkState->NumOperands - 1], WalkState));

            /*
             * Use value that was already previously returned
             * by the evaluation of this argument
             */
            Status = AcpiDsResultPop (&ObjDesc, WalkState);
            if (ACPI_FAILURE (Status))
            {
                /*
                 * Only error is underflow, and this indicates
                 * a missing or null operand!
                 */
                ACPI_EXCEPTION ((AE_INFO, Status,
                    "Missing or null operand"));
                return_ACPI_STATUS (Status);
            }
        }
        else
        {
            /* Create an ACPI_INTERNAL_OBJECT for the argument */

            ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType);
            if (!ObjDesc)
            {
                return_ACPI_STATUS (AE_NO_MEMORY);
            }

            /* Initialize the new object */

            Status = AcpiDsInitObjectFromOp (
                        WalkState, Arg, Opcode, &ObjDesc);
            if (ACPI_FAILURE (Status))
            {
                AcpiUtDeleteObjectDesc (ObjDesc);
                return_ACPI_STATUS (Status);
            }
        }

        /* Put the operand object on the object stack */

        Status = AcpiDsObjStackPush (ObjDesc, WalkState);
        if (ACPI_FAILURE (Status))
        {
            return_ACPI_STATUS (Status);
        }

        ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState));
    }

    return_ACPI_STATUS (AE_OK);
}
Пример #30
0
static ACPI_STATUS
AcpiDsBuildInternalObject (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (DsBuildInternalObject);


    *ObjDescPtr = NULL;
    if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP)
    {
        /*
         * This is a named object reference. If this name was
         * previously looked up in the namespace, it was stored in this op.
         * Otherwise, go ahead and look it up now
         */
        if (!Op->Common.Node)
        {
            Status = AcpiNsLookup (WalkState->ScopeInfo,
                        Op->Common.Value.String,
                        ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                        ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
                        ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node)));
            if (ACPI_FAILURE (Status))
            {
                /* Check if we are resolving a named reference within a package */

                if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) &&

                    ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) ||
                     (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)))
                {
                    /*
                     * We didn't find the target and we are populating elements
                     * of a package - ignore if slack enabled. Some ASL code
                     * contains dangling invalid references in packages and
                     * expects that no exception will be issued. Leave the
                     * element as a null element. It cannot be used, but it
                     * can be overwritten by subsequent ASL code - this is
                     * typically the case.
                     */
                    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                        "Ignoring unresolved reference in package [%4.4s]\n",
                        WalkState->ScopeInfo->Scope.Node->Name.Ascii));

                    return_ACPI_STATUS (AE_OK);
                }
                else
                {
                    ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status);
                }

                return_ACPI_STATUS (Status);
            }
        }
    }

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

    ObjDesc = AcpiUtCreateInternalObject (
                (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType);
    if (!ObjDesc)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode,
                &ObjDesc);
    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ObjDesc);
        return_ACPI_STATUS (Status);
    }

    *ObjDescPtr = ObjDesc;
    return_ACPI_STATUS (AE_OK);
}