Home | History | Annotate | Line # | Download | only in compiler
aslwalks.c revision 1.3.2.1
      1 /******************************************************************************
      2  *
      3  * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2015, 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     case AML_EXTERNAL_OP:
    256         /*
    257          * Not really a "runtime" opcode since it used by disassembler only.
    258          * The parser will find any issues with the operands.
    259          */
    260         return (AE_OK);
    261 
    262     default:
    263 
    264         break;
    265     }
    266 
    267     /* Ignore the non-executable opcodes */
    268 
    269     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
    270     {
    271         return (AE_OK);
    272     }
    273 
    274     switch (OpcodeClass)
    275     {
    276     case AML_CLASS_EXECUTE:
    277     case AML_CLASS_CREATE:
    278     case AML_CLASS_CONTROL:
    279     case AML_CLASS_RETURN_VALUE:
    280 
    281         /* TBD: Change class or fix typechecking for these */
    282 
    283         if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
    284             (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
    285             (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
    286         {
    287             break;
    288         }
    289 
    290         /* Reverse the runtime argument list */
    291 
    292         RuntimeArgTypes2 = 0;
    293         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
    294         {
    295             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
    296             RuntimeArgTypes2 |= ArgType;
    297             INCREMENT_ARG_LIST (RuntimeArgTypes);
    298         }
    299 
    300         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
    301         {
    302             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
    303 
    304             if (!ArgOp)
    305             {
    306                 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
    307                     "Null ArgOp in argument loop");
    308                 AslAbort ();
    309             }
    310 
    311             ThisNodeBtype = AnGetBtype (ArgOp);
    312             if (ThisNodeBtype == ACPI_UINT32_MAX)
    313             {
    314                 goto NextArgument;
    315             }
    316 
    317             /* Examine the arg based on the required type of the arg */
    318 
    319             switch (ArgType)
    320             {
    321             case ARGI_TARGETREF:
    322 
    323                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
    324                 {
    325                     /* ZERO is the placeholder for "don't store result" */
    326 
    327                     ThisNodeBtype = RequiredBtypes;
    328                     break;
    329                 }
    330 
    331                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
    332                 {
    333                     /*
    334                      * This is the case where an original reference to a resource
    335                      * descriptor field has been replaced by an (Integer) offset.
    336                      * These named fields are supported at compile-time only;
    337                      * the names are not passed to the interpreter (via the AML).
    338                      */
    339                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
    340                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    341                     {
    342                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
    343                     }
    344                     else
    345                     {
    346                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
    347                     }
    348                     break;
    349                 }
    350 
    351                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
    352                     (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
    353                 {
    354                     break;
    355                 }
    356 
    357                 ThisNodeBtype = RequiredBtypes;
    358                 break;
    359 
    360 
    361             case ARGI_REFERENCE:            /* References */
    362             case ARGI_INTEGER_REF:
    363             case ARGI_OBJECT_REF:
    364             case ARGI_DEVICE_REF:
    365 
    366                 switch (ArgOp->Asl.ParseOpcode)
    367                 {
    368                 case PARSEOP_LOCAL0:
    369                 case PARSEOP_LOCAL1:
    370                 case PARSEOP_LOCAL2:
    371                 case PARSEOP_LOCAL3:
    372                 case PARSEOP_LOCAL4:
    373                 case PARSEOP_LOCAL5:
    374                 case PARSEOP_LOCAL6:
    375                 case PARSEOP_LOCAL7:
    376 
    377                     /* TBD: implement analysis of current value (type) of the local */
    378                     /* For now, just treat any local as a typematch */
    379 
    380                     /*ThisNodeBtype = RequiredBtypes;*/
    381                     break;
    382 
    383                 case PARSEOP_ARG0:
    384                 case PARSEOP_ARG1:
    385                 case PARSEOP_ARG2:
    386                 case PARSEOP_ARG3:
    387                 case PARSEOP_ARG4:
    388                 case PARSEOP_ARG5:
    389                 case PARSEOP_ARG6:
    390 
    391                     /* Hard to analyze argument types, sow we won't */
    392                     /* For now, just treat any arg as a typematch */
    393 
    394                     /* ThisNodeBtype = RequiredBtypes; */
    395                     break;
    396 
    397                 case PARSEOP_DEBUG:
    398                 case PARSEOP_REFOF:
    399                 case PARSEOP_INDEX:
    400                 default:
    401 
    402                     break;
    403 
    404                 }
    405                 break;
    406 
    407             case ARGI_INTEGER:
    408             default:
    409 
    410                 break;
    411             }
    412 
    413 
    414             CommonBtypes = ThisNodeBtype & RequiredBtypes;
    415 
    416             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
    417             {
    418                 if (AnIsInternalMethod (ArgOp))
    419                 {
    420                     return (AE_OK);
    421                 }
    422 
    423                 /* Check a method call for a valid return value */
    424 
    425                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
    426                     RequiredBtypes, ThisNodeBtype);
    427             }
    428 
    429             /*
    430              * Now check if the actual type(s) match at least one
    431              * bit to the required type
    432              */
    433             else if (!CommonBtypes)
    434             {
    435                 /* No match -- this is a type mismatch error */
    436 
    437                 AnFormatBtype (StringBuffer, ThisNodeBtype);
    438                 AnFormatBtype (StringBuffer2, RequiredBtypes);
    439 
    440                 snprintf (MsgBuffer, sizeof(MsgBuffer), "[%s] found, %s operator requires [%s]",
    441                             StringBuffer, OpInfo->Name, StringBuffer2);
    442 
    443                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
    444             }
    445 
    446         NextArgument:
    447             ArgOp = ArgOp->Asl.Next;
    448             INCREMENT_ARG_LIST (RuntimeArgTypes2);
    449         }
    450         break;
    451 
    452     default:
    453 
    454         break;
    455     }
    456 
    457     return (AE_OK);
    458 }
    459 
    460 
    461 /*******************************************************************************
    462  *
    463  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
    464  *
    465  * PARAMETERS:  ASL_WALK_CALLBACK
    466  *
    467  * RETURN:      Status
    468  *
    469  * DESCRIPTION: Descending callback for the analysis walk. Checks for
    470  *              miscellaneous issues in the code.
    471  *
    472  ******************************************************************************/
    473 
    474 ACPI_STATUS
    475 AnOtherSemanticAnalysisWalkBegin (
    476     ACPI_PARSE_OBJECT       *Op,
    477     UINT32                  Level,
    478     void                    *Context)
    479 {
    480     ACPI_PARSE_OBJECT       *ArgNode;
    481     ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
    482     const ACPI_OPCODE_INFO  *OpInfo;
    483     ACPI_NAMESPACE_NODE     *Node;
    484 
    485 
    486     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    487 
    488     /*
    489      * Determine if an execution class operator actually does something by
    490      * checking if it has a target and/or the function return value is used.
    491      * (Target is optional, so a standalone statement can actually do nothing.)
    492      */
    493     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
    494         (OpInfo->Flags & AML_HAS_RETVAL) &&
    495         (!AnIsResultUsed (Op)))
    496     {
    497         if (OpInfo->Flags & AML_HAS_TARGET)
    498         {
    499             /*
    500              * Find the target node, it is always the last child. If the traget
    501              * is not specified in the ASL, a default node of type Zero was
    502              * created by the parser.
    503              */
    504             ArgNode = Op->Asl.Child;
    505             while (ArgNode->Asl.Next)
    506             {
    507                 PrevArgNode = ArgNode;
    508                 ArgNode = ArgNode->Asl.Next;
    509             }
    510 
    511             /* Divide() is the only weird case, it has two targets */
    512 
    513             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
    514             {
    515                 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
    516                     (PrevArgNode) &&
    517                     (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
    518                 {
    519                     AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    520                         Op, Op->Asl.ExternalName);
    521                 }
    522             }
    523             else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
    524             {
    525                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    526                     Op, Op->Asl.ExternalName);
    527             }
    528         }
    529         else
    530         {
    531             /*
    532              * Has no target and the result is not used. Only a couple opcodes
    533              * can have this combination.
    534              */
    535             switch (Op->Asl.ParseOpcode)
    536             {
    537             case PARSEOP_ACQUIRE:
    538             case PARSEOP_WAIT:
    539             case PARSEOP_LOADTABLE:
    540 
    541                 break;
    542 
    543             default:
    544 
    545                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    546                     Op, Op->Asl.ExternalName);
    547                 break;
    548             }
    549         }
    550     }
    551 
    552 
    553     /*
    554      * Semantic checks for individual ASL operators
    555      */
    556     switch (Op->Asl.ParseOpcode)
    557     {
    558     case PARSEOP_ACQUIRE:
    559     case PARSEOP_WAIT:
    560         /*
    561          * Emit a warning if the timeout parameter for these operators is not
    562          * ACPI_WAIT_FOREVER, and the result value from the operator is not
    563          * checked, meaning that a timeout could happen, but the code
    564          * would not know about it.
    565          */
    566 
    567         /* First child is the namepath, 2nd child is timeout */
    568 
    569         ArgNode = Op->Asl.Child;
    570         ArgNode = ArgNode->Asl.Next;
    571 
    572         /*
    573          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
    574          * 0xFFFF or greater
    575          */
    576         if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
    577              (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
    578              (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
    579         {
    580             break;
    581         }
    582 
    583         /*
    584          * The operation could timeout. If the return value is not used
    585          * (indicates timeout occurred), issue a warning
    586          */
    587         if (!AnIsResultUsed (Op))
    588         {
    589             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
    590                 Op->Asl.ExternalName);
    591         }
    592         break;
    593 
    594     case PARSEOP_CREATEFIELD:
    595         /*
    596          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
    597          */
    598         ArgNode = Op->Asl.Child;
    599         ArgNode = ArgNode->Asl.Next;
    600         ArgNode = ArgNode->Asl.Next;
    601 
    602         if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
    603            ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    604             (ArgNode->Asl.Value.Integer == 0)))
    605         {
    606             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
    607         }
    608         break;
    609 
    610     case PARSEOP_CONNECTION:
    611         /*
    612          * Ensure that the referenced operation region has the correct SPACE_ID.
    613          * From the grammar/parser, we know the parent is a FIELD definition.
    614          */
    615         ArgNode = Op->Asl.Parent;       /* Field definition */
    616         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
    617         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
    618         if (!Node)
    619         {
    620             break;
    621         }
    622 
    623         ArgNode = Node->Op;             /* OpRegion definition */
    624         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
    625         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
    626 
    627         /*
    628          * The Connection() operator is only valid for the following operation
    629          * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
    630          */
    631         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
    632             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
    633         {
    634             AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
    635         }
    636         break;
    637 
    638     case PARSEOP_FIELD:
    639         /*
    640          * Ensure that fields for GeneralPurposeIo and GenericSerialBus
    641          * contain at least one Connection() operator
    642          */
    643         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
    644         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
    645         if (!Node)
    646         {
    647             break;
    648         }
    649 
    650         ArgNode = Node->Op;             /* OpRegion definition */
    651         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
    652         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
    653 
    654         /* We are only interested in GeneralPurposeIo and GenericSerialBus */
    655 
    656         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
    657             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
    658         {
    659             break;
    660         }
    661 
    662         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
    663         ArgNode = ArgNode->Asl.Next;    /* AccessType */
    664         ArgNode = ArgNode->Asl.Next;    /* LockRule */
    665         ArgNode = ArgNode->Asl.Next;    /* UpdateRule */
    666         ArgNode = ArgNode->Asl.Next;    /* Start of FieldUnitList */
    667 
    668         /* Walk the FieldUnitList */
    669 
    670         while (ArgNode)
    671         {
    672             if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION)
    673             {
    674                 break;
    675             }
    676             else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG)
    677             {
    678                 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL);
    679                 break;
    680             }
    681 
    682             ArgNode = ArgNode->Asl.Next;
    683         }
    684         break;
    685 
    686     default:
    687 
    688         break;
    689     }
    690 
    691     return (AE_OK);
    692 }
    693