Пример #1
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;
}
Пример #2
0
ACPI_PARSE_OBJECT *
TrCreateValuedLeafNode (
    UINT32                  ParseOpcode,
    UINT64                  Value)
{
    ACPI_PARSE_OBJECT       *Op;


    Op = TrAllocateNode (ParseOpcode);

    DbgPrint (ASL_PARSE_OUTPUT,
              "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  "
              "Op %s  Value %8.8X%8.8X  ",
              Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
              ACPI_FORMAT_UINT64 (Value));
    Op->Asl.Value.Integer = Value;

    switch (ParseOpcode)
    {
    case PARSEOP_STRING_LITERAL:

        DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
        break;

    case PARSEOP_NAMESEG:

        DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
        break;

    case PARSEOP_NAMESTRING:

        DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
        break;

    case PARSEOP_EISAID:

        DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
        break;

    case PARSEOP_METHOD:

        DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
        break;

    case PARSEOP_INTEGER:

        DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
                  ACPI_FORMAT_UINT64 (Value));
        break;

    default:

        break;
    }

    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    return (Op);
}
Пример #3
0
static void
OpcCreateConcatenateNode (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_PARSE_OBJECT       *Node)
{
    ACPI_PARSE_OBJECT       *NewConcatOp;


    if (!Op->Asl.Child)
    {
        Op->Asl.Child = Node;
        Node->Asl.Parent = Op;
        return;
    }

    NewConcatOp = TrAllocateNode (PARSEOP_CONCATENATE);
    NewConcatOp->Asl.AmlOpcode = AML_CONCAT_OP;
    NewConcatOp->Asl.AcpiBtype = 0x7;
    NewConcatOp->Asl.LogicalLineNumber = Op->Asl.LogicalLineNumber;

    /* First arg is child of Op*/

    NewConcatOp->Asl.Child = Op->Asl.Child;
    Op->Asl.Child->Asl.Parent = NewConcatOp;

    /* Second arg is Node */

    NewConcatOp->Asl.Child->Asl.Next = Node;
    Node->Asl.Parent = NewConcatOp;

    /* Third arg is Zero (not used) */

    NewConcatOp->Asl.Child->Asl.Next->Asl.Next =
        TrAllocateNode (PARSEOP_ZERO);
    NewConcatOp->Asl.Child->Asl.Next->Asl.Next->Asl.Parent =
        NewConcatOp;

    Op->Asl.Child = NewConcatOp;
    NewConcatOp->Asl.Parent = Op;
}
Пример #4
0
ACPI_PARSE_OBJECT *
TrLinkPeerNodes (
    UINT32                  NumPeers,
    ...)
{
    ACPI_PARSE_OBJECT       *This;
    ACPI_PARSE_OBJECT       *Next;
    va_list                 ap;
    UINT32                  i;
    ACPI_PARSE_OBJECT       *Start;


    DbgPrint (ASL_PARSE_OUTPUT,
        "\nLinkPeerNodes: (%u) ", NumPeers);

    va_start (ap, NumPeers);
    This = va_arg (ap, ACPI_PARSE_OBJECT *);
    Start = This;

    /*
     * Link all peers
     */
    for (i = 0; i < (NumPeers -1); i++)
    {
        DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);

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

        /* Get another peer node */

        Next = va_arg (ap, ACPI_PARSE_OBJECT *);
        if (!Next)
        {
            Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
        }

        /* link new node to the current node */

        This->Asl.Next = Next;
        This = Next;
    }
    va_end (ap);

    DbgPrint (ASL_PARSE_OUTPUT,"\n\n");
    return (Start);
}
Пример #5
0
ACPI_PARSE_OBJECT *
TrCreateLeafNode (
    UINT32                  ParseOpcode)
{
    ACPI_PARSE_OBJECT       *Op;


    Op = TrAllocateNode (ParseOpcode);

    DbgPrint (ASL_PARSE_OUTPUT,
        "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
        Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode));

    return (Op);
}
Пример #6
0
void
OpcDoPrintf (
    ACPI_PARSE_OBJECT       *Op)
{
    ACPI_PARSE_OBJECT       *DestOp;


    /* Store destination is the Debug op */

    DestOp = TrAllocateNode (PARSEOP_DEBUG);
    DestOp->Asl.AmlOpcode = AML_DEBUG_OP;
    DestOp->Asl.Parent = Op;

    OpcParsePrintf (Op, DestOp);
}
Пример #7
0
ACPI_PARSE_OBJECT *
TrCreateNullTarget (
    void)
{
    ACPI_PARSE_OBJECT       *Op;


    Op = TrAllocateNode (PARSEOP_ZERO);
    Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);

    DbgPrint (ASL_PARSE_OUTPUT,
        "\nCreateNullTarget  Ln/Col %u/%u NewNode %p  Op %s\n",
        Op->Asl.LineNumber, Op->Asl.Column, Op,
        UtGetOpName (Op->Asl.ParseOpcode));

    return (Op);
}
Пример #8
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 = TrAllocateNode (PARSEOP_DEFAULT_ARG);

    /* Store External node as child */

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

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

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

        Prev->Asl.Next = ListOp;
    }
    else
    {
        Gbl_ExternalsListHead = ListOp;
    }
}
Пример #9
0
ACPI_PARSE_OBJECT *
TrLinkChildren (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  NumChildren,
    ...)
{
    ACPI_PARSE_OBJECT       *Child;
    ACPI_PARSE_OBJECT       *PrevChild;
    va_list                 ap;
    UINT32                  i;
    BOOLEAN                 FirstChild;


    va_start (ap, NumChildren);


    TrSetEndLineNumber (Op);

    DbgPrint (ASL_PARSE_OUTPUT,
        "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
        Op->Asl.LineNumber, Op->Asl.EndLine,
        Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));

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

        RootNode = Op;
        DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
        break;

    case PARSEOP_OPERATIONREGION:

        DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
        break;

    case PARSEOP_OR:

        DbgPrint (ASL_PARSE_OUTPUT, "OR->");
        break;

    default:

        /* Nothing to do for other opcodes */

        break;
    }

    /* Link the new node to it's children */

    PrevChild = NULL;
    FirstChild = TRUE;
    for (i = 0; i < NumChildren; i++)
    {
        Child = va_arg (ap, ACPI_PARSE_OBJECT *);

        if ((Child == PrevChild) && (Child != NULL))
        {
            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
                "Child node list invalid");
            va_end(ap);
            return (Op);
        }

        DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);

        /*
         * If child is NULL, this means that an optional argument
         * was omitted. We must create a placeholder with a special
         * opcode (DEFAULT_ARG) so that the code generator will know
         * that it must emit the correct default for this argument
         */
        if (!Child)
        {
            Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
        }

        /* Link first child to parent */

        if (FirstChild)
        {
            FirstChild = FALSE;
            Op->Asl.Child = Child;
        }

        /* Point all children to parent */

        Child->Asl.Parent = Op;

        /* Link children in a peer list */

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

        /*
         * This child might be a list, point all nodes in the list
         * to the same parent
         */
        while (Child->Asl.Next)
        {
            Child = Child->Asl.Next;
            Child->Asl.Parent = Op;
        }
        PrevChild = Child;
    }

    va_end(ap);
    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    return (Op);
}
Пример #10
0
ACPI_PARSE_OBJECT *
TrCreateNode (
    UINT32                  ParseOpcode,
    UINT32                  NumChildren,
    ...)
{
    ACPI_PARSE_OBJECT       *Op;
    ACPI_PARSE_OBJECT       *Child;
    ACPI_PARSE_OBJECT       *PrevChild;
    va_list                 ap;
    UINT32                  i;
    BOOLEAN                 FirstChild;


    va_start (ap, NumChildren);

    /* Allocate one new node */

    Op = TrAllocateNode (ParseOpcode);

    DbgPrint (ASL_PARSE_OUTPUT,
        "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
        Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode));

    /* Some extra debug output based on the parse opcode */

    switch (ParseOpcode)
    {
    case PARSEOP_DEFINITIONBLOCK:

        RootNode = Op;
        DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
        break;

    case PARSEOP_OPERATIONREGION:

        DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
        break;

    case PARSEOP_OR:

        DbgPrint (ASL_PARSE_OUTPUT, "OR->");
        break;

    default:

        /* Nothing to do for other opcodes */

        break;
    }

    /* Link the new node to its children */

    PrevChild = NULL;
    FirstChild = TRUE;
    for (i = 0; i < NumChildren; i++)
    {
        /* Get the next child */

        Child = va_arg (ap, ACPI_PARSE_OBJECT *);
        DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);

        /*
         * If child is NULL, this means that an optional argument
         * was omitted. We must create a placeholder with a special
         * opcode (DEFAULT_ARG) so that the code generator will know
         * that it must emit the correct default for this argument
         */
        if (!Child)
        {
            Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
        }

        /* Link first child to parent */

        if (FirstChild)
        {
            FirstChild = FALSE;
            Op->Asl.Child = Child;
        }

        /* Point all children to parent */

        Child->Asl.Parent = Op;

        /* Link children in a peer list */

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

        /*
         * This child might be a list, point all nodes in the list
         * to the same parent
         */
        while (Child->Asl.Next)
        {
            Child = Child->Asl.Next;
            Child->Asl.Parent = Op;
        }

        PrevChild = Child;
    }
    va_end(ap);

    DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
    return (Op);
}
Пример #11
0
ACPI_PARSE_OBJECT *
TrCreateConstantLeafNode (
    UINT32                  ParseOpcode)
{
    ACPI_PARSE_OBJECT       *Op = NULL;
    time_t                  CurrentTime;
    char                    *StaticTimeString;
    char                    *TimeString;
    char                    *Path;
    char                    *Filename;


    switch (ParseOpcode)
    {
    case PARSEOP___LINE__:

        Op = TrAllocateNode (PARSEOP_INTEGER);
        Op->Asl.Value.Integer = Op->Asl.LineNumber;
        break;

    case PARSEOP___PATH__:

        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);

        /* Op.Asl.Filename contains the full pathname to the file */

        Op->Asl.Value.String = Op->Asl.Filename;
        break;

    case PARSEOP___FILE__:

        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);

        /* Get the simple filename from the full path */

        FlSplitInputPathname (Op->Asl.Filename, &Path, &Filename);
        ACPI_FREE (Path);
        Op->Asl.Value.String = Filename;
        break;

    case PARSEOP___DATE__:

        Op = TrAllocateNode (PARSEOP_STRING_LITERAL);

        /* Get a copy of the current time */

        CurrentTime = time (NULL);
        StaticTimeString = ctime (&CurrentTime);
        TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
        strcpy (TimeString, StaticTimeString);

        TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
        Op->Asl.Value.String = TimeString;
        break;

    default: /* This would be an internal error */

        return (NULL);
    }

    DbgPrint (ASL_PARSE_OUTPUT,
        "\nCreateConstantLeafNode  Ln/Col %u/%u NewNode %p  Op %s  Value %8.8X%8.8X  ",
        Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
        ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
    return (Op);
}
Пример #12
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;
    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;

        /* 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;
        UtInternalizeName (ExternalName, &Next->Asl.Value.String);
        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 = 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;
}
Пример #13
0
ACPI_PARSE_OBJECT *
TrCreateAssignmentNode (
    ACPI_PARSE_OBJECT       *Target,
    ACPI_PARSE_OBJECT       *Source)
{
    ACPI_PARSE_OBJECT       *TargetOp;
    ACPI_PARSE_OBJECT       *SourceOp1;
    ACPI_PARSE_OBJECT       *SourceOp2;
    ACPI_PARSE_OBJECT       *Operator;


    DbgPrint (ASL_PARSE_OUTPUT,
        "\nTrCreateAssignmentNode  Line [%u to %u] Source %s Target %s\n",
        Source->Asl.LineNumber, Source->Asl.EndLine,
        UtGetOpName (Source->Asl.ParseOpcode),
        UtGetOpName (Target->Asl.ParseOpcode));

    TrSetNodeFlags (Target, NODE_IS_TARGET);

    switch (Source->Asl.ParseOpcode)
    {
    /*
     * Only these operators can be optimized because they have
     * a target operand
     */
    case PARSEOP_ADD:
    case PARSEOP_AND:
    case PARSEOP_DIVIDE:
    case PARSEOP_MOD:
    case PARSEOP_MULTIPLY:
    case PARSEOP_NOT:
    case PARSEOP_OR:
    case PARSEOP_SHIFTLEFT:
    case PARSEOP_SHIFTRIGHT:
    case PARSEOP_SUBTRACT:
    case PARSEOP_XOR:

        break;

    /* Otherwise, just create a normal Store operator */

    default:

        goto CannotOptimize;
    }

    /*
     * Transform the parse tree such that the target is moved to the
     * last operand of the operator
     */
    SourceOp1 = Source->Asl.Child;
    SourceOp2 = SourceOp1->Asl.Next;

    /* NOT only has one operand, but has a target */

    if (Source->Asl.ParseOpcode == PARSEOP_NOT)
    {
        SourceOp2 = SourceOp1;
    }

    /* DIVIDE has an extra target operand (remainder) */

    if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
    {
        SourceOp2 = SourceOp2->Asl.Next;
    }

    TargetOp = SourceOp2->Asl.Next;

    /*
     * Can't perform this optimization if there already is a target
     * for the operator (ZERO is a "no target" placeholder).
     */
    if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
    {
        goto CannotOptimize;
    }

    /* Link in the target as the final operand */

    SourceOp2->Asl.Next = Target;
    Target->Asl.Parent = Source;

    return (Source);


CannotOptimize:

    Operator = TrAllocateNode (PARSEOP_STORE);
    TrLinkChildren (Operator, 2, Source, Target);

    /* Set the appropriate line numbers for the new node */

    Operator->Asl.LineNumber        = Target->Asl.LineNumber;
    Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
    Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
    Operator->Asl.Column            = Target->Asl.Column;

    return (Operator);
}
Пример #14
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);
}
Пример #15
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;
}
Пример #16
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;
}
Пример #17
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;
    }
}
Пример #18
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);
}
Пример #19
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);
}
Пример #20
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;
}