aslwalks.c revision 229989
1172479Sedwin/******************************************************************************
2153761Swollman *
367578Swollman * Module Name: aslwalks.c - major analytical parse tree walks
42742Swollman *
52742Swollman *****************************************************************************/
62742Swollman
72742Swollman/*
8158421Swollman * Copyright (C) 2000 - 2012, Intel Corp.
92742Swollman * All rights reserved.
102742Swollman *
11158421Swollman * Redistribution and use in source and binary forms, with or without
12158421Swollman * modification, are permitted provided that the following conditions
132742Swollman * are met:
1486222Swollman * 1. Redistributions of source code must retain the above copyright
1520094Swollman *    notice, this list of conditions, and the following disclaimer,
1620094Swollman *    without modification.
1720094Swollman * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1820094Swollman *    substantially similar to the "NO WARRANTY" disclaimer below
1920094Swollman *    ("Disclaimer") and any redistribution must be conditioned upon
20158421Swollman *    including a substantially similar Disclaimer requirement for further
21158421Swollman *    binary redistribution.
2220094Swollman * 3. Neither the names of the above-listed copyright holders nor the names
232742Swollman *    of any contributors may be used to endorse or promote products derived
242742Swollman *    from this software without specific prior written permission.
252742Swollman *
262742Swollman * Alternatively, this software may be distributed under the terms of the
2714343Swollman * GNU General Public License ("GPL") version 2 as published by the Free
2858787Sru * Software Foundation.
2914343Swollman *
3030711Swollman * NO WARRANTY
3130711Swollman * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32149514Swollman * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3330711Swollman * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3430711Swollman * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3530711Swollman * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3630711Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3730711Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
382742Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3930711Swollman * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4030711Swollman * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4130711Swollman * POSSIBILITY OF SUCH DAMAGES.
4230711Swollman */
4330711Swollman
442742Swollman
4530711Swollman#include <contrib/dev/acpica/compiler/aslcompiler.h>
4630711Swollman#include "aslcompiler.y.h"
4730711Swollman#include <contrib/dev/acpica/include/acparser.h>
4830711Swollman#include <contrib/dev/acpica/include/amlcode.h>
4930711Swollman
5030711Swollman
5130711Swollman#define _COMPONENT          ACPI_COMPILER
5230711Swollman        ACPI_MODULE_NAME    ("aslwalks")
5330711Swollman
5430711Swollman
552742Swollman/*******************************************************************************
5630711Swollman *
5730711Swollman * FUNCTION:    AnMethodAnalysisWalkBegin
5830711Swollman *
5986222Swollman * PARAMETERS:  ASL_WALK_CALLBACK
6030711Swollman *
6130711Swollman * RETURN:      Status
622742Swollman *
6330711Swollman * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
642742Swollman *              1) Initialized local variables
652742Swollman *              2) Valid arguments
662742Swollman *              3) Return types
6719878Swollman *
68158421Swollman ******************************************************************************/
6919878Swollman
7019878SwollmanACPI_STATUS
7119878SwollmanAnMethodAnalysisWalkBegin (
7219878Swollman    ACPI_PARSE_OBJECT       *Op,
732742Swollman    UINT32                  Level,
7419878Swollman    void                    *Context)
752742Swollman{
7619878Swollman    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
772742Swollman    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
78158421Swollman    ACPI_PARSE_OBJECT       *Next;
792742Swollman    UINT32                  RegisterNumber;
802742Swollman    UINT32                  i;
8119878Swollman    char                    LocalName[] = "Local0";
822742Swollman    char                    ArgName[] = "Arg0";
8319878Swollman    ACPI_PARSE_OBJECT       *ArgNode;
842742Swollman    ACPI_PARSE_OBJECT       *NextType;
8519878Swollman    ACPI_PARSE_OBJECT       *NextParamType;
862742Swollman    UINT8                   ActualArgs = 0;
8719878Swollman
882742Swollman
89158421Swollman    switch (Op->Asl.ParseOpcode)
90158421Swollman    {
912742Swollman    case PARSEOP_METHOD:
922742Swollman
9314343Swollman        TotalMethods++;
9419878Swollman
9519878Swollman        /* Create and init method info */
962742Swollman
9719878Swollman        MethodInfo       = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
9819878Swollman        MethodInfo->Next = WalkInfo->MethodStack;
9919878Swollman        MethodInfo->Op = Op;
10019878Swollman
10119878Swollman        WalkInfo->MethodStack = MethodInfo;
1022742Swollman
1032742Swollman        /* Get the name node, ignored here */
1042742Swollman
1052742Swollman        Next = Op->Asl.Child;
10686222Swollman
10730711Swollman        /* Get the NumArguments node */
1082742Swollman
1092742Swollman        Next = Next->Asl.Next;
110158421Swollman        MethodInfo->NumArguments = (UINT8)
111158421Swollman            (((UINT8) Next->Asl.Value.Integer) & 0x07);
1122742Swollman
1132742Swollman        /* Get the SerializeRule and SyncLevel nodes, ignored here */
11430711Swollman
11530711Swollman        Next = Next->Asl.Next;
1162742Swollman        Next = Next->Asl.Next;
1172742Swollman        ArgNode = Next;
1182742Swollman
1192742Swollman        /* Get the ReturnType node */
12030711Swollman
12130711Swollman        Next = Next->Asl.Next;
12230711Swollman
1232742Swollman        NextType = Next->Asl.Child;
1242742Swollman        while (NextType)
1252742Swollman        {
1262742Swollman            /* Get and map each of the ReturnTypes */
12730711Swollman
1282742Swollman            MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
1292742Swollman            NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1302742Swollman            NextType = NextType->Asl.Next;
1312742Swollman        }
13230711Swollman
1332742Swollman        /* Get the ParameterType node */
1342742Swollman
135158421Swollman        Next = Next->Asl.Next;
1362742Swollman
1372742Swollman        NextType = Next->Asl.Child;
13830711Swollman        while (NextType)
1392742Swollman        {
1402742Swollman            if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
1412742Swollman            {
1422742Swollman                NextParamType = NextType->Asl.Child;
1432742Swollman                while (NextParamType)
1442742Swollman                {
1452742Swollman                    MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
14619878Swollman                    NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1472742Swollman                    NextParamType = NextParamType->Asl.Next;
1482742Swollman                }
1492742Swollman            }
1502742Swollman            else
15130711Swollman            {
1522742Swollman                MethodInfo->ValidArgTypes[ActualArgs] =
1532742Swollman                    AnMapObjTypeToBtype (NextType);
1542742Swollman                NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1552742Swollman                ActualArgs++;
15630711Swollman            }
15730711Swollman
15830711Swollman            NextType = NextType->Asl.Next;
1592742Swollman        }
1602742Swollman
1612742Swollman        if ((MethodInfo->NumArguments) &&
1622742Swollman            (MethodInfo->NumArguments != ActualArgs))
1632742Swollman        {
1642742Swollman            /* error: Param list did not match number of args */
16530711Swollman        }
1662742Swollman
16730711Swollman        /* Allow numarguments == 0 for Function() */
16830711Swollman
16930711Swollman        if ((!MethodInfo->NumArguments) && (ActualArgs))
17030711Swollman        {
17130711Swollman            MethodInfo->NumArguments = ActualArgs;
17230711Swollman            ArgNode->Asl.Value.Integer |= ActualArgs;
17330711Swollman        }
1742742Swollman
17530711Swollman        /*
1762742Swollman         * Actual arguments are initialized at method entry.
1772742Swollman         * All other ArgX "registers" can be used as locals, so we
1782742Swollman         * track their initialization.
1792742Swollman         */
18030711Swollman        for (i = 0; i < MethodInfo->NumArguments; i++)
1812742Swollman        {
1822742Swollman            MethodInfo->ArgInitialized[i] = TRUE;
1832742Swollman        }
1842742Swollman        break;
1852742Swollman
1862742Swollman
1872742Swollman    case PARSEOP_METHODCALL:
1882742Swollman
1892742Swollman        if (MethodInfo &&
1902742Swollman           (Op->Asl.Node == MethodInfo->Op->Asl.Node))
1912742Swollman        {
19219878Swollman            AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
1932742Swollman        }
19419878Swollman        break;
1952742Swollman
19619878Swollman
1972742Swollman    case PARSEOP_LOCAL0:
1982742Swollman    case PARSEOP_LOCAL1:
19919878Swollman    case PARSEOP_LOCAL2:
20019878Swollman    case PARSEOP_LOCAL3:
2012742Swollman    case PARSEOP_LOCAL4:
20219878Swollman    case PARSEOP_LOCAL5:
20319878Swollman    case PARSEOP_LOCAL6:
2042742Swollman    case PARSEOP_LOCAL7:
20530711Swollman
20619878Swollman        if (!MethodInfo)
20719878Swollman        {
20819878Swollman            /*
20919878Swollman             * Local was used outside a control method, or there was an error
21030711Swollman             * in the method declaration.
21143014Swollman             */
21243543Swollman            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
21358787Sru            return (AE_ERROR);
214163302Sru        }
215163302Sru
216163302Sru        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
217163302Sru
218163302Sru        /*
219163302Sru         * If the local is being used as a target, mark the local
220163302Sru         * initialized
221171948Sedwin         */
222171948Sedwin        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
223171948Sedwin        {
224171948Sedwin            MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
225171948Sedwin        }
226171948Sedwin
227172479Sedwin        /*
228172479Sedwin         * Otherwise, this is a reference, check if the local
229172479Sedwin         * has been previously initialized.
230172479Sedwin         *
231172479Sedwin         * The only operator that accepts an uninitialized value is ObjectType()
232172479Sedwin         */
233172479Sedwin        else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
234172479Sedwin                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
235172479Sedwin        {
236172479Sedwin            LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
237171948Sedwin            AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
238172479Sedwin        }
239172479Sedwin        break;
24020094Swollman
2412742Swollman
2422742Swollman    case PARSEOP_ARG0:
24319878Swollman    case PARSEOP_ARG1:
2442742Swollman    case PARSEOP_ARG2:
2452742Swollman    case PARSEOP_ARG3:
2462742Swollman    case PARSEOP_ARG4:
2472742Swollman    case PARSEOP_ARG5:
24830711Swollman    case PARSEOP_ARG6:
24930711Swollman
2502742Swollman        if (!MethodInfo)
2512742Swollman        {
2522742Swollman            /*
253169811Swollman             * Arg was used outside a control method, or there was an error
254169811Swollman             * in the method declaration.
25530711Swollman             */
2562742Swollman            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
2572742Swollman            return (AE_ERROR);
2582742Swollman        }
259158421Swollman
260158421Swollman        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
261158421Swollman        ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
26230711Swollman
2632742Swollman        /*
2642742Swollman         * If the Arg is being used as a target, mark the local
26530711Swollman         * initialized
2662742Swollman         */
2672742Swollman        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
2682742Swollman        {
2692742Swollman            MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
2702742Swollman        }
27130711Swollman
2722742Swollman        /*
2732742Swollman         * Otherwise, this is a reference, check if the Arg
2742742Swollman         * has been previously initialized.
2752742Swollman         *
27619878Swollman         * The only operator that accepts an uninitialized value is ObjectType()
27730711Swollman         */
27830711Swollman        else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
2792742Swollman                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
2802742Swollman        {
2812742Swollman            AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
282158421Swollman        }
283158421Swollman
28430711Swollman        /* Flag this arg if it is not a "real" argument to the method */
28530711Swollman
2862742Swollman        if (RegisterNumber >= MethodInfo->NumArguments)
2872742Swollman        {
2882742Swollman            AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
2892742Swollman        }
2902742Swollman        break;
2912742Swollman
2922742Swollman
29330711Swollman    case PARSEOP_RETURN:
29430711Swollman
29530711Swollman        if (!MethodInfo)
2962742Swollman        {
2972742Swollman            /*
2982742Swollman             * Probably was an error in the method declaration,
2992742Swollman             * no additional error here
30030711Swollman             */
30130711Swollman            ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
3022742Swollman            return (AE_ERROR);
3032742Swollman        }
3042742Swollman
3052742Swollman        /*
3062742Swollman         * A child indicates a possible return value. A simple Return or
30730711Swollman         * Return() is marked with NODE_IS_NULL_RETURN by the parser so
30886222Swollman         * that it is not counted as a "real" return-with-value, although
3092742Swollman         * the AML code that is actually emitted is Return(0). The AML
3102742Swollman         * definition of Return has a required parameter, so we are
3112742Swollman         * forced to convert a null return to Return(0).
3122742Swollman         */
3132742Swollman        if ((Op->Asl.Child) &&
31430711Swollman            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
3152742Swollman            (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
31630711Swollman        {
3172742Swollman            MethodInfo->NumReturnWithValue++;
3182742Swollman        }
319158421Swollman        else
3202742Swollman        {
32186222Swollman            MethodInfo->NumReturnNoValue++;
32214343Swollman        }
323158421Swollman        break;
324158421Swollman
325158421Swollman
326158421Swollman    case PARSEOP_BREAK:
3272742Swollman    case PARSEOP_CONTINUE:
3282742Swollman
3292742Swollman        Next = Op->Asl.Parent;
33019878Swollman        while (Next)
33130711Swollman        {
3322742Swollman            if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
3332742Swollman            {
3342742Swollman                break;
3352742Swollman            }
3362742Swollman            Next = Next->Asl.Parent;
3372742Swollman        }
33819878Swollman
3392742Swollman        if (!Next)
34019878Swollman        {
3412742Swollman            AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
34219878Swollman        }
3432742Swollman        break;
34419878Swollman
3452742Swollman
34619878Swollman    case PARSEOP_STALL:
34719878Swollman
3482742Swollman        /* We can range check if the argument is an integer */
34919878Swollman
350149514Swollman        if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
3512742Swollman            (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
3522742Swollman        {
35319878Swollman            AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
3542742Swollman        }
35558787Sru        break;
356158421Swollman
35758787Sru
35858787Sru    case PARSEOP_DEVICE:
35958787Sru    case PARSEOP_EVENT:
36058787Sru    case PARSEOP_MUTEX:
36143014Swollman    case PARSEOP_OPERATIONREGION:
3622742Swollman    case PARSEOP_POWERRESOURCE:
3632742Swollman    case PARSEOP_PROCESSOR:
3642742Swollman    case PARSEOP_THERMALZONE:
3652742Swollman
3662742Swollman        /*
3672742Swollman         * The first operand is a name to be created in the namespace.
3682742Swollman         * Check against the reserved list.
3692742Swollman         */
3702742Swollman        i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
3712742Swollman        if (i < ACPI_VALID_RESERVED_NAME_MAX)
3722742Swollman        {
37330711Swollman            AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
3742742Swollman        }
3752742Swollman        break;
3762742Swollman
3772742Swollman
37830711Swollman    case PARSEOP_NAME:
37930711Swollman
38030711Swollman        /* Typecheck any predefined names statically defined with Name() */
3812742Swollman
3822742Swollman        ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
3832742Swollman
3842742Swollman        /* Special typechecking for _HID */
38530711Swollman
38630711Swollman        if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
38730711Swollman        {
3882742Swollman            Next = Op->Asl.Child->Asl.Next;
3892742Swollman            AnCheckId (Next, ASL_TYPE_HID);
3902742Swollman        }
3912742Swollman
39219878Swollman        /* Special typechecking for _CID */
3932742Swollman
3942742Swollman        else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
3952742Swollman        {
3962742Swollman            Next = Op->Asl.Child->Asl.Next;
3972742Swollman
39814343Swollman            if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
3992742Swollman                (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
4002742Swollman            {
4012742Swollman                Next = Next->Asl.Child;
40230711Swollman                while (Next)
40320094Swollman                {
40419878Swollman                    AnCheckId (Next, ASL_TYPE_CID);
4052742Swollman                    Next = Next->Asl.Next;
40619878Swollman                }
4072742Swollman            }
40819878Swollman            else
4092742Swollman            {
41019878Swollman                AnCheckId (Next, ASL_TYPE_CID);
4112742Swollman            }
41219878Swollman        }
4132742Swollman        break;
41419878Swollman
4152742Swollman
4162742Swollman    default:
41719878Swollman        break;
4182742Swollman    }
4192742Swollman
4202742Swollman    return (AE_OK);
42119878Swollman}
42219878Swollman
4232742Swollman
42419878Swollman/*******************************************************************************
42519878Swollman *
42630711Swollman * FUNCTION:    AnMethodAnalysisWalkEnd
42719878Swollman *
4288029Swollman * PARAMETERS:  ASL_WALK_CALLBACK
4292742Swollman *
4302742Swollman * RETURN:      Status
4312742Swollman *
43230711Swollman * DESCRIPTION: Ascending callback for analysis walk. Complete method
4332742Swollman *              return analysis.
4342742Swollman *
435158421Swollman ******************************************************************************/
436158421Swollman
437169811SwollmanACPI_STATUS
438169811SwollmanAnMethodAnalysisWalkEnd (
439169811Swollman    ACPI_PARSE_OBJECT       *Op,
440169811Swollman    UINT32                  Level,
441169811Swollman    void                    *Context)
442169811Swollman{
443169811Swollman    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
444169811Swollman    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
445169811Swollman
446169811Swollman
447169811Swollman    switch (Op->Asl.ParseOpcode)
448169811Swollman    {
449169811Swollman    case PARSEOP_METHOD:
450169811Swollman    case PARSEOP_RETURN:
45120094Swollman        if (!MethodInfo)
45220094Swollman        {
45320094Swollman            printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
4542742Swollman            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
4552742Swollman                "No method info for this method");
4562742Swollman
45730711Swollman            CmCleanupAndExit ();
4582742Swollman            return (AE_AML_INTERNAL);
45930711Swollman        }
46030711Swollman        break;
46130711Swollman
4622742Swollman    default:
4632742Swollman        break;
4642742Swollman    }
46530711Swollman
46630711Swollman    switch (Op->Asl.ParseOpcode)
46730711Swollman    {
46830711Swollman    case PARSEOP_METHOD:
4692742Swollman
4702742Swollman        WalkInfo->MethodStack = MethodInfo->Next;
4712742Swollman
4722742Swollman        /*
47330711Swollman         * Check if there is no return statement at the end of the
4742742Swollman         * method AND we can actually get there -- i.e., the execution
4752742Swollman         * of the method can possibly terminate without a return statement.
4762742Swollman         */
47714343Swollman        if ((!AnLastStatementIsReturn (Op)) &&
47819878Swollman            (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
47943014Swollman        {
48043014Swollman            /*
48143014Swollman             * No return statement, and execution can possibly exit
48258787Sru             * via this path. This is equivalent to Return ()
48358787Sru             */
48458787Sru            MethodInfo->NumReturnNoValue++;
48543014Swollman        }
48643014Swollman
48743014Swollman        /*
48843014Swollman         * Check for case where some return statements have a return value
48943014Swollman         * and some do not. Exit without a return statement is a return with
49043014Swollman         * no value
4912742Swollman         */
4922742Swollman        if (MethodInfo->NumReturnNoValue &&
4932742Swollman            MethodInfo->NumReturnWithValue)
4942742Swollman        {
49530711Swollman            AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
4962742Swollman                Op->Asl.ExternalName);
4972742Swollman        }
4982742Swollman
4992742Swollman        /*
50030711Swollman         * If there are any RETURN() statements with no value, or there is a
5012742Swollman         * control path that allows the method to exit without a return value,
50214343Swollman         * we mark the method as a method that does not return a value. This
50330711Swollman         * knowledge can be used to check method invocations that expect a
50430711Swollman         * returned value.
50558787Sru         */
50658787Sru        if (MethodInfo->NumReturnNoValue)
50730711Swollman        {
50814343Swollman            if (MethodInfo->NumReturnWithValue)
5092742Swollman            {
5102742Swollman                Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
5112742Swollman            }
51219878Swollman            else
51330711Swollman            {
5142742Swollman                Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
5152742Swollman            }
5162742Swollman        }
5172742Swollman
51830711Swollman        /*
51930711Swollman         * Check predefined method names for correct return behavior
5202742Swollman         * and correct number of arguments. Also, some special checks
5212742Swollman         * For GPE and _REG methods.
5222742Swollman         */
5232742Swollman        if (ApCheckForPredefinedMethod (Op, MethodInfo))
52419878Swollman        {
52586222Swollman            /* Special check for two names like _L01 and _E01 in same scope */
52686222Swollman
52786222Swollman            ApCheckForGpeNameConflict (Op);
52886222Swollman
52986222Swollman            /*
53086222Swollman             * Special check for _REG: Must have an operation region definition
5312742Swollman             * within the same scope!
5322742Swollman             */
5332742Swollman            ApCheckRegMethod (Op);
534158421Swollman        }
53530711Swollman
53630711Swollman        ACPI_FREE (MethodInfo);
53730711Swollman        break;
53830711Swollman
5392742Swollman
5402742Swollman    case PARSEOP_NAME:
54119878Swollman
54230711Swollman         /* Special check for two names like _L01 and _E01 in same scope */
54330711Swollman
5442742Swollman        ApCheckForGpeNameConflict (Op);
5452742Swollman        break;
5462742Swollman
5472742Swollman
5482742Swollman    case PARSEOP_RETURN:
54930711Swollman
5502742Swollman        /*
5512742Swollman         * If the parent is a predefined method name, attempt to typecheck
5522742Swollman         * the return value. Only static types can be validated.
5532742Swollman         */
55430711Swollman        ApCheckPredefinedReturnValue (Op, MethodInfo);
5552742Swollman
5562742Swollman        /*
5572742Swollman         * The parent block does not "exit" and continue execution -- the
55830711Swollman         * method is terminated here with the Return() statement.
55930711Swollman         */
56030711Swollman        Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
56158787Sru
5622742Swollman        /* Used in the "typing" pass later */
5632742Swollman
5642742Swollman        Op->Asl.ParentMethod = MethodInfo->Op;
56558787Sru
56658787Sru        /*
56758787Sru         * If there is a peer node after the return statement, then this
56858787Sru         * node is unreachable code -- i.e., it won't be executed because of
56958787Sru         * the preceeding Return() statement.
57058787Sru         */
57158787Sru        if (Op->Asl.Next)
57258787Sru        {
5732742Swollman            AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
57419878Swollman        }
57514343Swollman        break;
57619878Swollman
57719878Swollman
5782742Swollman    case PARSEOP_IF:
5792742Swollman
58058787Sru        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
58158787Sru            (Op->Asl.Next) &&
5822742Swollman            (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
5832742Swollman        {
5842742Swollman            /*
5852742Swollman             * This IF has a corresponding ELSE. The IF block has no exit,
58630711Swollman             * (it contains an unconditional Return)
5872742Swollman             * mark the ELSE block to remember this fact.
5882742Swollman             */
5892742Swollman            Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
5902742Swollman        }
5912742Swollman        break;
59286222Swollman
5932742Swollman
5942742Swollman    case PARSEOP_ELSE:
5952742Swollman
5962742Swollman        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
5972742Swollman            (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
59830711Swollman        {
5992742Swollman            /*
6002742Swollman             * This ELSE block has no exit and the corresponding IF block
601149514Swollman             * has no exit either. Therefore, the parent node has no exit.
602149514Swollman             */
603149514Swollman            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
604149514Swollman        }
605149514Swollman        break;
606149514Swollman
607149514Swollman
608149514Swollman    default:
609149514Swollman
610149514Swollman        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
611149514Swollman            (Op->Asl.Parent))
612149514Swollman        {
613149514Swollman            /* If this node has no exit, then the parent has no exit either */
614149514Swollman
615149514Swollman            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
616158421Swollman        }
617158421Swollman        break;
618158421Swollman    }
619158421Swollman
620158421Swollman    return (AE_OK);
621158421Swollman}
622149514Swollman
6232742Swollman
62419878Swollman/*******************************************************************************
6252742Swollman *
62619878Swollman * FUNCTION:    AnMethodTypingWalkEnd
6272742Swollman *
62819878Swollman * PARAMETERS:  ASL_WALK_CALLBACK
6292742Swollman *
63019878Swollman * RETURN:      Status
6312742Swollman *
63219878Swollman * DESCRIPTION: Ascending callback for typing walk. Complete the method
6332742Swollman *              return analysis. Check methods for:
63419878Swollman *              1) Initialized local variables
6352742Swollman *              2) Valid arguments
6362742Swollman *              3) Return types
63719878Swollman *
6382742Swollman ******************************************************************************/
63919878Swollman
6402742SwollmanACPI_STATUS
64119878SwollmanAnMethodTypingWalkEnd (
64220094Swollman    ACPI_PARSE_OBJECT       *Op,
64319878Swollman    UINT32                  Level,
64419878Swollman    void                    *Context)
645149514Swollman{
646149514Swollman    UINT32                  ThisNodeBtype;
647158421Swollman
648158421Swollman
649158421Swollman    switch (Op->Asl.ParseOpcode)
650158421Swollman    {
651158421Swollman    case PARSEOP_METHOD:
6522742Swollman
6532742Swollman        Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
65414343Swollman        break;
65519878Swollman
6562742Swollman    case PARSEOP_RETURN:
6572742Swollman
6582742Swollman        if ((Op->Asl.Child) &&
6592742Swollman            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
6602742Swollman        {
6612742Swollman            ThisNodeBtype = AnGetBtype (Op->Asl.Child);
66286222Swollman
6632742Swollman            if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
6642742Swollman                (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
6652742Swollman            {
6662742Swollman                /*
6672742Swollman                 * The called method is untyped at this time (typically a
66830711Swollman                 * forward reference).
6692742Swollman                 *
6702742Swollman                 * Check for a recursive method call first.
6712742Swollman                 */
6722742Swollman                if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
67330711Swollman                {
674                    /* We must type the method here */
675
676                    TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
677                        ASL_WALK_VISIT_UPWARD, NULL,
678                        AnMethodTypingWalkEnd, NULL);
679
680                    ThisNodeBtype = AnGetBtype (Op->Asl.Child);
681                }
682            }
683
684            /* Returns a value, save the value type */
685
686            if (Op->Asl.ParentMethod)
687            {
688                Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
689            }
690        }
691        break;
692
693    default:
694        break;
695    }
696
697    return (AE_OK);
698}
699
700
701/*******************************************************************************
702 *
703 * FUNCTION:    AnOperandTypecheckWalkEnd
704 *
705 * PARAMETERS:  ASL_WALK_CALLBACK
706 *
707 * RETURN:      Status
708 *
709 * DESCRIPTION: Ascending callback for analysis walk. Complete method
710 *              return analysis.
711 *
712 ******************************************************************************/
713
714ACPI_STATUS
715AnOperandTypecheckWalkEnd (
716    ACPI_PARSE_OBJECT       *Op,
717    UINT32                  Level,
718    void                    *Context)
719{
720    const ACPI_OPCODE_INFO  *OpInfo;
721    UINT32                  RuntimeArgTypes;
722    UINT32                  RuntimeArgTypes2;
723    UINT32                  RequiredBtypes;
724    UINT32                  ThisNodeBtype;
725    UINT32                  CommonBtypes;
726    UINT32                  OpcodeClass;
727    ACPI_PARSE_OBJECT       *ArgOp;
728    UINT32                  ArgType;
729
730
731    switch (Op->Asl.AmlOpcode)
732    {
733    case AML_RAW_DATA_BYTE:
734    case AML_RAW_DATA_WORD:
735    case AML_RAW_DATA_DWORD:
736    case AML_RAW_DATA_QWORD:
737    case AML_RAW_DATA_BUFFER:
738    case AML_RAW_DATA_CHAIN:
739    case AML_PACKAGE_LENGTH:
740    case AML_UNASSIGNED_OPCODE:
741    case AML_DEFAULT_ARG_OP:
742
743        /* Ignore the internal (compiler-only) AML opcodes */
744
745        return (AE_OK);
746
747    default:
748        break;
749    }
750
751    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
752    if (!OpInfo)
753    {
754        return (AE_OK);
755    }
756
757    ArgOp           = Op->Asl.Child;
758    RuntimeArgTypes = OpInfo->RuntimeArgs;
759    OpcodeClass     = OpInfo->Class;
760
761#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
762    /*
763     * Update 11/2008: In practice, we can't perform this check. A simple
764     * analysis is not sufficient. Also, it can cause errors when compiling
765     * disassembled code because of the way Switch operators are implemented
766     * (a While(One) loop with a named temp variable created within.)
767     */
768
769    /*
770     * If we are creating a named object, check if we are within a while loop
771     * by checking if the parent is a WHILE op. This is a simple analysis, but
772     * probably sufficient for many cases.
773     *
774     * Allow Scope(), Buffer(), and Package().
775     */
776    if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
777        ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
778    {
779        if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
780        {
781            AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
782        }
783    }
784#endif
785
786    /*
787     * Special case for control opcodes IF/RETURN/WHILE since they
788     * have no runtime arg list (at this time)
789     */
790    switch (Op->Asl.AmlOpcode)
791    {
792    case AML_IF_OP:
793    case AML_WHILE_OP:
794    case AML_RETURN_OP:
795
796        if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
797        {
798            /* Check for an internal method */
799
800            if (AnIsInternalMethod (ArgOp))
801            {
802                return (AE_OK);
803            }
804
805            /* The lone arg is a method call, check it */
806
807            RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
808            if (Op->Asl.AmlOpcode == AML_RETURN_OP)
809            {
810                RequiredBtypes = 0xFFFFFFFF;
811            }
812
813            ThisNodeBtype = AnGetBtype (ArgOp);
814            if (ThisNodeBtype == ACPI_UINT32_MAX)
815            {
816                return (AE_OK);
817            }
818            AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
819                RequiredBtypes, ThisNodeBtype);
820        }
821        return (AE_OK);
822
823    default:
824        break;
825    }
826
827    /* Ignore the non-executable opcodes */
828
829    if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
830    {
831        return (AE_OK);
832    }
833
834    switch (OpcodeClass)
835    {
836    case AML_CLASS_EXECUTE:
837    case AML_CLASS_CREATE:
838    case AML_CLASS_CONTROL:
839    case AML_CLASS_RETURN_VALUE:
840
841        /* TBD: Change class or fix typechecking for these */
842
843        if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
844            (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
845            (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
846        {
847            break;
848        }
849
850        /* Reverse the runtime argument list */
851
852        RuntimeArgTypes2 = 0;
853        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
854        {
855            RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
856            RuntimeArgTypes2 |= ArgType;
857            INCREMENT_ARG_LIST (RuntimeArgTypes);
858        }
859
860        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
861        {
862            RequiredBtypes = AnMapArgTypeToBtype (ArgType);
863
864            ThisNodeBtype = AnGetBtype (ArgOp);
865            if (ThisNodeBtype == ACPI_UINT32_MAX)
866            {
867                goto NextArgument;
868            }
869
870            /* Examine the arg based on the required type of the arg */
871
872            switch (ArgType)
873            {
874            case ARGI_TARGETREF:
875
876                if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
877                {
878                    /* ZERO is the placeholder for "don't store result" */
879
880                    ThisNodeBtype = RequiredBtypes;
881                    break;
882                }
883
884                if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
885                {
886                    /*
887                     * This is the case where an original reference to a resource
888                     * descriptor field has been replaced by an (Integer) offset.
889                     * These named fields are supported at compile-time only;
890                     * the names are not passed to the interpreter (via the AML).
891                     */
892                    if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
893                        (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
894                    {
895                        AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
896                    }
897                    else
898                    {
899                        AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
900                    }
901                    break;
902                }
903
904                if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
905                    (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
906                {
907                    break;
908                }
909
910                ThisNodeBtype = RequiredBtypes;
911                break;
912
913
914            case ARGI_REFERENCE:            /* References */
915            case ARGI_INTEGER_REF:
916            case ARGI_OBJECT_REF:
917            case ARGI_DEVICE_REF:
918
919                switch (ArgOp->Asl.ParseOpcode)
920                {
921                case PARSEOP_LOCAL0:
922                case PARSEOP_LOCAL1:
923                case PARSEOP_LOCAL2:
924                case PARSEOP_LOCAL3:
925                case PARSEOP_LOCAL4:
926                case PARSEOP_LOCAL5:
927                case PARSEOP_LOCAL6:
928                case PARSEOP_LOCAL7:
929
930                    /* TBD: implement analysis of current value (type) of the local */
931                    /* For now, just treat any local as a typematch */
932
933                    /*ThisNodeBtype = RequiredBtypes;*/
934                    break;
935
936                case PARSEOP_ARG0:
937                case PARSEOP_ARG1:
938                case PARSEOP_ARG2:
939                case PARSEOP_ARG3:
940                case PARSEOP_ARG4:
941                case PARSEOP_ARG5:
942                case PARSEOP_ARG6:
943
944                    /* Hard to analyze argument types, sow we won't */
945                    /* For now, just treat any arg as a typematch */
946
947                    /* ThisNodeBtype = RequiredBtypes; */
948                    break;
949
950                case PARSEOP_DEBUG:
951                    break;
952
953                case PARSEOP_REFOF:
954                case PARSEOP_INDEX:
955                default:
956                    break;
957
958                }
959                break;
960
961            case ARGI_INTEGER:
962            default:
963                break;
964            }
965
966
967            CommonBtypes = ThisNodeBtype & RequiredBtypes;
968
969            if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
970            {
971                if (AnIsInternalMethod (ArgOp))
972                {
973                    return (AE_OK);
974                }
975
976                /* Check a method call for a valid return value */
977
978                AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
979                    RequiredBtypes, ThisNodeBtype);
980            }
981
982            /*
983             * Now check if the actual type(s) match at least one
984             * bit to the required type
985             */
986            else if (!CommonBtypes)
987            {
988                /* No match -- this is a type mismatch error */
989
990                AnFormatBtype (StringBuffer, ThisNodeBtype);
991                AnFormatBtype (StringBuffer2, RequiredBtypes);
992
993                sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
994                            StringBuffer, OpInfo->Name, StringBuffer2);
995
996                AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
997            }
998
999        NextArgument:
1000            ArgOp = ArgOp->Asl.Next;
1001            INCREMENT_ARG_LIST (RuntimeArgTypes2);
1002        }
1003        break;
1004
1005    default:
1006        break;
1007    }
1008
1009    return (AE_OK);
1010}
1011
1012
1013/*******************************************************************************
1014 *
1015 * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
1016 *
1017 * PARAMETERS:  ASL_WALK_CALLBACK
1018 *
1019 * RETURN:      Status
1020 *
1021 * DESCRIPTION: Descending callback for the analysis walk. Checks for
1022 *              miscellaneous issues in the code.
1023 *
1024 ******************************************************************************/
1025
1026ACPI_STATUS
1027AnOtherSemanticAnalysisWalkBegin (
1028    ACPI_PARSE_OBJECT       *Op,
1029    UINT32                  Level,
1030    void                    *Context)
1031{
1032    ACPI_PARSE_OBJECT       *ArgNode;
1033    ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
1034    const ACPI_OPCODE_INFO  *OpInfo;
1035    ACPI_NAMESPACE_NODE     *Node;
1036
1037
1038    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1039
1040    /*
1041     * Determine if an execution class operator actually does something by
1042     * checking if it has a target and/or the function return value is used.
1043     * (Target is optional, so a standalone statement can actually do nothing.)
1044     */
1045    if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
1046        (OpInfo->Flags & AML_HAS_RETVAL) &&
1047        (!AnIsResultUsed (Op)))
1048    {
1049        if (OpInfo->Flags & AML_HAS_TARGET)
1050        {
1051            /*
1052             * Find the target node, it is always the last child. If the traget
1053             * is not specified in the ASL, a default node of type Zero was
1054             * created by the parser.
1055             */
1056            ArgNode = Op->Asl.Child;
1057            while (ArgNode->Asl.Next)
1058            {
1059                PrevArgNode = ArgNode;
1060                ArgNode = ArgNode->Asl.Next;
1061            }
1062
1063            /* Divide() is the only weird case, it has two targets */
1064
1065            if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
1066            {
1067                if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
1068                    (PrevArgNode) &&
1069                    (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
1070                {
1071                    AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1072                        Op, Op->Asl.ExternalName);
1073                }
1074            }
1075            else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
1076            {
1077                AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1078                    Op, Op->Asl.ExternalName);
1079            }
1080        }
1081        else
1082        {
1083            /*
1084             * Has no target and the result is not used. Only a couple opcodes
1085             * can have this combination.
1086             */
1087            switch (Op->Asl.ParseOpcode)
1088            {
1089            case PARSEOP_ACQUIRE:
1090            case PARSEOP_WAIT:
1091            case PARSEOP_LOADTABLE:
1092                break;
1093
1094            default:
1095                AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1096                    Op, Op->Asl.ExternalName);
1097                break;
1098            }
1099        }
1100    }
1101
1102
1103    /*
1104     * Semantic checks for individual ASL operators
1105     */
1106    switch (Op->Asl.ParseOpcode)
1107    {
1108    case PARSEOP_ACQUIRE:
1109    case PARSEOP_WAIT:
1110        /*
1111         * Emit a warning if the timeout parameter for these operators is not
1112         * ACPI_WAIT_FOREVER, and the result value from the operator is not
1113         * checked, meaning that a timeout could happen, but the code
1114         * would not know about it.
1115         */
1116
1117        /* First child is the namepath, 2nd child is timeout */
1118
1119        ArgNode = Op->Asl.Child;
1120        ArgNode = ArgNode->Asl.Next;
1121
1122        /*
1123         * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
1124         * 0xFFFF or greater
1125         */
1126        if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
1127             (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
1128             (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
1129        {
1130            break;
1131        }
1132
1133        /*
1134         * The operation could timeout. If the return value is not used
1135         * (indicates timeout occurred), issue a warning
1136         */
1137        if (!AnIsResultUsed (Op))
1138        {
1139            AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
1140                Op->Asl.ExternalName);
1141        }
1142        break;
1143
1144    case PARSEOP_CREATEFIELD:
1145        /*
1146         * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
1147         */
1148        ArgNode = Op->Asl.Child;
1149        ArgNode = ArgNode->Asl.Next;
1150        ArgNode = ArgNode->Asl.Next;
1151
1152        if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
1153           ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
1154            (ArgNode->Asl.Value.Integer == 0)))
1155        {
1156            AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
1157        }
1158        break;
1159
1160    case PARSEOP_CONNECTION:
1161        /*
1162         * Ensure that the referenced operation region has the correct SPACE_ID.
1163         * From the grammar/parser, we know the parent is a FIELD definition.
1164         */
1165        ArgNode = Op->Asl.Parent;       /* Field definition */
1166        ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
1167        Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
1168
1169        ArgNode = Node->Op;             /* OpRegion definition */
1170        ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
1171        ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
1172
1173        /*
1174         * The Connection() operator is only valid for the following operation
1175         * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
1176         */
1177        if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
1178            (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
1179        {
1180            AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
1181        }
1182        break;
1183
1184    case PARSEOP_FIELD:
1185        /*
1186         * Ensure that fields for GeneralPurposeIo and GenericSerialBus
1187         * contain at least one Connection() operator
1188         */
1189        ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
1190        Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
1191        if (!Node)
1192        {
1193            break;
1194        }
1195
1196        ArgNode = Node->Op;             /* OpRegion definition */
1197        ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
1198        ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
1199
1200        /* We are only interested in GeneralPurposeIo and GenericSerialBus */
1201
1202        if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
1203            (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
1204        {
1205            break;
1206        }
1207
1208        ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
1209        ArgNode = ArgNode->Asl.Next;    /* AccessType */
1210        ArgNode = ArgNode->Asl.Next;    /* LockRule */
1211        ArgNode = ArgNode->Asl.Next;    /* UpdateRule */
1212        ArgNode = ArgNode->Asl.Next;    /* Start of FieldUnitList */
1213
1214        /* Walk the FieldUnitList */
1215
1216        while (ArgNode)
1217        {
1218            if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION)
1219            {
1220                break;
1221            }
1222            else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG)
1223            {
1224                AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL);
1225                break;
1226            }
1227
1228            ArgNode = ArgNode->Asl.Next;
1229        }
1230        break;
1231
1232    default:
1233        break;
1234    }
1235
1236    return (AE_OK);
1237}
1238