Example #1
0
static void
OpcDoUnicode (
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_PARSE_OBJECT       *InitializerOp;
    UINT32                  Length;
    UINT32                  Count;
    UINT32                  i;
    UINT8                   *AsciiString;
    UINT16                  *UnicodeString;
    ACPI_PARSE_OBJECT       *BufferLengthOp;


    /* Change op into a buffer object */

    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    UtSetParseOpName (Op);

    /* Buffer Length is first, followed by the string */

    BufferLengthOp = Op->Asl.Child;
    InitializerOp = BufferLengthOp->Asl.Next;

    AsciiString = (UINT8 *) InitializerOp->Asl.Value.String;

    /* Create a new buffer for the Unicode string */

    Count = strlen (InitializerOp->Asl.Value.String) + 1;
    Length = Count * sizeof (UINT16);
    UnicodeString = UtLocalCalloc (Length);

    /* Convert to Unicode string (including null terminator) */

    for (i = 0; i < Count; i++)
    {
        UnicodeString[i] = (UINT16) AsciiString[i];
    }

    /*
     * Just set the buffer size node to be the buffer length, regardless
     * of whether it was previously an integer or a default_arg placeholder
     */
    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
    BufferLengthOp->Asl.AmlOpcode     = AML_DWORD_OP;
    BufferLengthOp->Asl.Value.Integer = Length;
    UtSetParseOpName (BufferLengthOp);

    (void) OpcSetOptimalIntegerSize (BufferLengthOp);

    /* The Unicode string is a raw data buffer */

    InitializerOp->Asl.Value.Buffer   = (UINT8 *) UnicodeString;
    InitializerOp->Asl.AmlOpcode      = AML_RAW_DATA_BUFFER;
    InitializerOp->Asl.AmlLength      = Length;
    InitializerOp->Asl.ParseOpcode    = PARSEOP_RAW_DATA;
    InitializerOp->Asl.Child          = NULL;
    UtSetParseOpName (InitializerOp);
}
Example #2
0
static void
OpcDoConnection (
    ACPI_PARSE_OBJECT       *Op)
{
    ASL_RESOURCE_NODE       *Rnode;
    ACPI_PARSE_OBJECT       *BufferOp;
    ACPI_PARSE_OBJECT       *BufferLengthOp;
    ACPI_PARSE_OBJECT       *BufferDataOp;
    ASL_RESOURCE_INFO       Info;
    UINT8                   State;


    Op->Asl.AmlOpcodeLength = 1;

    if (Op->Asl.Child->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)
    {
        return;
    }

    BufferOp = Op->Asl.Child;
    BufferLengthOp = BufferOp->Asl.Child;
    BufferDataOp = BufferLengthOp->Asl.Next;

    Info.DescriptorTypeOp = BufferDataOp->Asl.Next;
    Info.CurrentByteOffset = 0;
    State = ACPI_RSTATE_NORMAL;
    Rnode = RsDoOneResourceDescriptor (&Info, &State);
    if (!Rnode)
    {
        return; /* error */
    }

    /*
     * Transform the nodes into the following
     *
     * Op           -> AML_BUFFER_OP
     * First Child  -> BufferLength
     * Second Child -> Descriptor Buffer (raw byte data)
     */
    BufferOp->Asl.ParseOpcode         = PARSEOP_BUFFER;
    BufferOp->Asl.AmlOpcode           = AML_BUFFER_OP;
    BufferOp->Asl.CompileFlags        = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
    UtSetParseOpName (BufferOp);

    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
    BufferLengthOp->Asl.Value.Integer = Rnode->BufferLength;
    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
    UtSetParseOpName (BufferLengthOp);

    BufferDataOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
    BufferDataOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
    BufferDataOp->Asl.AmlOpcodeLength     = 0;
    BufferDataOp->Asl.AmlLength           = Rnode->BufferLength;
    BufferDataOp->Asl.Value.Buffer        = (UINT8 *) Rnode;
    UtSetParseOpName (BufferDataOp);
}
Example #3
0
static void
TrAmlInitNode (
    ACPI_PARSE_OBJECT       *Op,
    UINT16                  ParseOpcode)
{

    Op->Asl.ParseOpcode = ParseOpcode;
    UtSetParseOpName (Op);
}
Example #4
0
static void
OpcDoUuId (
    ACPI_PARSE_OBJECT       *Op)
{
    char                    *InString;
    UINT8                   *Buffer;
    ACPI_STATUS             Status = AE_OK;
    ACPI_PARSE_OBJECT       *NewOp;


    InString = (char *) Op->Asl.Value.String;
    Buffer = UtLocalCalloc (16);

    Status = AuValidateUuid (InString);
    if (ACPI_FAILURE (Status))
    {
        AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
    }
    else
    {
        AcpiUtConvertStringToUuid (InString, Buffer);
    }

    /* Change Op to a Buffer */

    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    Op->Common.AmlOpcode = AML_BUFFER_OP;

    /* Disable further optimization */

    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    UtSetParseOpName (Op);

    /* Child node is the buffer length */

    NewOp = TrAllocateNode (PARSEOP_INTEGER);

    NewOp->Asl.AmlOpcode     = AML_BYTE_OP;
    NewOp->Asl.Value.Integer = 16;
    NewOp->Asl.Parent        = Op;

    Op->Asl.Child = NewOp;
    Op = NewOp;

    /* Peer to the child is the raw buffer data */

    NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
    NewOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
    NewOp->Asl.AmlLength     = 16;
    NewOp->Asl.Value.String  = (char *) Buffer;
    NewOp->Asl.Parent        = Op->Asl.Parent;

    Op->Asl.Next = NewOp;
}
Example #5
0
void
ExDoExternal (
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_PARSE_OBJECT       *ListOp;
    ACPI_PARSE_OBJECT       *Prev;
    ACPI_PARSE_OBJECT       *Next;
    ACPI_PARSE_OBJECT       *ArgCountOp;


    ArgCountOp = Op->Asl.Child->Asl.Next->Asl.Next;
    ArgCountOp->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    ArgCountOp->Asl.ParseOpcode = PARSEOP_BYTECONST;
    ArgCountOp->Asl.Value.Integer = 0;
    UtSetParseOpName (ArgCountOp);

    /* Create new list node of arbitrary type */

    ListOp = TrAllocateOp (PARSEOP_DEFAULT_ARG);

    /* Store External node as child */

    ListOp->Asl.Child = Op;
    ListOp->Asl.Next = NULL;

    if (AslGbl_ExternalsListHead)
    {
        /* Link new External to end of list */

        Prev = AslGbl_ExternalsListHead;
        Next = Prev;
        while (Next)
        {
            Prev = Next;
            Next = Next->Asl.Next;
        }

        Prev->Asl.Next = ListOp;
    }
    else
    {
        AslGbl_ExternalsListHead = ListOp;
    }
}
Example #6
0
ACPI_PARSE_OBJECT *
TrCreateTargetOperand (
    ACPI_PARSE_OBJECT       *OriginalOp,
    ACPI_PARSE_OBJECT       *ParentOp)
{
    ACPI_PARSE_OBJECT       *Op;


    if (!OriginalOp)
    {
        return (NULL);
    }

    Op = TrGetNextNode ();

    /* Copy the pertinent values (omit link pointer fields) */

    Op->Asl.Value               = OriginalOp->Asl.Value;
    Op->Asl.Filename            = OriginalOp->Asl.Filename;
    Op->Asl.LineNumber          = OriginalOp->Asl.LineNumber;
    Op->Asl.LogicalLineNumber   = OriginalOp->Asl.LogicalLineNumber;
    Op->Asl.LogicalByteOffset   = OriginalOp->Asl.LogicalByteOffset;
    Op->Asl.Column              = OriginalOp->Asl.Column;
    Op->Asl.Flags               = OriginalOp->Asl.Flags;
    Op->Asl.CompileFlags        = OriginalOp->Asl.CompileFlags;
    Op->Asl.AmlOpcode           = OriginalOp->Asl.AmlOpcode;
    Op->Asl.ParseOpcode         = OriginalOp->Asl.ParseOpcode;
    Op->Asl.Parent              = ParentOp;
    UtSetParseOpName (Op);

    /* Copy a possible subtree below this node */

    if (OriginalOp->Asl.Child)
    {
        Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
    }

    if (OriginalOp->Asl.Next) /* Null for top-level node */
    {
        Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
    }

    return (Op);
}
Example #7
0
ACPI_PARSE_OBJECT *
TrAllocateNode (
    UINT32                  ParseOpcode)
{
    ACPI_PARSE_OBJECT       *Op;


    Op = TrGetNextNode ();

    Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
    Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
    Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
    Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
    Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
    Op->Asl.Column            = Gbl_CurrentColumn;

    UtSetParseOpName (Op);
    return (Op);
}
Example #8
0
static void
OpcParsePrintf (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_PARSE_OBJECT       *DestOp)
{
    char                    *Format;
    char                    *StartPosition = NULL;
    ACPI_PARSE_OBJECT       *ArgNode;
    ACPI_PARSE_OBJECT       *NextNode;
    UINT32                  StringLength = 0;
    char                    *NewString;
    BOOLEAN                 StringToProcess = FALSE;
    ACPI_PARSE_OBJECT       *NewOp;


    /* Get format string */

    Format = ACPI_CAST_PTR (char, Op->Asl.Child->Asl.Value.String);
    ArgNode = Op->Asl.Child->Asl.Next;

    /*
     * Detach argument list so that we can use a NULL check to distinguish
     * the first concatenation operation we need to make
     */
    Op->Asl.Child = NULL;

    for (; *Format; ++Format)
    {
        if (*Format != '%')
        {
            if (!StringToProcess)
            {
                /* Mark the beginning of a string */

                StartPosition = Format;
                StringToProcess = TRUE;
            }

            ++StringLength;
            continue;
        }

        /* Save string, if any, to new string object and concat it */

        if (StringToProcess)
        {
            NewString = UtStringCacheCalloc (StringLength + 1);
            strncpy (NewString, StartPosition, StringLength);

            NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
            NewOp->Asl.Value.String = NewString;
            NewOp->Asl.AmlOpcode = AML_STRING_OP;
            NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
            NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;

            OpcCreateConcatenateNode(Op, NewOp);

            StringLength = 0;
            StringToProcess = FALSE;
        }

        ++Format;

        /*
         * We have a format parameter and will need an argument to go
         * with it
         */
        if (!ArgNode ||
            ArgNode->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
        {
            AslError(ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, NULL);
            return;
        }

        /*
         * We do not support sub-specifiers of printf (flags, width,
         * precision, length). For specifiers we only support %x/%X for
         * hex or %s for strings. Also, %o for generic "acpi object".
         */
        switch (*Format)
        {
        case 's':

            if (ArgNode->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgNode,
                    "String required");
                return;
            }

            NextNode = ArgNode->Asl.Next;
            ArgNode->Asl.Next = NULL;
            OpcCreateConcatenateNode(Op, ArgNode);
            ArgNode = NextNode;
            continue;

        case 'X':
        case 'x':
        case 'o':

            NextNode = ArgNode->Asl.Next;
            ArgNode->Asl.Next = NULL;

            /*
             * Append an empty string if the first argument is
             * not a string. This will implicitly conver the 2nd
             * concat source to a string per the ACPI specification.
             */
            if (!Op->Asl.Child)
            {
                NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
                NewOp->Asl.Value.String = "";
                NewOp->Asl.AmlOpcode = AML_STRING_OP;
                NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
                NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;

                OpcCreateConcatenateNode(Op, NewOp);
            }

            OpcCreateConcatenateNode(Op, ArgNode);
            ArgNode = NextNode;
            break;

        default:

            AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Op,
                "Unrecognized format specifier");
            continue;
        }
    }

    /* Process any remaining string */

    if (StringToProcess)
    {
        NewString = UtStringCacheCalloc (StringLength + 1);
        strncpy (NewString, StartPosition, StringLength);

        NewOp = TrAllocateNode (PARSEOP_STRING_LITERAL);
        NewOp->Asl.Value.String = NewString;
        NewOp->Asl.AcpiBtype = ACPI_BTYPE_STRING;
        NewOp->Asl.AmlOpcode = AML_STRING_OP;
        NewOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;

        OpcCreateConcatenateNode(Op, NewOp);
    }

    /*
     * If we get here and there's no child node then Format
     * was an empty string. Just make a no op.
     */
    if (!Op->Asl.Child)
    {
        Op->Asl.ParseOpcode = PARSEOP_NOOP;
        AslError(ASL_WARNING, ASL_MSG_NULL_STRING, Op,
            "Converted to NOOP");
        return;
    }

     /* Check for erroneous extra arguments */

    if (ArgNode &&
        ArgNode->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
    {
        AslError(ASL_WARNING, ASL_MSG_ARG_COUNT_HI, ArgNode,
            "Extra arguments ignored");
    }

    /* Change Op to a Store */

    Op->Asl.ParseOpcode = PARSEOP_STORE;
    Op->Common.AmlOpcode = AML_STORE_OP;
    Op->Asl.CompileFlags  = 0;

    /* Disable further optimization */

    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    UtSetParseOpName (Op);

    /* Set Store destination */

    Op->Asl.Child->Asl.Next = DestOp;
}
Example #9
0
static void
OpcDoEisaId (
    ACPI_PARSE_OBJECT       *Op)
{
    UINT32                  EisaId = 0;
    UINT32                  BigEndianId;
    char                    *InString;
    ACPI_STATUS             Status = AE_OK;
    UINT32                  i;


    InString = (char *) Op->Asl.Value.String;

    /*
     * The EISAID string must be exactly 7 characters and of the form
     * "UUUXXXX" -- 3 uppercase letters and 4 hex digits (e.g., "PNP0001")
     */
    if (ACPI_STRLEN (InString) != 7)
    {
        Status = AE_BAD_PARAMETER;
    }
    else
    {
        /* Check all 7 characters for correct format */

        for (i = 0; i < 7; i++)
        {
            /* First 3 characters must be uppercase letters */

            if (i < 3)
            {
                if (!isupper ((int) InString[i]))
                {
                    Status = AE_BAD_PARAMETER;
                }
            }

            /* Last 4 characters must be hex digits */

            else if (!isxdigit ((int) InString[i]))
            {
                Status = AE_BAD_PARAMETER;
            }
        }
    }

    if (ACPI_FAILURE (Status))
    {
        AslError (ASL_ERROR, ASL_MSG_INVALID_EISAID, Op, Op->Asl.Value.String);
    }
    else
    {
        /* Create ID big-endian first (bits are contiguous) */

        BigEndianId =
            (UINT32) ((UINT8) (InString[0] - 0x40)) << 26 |
            (UINT32) ((UINT8) (InString[1] - 0x40)) << 21 |
            (UINT32) ((UINT8) (InString[2] - 0x40)) << 16 |

            (AcpiUtAsciiCharToHex (InString[3])) << 12 |
            (AcpiUtAsciiCharToHex (InString[4])) << 8  |
            (AcpiUtAsciiCharToHex (InString[5])) << 4  |
             AcpiUtAsciiCharToHex (InString[6]);

        /* Swap to little-endian to get final ID (see function header) */

        EisaId = AcpiUtDwordByteSwap (BigEndianId);
    }

    /*
     * Morph the Op into an integer, regardless of whether there
     * was an error in the EISAID string
     */
    Op->Asl.Value.Integer = EisaId;

    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    Op->Asl.ParseOpcode = PARSEOP_INTEGER;
    (void) OpcSetOptimalIntegerSize (Op);

    /* Op is now an integer */

    UtSetParseOpName (Op);
}
Example #10
0
static ACPI_STATUS
LkNamespaceLocateBegin (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;
    ACPI_OBJECT_TYPE        ObjectType;
    char                    *Path;
    UINT8                   PassedArgs;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_PARSE_OBJECT       *OwningOp;
    ACPI_PARSE_OBJECT       *SpaceIdOp;
    UINT32                  MinimumLength;
    UINT32                  Temp;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  Flags;


    ACPI_FUNCTION_TRACE_PTR (LkNamespaceLocateBegin, Op);

    /*
     * If this node is the actual declaration of a name
     * [such as the XXXX name in "Method (XXXX)"],
     * we are not interested in it here.  We only care about names that are
     * references to other objects within the namespace and the parent objects
     * of name declarations
     */
    if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
    {
        return (AE_OK);
    }

    /* We are only interested in opcodes that have an associated name */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);

    if ((!(OpInfo->Flags & AML_NAMED)) &&
        (!(OpInfo->Flags & AML_CREATE)) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
        (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
    {
        return (AE_OK);
    }

    /*
     * We must enable the "search-to-root" for single NameSegs, but
     * we have to be very careful about opening up scopes
     */
    Flags = ACPI_NS_SEARCH_PARENT;
    if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
        (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
        (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
    {
        /*
         * These are name references, do not push the scope stack
         * for them.
         */
        Flags |= ACPI_NS_DONT_OPEN_SCOPE;
    }

    /* Get the NamePath from the appropriate place */

    if (OpInfo->Flags & AML_NAMED)
    {
        /* For nearly all NAMED operators, the name reference is the first child */

        Path = Op->Asl.Child->Asl.Value.String;
        if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
        {
            /*
             * ALIAS is the only oddball opcode, the name declaration
             * (alias name) is the second operand
             */
            Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
        }
    }
    else if (OpInfo->Flags & AML_CREATE)
    {
        /* Name must appear as the last parameter */

        NextOp = Op->Asl.Child;
        while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
        {
            NextOp = NextOp->Asl.Next;
        }
        Path = NextOp->Asl.Value.String;
    }
    else
    {
        Path = Op->Asl.Value.String;
    }

    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "Type=%s\n", AcpiUtGetTypeName (ObjectType)));

    /*
     * Lookup the name in the namespace.  Name must exist at this point, or it
     * is an invalid reference.
     *
     * The namespace is also used as a lookup table for references to resource
     * descriptors and the fields within them.
     */
    Gbl_NsLookupCount++;

    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
                ACPI_IMODE_EXECUTE, Flags, WalkState, &(Node));
    if (ACPI_FAILURE (Status))
    {
        if (Status == AE_NOT_FOUND)
        {
            /*
             * We didn't find the name reference by path -- we can qualify this
             * a little better before we print an error message
             */
            if (strlen (Path) == ACPI_NAME_SIZE)
            {
                /* A simple, one-segment ACPI name */

                if (LkObjectExists (Path))
                {
                    /*
                     * There exists such a name, but we couldn't get to it
                     * from this scope
                     */
                    AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
                        Op->Asl.ExternalName);
                }
                else
                {
                    /* The name doesn't exist, period */

                    if ((Op->Asl.Parent) &&
                        (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
                    {
                        /* Ignore not found if parent is CondRefOf */

                        return (AE_OK);
                    }

                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
                        Op, Op->Asl.ExternalName);
                }
            }
            else
            {
                /* Check for a fully qualified path */

                if (Path[0] == AML_ROOT_PREFIX)
                {
                    /* Gave full path, the object does not exist */

                    if ((Op->Asl.Parent) &&
                        (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
                    {
                        /* Ignore not found if parent is CondRefOf */

                        return (AE_OK);
                    }

                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
                        Op->Asl.ExternalName);
                }
                else
                {
                    /*
                     * We can't tell whether it doesn't exist or just
                     * can't be reached.
                     */
                    AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
                        Op->Asl.ExternalName);
                }
            }

            Status = AE_OK;
        }
        return (Status);
    }

    /* Check for a reference vs. name declaration */

    if (!(OpInfo->Flags & AML_NAMED) &&
        !(OpInfo->Flags & AML_CREATE))
    {
        /* This node has been referenced, mark it for reference check */

        Node->Flags |= ANOBJ_IS_REFERENCED;
    }

    /* Attempt to optimize the NamePath */

    OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);

    /*
     * 1) Dereference an alias (A name reference that is an alias)
     *    Aliases are not nested, the alias always points to the final object
     */
    if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
        (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
    {
        /* This node points back to the original PARSEOP_ALIAS */

        NextOp = Node->Op;

        /* The first child is the alias target op */

        NextOp = NextOp->Asl.Child;

        /* That in turn points back to original target alias node */

        if (NextOp->Asl.Node)
        {
            Node = NextOp->Asl.Node;
        }

        /* Else - forward reference to alias, will be resolved later */
    }

    /* 2) Check for a reference to a resource descriptor */

    if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
             (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    {
        /*
         * This was a reference to a field within a resource descriptor.  Extract
         * the associated field offset (either a bit or byte offset depending on
         * the field type) and change the named reference into an integer for
         * AML code generation
         */
        Temp = Node->Value;
        if (Node->Flags & ANOBJ_IS_BIT_OFFSET)
        {
            Op->Asl.CompileFlags |= NODE_IS_BIT_OFFSET;
        }

        /* Perform BitOffset <--> ByteOffset conversion if necessary */

        switch (Op->Asl.Parent->Asl.AmlOpcode)
        {
        case AML_CREATE_FIELD_OP:

            /* We allow a Byte offset to Bit Offset conversion for this op */

            if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET))
            {
                /* Simply multiply byte offset times 8 to get bit offset */

                Temp = ACPI_MUL_8 (Temp);
            }
            break;


        case AML_CREATE_BIT_FIELD_OP:

            /* This op requires a Bit Offset */

            if (!(Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET))
            {
                AslError (ASL_ERROR, ASL_MSG_BYTES_TO_BITS, Op, NULL);
            }
            break;


        case AML_CREATE_BYTE_FIELD_OP:
        case AML_CREATE_WORD_FIELD_OP:
        case AML_CREATE_DWORD_FIELD_OP:
        case AML_CREATE_QWORD_FIELD_OP:
        case AML_INDEX_OP:

            /* These Ops require Byte offsets */

            if (Op->Asl.CompileFlags & NODE_IS_BIT_OFFSET)
            {
                AslError (ASL_ERROR, ASL_MSG_BITS_TO_BYTES, Op, NULL);
            }
            break;


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

        /* Now convert this node to an integer whose value is the field offset */

        Op->Asl.AmlLength       = 0;
        Op->Asl.ParseOpcode     = PARSEOP_INTEGER;
        Op->Asl.Value.Integer   = (UINT64) Temp;
        Op->Asl.CompileFlags   |= NODE_IS_RESOURCE_FIELD;

        OpcGenerateAmlOpcode (Op);
    }

    /* 3) Check for a method invocation */

    else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
                (Node->Type == ACPI_TYPE_METHOD) &&
                (Op->Asl.Parent) &&
                (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||

                (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
    {

        /*
         * A reference to a method within one of these opcodes is not an
         * invocation of the method, it is simply a reference to the method.
         */
        if ((Op->Asl.Parent) &&
           ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)      ||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_DEREFOF)    ||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
        {
            return (AE_OK);
        }
        /*
         * There are two types of method invocation:
         * 1) Invocation with arguments -- the parser recognizes this
         *    as a METHODCALL.
         * 2) Invocation with no arguments --the parser cannot determine that
         *    this is a method invocation, therefore we have to figure it out
         *    here.
         */
        if (Node->Type != ACPI_TYPE_METHOD)
        {
            sprintf (MsgBuffer, "%s is a %s",
                    Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));

            AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, MsgBuffer);
            return (AE_OK);
        }

        /* Save the method node in the caller's op */

        Op->Asl.Node = Node;
        if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
        {
            return (AE_OK);
        }

        /*
         * This is a method invocation, with or without arguments.
         * Count the number of arguments, each appears as a child
         * under the parent node
         */
        Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
        UtSetParseOpName (Op);

        PassedArgs = 0;
        NextOp     = Op->Asl.Child;

        while (NextOp)
        {
            PassedArgs++;
            NextOp = NextOp->Asl.Next;
        }

        if (Node->Value != ASL_EXTERNAL_METHOD)
        {
            /*
             * Check the parsed arguments with the number expected by the
             * method declaration itself
             */
            if (PassedArgs != Node->Value)
            {
                sprintf (MsgBuffer, "%s requires %d", Op->Asl.ExternalName,
                            Node->Value);

                if (PassedArgs < Node->Value)
                {
                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, MsgBuffer);
                }
                else
                {
                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, MsgBuffer);
                }
            }
        }
    }

    /* 4) Check for an ASL Field definition */

    else if ((Op->Asl.Parent) &&
            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
    {
        /*
         * Offset checking for fields.  If the parent operation region has a
         * constant length (known at compile time), we can check fields
         * defined in that region against the region length.  This will catch
         * fields and field units that cannot possibly fit within the region.
         *
         * Note: Index fields do not directly reference an operation region,
         * thus they are not included in this check.
         */
        if (Op == Op->Asl.Parent->Asl.Child)
        {
            /*
             * This is the first child of the field node, which is
             * the name of the region.  Get the parse node for the
             * region -- which contains the length of the region.
             */
            OwningOp = Node->Op;
            Op->Asl.Parent->Asl.ExtraValue =
                ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);

            /* Examine the field access width */

            switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
            {
            case AML_FIELD_ACCESS_ANY:
            case AML_FIELD_ACCESS_BYTE:
            case AML_FIELD_ACCESS_BUFFER:
            default:
                MinimumLength = 1;
                break;

            case AML_FIELD_ACCESS_WORD:
                MinimumLength = 2;
                break;

            case AML_FIELD_ACCESS_DWORD:
                MinimumLength = 4;
                break;

            case AML_FIELD_ACCESS_QWORD:
                MinimumLength = 8;
                break;
            }

            /*
             * Is the region at least as big as the access width?
             * Note: DataTableRegions have 0 length
             */
            if (((UINT32) OwningOp->Asl.Value.Integer) &&
                ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
            {
                AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
            }

            /*
             * Check EC/CMOS/SMBUS fields to make sure that the correct
             * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
             */
            SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
            switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
            {
            case REGION_EC:
            case REGION_CMOS:

                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BYTE)
                {
                    AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
                }
                break;

            case REGION_SMBUS:

                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer != AML_FIELD_ACCESS_BUFFER)
                {
                    AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
                }
                break;

            default:

                /* Nothing to do for other address spaces */
                break;
            }
        }
        else
        {
            /*
             * This is one element of the field list.  Check to make sure
             * that it does not go beyond the end of the parent operation region.
             *
             * In the code below:
             *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
             *    Op->Asl.ExtraValue                  - Field start offset (bits)
             *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
             *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
             */
            if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
            {
                LkCheckFieldRange (Op,
                            Op->Asl.Parent->Asl.ExtraValue,
                            Op->Asl.ExtraValue,
                            (UINT32) Op->Asl.Child->Asl.Value.Integer,
                            Op->Asl.Child->Asl.ExtraValue);
            }
        }
    }

    Op->Asl.Node = Node;
    return (Status);
}
Example #11
0
static void
ExMoveExternals (
    ACPI_PARSE_OBJECT       *DefinitionBlockOp)
{
    ACPI_PARSE_OBJECT       *ParentOp;
    ACPI_PARSE_OBJECT       *ExternalOp;
    ACPI_PARSE_OBJECT       *PredicateOp;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_PARSE_OBJECT       *Prev;
    ACPI_PARSE_OBJECT       *Next;
    char                    *ExternalName;
    ACPI_OBJECT_TYPE        ObjType;
    ACPI_STATUS             Status;
    UINT32                  i;


    if (!AslGbl_ExternalsListHead)
    {
        return;
    }

    /* Remove the External nodes from the tree */

    NextOp = AslGbl_ExternalsListHead;
    while (NextOp)
    {
        /*
         * The External is stored in child pointer of each node in the
         * list
         */
        ExternalOp = NextOp->Asl.Child;

        /* Get/set the fully qualified name */

        ExternalName = AcpiNsGetNormalizedPathname (ExternalOp->Asl.Node, TRUE);
        ExternalOp->Asl.ExternalName = ExternalName;
        ExternalOp->Asl.Namepath = ExternalName;

        /* Set line numbers (for listings, etc.) */

        ExternalOp->Asl.LineNumber = 0;
        ExternalOp->Asl.LogicalLineNumber = 0;

        Next = ExternalOp->Asl.Child;
        Next->Asl.LineNumber = 0;
        Next->Asl.LogicalLineNumber = 0;

        if (Next->Asl.ParseOpcode == PARSEOP_NAMESEG)
        {
            Next->Asl.ParseOpcode = PARSEOP_NAMESTRING;
        }

        Next->Asl.ExternalName = ExternalName;
        Status = UtInternalizeName (ExternalName, &Next->Asl.Value.String);
        if (ACPI_FAILURE (Status))
        {
            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL,
                Next, "Could not internalize namestring");
            return;
        }

        Next->Asl.AmlLength = strlen (Next->Asl.Value.String);

        Next = Next->Asl.Next;
        Next->Asl.LineNumber = 0;
        Next->Asl.LogicalLineNumber = 0;

        Next = Next->Asl.Next;
        Next->Asl.LineNumber = 0;
        Next->Asl.LogicalLineNumber = 0;

        Next = Next->Asl.Next;
        Next->Asl.LineNumber = 0;
        Next->Asl.LogicalLineNumber = 0;

        ParentOp = ExternalOp->Asl.Parent;
        Prev = Next = ParentOp->Asl.Child;

        /* Now find the External node's position in parse tree */

        while (Next != ExternalOp)
        {
            Prev = Next;
            Next = Next->Asl.Next;
        }

        /* Remove the External from the parse tree */

        if (Prev == ExternalOp)
        {
            /* External was the first child node */

            ParentOp->Asl.Child = ExternalOp->Asl.Next;
        }

        Prev->Asl.Next = ExternalOp->Asl.Next;
        ExternalOp->Asl.Next = NULL;
        ExternalOp->Asl.Parent = AslGbl_ExternalsListHead;

        /* Point the External to the next in the list */

        if (NextOp->Asl.Next)
        {
            ExternalOp->Asl.Next = NextOp->Asl.Next->Asl.Child;
        }

        NextOp = NextOp->Asl.Next;
    }

    /*
     * Loop again to remove MethodObj Externals for which
     * a MethodCall was not found (dead external reference)
     */
    Prev = AslGbl_ExternalsListHead->Asl.Child;
    Next = Prev;
    while (Next)
    {
        ObjType = (ACPI_OBJECT_TYPE)
            Next->Asl.Child->Asl.Next->Asl.Value.Integer;

        if (ObjType == ACPI_TYPE_METHOD &&
            !(Next->Asl.CompileFlags & OP_VISITED))
        {
            if (Next == Prev)
            {
                AslGbl_ExternalsListHead->Asl.Child = Next->Asl.Next;
                Next->Asl.Next = NULL;
                Prev = AslGbl_ExternalsListHead->Asl.Child;
                Next = Prev;
                continue;
            }
            else
            {
                Prev->Asl.Next = Next->Asl.Next;
                Next->Asl.Next = NULL;
                Next = Prev->Asl.Next;
                continue;
            }
        }

        Prev = Next;
        Next = Next->Asl.Next;
    }

    /* If list is now empty, don't bother to make If (0) block */

    if (!AslGbl_ExternalsListHead->Asl.Child)
    {
        return;
    }

    /* Convert Gbl_ExternalsListHead parent to If(). */

    AslGbl_ExternalsListHead->Asl.ParseOpcode = PARSEOP_IF;
    AslGbl_ExternalsListHead->Asl.AmlOpcode = AML_IF_OP;
    AslGbl_ExternalsListHead->Asl.CompileFlags = OP_AML_PACKAGE;
    UtSetParseOpName (AslGbl_ExternalsListHead);

    /* Create a Zero op for the If predicate */

    PredicateOp = TrAllocateOp (PARSEOP_ZERO);
    PredicateOp->Asl.AmlOpcode = AML_ZERO_OP;

    PredicateOp->Asl.Parent = AslGbl_ExternalsListHead;
    PredicateOp->Asl.Child = NULL;
    PredicateOp->Asl.Next = AslGbl_ExternalsListHead->Asl.Child;
    AslGbl_ExternalsListHead->Asl.Child = PredicateOp;

    /* Set line numbers (for listings, etc.) */

    AslGbl_ExternalsListHead->Asl.LineNumber = 0;
    AslGbl_ExternalsListHead->Asl.LogicalLineNumber = 0;

    PredicateOp->Asl.LineNumber = 0;
    PredicateOp->Asl.LogicalLineNumber = 0;

    /* Insert block back in the list */

    Prev = DefinitionBlockOp->Asl.Child;
    Next = Prev;

    /* Find last default arg */

    for (i = 0; i < 6; i++)
    {
        Prev = Next;
        Next = Prev->Asl.Next;
    }

    if (Next)
    {
        /* Definition Block is not empty */

        AslGbl_ExternalsListHead->Asl.Next = Next;
    }
    else
    {
        /* Definition Block is empty. */

        AslGbl_ExternalsListHead->Asl.Next = NULL;
    }

    Prev->Asl.Next = AslGbl_ExternalsListHead;
    AslGbl_ExternalsListHead->Asl.Parent = Prev->Asl.Parent;
}
Example #12
0
static void
TrTransformSubtree (
    ACPI_PARSE_OBJECT           *Op)
{
    ACPI_PARSE_OBJECT           *MethodOp;


    if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
    {
        return;
    }

    switch (Op->Asl.ParseOpcode)
    {
    case PARSEOP_DEFINITION_BLOCK:

        TrDoDefinitionBlock (Op);
        break;

    case PARSEOP_SWITCH:

        TrDoSwitch (Op);
        break;

    case PARSEOP_METHOD:
        /*
         * TBD: Zero the tempname (_T_x) count. Probably shouldn't be a global,
         * however
         */
        AslGbl_TempCount = 0;
        break;

    case PARSEOP_EXTERNAL:

        ExDoExternal (Op);
        break;

    case PARSEOP___METHOD__:

        /* Transform to a string op containing the parent method name */

        Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
        UtSetParseOpName (Op);

        /* Find the parent control method op */

        MethodOp = Op;
        while (MethodOp)
        {
            if (MethodOp->Asl.ParseOpcode == PARSEOP_METHOD)
            {
                /* First child contains the method name */

                MethodOp = MethodOp->Asl.Child;
                Op->Asl.Value.String = MethodOp->Asl.Value.String;
                return;
            }

            MethodOp = MethodOp->Asl.Parent;
        }

        /* At the root, invocation not within a control method */

        Op->Asl.Value.String = "\\";
        break;

    case PARSEOP_UNLOAD:

        AslError (ASL_WARNING, ASL_MSG_UNLOAD, Op, NULL);
        break;

    case PARSEOP_SLEEP:

        /* Remark for very long sleep values */

        if (Op->Asl.Child->Asl.Value.Integer > 1000)
        {
            AslError (ASL_REMARK, ASL_MSG_LONG_SLEEP, Op, NULL);
        }
        break;

    default:

        /* Nothing to do here for other opcodes */

        break;
    }
}
Example #13
0
static ACPI_STATUS
TrSimpleConstantReduction (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_PARSE_OBJECT       *RootOp;
    ACPI_PARSE_OBJECT       *OriginalParentOp;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_STATUS             Status;


    DbgPrint (ASL_PARSE_OUTPUT,
        "Simple subtree constant reduction, operator to constant\n");

    /* Allocate a new temporary root for this subtree */

    RootOp = TrAllocateNode (PARSEOP_INTEGER);
    if (!RootOp)
    {
        return (AE_NO_MEMORY);
    }

    RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;

    OriginalParentOp = Op->Common.Parent;
    Op->Common.Parent = RootOp;

    /* Hand off the subtree to the AML interpreter */

    WalkState->CallerReturnDesc = &ObjDesc;

    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
        OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);

    /* Restore original parse tree */

    Op->Common.Parent = OriginalParentOp;

    if (ACPI_FAILURE (Status))
    {
        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant Subtree evaluation(1), %s\n",
            AcpiFormatException (Status));
        return (Status);
    }

    /* Get the final result */

    Status = AcpiDsResultPop (&ObjDesc, WalkState);
    if (ACPI_FAILURE (Status))
    {
        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant Subtree evaluation(2), %s\n",
            AcpiFormatException (Status));
        return (Status);
    }

    /* Disconnect any existing children, install new constant */

    Op->Asl.Child = NULL;
    TrInstallReducedConstant (Op, ObjDesc);

    UtSetParseOpName (Op);
    return (AE_OK);
}
Example #14
0
void
RsDoResourceTemplate (
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_PARSE_OBJECT       *BufferLengthOp;
    ACPI_PARSE_OBJECT       *BufferOp;
    ACPI_PARSE_OBJECT       *DescriptorTypeOp;
    ACPI_PARSE_OBJECT       *LastOp = NULL;
    UINT32                  CurrentByteOffset = 0;
    ASL_RESOURCE_NODE       HeadRnode;
    ASL_RESOURCE_NODE       *PreviousRnode;
    ASL_RESOURCE_NODE       *Rnode;
    ASL_RESOURCE_INFO       Info;
    UINT8                   State;


    /* Mark parent as containing a resource template */

    if (Op->Asl.Parent)
    {
        Op->Asl.Parent->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
    }

    /* ResourceTemplate Opcode is first (Op) */
    /* Buffer Length node is first child */

    BufferLengthOp = ASL_GET_CHILD_NODE (Op);

    /* Buffer Op is first peer */

    BufferOp = ASL_GET_PEER_NODE (BufferLengthOp);

    /* First Descriptor type is next */

    DescriptorTypeOp = ASL_GET_PEER_NODE (BufferOp);

    /*
     * Process all resource descriptors in the list
     * Note: It is assumed that the EndTag node has been automatically
     * inserted at the end of the template by the parser.
     */
    State = ACPI_RSTATE_NORMAL;
    PreviousRnode = &HeadRnode;
    while (DescriptorTypeOp)
    {
        /* Save information for optional mapfile */

        if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
        {
            Info.MappingOp = Op->Asl.Parent;
        }
        else
        {
            Info.MappingOp = DescriptorTypeOp;
        }

        Info.DescriptorTypeOp = DescriptorTypeOp;
        Info.CurrentByteOffset = CurrentByteOffset;

        DescriptorTypeOp->Asl.CompileFlags |= NODE_IS_RESOURCE_DESC;
        Rnode = RsDoOneResourceDescriptor (&Info, &State);

        /*
         * Update current byte offset to indicate the number of bytes from the
         * start of the buffer. Buffer can include multiple descriptors, we
         * must keep track of the offset of not only each descriptor, but each
         * element (field) within each descriptor as well.
         */
        CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, Rnode);

        /* Get the next descriptor in the list */

        LastOp = DescriptorTypeOp;
        DescriptorTypeOp = ASL_GET_PEER_NODE (DescriptorTypeOp);
    }

    if (State == ACPI_RSTATE_DEPENDENT_LIST)
    {
        if (LastOp)
        {
            LastOp = LastOp->Asl.Parent;
        }
        AslError (ASL_ERROR, ASL_MSG_MISSING_ENDDEPENDENT, LastOp, NULL);
    }

    /*
     * Transform the nodes into the following
     *
     * Op           -> AML_BUFFER_OP
     * First Child  -> BufferLength
     * Second Child -> Descriptor Buffer (raw byte data)
     */
    Op->Asl.ParseOpcode               = PARSEOP_BUFFER;
    Op->Asl.AmlOpcode                 = AML_BUFFER_OP;
    Op->Asl.CompileFlags              = NODE_AML_PACKAGE | NODE_IS_RESOURCE_DESC;
    UtSetParseOpName (Op);

    BufferLengthOp->Asl.ParseOpcode   = PARSEOP_INTEGER;
    BufferLengthOp->Asl.Value.Integer = CurrentByteOffset;
    (void) OpcSetOptimalIntegerSize (BufferLengthOp);
    UtSetParseOpName (BufferLengthOp);

    BufferOp->Asl.ParseOpcode         = PARSEOP_RAW_DATA;
    BufferOp->Asl.AmlOpcode           = AML_RAW_DATA_CHAIN;
    BufferOp->Asl.AmlOpcodeLength     = 0;
    BufferOp->Asl.AmlLength           = CurrentByteOffset;
    BufferOp->Asl.Value.Buffer        = (UINT8 *) HeadRnode.Next;
    BufferOp->Asl.CompileFlags       |= NODE_IS_RESOURCE_DATA;
    UtSetParseOpName (BufferOp);

    return;
}
Example #15
0
ACPI_PARSE_OBJECT *
TrSetOpIntegerValue (
    UINT32                  ParseOpcode,
    ACPI_PARSE_OBJECT       *Op)
{

    if (!Op)
    {
        return (NULL);
    }

    DbgPrint (ASL_PARSE_OUTPUT,
        "\nUpdateOp: Old - %s, New - %s\n",
        UtGetOpName (Op->Asl.ParseOpcode),
        UtGetOpName (ParseOpcode));

    /* Assign new opcode and name */

    if (Op->Asl.ParseOpcode == PARSEOP_ONES)
    {
        switch (ParseOpcode)
        {
        case PARSEOP_BYTECONST:

            Op->Asl.Value.Integer = ACPI_UINT8_MAX;
            break;

        case PARSEOP_WORDCONST:

            Op->Asl.Value.Integer = ACPI_UINT16_MAX;
            break;

        case PARSEOP_DWORDCONST:

            Op->Asl.Value.Integer = ACPI_UINT32_MAX;
            break;

        /* Don't need to do the QWORD case */

        default:

            /* Don't care about others */
            break;
        }
    }

    Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
    UtSetParseOpName (Op);

    /*
     * For the BYTE, WORD, and DWORD constants, make sure that the integer
     * that was passed in will actually fit into the data type
     */
    switch (ParseOpcode)
    {
    case PARSEOP_BYTECONST:

        UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
        Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
        break;

    case PARSEOP_WORDCONST:

        UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
        Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
        break;

    case PARSEOP_DWORDCONST:

        UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
        Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
        break;

    default:

        /* Don't care about others, don't need to check QWORD */

        break;
    }

    /* Converter: if this is a method invocation, turn off capture comments */

    if (AcpiGbl_CaptureComments &&
        (ParseOpcode == PARSEOP_METHODCALL))
    {
        Gbl_CommentState.CaptureComments = FALSE;
    }

    return (Op);
}
Example #16
0
static ACPI_STATUS
XfNamespaceLocateBegin (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState = (ACPI_WALK_STATE *) Context;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;
    ACPI_OBJECT_TYPE        ObjectType;
    char                    *Path;
    UINT8                   PassedArgs;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_PARSE_OBJECT       *OwningOp;
    ACPI_PARSE_OBJECT       *SpaceIdOp;
    UINT32                  MinimumLength;
    UINT32                  Offset;
    UINT32                  FieldBitLength;
    UINT32                  TagBitLength;
    UINT8                   Message = 0;
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  Flags;
    ASL_METHOD_LOCAL        *MethodLocals = NULL;
    ASL_METHOD_LOCAL        *MethodArgs = NULL;
    int                     RegisterNumber;
    UINT32                  i;


    ACPI_FUNCTION_TRACE_PTR (XfNamespaceLocateBegin, Op);


    if ((Op->Asl.AmlOpcode == AML_METHOD_OP) && Op->Asl.Node)
    {
        Node = Op->Asl.Node;

        /* Support for method LocalX/ArgX analysis */

        if (!Node->MethodLocals)
        {
            /* Create local/arg info blocks */

            MethodLocals = UtLocalCalloc (
                sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_LOCALS);
            Node->MethodLocals = MethodLocals;

            MethodArgs = UtLocalCalloc (
                sizeof (ASL_METHOD_LOCAL) * ACPI_METHOD_NUM_ARGS);
            Node->MethodArgs = MethodArgs;

            /*
             * Get the method argument count
             * First, get the name node
             */
            NextOp = Op->Asl.Child;

            /* Get the NumArguments node */

            NextOp = NextOp->Asl.Next;
            Node->ArgCount = (UINT8)
                (((UINT8) NextOp->Asl.Value.Integer) & 0x07);

            /* We will track all possible ArgXs */

            for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++)
            {
                if (i < Node->ArgCount)
                {
                    /* Real Args are always "initialized" */

                    MethodArgs[i].Flags = ASL_ARG_INITIALIZED;
                }
                else
                {
                    /* Other ArgXs can be used as locals */

                    MethodArgs[i].Flags = ASL_ARG_IS_LOCAL;
                }

                MethodArgs[i].Op = Op;
            }
        }
    }

    /*
     * If this node is the actual declaration of a name
     * [such as the XXXX name in "Method (XXXX)"],
     * we are not interested in it here. We only care about names that are
     * references to other objects within the namespace and the parent objects
     * of name declarations
     */
    if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION)
    {
        return_ACPI_STATUS (AE_OK);
    }

    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);

    /* Check method LocalX variables */

    if (OpInfo->Type == AML_TYPE_LOCAL_VARIABLE)
    {
        /* Find parent method Op */

        NextOp = XfGetParentMethod (Op);
        if (!NextOp)
        {
            return_ACPI_STATUS (AE_OK);
        }

        /* Get method node */

        Node = NextOp->Asl.Node;

        RegisterNumber = Op->Asl.AmlOpcode & 0x0007; /* 0x60 through 0x67 */
        MethodLocals = Node->MethodLocals;

        if (Op->Asl.CompileFlags & OP_IS_TARGET)
        {
            /* Local is being initialized */

            MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_INITIALIZED;
            MethodLocals[RegisterNumber].Op = Op;

            return_ACPI_STATUS (AE_OK);
        }

        /* Mark this Local as referenced */

        MethodLocals[RegisterNumber].Flags |= ASL_LOCAL_REFERENCED;
        MethodLocals[RegisterNumber].Op = Op;

        return_ACPI_STATUS (AE_OK);
    }

    /* Check method ArgX variables */

    if (OpInfo->Type == AML_TYPE_METHOD_ARGUMENT)
    {
        /* Find parent method Op */

        NextOp = XfGetParentMethod (Op);
        if (!NextOp)
        {
            return_ACPI_STATUS (AE_OK);
        }

        /* Get method node */

        Node = NextOp->Asl.Node;

        /* Get Arg # */

        RegisterNumber = Op->Asl.AmlOpcode - AML_ARG0; /* 0x68 through 0x6F */
        MethodArgs = Node->MethodArgs;

        /* Mark this Arg as referenced */

        MethodArgs[RegisterNumber].Flags |= ASL_ARG_REFERENCED;
        MethodArgs[RegisterNumber].Op = Op;

        if (Op->Asl.CompileFlags & OP_IS_TARGET)
        {
            /* Arg is being initialized */

            MethodArgs[RegisterNumber].Flags |= ASL_ARG_INITIALIZED;
        }

        return_ACPI_STATUS (AE_OK);
    }

    /*
     * After method ArgX and LocalX, we are only interested in opcodes
     * that have an associated name
     */
    if ((!(OpInfo->Flags & AML_NAMED)) &&
        (!(OpInfo->Flags & AML_CREATE)) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
        (Op->Asl.ParseOpcode != PARSEOP_METHODCALL) &&
        (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /*
     * One special case: CondRefOf operator - we don't care if the name exists
     * or not at this point, just ignore it, the point of the operator is to
     * determine if the name exists at runtime.
     */
    if ((Op->Asl.Parent) &&
        (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /*
     * We must enable the "search-to-root" for single NameSegs, but
     * we have to be very careful about opening up scopes
     */
    Flags = ACPI_NS_SEARCH_PARENT;
    if ((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
        (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)    ||
        (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
        (Op->Asl.ParseOpcode == PARSEOP_EXTERNAL))
    {
        /*
         * These are name references, do not push the scope stack
         * for them.
         */
        Flags |= ACPI_NS_DONT_OPEN_SCOPE;
    }

    /* Get the NamePath from the appropriate place */

    if (OpInfo->Flags & AML_NAMED)
    {
        /* For nearly all NAMED operators, the name reference is the first child */

        Path = Op->Asl.Child->Asl.Value.String;
        if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
        {
            /*
             * ALIAS is the only oddball opcode, the name declaration
             * (alias name) is the second operand
             */
            Path = Op->Asl.Child->Asl.Next->Asl.Value.String;
        }
    }
    else if (OpInfo->Flags & AML_CREATE)
    {
        /* Name must appear as the last parameter */

        NextOp = Op->Asl.Child;
        while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
        {
            NextOp = NextOp->Asl.Next;
        }

        Path = NextOp->Asl.Value.String;
    }
    else
    {
        Path = Op->Asl.Value.String;
    }

    ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode);
    ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
        "Type=%s\n", AcpiUtGetTypeName (ObjectType)));

    /*
     * Lookup the name in the namespace. Name must exist at this point, or it
     * is an invalid reference.
     *
     * The namespace is also used as a lookup table for references to resource
     * descriptors and the fields within them.
     */
    AslGbl_NsLookupCount++;

    Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType,
        ACPI_IMODE_EXECUTE, Flags, WalkState, &Node);
    if (ACPI_FAILURE (Status))
    {
        if (Status == AE_NOT_FOUND)
        {
            /*
             * We didn't find the name reference by path -- we can qualify this
             * a little better before we print an error message
             */
            if (strlen (Path) == ACPI_NAME_SIZE)
            {
                /* A simple, one-segment ACPI name */

                if (XfObjectExists (Path))
                {
                    /*
                     * There exists such a name, but we couldn't get to it
                     * from this scope
                     */
                    AslError (ASL_ERROR, ASL_MSG_NOT_REACHABLE, Op,
                        Op->Asl.ExternalName);
                }
                else
                {
                    /* The name doesn't exist, period */

                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST,
                        Op, Op->Asl.ExternalName);
                }
            }
            else
            {
                /* The NamePath contains multiple NameSegs */

                if ((OpInfo->Flags & AML_CREATE) ||
                    (OpInfo->ObjectType == ACPI_TYPE_LOCAL_ALIAS))
                {
                    /*
                     * The new name is the last parameter. For the
                     * CreateXXXXField and Alias operators
                     */
                    NextOp = Op->Asl.Child;
                    while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
                    {
                        NextOp = NextOp->Asl.Next;
                    }

                    AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, NextOp,
                        NextOp->Asl.ExternalName);
                }
                else if (OpInfo->Flags & AML_NAMED)
                {
                    /* The new name is the first parameter */

                    AslError (ASL_ERROR, ASL_MSG_PREFIX_NOT_EXIST, Op,
                        Op->Asl.ExternalName);
                }
                else if (Path[0] == AML_ROOT_PREFIX)
                {
                    /* Full namepath from root, the object does not exist */

                    AslError (ASL_ERROR, ASL_MSG_NOT_EXIST, Op,
                        Op->Asl.ExternalName);
                }
                else
                {
                    /*
                     * Generic "not found" error. Cannot determine whether it
                     * doesn't exist or just can't be reached. However, we
                     * can differentiate between a NameSeg vs. NamePath.
                     */
                    if (strlen (Op->Asl.ExternalName) == ACPI_NAME_SIZE)
                    {
                        AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op,
                            Op->Asl.ExternalName);
                    }
                    else
                    {
                        AslError (ASL_ERROR, ASL_MSG_NAMEPATH_NOT_EXIST, Op,
                            Op->Asl.ExternalName);
                    }
                }
            }

            Status = AE_OK;
        }

        return_ACPI_STATUS (Status);
    }

    /* Check for an attempt to access an object in another method */

    if (!XfValidateCrossReference (Op, OpInfo, Node))
    {
        AslError (ASL_ERROR, ASL_MSG_TEMPORARY_OBJECT, Op,
            Op->Asl.ExternalName);
        return_ACPI_STATUS (Status);
    }

    /* Object was found above, check for an illegal forward reference */

    if (Op->Asl.CompileFlags & OP_NOT_FOUND_DURING_LOAD)
    {
        /*
         * During the load phase, this Op was flagged as a possible
         * illegal forward reference
         *
         * Note: Allow "forward references" from within a method to an
         * object that is not within any method (module-level code)
         */
        if (!WalkState->ScopeInfo || (UtGetParentMethod (Node) &&
            !UtNodeIsDescendantOf (WalkState->ScopeInfo->Scope.Node,
                UtGetParentMethod (Node))))
        {
            AslError (ASL_ERROR, ASL_MSG_ILLEGAL_FORWARD_REF, Op,
                Op->Asl.ExternalName);
        }
    }

    /* Check for a reference vs. name declaration */

    if (!(OpInfo->Flags & AML_NAMED) &&
        !(OpInfo->Flags & AML_CREATE))
    {
        /* This node has been referenced, mark it for reference check */

        Node->Flags |= ANOBJ_IS_REFERENCED;
    }

    /* Attempt to optimize the NamePath */

    OptOptimizeNamePath (Op, OpInfo->Flags, WalkState, Path, Node);

    /*
     * 1) Dereference an alias (A name reference that is an alias)
     *    Aliases are not nested, the alias always points to the final object
     */
    if ((Op->Asl.ParseOpcode != PARSEOP_ALIAS) &&
        (Node->Type == ACPI_TYPE_LOCAL_ALIAS))
    {
        /* This node points back to the original PARSEOP_ALIAS */

        NextOp = Node->Op;

        /* The first child is the alias target op */

        NextOp = NextOp->Asl.Child;

        /* That in turn points back to original target alias node */

        if (NextOp->Asl.Node)
        {
            Node = NextOp->Asl.Node;
        }

        /* Else - forward reference to alias, will be resolved later */
    }

    /* 2) Check for a reference to a resource descriptor */

    if ((Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
        (Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    {
        /*
         * This was a reference to a field within a resource descriptor.
         * Extract the associated field offset (either a bit or byte
         * offset depending on the field type) and change the named
         * reference into an integer for AML code generation
         */
        Offset = Node->Value;
        TagBitLength = Node->Length;

        /*
         * If a field is being created, generate the length (in bits) of
         * the field. Note: Opcodes other than CreateXxxField and Index
         * can come through here. For other opcodes, we just need to
         * convert the resource tag reference to an integer offset.
         */
        switch (Op->Asl.Parent->Asl.AmlOpcode)
        {
        case AML_CREATE_FIELD_OP: /* Variable "Length" field, in bits */
            /*
             * We know the length operand is an integer constant because
             * we know that it contains a reference to a resource
             * descriptor tag.
             */
            FieldBitLength = (UINT32) Op->Asl.Next->Asl.Value.Integer;
            break;

        case AML_CREATE_BIT_FIELD_OP:

            FieldBitLength = 1;
            break;

        case AML_CREATE_BYTE_FIELD_OP:
        case AML_INDEX_OP:

            FieldBitLength = 8;
            break;

        case AML_CREATE_WORD_FIELD_OP:

            FieldBitLength = 16;
            break;

        case AML_CREATE_DWORD_FIELD_OP:

            FieldBitLength = 32;
            break;

        case AML_CREATE_QWORD_FIELD_OP:

            FieldBitLength = 64;
            break;

        default:

            FieldBitLength = 0;
            break;
        }

        /* Check the field length against the length of the resource tag */

        if (FieldBitLength)
        {
            if (TagBitLength < FieldBitLength)
            {
                Message = ASL_MSG_TAG_SMALLER;
            }
            else if (TagBitLength > FieldBitLength)
            {
                Message = ASL_MSG_TAG_LARGER;
            }

            if (Message)
            {
                sprintf (AslGbl_MsgBuffer,
                    "Size mismatch, Tag: %u bit%s, Field: %u bit%s",
                    TagBitLength, (TagBitLength > 1) ? "s" : "",
                    FieldBitLength, (FieldBitLength > 1) ? "s" : "");

                AslError (ASL_WARNING, Message, Op, AslGbl_MsgBuffer);
            }
        }

        /* Convert the BitOffset to a ByteOffset for certain opcodes */

        switch (Op->Asl.Parent->Asl.AmlOpcode)
        {
        case AML_CREATE_BYTE_FIELD_OP:
        case AML_CREATE_WORD_FIELD_OP:
        case AML_CREATE_DWORD_FIELD_OP:
        case AML_CREATE_QWORD_FIELD_OP:
        case AML_INDEX_OP:

            Offset = ACPI_DIV_8 (Offset);
            break;

        default:

            break;
        }

        /* Now convert this node to an integer whose value is the field offset */

        Op->Asl.AmlLength = 0;
        Op->Asl.ParseOpcode = PARSEOP_INTEGER;
        Op->Asl.Value.Integer = (UINT64) Offset;
        Op->Asl.CompileFlags |= OP_IS_RESOURCE_FIELD;

        OpcGenerateAmlOpcode (Op);
    }

    /* 3) Check for a method invocation */

    else if ((((Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || (Op->Asl.ParseOpcode == PARSEOP_NAMESEG)) &&
                (Node->Type == ACPI_TYPE_METHOD) &&
                (Op->Asl.Parent) &&
                (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_METHOD))   ||

                (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
    {
        /*
         * A reference to a method within one of these opcodes is not an
         * invocation of the method, it is simply a reference to the method.
         *
         * September 2016: Removed DeRefOf from this list
         */
        if ((Op->Asl.Parent) &&
            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_REFOF)     ||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_PACKAGE)    ||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)||
            (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_OBJECTTYPE)))
        {
            return_ACPI_STATUS (AE_OK);
        }

        /*
         * There are two types of method invocation:
         * 1) Invocation with arguments -- the parser recognizes this
         *    as a METHODCALL.
         * 2) Invocation with no arguments --the parser cannot determine that
         *    this is a method invocation, therefore we have to figure it out
         *    here.
         */
        if (Node->Type != ACPI_TYPE_METHOD)
        {
            sprintf (AslGbl_MsgBuffer, "%s is a %s",
                Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type));

            AslError (ASL_ERROR, ASL_MSG_NOT_METHOD, Op, AslGbl_MsgBuffer);
            return_ACPI_STATUS (AE_OK);
        }

        /* Save the method node in the caller's op */

        Op->Asl.Node = Node;
        if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONDREFOF)
        {
            return_ACPI_STATUS (AE_OK);
        }

        /*
         * This is a method invocation, with or without arguments.
         * Count the number of arguments, each appears as a child
         * under the parent node
         */
        Op->Asl.ParseOpcode = PARSEOP_METHODCALL;
        UtSetParseOpName (Op);

        PassedArgs = 0;
        NextOp = Op->Asl.Child;

        while (NextOp)
        {
            PassedArgs++;
            NextOp = NextOp->Asl.Next;
        }

        if (Node->Value != ASL_EXTERNAL_METHOD &&
            Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_EXTERNAL)
        {
            /*
             * Check the parsed arguments with the number expected by the
             * method declaration itself
             */
            if (PassedArgs != Node->Value)
            {
                sprintf (AslGbl_MsgBuffer, "%s requires %u", Op->Asl.ExternalName,
                    Node->Value);

                if (PassedArgs < Node->Value)
                {
                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_LO, Op, AslGbl_MsgBuffer);
                }
                else
                {
                    AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_HI, Op, AslGbl_MsgBuffer);
                }
            }
        }
    }

    /* 4) Check for an ASL Field definition */

    else if ((Op->Asl.Parent) &&
            ((Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_FIELD)     ||
             (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_BANKFIELD)))
    {
        /*
         * Offset checking for fields. If the parent operation region has a
         * constant length (known at compile time), we can check fields
         * defined in that region against the region length. This will catch
         * fields and field units that cannot possibly fit within the region.
         *
         * Note: Index fields do not directly reference an operation region,
         * thus they are not included in this check.
         */
        if (Op == Op->Asl.Parent->Asl.Child)
        {
            /*
             * This is the first child of the field node, which is
             * the name of the region. Get the parse node for the
             * region -- which contains the length of the region.
             */
            OwningOp = Node->Op;
            Op->Asl.Parent->Asl.ExtraValue =
                ACPI_MUL_8 ((UINT32) OwningOp->Asl.Value.Integer);

            /* Examine the field access width */

            switch ((UINT8) Op->Asl.Parent->Asl.Value.Integer)
            {
            case AML_FIELD_ACCESS_ANY:
            case AML_FIELD_ACCESS_BYTE:
            case AML_FIELD_ACCESS_BUFFER:
            default:

                MinimumLength = 1;
                break;

            case AML_FIELD_ACCESS_WORD:

                MinimumLength = 2;
                break;

            case AML_FIELD_ACCESS_DWORD:

                MinimumLength = 4;
                break;

            case AML_FIELD_ACCESS_QWORD:

                MinimumLength = 8;
                break;
            }

            /*
             * Is the region at least as big as the access width?
             * Note: DataTableRegions have 0 length
             */
            if (((UINT32) OwningOp->Asl.Value.Integer) &&
                ((UINT32) OwningOp->Asl.Value.Integer < MinimumLength))
            {
                AslError (ASL_ERROR, ASL_MSG_FIELD_ACCESS_WIDTH, Op, NULL);
            }

            /*
             * Check EC/CMOS/SMBUS fields to make sure that the correct
             * access type is used (BYTE for EC/CMOS, BUFFER for SMBUS)
             */
            SpaceIdOp = OwningOp->Asl.Child->Asl.Next;
            switch ((UINT32) SpaceIdOp->Asl.Value.Integer)
            {
            case ACPI_ADR_SPACE_EC:
            case ACPI_ADR_SPACE_CMOS:
            case ACPI_ADR_SPACE_GPIO:

                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
                    AML_FIELD_ACCESS_BYTE)
                {
                    AslError (ASL_ERROR, ASL_MSG_REGION_BYTE_ACCESS, Op, NULL);
                }
                break;

            case ACPI_ADR_SPACE_SMBUS:
            case ACPI_ADR_SPACE_IPMI:
            case ACPI_ADR_SPACE_GSBUS:

                if ((UINT8) Op->Asl.Parent->Asl.Value.Integer !=
                    AML_FIELD_ACCESS_BUFFER)
                {
                    AslError (ASL_ERROR, ASL_MSG_REGION_BUFFER_ACCESS, Op, NULL);
                }
                break;

            default:

                /* Nothing to do for other address spaces */

                break;
            }
        }
        else
        {
            /*
             * This is one element of the field list. Check to make sure
             * that it does not go beyond the end of the parent operation region.
             *
             * In the code below:
             *    Op->Asl.Parent->Asl.ExtraValue      - Region Length (bits)
             *    Op->Asl.ExtraValue                  - Field start offset (bits)
             *    Op->Asl.Child->Asl.Value.Integer32  - Field length (bits)
             *    Op->Asl.Child->Asl.ExtraValue       - Field access width (bits)
             */
            if (Op->Asl.Parent->Asl.ExtraValue && Op->Asl.Child)
            {
                XfCheckFieldRange (Op,
                    Op->Asl.Parent->Asl.ExtraValue,
                    Op->Asl.ExtraValue,
                    (UINT32) Op->Asl.Child->Asl.Value.Integer,
                    Op->Asl.Child->Asl.ExtraValue);
            }
        }
    }

    /* 5) Check for a connection object */
#if 0
    else if (Op->Asl.Parent->Asl.ParseOpcode == PARSEOP_CONNECTION)
    {
        return_ACPI_STATUS (Status);
    }
#endif

    Op->Asl.Node = Node;
    return_ACPI_STATUS (Status);
}
Example #17
0
static void
OpcDoUuId (
    ACPI_PARSE_OBJECT       *Op)
{
    char                    *InString;
    char                    *Buffer;
    ACPI_STATUS             Status = AE_OK;
    ACPI_NATIVE_UINT        i;
    ACPI_PARSE_OBJECT       *NewOp;


    InString = (char *) Op->Asl.Value.String;

    if (ACPI_STRLEN (InString) != 36)
    {
        Status = AE_BAD_PARAMETER;
    }
    else
    {
        /* Check all 36 characters for correct format */

        for (i = 0; i < 36; i++)
        {
            if ((i == 8) || (i == 13) || (i == 18) || (i == 23))
            {
                if (InString[i] != '-')
                {
                    Status = AE_BAD_PARAMETER;
                }
            }
            else
            {
                if (!isxdigit (InString[i]))
                {
                    Status = AE_BAD_PARAMETER;
                }
            }
        }
    }

    Buffer = UtLocalCalloc (16);

    if (ACPI_FAILURE (Status))
    {
        AslError (ASL_ERROR, ASL_MSG_INVALID_UUID, Op, Op->Asl.Value.String);
    }
    else for (i = 0; i < 16; i++)
    {
        Buffer[i]  = (char) (UtHexCharToValue (InString[OpcMapToUUID[i]]) << 4);
        Buffer[i] |= (char)  UtHexCharToValue (InString[OpcMapToUUID[i] + 1]);
    }

    /* Change Op to a Buffer */

    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    Op->Common.AmlOpcode = AML_BUFFER_OP;

    /* Disable further optimization */

    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    UtSetParseOpName (Op);

    /* Child node is the buffer length */

    NewOp = TrAllocateNode (PARSEOP_INTEGER);

    NewOp->Asl.AmlOpcode     = AML_BYTE_OP;
    NewOp->Asl.Value.Integer = 16;
    NewOp->Asl.Parent        = Op;

    Op->Asl.Child = NewOp;
    Op = NewOp;

    /* Peer to the child is the raw buffer data */

    NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
    NewOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
    NewOp->Asl.AmlLength     = 16;
    NewOp->Asl.Value.String  = (char *) Buffer;
    NewOp->Asl.Parent        = Op->Asl.Parent;

    Op->Asl.Next = NewOp;
}
Example #18
0
static void
TrInstallReducedConstant (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_OPERAND_OBJECT     *ObjDesc)
{
    ACPI_PARSE_OBJECT       *LengthOp;
    ACPI_PARSE_OBJECT       *DataOp;


    TotalFolds++;
    AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
        Op->Asl.ParseOpName);

    /*
     * Because we know we executed type 3/4/5 opcodes above, we know that
     * the result must be either an Integer, String, or Buffer.
     */
    switch (ObjDesc->Common.Type)
    {
    case ACPI_TYPE_INTEGER:

        OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);

        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant expression reduced to (%s) %8.8X%8.8X\n\n",
            Op->Asl.ParseOpName,
            ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
        break;

    case ACPI_TYPE_STRING:

        Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
        Op->Common.AmlOpcode = AML_STRING_OP;
        Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;
        Op->Common.Value.String = ObjDesc->String.Pointer;

        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant expression reduced to (STRING) %s\n\n",
            Op->Common.Value.String);
        break;

    case ACPI_TYPE_BUFFER:
        /*
         * Create a new parse subtree of the form:
         *
         * BUFFER (Buffer AML opcode)
         *    INTEGER (Buffer length in bytes)
         *    RAW_DATA (Buffer byte data)
         */
        Op->Asl.ParseOpcode = PARSEOP_BUFFER;
        Op->Common.AmlOpcode = AML_BUFFER_OP;
        Op->Asl.CompileFlags = NODE_AML_PACKAGE;
        UtSetParseOpName (Op);

        /* Child node is the buffer length */

        LengthOp = TrAllocateNode (PARSEOP_INTEGER);

        LengthOp->Asl.AmlOpcode = AML_DWORD_OP;
        LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
        LengthOp->Asl.Parent = Op;
        (void) OpcSetOptimalIntegerSize (LengthOp);

        Op->Asl.Child = LengthOp;

        /* Next child is the raw buffer data */

        DataOp = TrAllocateNode (PARSEOP_RAW_DATA);
        DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
        DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;
        DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
        DataOp->Asl.Parent = Op;

        LengthOp->Asl.Next = DataOp;

        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant expression reduced to (BUFFER) length %X\n\n",
            ObjDesc->Buffer.Length);
        break;

    default:
        break;
    }
}
Example #19
0
static ACPI_STATUS
TrTransformToStoreOp (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_PARSE_OBJECT       *OriginalTarget;
    ACPI_PARSE_OBJECT       *NewTarget;
    ACPI_PARSE_OBJECT       *Child1;
    ACPI_PARSE_OBJECT       *Child2;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PARSE_OBJECT       *NewParent;
    ACPI_PARSE_OBJECT       *OriginalParent;
    ACPI_STATUS             Status;


    /* Extract the operands */

    Child1 = Op->Asl.Child;
    Child2 = Child1->Asl.Next;

    /*
     * Special case for DIVIDE -- it has two targets. The first
     * is for the remainder and if present, we will not attempt
     * to reduce the expression.
     */
    if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE)
    {
        Child2 = Child2->Asl.Next;
        if (Child2->Asl.ParseOpcode != PARSEOP_ZERO)
        {
            DbgPrint (ASL_PARSE_OUTPUT,
                "Cannot reduce DIVIDE - has two targets\n\n");
            return (AE_OK);
        }
    }

    DbgPrint (ASL_PARSE_OUTPUT,
        "Reduction/Transform to StoreOp: Store(%s, %s)\n",
        Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);

    /*
     * Create a NULL (zero) target so that we can use the
     * interpreter to evaluate the expression.
     */
    NewTarget = TrCreateNullTarget ();
    NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP;

    /* Handle one-operand cases (NOT, TOBCD, etc.) */

    if (!Child2->Asl.Next)
    {
        Child2 = Child1;
    }

    /* Link in new NULL target as the last operand */

    OriginalTarget = Child2->Asl.Next;
    Child2->Asl.Next = NewTarget;
    NewTarget->Asl.Parent = OriginalTarget->Asl.Parent;

    NewParent = TrAllocateNode (PARSEOP_INTEGER);
    NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;

    OriginalParent = Op->Common.Parent;
    Op->Common.Parent = NewParent;

    /* Hand off the subtree to the AML interpreter */

    WalkState->CallerReturnDesc = &ObjDesc;

    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
        OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
    if (ACPI_FAILURE (Status))
    {
        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant Subtree evaluation(3), %s\n",
            AcpiFormatException (Status));
        goto EvalError;
    }

    /* Get the final result */

    Status = AcpiDsResultPop (&ObjDesc, WalkState);
    if (ACPI_FAILURE (Status))
    {
        DbgPrint (ASL_PARSE_OUTPUT,
            "Constant Subtree evaluation(4), %s\n",
            AcpiFormatException (Status));
        goto EvalError;
    }

    /* Truncate any subtree expressions, they have been evaluated */

    Child1->Asl.Child = NULL;

    /* Folded constant is in ObjDesc, store into Child1 */

    TrInstallReducedConstant (Child1, ObjDesc);

    /* Convert operator to STORE */

    Op->Asl.ParseOpcode = PARSEOP_STORE;
    Op->Asl.AmlOpcode = AML_STORE_OP;
    UtSetParseOpName (Op);
    Op->Common.Parent = OriginalParent;

    /* First child is the folded constant */

    /* Second child will be the target */

    Child1->Asl.Next = OriginalTarget;
    return (AE_OK);


EvalError:

    /* Restore original links */

    Op->Common.Parent = OriginalParent;
    Child2->Asl.Next = OriginalTarget;
    return (Status);
}
Example #20
0
ACPI_PARSE_OBJECT *
TrUpdateNode (
    UINT32                  ParseOpcode,
    ACPI_PARSE_OBJECT       *Op)
{

    if (!Op)
    {
        return (NULL);
    }

    DbgPrint (ASL_PARSE_OUTPUT,
        "\nUpdateNode: Old - %s, New - %s\n\n",
        UtGetOpName (Op->Asl.ParseOpcode),
        UtGetOpName (ParseOpcode));

    /* Assign new opcode and name */

    if (Op->Asl.ParseOpcode == PARSEOP_ONES)
    {
        switch (ParseOpcode)
        {
        case PARSEOP_BYTECONST:

            Op->Asl.Value.Integer = ACPI_UINT8_MAX;
            break;

        case PARSEOP_WORDCONST:

            Op->Asl.Value.Integer = ACPI_UINT16_MAX;
            break;

        case PARSEOP_DWORDCONST:

            Op->Asl.Value.Integer = ACPI_UINT32_MAX;
            break;

        /* Don't need to do the QWORD case */

        default:

            /* Don't care about others */
            break;
        }
    }

    Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
    UtSetParseOpName (Op);

    /*
     * For the BYTE, WORD, and DWORD constants, make sure that the integer
     * that was passed in will actually fit into the data type
     */
    switch (ParseOpcode)
    {
    case PARSEOP_BYTECONST:

        UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
        Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
        break;

    case PARSEOP_WORDCONST:

        UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
        Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
        break;

    case PARSEOP_DWORDCONST:

        UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
        Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
        break;

    default:

        /* Don't care about others, don't need to check QWORD */

        break;
    }

    return (Op);
}
Example #21
0
static void
OpcDoPld (
    ACPI_PARSE_OBJECT       *Op)
{
    UINT8                   *Buffer;
    ACPI_PARSE_OBJECT       *Node;
    ACPI_PLD_INFO           PldInfo;
    ACPI_PARSE_OBJECT       *NewOp;


    if (!Op)
    {
        AslError(ASL_ERROR, ASL_MSG_NOT_EXIST, Op, NULL);
        return;
    }

    if (Op->Asl.ParseOpcode != PARSEOP_TOPLD)
    {
        AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Op, NULL);
        return;
    }

    Buffer = UtLocalCalloc (ACPI_PLD_BUFFER_SIZE);
    if (!Buffer)
    {
        AslError(ASL_ERROR, ASL_MSG_BUFFER_ALLOCATION, Op, NULL);
        return;
    }

    ACPI_MEMSET (&PldInfo, 0, sizeof (ACPI_PLD_INFO));

    Node = Op->Asl.Child;
    while (Node)
    {
        switch (Node->Asl.ParseOpcode)
        {
        case PARSEOP_PLD_REVISION:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 127)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            PldInfo.Revision = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_IGNORECOLOR:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 1)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            PldInfo.IgnoreColor = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_RED:
        case PARSEOP_PLD_GREEN:
        case PARSEOP_PLD_BLUE:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 255)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            if (Node->Asl.ParseOpcode == PARSEOP_PLD_RED)
            {
                PldInfo.Red = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            else if (Node->Asl.ParseOpcode == PARSEOP_PLD_GREEN)
            {
                PldInfo.Green = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            else /* PARSEOP_PLD_BLUE */
            {
                PldInfo.Blue = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            break;

        case PARSEOP_PLD_WIDTH:
        case PARSEOP_PLD_HEIGHT:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 65535)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            if (Node->Asl.ParseOpcode == PARSEOP_PLD_WIDTH)
            {
                PldInfo.Width = (UINT16) Node->Asl.Child->Asl.Value.Integer;
            }
            else /* PARSEOP_PLD_HEIGHT */
            {
                PldInfo.Height = (UINT16) Node->Asl.Child->Asl.Value.Integer;
            }

            break;

        case PARSEOP_PLD_USERVISIBLE:
        case PARSEOP_PLD_DOCK:
        case PARSEOP_PLD_LID:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 1)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            if (Node->Asl.ParseOpcode == PARSEOP_PLD_USERVISIBLE)
            {
                PldInfo.UserVisible = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            else if (Node->Asl.ParseOpcode == PARSEOP_PLD_DOCK)
            {
                PldInfo.Dock = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            else
            {
                PldInfo.Lid = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }

            break;

        case PARSEOP_PLD_PANEL:

            if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
            {
                if (Node->Asl.Child->Asl.Value.Integer > 6)
                {
                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                    break;
                }
            }
            else /* PARSEOP_STRING */
            {
                if (!OpcFindName(AslPldPanelList,
                    Node->Asl.Child->Asl.Value.String,
                    &Node->Asl.Child->Asl.Value.Integer))
                {
                    AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
                    break;
                }
            }

            PldInfo.Panel = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_VERTICALPOSITION:

            if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
            {
                if (Node->Asl.Child->Asl.Value.Integer > 2)
                {
                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                    break;
                }
            }
            else /* PARSEOP_STRING */
            {
                if (!OpcFindName(AslPldVerticalPositionList,
                    Node->Asl.Child->Asl.Value.String,
                    &Node->Asl.Child->Asl.Value.Integer))
                {
                    AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
                    break;
                }
            }

            PldInfo.VerticalPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_HORIZONTALPOSITION:

            if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
            {
                if (Node->Asl.Child->Asl.Value.Integer > 2)
                {
                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                    break;
                }
            }
            else /* PARSEOP_STRING */
            {
                if (!OpcFindName(AslPldHorizontalPositionList,
                    Node->Asl.Child->Asl.Value.String,
                    &Node->Asl.Child->Asl.Value.Integer))
                {
                    AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
                    break;
                }
            }

            PldInfo.HorizontalPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_SHAPE:

            if (Node->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER)
            {
                if (Node->Asl.Child->Asl.Value.Integer > 8)
                {
                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                    break;
                }
            }
            else /* PARSEOP_STRING */
            {
                if (!OpcFindName(AslPldShapeList,
                    Node->Asl.Child->Asl.Value.String,
                    &Node->Asl.Child->Asl.Value.Integer))
                {
                    AslError(ASL_ERROR, ASL_MSG_INVALID_OPERAND, Node, NULL);
                    break;
                }
            }

            PldInfo.Shape = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_GROUPORIENTATION:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 1)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            PldInfo.GroupOrientation = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_GROUPTOKEN:
        case PARSEOP_PLD_GROUPPOSITION:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 255)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }


            if (Node->Asl.ParseOpcode == PARSEOP_PLD_GROUPTOKEN)
            {
                PldInfo.GroupToken = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            else /* PARSEOP_PLD_GROUPPOSITION */
            {
                PldInfo.GroupPosition = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }

            break;

        case PARSEOP_PLD_BAY:
        case PARSEOP_PLD_EJECTABLE:
        case PARSEOP_PLD_EJECTREQUIRED:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 1)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            if (Node->Asl.ParseOpcode == PARSEOP_PLD_BAY)
            {
                PldInfo.Bay = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            else if (Node->Asl.ParseOpcode == PARSEOP_PLD_EJECTABLE)
            {
                PldInfo.Ejectable = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            else /* PARSEOP_PLD_EJECTREQUIRED */
            {
                PldInfo.OspmEjectRequired = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }

            break;

        case PARSEOP_PLD_CABINETNUMBER:
        case PARSEOP_PLD_CARDCAGENUMBER:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 255)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            if (Node->Asl.ParseOpcode == PARSEOP_PLD_CABINETNUMBER)
            {
                PldInfo.CabinetNumber = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }
            else /* PARSEOP_PLD_CARDCAGENUMBER */
            {
                PldInfo.CardCageNumber = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            }

            break;

        case PARSEOP_PLD_REFERENCE:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 1)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            PldInfo.Reference = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_ROTATION:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 7)
            {
                switch (Node->Asl.Child->Asl.Value.Integer)
                {
                case 45:

                    Node->Asl.Child->Asl.Value.Integer = 1;
                    break;

                case 90:

                    Node->Asl.Child->Asl.Value.Integer = 2;
                    break;

                case 135:

                    Node->Asl.Child->Asl.Value.Integer = 3;
                    break;

                case 180:

                    Node->Asl.Child->Asl.Value.Integer = 4;
                    break;

                case 225:

                    Node->Asl.Child->Asl.Value.Integer = 5;
                    break;

                case 270:

                    Node->Asl.Child->Asl.Value.Integer = 6;
                    break;

                case 315:

                    Node->Asl.Child->Asl.Value.Integer = 7;
                    break;

                default:

                    AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                    break;
                }
            }

            PldInfo.Rotation = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_ORDER:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 31)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            PldInfo.Order = (UINT8) Node->Asl.Child->Asl.Value.Integer;
            break;

        case PARSEOP_PLD_VERTICALOFFSET:
        case PARSEOP_PLD_HORIZONTALOFFSET:

            if (Node->Asl.Child->Asl.ParseOpcode != PARSEOP_INTEGER)
            {
                AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
                break;
            }

            if (Node->Asl.Child->Asl.Value.Integer > 65535)
            {
                AslError(ASL_ERROR, ASL_MSG_RANGE, Node, NULL);
                break;
            }

            if (Node->Asl.ParseOpcode == PARSEOP_PLD_VERTICALOFFSET)
            {
                PldInfo.VerticalOffset = (UINT16) Node->Asl.Child->Asl.Value.Integer;
            }
            else /* PARSEOP_PLD_HORIZONTALOFFSET */
            {
                PldInfo.HorizontalOffset = (UINT16) Node->Asl.Child->Asl.Value.Integer;
            }

            break;

        default:

            AslError(ASL_ERROR, ASL_MSG_INVALID_TYPE, Node, NULL);
            break;
        }

        Node = Node->Asl.Next;
    }

    Buffer = OpcEncodePldBuffer(&PldInfo);

    /* Change Op to a Buffer */

    Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    Op->Common.AmlOpcode = AML_BUFFER_OP;

    /* Disable further optimization */

    Op->Asl.CompileFlags &= ~NODE_COMPILE_TIME_CONST;
    UtSetParseOpName (Op);

    /* Child node is the buffer length */

    NewOp = TrAllocateNode (PARSEOP_INTEGER);

    NewOp->Asl.AmlOpcode     = AML_BYTE_OP;
    NewOp->Asl.Value.Integer = 20;
    NewOp->Asl.Parent        = Op;

    Op->Asl.Child = NewOp;
    Op = NewOp;

    /* Peer to the child is the raw buffer data */

    NewOp = TrAllocateNode (PARSEOP_RAW_DATA);
    NewOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
    NewOp->Asl.AmlLength     = 20;
    NewOp->Asl.Value.String  = ACPI_CAST_PTR (char, Buffer);
    NewOp->Asl.Parent        = Op->Asl.Parent;

    Op->Asl.Next = NewOp;
}
Example #22
0
ACPI_STATUS
OpcAmlConstantWalk (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_WALK_STATE         *WalkState;
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PARSE_OBJECT       *RootOp;
    ACPI_PARSE_OBJECT       *OriginalParentOp;
    UINT8                   WalkType;


    /*
     * Only interested in subtrees that could possibly contain
     * expressions that can be evaluated at this time
     */
    if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) ||
          (Op->Asl.CompileFlags & NODE_IS_TARGET))
    {
        return (AE_OK);
    }

    /* Set the walk type based on the reduction used for this op */

    if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
    {
        /* Op is a TermArg, constant folding is merely optional */

        if (!Gbl_FoldConstants)
        {
            return (AE_CTRL_DEPTH);
        }

        WalkType = ACPI_WALK_CONST_OPTIONAL;
    }
    else
    {
        /* Op is a DataObject, the expression MUST reduced to a constant */

        WalkType = ACPI_WALK_CONST_REQUIRED;
    }

    /* Create a new walk state */

    WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
    if (!WalkState)
    {
        return AE_NO_MEMORY;
    }

    WalkState->NextOp = NULL;
    WalkState->Params = NULL;
    WalkState->WalkType = WalkType;
    WalkState->CallerReturnDesc = &ObjDesc;

    /*
     * Examine the entire subtree -- all nodes must be constants
     * or type 3/4/5 opcodes
     */
    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
        OpcAmlCheckForConstant, NULL, WalkState);

    /*
     * Did we find an entire subtree that contains all constants and type 3/4/5
     * opcodes?  (Only AE_OK or AE_TYPE returned from above)
     */
    if (Status == AE_TYPE)
    {
        /* Subtree cannot be reduced to a constant */

        if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL)
        {
            AcpiDsDeleteWalkState (WalkState);
            return (AE_OK);
        }

        /* Don't descend any further, and use a default "constant" value */

        Status = AE_CTRL_DEPTH;
    }
    else
    {
        /* Subtree can be reduced */

        /* Allocate a new temporary root for this subtree */

        RootOp = TrAllocateNode (PARSEOP_INTEGER);
        if (!RootOp)
        {
            return (AE_NO_MEMORY);
        }

        RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;

        OriginalParentOp = Op->Common.Parent;
        Op->Common.Parent = RootOp;

        /* Hand off the subtree to the AML interpreter */

        Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
            OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
        Op->Common.Parent = OriginalParentOp;

        /* TBD: we really *should* release the RootOp node */

        if (ACPI_SUCCESS (Status))
        {
            TotalFolds++;

            /* Get the final result */

            Status = AcpiDsResultPop (&ObjDesc, WalkState);
        }

        /* Check for error from the ACPICA core */

        if (ACPI_FAILURE (Status))
        {
            AslCoreSubsystemError (Op, Status,
                "Failure during constant evaluation", FALSE);
        }
    }

    if (ACPI_FAILURE (Status))
    {
        /* We could not resolve the subtree for some reason */

        AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
            Op->Asl.ParseOpName);

        /* Set the subtree value to ZERO anyway. Eliminates further errors */

        OpcUpdateIntegerNode (Op, 0);
    }
    else
    {
        AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
            Op->Asl.ParseOpName);

        /*
         * Because we know we executed type 3/4/5 opcodes above, we know that
         * the result must be either an Integer, String, or Buffer.
         */
        switch (ObjDesc->Common.Type)
        {
        case ACPI_TYPE_INTEGER:

            OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);

            DbgPrint (ASL_PARSE_OUTPUT,
                "Constant expression reduced to (%s) %8.8X%8.8X\n",
                Op->Asl.ParseOpName,
                ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
            break;


        case ACPI_TYPE_STRING:

            Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
            Op->Common.AmlOpcode = AML_STRING_OP;
            Op->Asl.AmlLength = ACPI_STRLEN (ObjDesc->String.Pointer) + 1;
            Op->Common.Value.String = ObjDesc->String.Pointer;

            DbgPrint (ASL_PARSE_OUTPUT,
                "Constant expression reduced to (STRING) %s\n",
                Op->Common.Value.String);

            break;


        case ACPI_TYPE_BUFFER:

            Op->Asl.ParseOpcode = PARSEOP_BUFFER;
            Op->Common.AmlOpcode = AML_BUFFER_OP;
            Op->Asl.CompileFlags = NODE_AML_PACKAGE;
            UtSetParseOpName (Op);

            /* Child node is the buffer length */

            RootOp = TrAllocateNode (PARSEOP_INTEGER);

            RootOp->Asl.AmlOpcode = AML_DWORD_OP;
            RootOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
            RootOp->Asl.Parent = Op;

            (void) OpcSetOptimalIntegerSize (RootOp);

            Op->Asl.Child = RootOp;
            Op = RootOp;
            UtSetParseOpName (Op);

            /* Peer to the child is the raw buffer data */

            RootOp = TrAllocateNode (PARSEOP_RAW_DATA);
            RootOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
            RootOp->Asl.AmlLength = ObjDesc->Buffer.Length;
            RootOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
            RootOp->Asl.Parent = Op->Asl.Parent;

            Op->Asl.Next = RootOp;
            Op = RootOp;

            DbgPrint (ASL_PARSE_OUTPUT,
                "Constant expression reduced to (BUFFER) length %X\n",
                ObjDesc->Buffer.Length);
            break;


        default:
            printf ("Unsupported return type: %s\n",
                AcpiUtGetObjectTypeName (ObjDesc));
            break;
        }
    }

    UtSetParseOpName (Op);
    Op->Asl.Child = NULL;

    AcpiDsDeleteWalkState (WalkState);
    return (AE_CTRL_DEPTH);
}
Example #23
0
static void
ExMoveExternals (
    ACPI_PARSE_OBJECT       *DefinitionBlockOp)
{
    ACPI_PARSE_OBJECT       *ParentOp;
    ACPI_PARSE_OBJECT       *ExternalOp;
    ACPI_PARSE_OBJECT       *PredicateOp;
    ACPI_PARSE_OBJECT       *NextOp;
    ACPI_PARSE_OBJECT       *Prev;
    ACPI_PARSE_OBJECT       *Next;
    ACPI_OBJECT_TYPE        ObjType;
    UINT32                  i;


    if (!Gbl_ExternalsListHead)
    {
        return;
    }

    /* Remove the External nodes from the tree */

    NextOp = Gbl_ExternalsListHead;
    while (NextOp)
    {
        /*
         * The External is stored in child pointer of each node in the
         * list
         */
        ExternalOp = NextOp->Asl.Child;

        /* Set line numbers (for listings, etc.) */

        ExternalOp->Asl.LineNumber = 0;
        ExternalOp->Asl.LogicalLineNumber = 0;

        Next = ExternalOp->Asl.Child;
        Next->Asl.LineNumber = 0;
        Next->Asl.LogicalLineNumber = 0;

        Next = Next->Asl.Next;
        Next->Asl.LineNumber = 0;
        Next->Asl.LogicalLineNumber = 0;

        Next = Next->Asl.Next;
        Next->Asl.LineNumber = 0;
        Next->Asl.LogicalLineNumber = 0;

        Next = Next->Asl.Next;
        Next->Asl.LineNumber = 0;
        Next->Asl.LogicalLineNumber = 0;

        ParentOp = ExternalOp->Asl.Parent;
        Prev = Next = ParentOp->Asl.Child;

        /* Now find the External node's position in parse tree */

        while (Next != ExternalOp)
        {
            Prev = Next;
            Next = Next->Asl.Next;
        }

        /* Remove the External from the parse tree */

        if (Prev == ExternalOp)
        {
            /* External was the first child node */

            ParentOp->Asl.Child = ExternalOp->Asl.Next;
        }

        Prev->Asl.Next = ExternalOp->Asl.Next;
        ExternalOp->Asl.Next = NULL;
        ExternalOp->Asl.Parent = Gbl_ExternalsListHead;

        /* Point the External to the next in the list */

        if (NextOp->Asl.Next)
        {
            ExternalOp->Asl.Next = NextOp->Asl.Next->Asl.Child;
        }

        NextOp = NextOp->Asl.Next;
    }

    /*
     * Loop again to remove MethodObj Externals for which
     * a MethodCall was not found (dead external reference)
     */
    Prev = Gbl_ExternalsListHead->Asl.Child;
    Next = Prev;
    while (Next)
    {
        ObjType = (ACPI_OBJECT_TYPE)
            Next->Asl.Child->Asl.Next->Asl.Value.Integer;

        if (ObjType == ACPI_TYPE_METHOD &&
            !(Next->Asl.CompileFlags & NODE_VISITED))
        {
            if (Next == Prev)
            {
                Gbl_ExternalsListHead->Asl.Child = Next->Asl.Next;
                Next->Asl.Next = NULL;
                Prev = Gbl_ExternalsListHead->Asl.Child;
                Next = Prev;
                continue;
            }
            else
            {
                Prev->Asl.Next = Next->Asl.Next;
                Next->Asl.Next = NULL;
                Next = Prev->Asl.Next;
                continue;
            }
        }

        Prev = Next;
        Next = Next->Asl.Next;
    }

    /* If list is now empty, don't bother to make If (0) block */

    if (!Gbl_ExternalsListHead->Asl.Child)
    {
        return;
    }

    /* Convert Gbl_ExternalsListHead parent to If(). */

    Gbl_ExternalsListHead->Asl.ParseOpcode = PARSEOP_IF;
    Gbl_ExternalsListHead->Asl.AmlOpcode = AML_IF_OP;
    Gbl_ExternalsListHead->Asl.CompileFlags = NODE_AML_PACKAGE;
    UtSetParseOpName (Gbl_ExternalsListHead);

    /* Create a Zero op for the If predicate */

    PredicateOp = TrAllocateNode (PARSEOP_ZERO);
    PredicateOp->Asl.AmlOpcode = AML_ZERO_OP;

    PredicateOp->Asl.Parent = Gbl_ExternalsListHead;
    PredicateOp->Asl.Child = NULL;
    PredicateOp->Asl.Next = Gbl_ExternalsListHead->Asl.Child;
    Gbl_ExternalsListHead->Asl.Child = PredicateOp;

    /* Set line numbers (for listings, etc.) */

    Gbl_ExternalsListHead->Asl.LineNumber = 0;
    Gbl_ExternalsListHead->Asl.LogicalLineNumber = 0;

    PredicateOp->Asl.LineNumber = 0;
    PredicateOp->Asl.LogicalLineNumber = 0;

    /* Insert block back in the list */

    Prev = DefinitionBlockOp->Asl.Child;
    Next = Prev;

    /* Find last default arg */

    for (i = 0; i < 6; i++)
    {
        Prev = Next;
        Next = Prev->Asl.Next;
    }

    if (Next)
    {
        /* Definition Block is not empty */

        Gbl_ExternalsListHead->Asl.Next = Next;
    }
    else
    {
        /* Definition Block is empty. */

        Gbl_ExternalsListHead->Asl.Next = NULL;
    }

    Prev->Asl.Next = Gbl_ExternalsListHead;
    Gbl_ExternalsListHead->Asl.Parent = Prev->Asl.Parent;
}