Home | History | Annotate | Line # | Download | only in compiler
aslwalks.c revision 1.1.1.4
      1 /******************************************************************************
      2  *
      3  * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2014, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "aslcompiler.h"
     45 #include "aslcompiler.y.h"
     46 #include "acparser.h"
     47 #include "amlcode.h"
     48 
     49 
     50 #define _COMPONENT          ACPI_COMPILER
     51         ACPI_MODULE_NAME    ("aslwalks")
     52 
     53 
     54 /*******************************************************************************
     55  *
     56  * FUNCTION:    AnMethodTypingWalkEnd
     57  *
     58  * PARAMETERS:  ASL_WALK_CALLBACK
     59  *
     60  * RETURN:      Status
     61  *
     62  * DESCRIPTION: Ascending callback for typing walk. Complete the method
     63  *              return analysis. Check methods for:
     64  *              1) Initialized local variables
     65  *              2) Valid arguments
     66  *              3) Return types
     67  *
     68  ******************************************************************************/
     69 
     70 ACPI_STATUS
     71 AnMethodTypingWalkEnd (
     72     ACPI_PARSE_OBJECT       *Op,
     73     UINT32                  Level,
     74     void                    *Context)
     75 {
     76     UINT32                  ThisNodeBtype;
     77 
     78 
     79     switch (Op->Asl.ParseOpcode)
     80     {
     81     case PARSEOP_METHOD:
     82 
     83         Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
     84         break;
     85 
     86     case PARSEOP_RETURN:
     87 
     88         if ((Op->Asl.Child) &&
     89             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
     90         {
     91             ThisNodeBtype = AnGetBtype (Op->Asl.Child);
     92 
     93             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
     94                 (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
     95             {
     96                 /*
     97                  * The called method is untyped at this time (typically a
     98                  * forward reference).
     99                  *
    100                  * Check for a recursive method call first.
    101                  */
    102                 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
    103                 {
    104                     /* We must type the method here */
    105 
    106                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
    107                         ASL_WALK_VISIT_UPWARD, NULL,
    108                         AnMethodTypingWalkEnd, NULL);
    109 
    110                     ThisNodeBtype = AnGetBtype (Op->Asl.Child);
    111                 }
    112             }
    113 
    114             /* Returns a value, save the value type */
    115 
    116             if (Op->Asl.ParentMethod)
    117             {
    118                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
    119             }
    120         }
    121         break;
    122 
    123     default:
    124 
    125         break;
    126     }
    127 
    128     return (AE_OK);
    129 }
    130 
    131 
    132 /*******************************************************************************
    133  *
    134  * FUNCTION:    AnOperandTypecheckWalkEnd
    135  *
    136  * PARAMETERS:  ASL_WALK_CALLBACK
    137  *
    138  * RETURN:      Status
    139  *
    140  * DESCRIPTION: Ascending callback for analysis walk. Complete method
    141  *              return analysis.
    142  *
    143  ******************************************************************************/
    144 
    145 ACPI_STATUS
    146 AnOperandTypecheckWalkEnd (
    147     ACPI_PARSE_OBJECT       *Op,
    148     UINT32                  Level,
    149     void                    *Context)
    150 {
    151     const ACPI_OPCODE_INFO  *OpInfo;
    152     UINT32                  RuntimeArgTypes;
    153     UINT32                  RuntimeArgTypes2;
    154     UINT32                  RequiredBtypes;
    155     UINT32                  ThisNodeBtype;
    156     UINT32                  CommonBtypes;
    157     UINT32                  OpcodeClass;
    158     ACPI_PARSE_OBJECT       *ArgOp;
    159     UINT32                  ArgType;
    160 
    161 
    162     switch (Op->Asl.AmlOpcode)
    163     {
    164     case AML_RAW_DATA_BYTE:
    165     case AML_RAW_DATA_WORD:
    166     case AML_RAW_DATA_DWORD:
    167     case AML_RAW_DATA_QWORD:
    168     case AML_RAW_DATA_BUFFER:
    169     case AML_RAW_DATA_CHAIN:
    170     case AML_PACKAGE_LENGTH:
    171     case AML_UNASSIGNED_OPCODE:
    172     case AML_DEFAULT_ARG_OP:
    173 
    174         /* Ignore the internal (compiler-only) AML opcodes */
    175 
    176         return (AE_OK);
    177 
    178     default:
    179 
    180         break;
    181     }
    182 
    183     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    184     if (!OpInfo)
    185     {
    186         return (AE_OK);
    187     }
    188 
    189     ArgOp           = Op->Asl.Child;
    190     RuntimeArgTypes = OpInfo->RuntimeArgs;
    191     OpcodeClass     = OpInfo->Class;
    192 
    193 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
    194     /*
    195      * Update 11/2008: In practice, we can't perform this check. A simple
    196      * analysis is not sufficient. Also, it can cause errors when compiling
    197      * disassembled code because of the way Switch operators are implemented
    198      * (a While(One) loop with a named temp variable created within.)
    199      */
    200 
    201     /*
    202      * If we are creating a named object, check if we are within a while loop
    203      * by checking if the parent is a WHILE op. This is a simple analysis, but
    204      * probably sufficient for many cases.
    205      *
    206      * Allow Scope(), Buffer(), and Package().
    207      */
    208     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
    209         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
    210     {
    211         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
    212         {
    213             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
    214         }
    215     }
    216 #endif
    217 
    218     /*
    219      * Special case for control opcodes IF/RETURN/WHILE since they
    220      * have no runtime arg list (at this time)
    221      */
    222     switch (Op->Asl.AmlOpcode)
    223     {
    224     case AML_IF_OP:
    225     case AML_WHILE_OP:
    226     case AML_RETURN_OP:
    227 
    228         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
    229         {
    230             /* Check for an internal method */
    231 
    232             if (AnIsInternalMethod (ArgOp))
    233             {
    234                 return (AE_OK);
    235             }
    236 
    237             /* The lone arg is a method call, check it */
    238 
    239             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
    240             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
    241             {
    242                 RequiredBtypes = 0xFFFFFFFF;
    243             }
    244 
    245             ThisNodeBtype = AnGetBtype (ArgOp);
    246             if (ThisNodeBtype == ACPI_UINT32_MAX)
    247             {
    248                 return (AE_OK);
    249             }
    250             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
    251                 RequiredBtypes, ThisNodeBtype);
    252         }
    253         return (AE_OK);
    254 
    255     default:
    256 
    257         break;
    258     }
    259 
    260     /* Ignore the non-executable opcodes */
    261 
    262     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
    263     {
    264         return (AE_OK);
    265     }
    266 
    267     switch (OpcodeClass)
    268     {
    269     case AML_CLASS_EXECUTE:
    270     case AML_CLASS_CREATE:
    271     case AML_CLASS_CONTROL:
    272     case AML_CLASS_RETURN_VALUE:
    273 
    274         /* TBD: Change class or fix typechecking for these */
    275 
    276         if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
    277             (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
    278             (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
    279         {
    280             break;
    281         }
    282 
    283         /* Reverse the runtime argument list */
    284 
    285         RuntimeArgTypes2 = 0;
    286         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
    287         {
    288             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
    289             RuntimeArgTypes2 |= ArgType;
    290             INCREMENT_ARG_LIST (RuntimeArgTypes);
    291         }
    292 
    293         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
    294         {
    295             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
    296 
    297             ThisNodeBtype = AnGetBtype (ArgOp);
    298             if (ThisNodeBtype == ACPI_UINT32_MAX)
    299             {
    300                 goto NextArgument;
    301             }
    302 
    303             /* Examine the arg based on the required type of the arg */
    304 
    305             switch (ArgType)
    306             {
    307             case ARGI_TARGETREF:
    308 
    309                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
    310                 {
    311                     /* ZERO is the placeholder for "don't store result" */
    312 
    313                     ThisNodeBtype = RequiredBtypes;
    314                     break;
    315                 }
    316 
    317                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
    318                 {
    319                     /*
    320                      * This is the case where an original reference to a resource
    321                      * descriptor field has been replaced by an (Integer) offset.
    322                      * These named fields are supported at compile-time only;
    323                      * the names are not passed to the interpreter (via the AML).
    324                      */
    325                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
    326                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    327                     {
    328                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
    329                     }
    330                     else
    331                     {
    332                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
    333                     }
    334                     break;
    335                 }
    336 
    337                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
    338                     (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
    339                 {
    340                     break;
    341                 }
    342 
    343                 ThisNodeBtype = RequiredBtypes;
    344                 break;
    345 
    346 
    347             case ARGI_REFERENCE:            /* References */
    348             case ARGI_INTEGER_REF:
    349             case ARGI_OBJECT_REF:
    350             case ARGI_DEVICE_REF:
    351 
    352                 switch (ArgOp->Asl.ParseOpcode)
    353                 {
    354                 case PARSEOP_LOCAL0:
    355                 case PARSEOP_LOCAL1:
    356                 case PARSEOP_LOCAL2:
    357                 case PARSEOP_LOCAL3:
    358                 case PARSEOP_LOCAL4:
    359                 case PARSEOP_LOCAL5:
    360                 case PARSEOP_LOCAL6:
    361                 case PARSEOP_LOCAL7:
    362 
    363                     /* TBD: implement analysis of current value (type) of the local */
    364                     /* For now, just treat any local as a typematch */
    365 
    366                     /*ThisNodeBtype = RequiredBtypes;*/
    367                     break;
    368 
    369                 case PARSEOP_ARG0:
    370                 case PARSEOP_ARG1:
    371                 case PARSEOP_ARG2:
    372                 case PARSEOP_ARG3:
    373                 case PARSEOP_ARG4:
    374                 case PARSEOP_ARG5:
    375                 case PARSEOP_ARG6:
    376 
    377                     /* Hard to analyze argument types, sow we won't */
    378                     /* For now, just treat any arg as a typematch */
    379 
    380                     /* ThisNodeBtype = RequiredBtypes; */
    381                     break;
    382 
    383                 case PARSEOP_DEBUG:
    384 
    385                     break;
    386 
    387                 case PARSEOP_REFOF:
    388                 case PARSEOP_INDEX:
    389                 default:
    390 
    391                     break;
    392 
    393                 }
    394                 break;
    395 
    396             case ARGI_INTEGER:
    397             default:
    398 
    399                 break;
    400             }
    401 
    402 
    403             CommonBtypes = ThisNodeBtype & RequiredBtypes;
    404 
    405             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
    406             {
    407                 if (AnIsInternalMethod (ArgOp))
    408                 {
    409                     return (AE_OK);
    410                 }
    411 
    412                 /* Check a method call for a valid return value */
    413 
    414                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
    415                     RequiredBtypes, ThisNodeBtype);
    416             }
    417 
    418             /*
    419              * Now check if the actual type(s) match at least one
    420              * bit to the required type
    421              */
    422             else if (!CommonBtypes)
    423             {
    424                 /* No match -- this is a type mismatch error */
    425 
    426                 AnFormatBtype (StringBuffer, ThisNodeBtype);
    427                 AnFormatBtype (StringBuffer2, RequiredBtypes);
    428 
    429                 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
    430                             StringBuffer, OpInfo->Name, StringBuffer2);
    431 
    432                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
    433             }
    434 
    435         NextArgument:
    436             ArgOp = ArgOp->Asl.Next;
    437             INCREMENT_ARG_LIST (RuntimeArgTypes2);
    438         }
    439         break;
    440 
    441     default:
    442 
    443         break;
    444     }
    445 
    446     return (AE_OK);
    447 }
    448 
    449 
    450 /*******************************************************************************
    451  *
    452  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
    453  *
    454  * PARAMETERS:  ASL_WALK_CALLBACK
    455  *
    456  * RETURN:      Status
    457  *
    458  * DESCRIPTION: Descending callback for the analysis walk. Checks for
    459  *              miscellaneous issues in the code.
    460  *
    461  ******************************************************************************/
    462 
    463 ACPI_STATUS
    464 AnOtherSemanticAnalysisWalkBegin (
    465     ACPI_PARSE_OBJECT       *Op,
    466     UINT32                  Level,
    467     void                    *Context)
    468 {
    469     ACPI_PARSE_OBJECT       *ArgNode;
    470     ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
    471     const ACPI_OPCODE_INFO  *OpInfo;
    472     ACPI_NAMESPACE_NODE     *Node;
    473 
    474 
    475     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    476 
    477     /*
    478      * Determine if an execution class operator actually does something by
    479      * checking if it has a target and/or the function return value is used.
    480      * (Target is optional, so a standalone statement can actually do nothing.)
    481      */
    482     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
    483         (OpInfo->Flags & AML_HAS_RETVAL) &&
    484         (!AnIsResultUsed (Op)))
    485     {
    486         if (OpInfo->Flags & AML_HAS_TARGET)
    487         {
    488             /*
    489              * Find the target node, it is always the last child. If the traget
    490              * is not specified in the ASL, a default node of type Zero was
    491              * created by the parser.
    492              */
    493             ArgNode = Op->Asl.Child;
    494             while (ArgNode->Asl.Next)
    495             {
    496                 PrevArgNode = ArgNode;
    497                 ArgNode = ArgNode->Asl.Next;
    498             }
    499 
    500             /* Divide() is the only weird case, it has two targets */
    501 
    502             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
    503             {
    504                 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
    505                     (PrevArgNode) &&
    506                     (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
    507                 {
    508                     AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    509                         Op, Op->Asl.ExternalName);
    510                 }
    511             }
    512             else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
    513             {
    514                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    515                     Op, Op->Asl.ExternalName);
    516             }
    517         }
    518         else
    519         {
    520             /*
    521              * Has no target and the result is not used. Only a couple opcodes
    522              * can have this combination.
    523              */
    524             switch (Op->Asl.ParseOpcode)
    525             {
    526             case PARSEOP_ACQUIRE:
    527             case PARSEOP_WAIT:
    528             case PARSEOP_LOADTABLE:
    529 
    530                 break;
    531 
    532             default:
    533 
    534                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    535                     Op, Op->Asl.ExternalName);
    536                 break;
    537             }
    538         }
    539     }
    540 
    541 
    542     /*
    543      * Semantic checks for individual ASL operators
    544      */
    545     switch (Op->Asl.ParseOpcode)
    546     {
    547     case PARSEOP_ACQUIRE:
    548     case PARSEOP_WAIT:
    549         /*
    550          * Emit a warning if the timeout parameter for these operators is not
    551          * ACPI_WAIT_FOREVER, and the result value from the operator is not
    552          * checked, meaning that a timeout could happen, but the code
    553          * would not know about it.
    554          */
    555 
    556         /* First child is the namepath, 2nd child is timeout */
    557 
    558         ArgNode = Op->Asl.Child;
    559         ArgNode = ArgNode->Asl.Next;
    560 
    561         /*
    562          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
    563          * 0xFFFF or greater
    564          */
    565         if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
    566              (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
    567              (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
    568         {
    569             break;
    570         }
    571 
    572         /*
    573          * The operation could timeout. If the return value is not used
    574          * (indicates timeout occurred), issue a warning
    575          */
    576         if (!AnIsResultUsed (Op))
    577         {
    578             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
    579                 Op->Asl.ExternalName);
    580         }
    581         break;
    582 
    583     case PARSEOP_CREATEFIELD:
    584         /*
    585          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
    586          */
    587         ArgNode = Op->Asl.Child;
    588         ArgNode = ArgNode->Asl.Next;
    589         ArgNode = ArgNode->Asl.Next;
    590 
    591         if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
    592            ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    593             (ArgNode->Asl.Value.Integer == 0)))
    594         {
    595             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
    596         }
    597         break;
    598 
    599     case PARSEOP_CONNECTION:
    600         /*
    601          * Ensure that the referenced operation region has the correct SPACE_ID.
    602          * From the grammar/parser, we know the parent is a FIELD definition.
    603          */
    604         ArgNode = Op->Asl.Parent;       /* Field definition */
    605         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
    606         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
    607         if (!Node)
    608         {
    609             break;
    610         }
    611 
    612         ArgNode = Node->Op;             /* OpRegion definition */
    613         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
    614         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
    615 
    616         /*
    617          * The Connection() operator is only valid for the following operation
    618          * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
    619          */
    620         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
    621             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
    622         {
    623             AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
    624         }
    625         break;
    626 
    627     case PARSEOP_FIELD:
    628         /*
    629          * Ensure that fields for GeneralPurposeIo and GenericSerialBus
    630          * contain at least one Connection() operator
    631          */
    632         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
    633         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
    634         if (!Node)
    635         {
    636             break;
    637         }
    638 
    639         ArgNode = Node->Op;             /* OpRegion definition */
    640         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
    641         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
    642 
    643         /* We are only interested in GeneralPurposeIo and GenericSerialBus */
    644 
    645         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
    646             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
    647         {
    648             break;
    649         }
    650 
    651         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
    652         ArgNode = ArgNode->Asl.Next;    /* AccessType */
    653         ArgNode = ArgNode->Asl.Next;    /* LockRule */
    654         ArgNode = ArgNode->Asl.Next;    /* UpdateRule */
    655         ArgNode = ArgNode->Asl.Next;    /* Start of FieldUnitList */
    656 
    657         /* Walk the FieldUnitList */
    658 
    659         while (ArgNode)
    660         {
    661             if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION)
    662             {
    663                 break;
    664             }
    665             else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG)
    666             {
    667                 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL);
    668                 break;
    669             }
    670 
    671             ArgNode = ArgNode->Asl.Next;
    672         }
    673         break;
    674 
    675     default:
    676 
    677         break;
    678     }
    679 
    680     return (AE_OK);
    681 }
    682