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 
  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                 sprintf (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         if (!Node)
 609         {
 610             break;
 611         }
 612 
 613         ArgNode = Node->Op;             /* OpRegion definition */
 614         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
 615         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
 616 
 617         /*
 618          * The Connection() operator is only valid for the following operation
 619          * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
 620          */
 621         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
 622             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
 623         {
 624             AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
 625         }
 626         break;
 627 
 628     case PARSEOP_FIELD:
 629         /*
 630          * Ensure that fields for GeneralPurposeIo and GenericSerialBus
 631          * contain at least one Connection() operator
 632          */
 633         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
 634         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
 635         if (!Node)
 636         {
 637             break;
 638         }
 639 
 640         ArgNode = Node->Op;             /* OpRegion definition */
 641         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
 642         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
 643 
 644         /* We are only interested in GeneralPurposeIo and GenericSerialBus */
 645 
 646         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
 647             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
 648         {
 649             break;
 650         }
 651 
 652         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
 653         ArgNode = ArgNode->Asl.Next;    /* AccessType */
 654         ArgNode = ArgNode->Asl.Next;    /* LockRule */
 655         ArgNode = ArgNode->Asl.Next;    /* UpdateRule */
 656         ArgNode = ArgNode->Asl.Next;    /* Start of FieldUnitList */
 657 
 658         /* Walk the FieldUnitList */
 659 
 660         while (ArgNode)
 661         {
 662             if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION)
 663             {
 664                 break;
 665             }
 666             else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG)
 667             {
 668                 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL);
 669                 break;
 670             }
 671 
 672             ArgNode = ArgNode->Asl.Next;
 673         }
 674         break;
 675 
 676     default:
 677 
 678         break;
 679     }
 680 
 681     return (AE_OK);
 682 }