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