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