1efcc2a30SJung-uk Kim /****************************************************************************** 2efcc2a30SJung-uk Kim * 3efcc2a30SJung-uk Kim * Module Name: aslmethod.c - Control method analysis walk 4efcc2a30SJung-uk Kim * 5efcc2a30SJung-uk Kim *****************************************************************************/ 6efcc2a30SJung-uk Kim 7efcc2a30SJung-uk Kim /* 8efcc2a30SJung-uk Kim * Copyright (C) 2000 - 2013, Intel Corp. 9efcc2a30SJung-uk Kim * All rights reserved. 10efcc2a30SJung-uk Kim * 11efcc2a30SJung-uk Kim * Redistribution and use in source and binary forms, with or without 12efcc2a30SJung-uk Kim * modification, are permitted provided that the following conditions 13efcc2a30SJung-uk Kim * are met: 14efcc2a30SJung-uk Kim * 1. Redistributions of source code must retain the above copyright 15efcc2a30SJung-uk Kim * notice, this list of conditions, and the following disclaimer, 16efcc2a30SJung-uk Kim * without modification. 17efcc2a30SJung-uk Kim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18efcc2a30SJung-uk Kim * substantially similar to the "NO WARRANTY" disclaimer below 19efcc2a30SJung-uk Kim * ("Disclaimer") and any redistribution must be conditioned upon 20efcc2a30SJung-uk Kim * including a substantially similar Disclaimer requirement for further 21efcc2a30SJung-uk Kim * binary redistribution. 22efcc2a30SJung-uk Kim * 3. Neither the names of the above-listed copyright holders nor the names 23efcc2a30SJung-uk Kim * of any contributors may be used to endorse or promote products derived 24efcc2a30SJung-uk Kim * from this software without specific prior written permission. 25efcc2a30SJung-uk Kim * 26efcc2a30SJung-uk Kim * Alternatively, this software may be distributed under the terms of the 27efcc2a30SJung-uk Kim * GNU General Public License ("GPL") version 2 as published by the Free 28efcc2a30SJung-uk Kim * Software Foundation. 29efcc2a30SJung-uk Kim * 30efcc2a30SJung-uk Kim * NO WARRANTY 31efcc2a30SJung-uk Kim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32efcc2a30SJung-uk Kim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33efcc2a30SJung-uk Kim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34efcc2a30SJung-uk Kim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35efcc2a30SJung-uk Kim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36efcc2a30SJung-uk Kim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37efcc2a30SJung-uk Kim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38efcc2a30SJung-uk Kim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39efcc2a30SJung-uk Kim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40efcc2a30SJung-uk Kim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41efcc2a30SJung-uk Kim * POSSIBILITY OF SUCH DAMAGES. 42efcc2a30SJung-uk Kim */ 43efcc2a30SJung-uk Kim 44efcc2a30SJung-uk Kim 45efcc2a30SJung-uk Kim #include <contrib/dev/acpica/compiler/aslcompiler.h> 46efcc2a30SJung-uk Kim #include "aslcompiler.y.h" 47a9d8d09cSJung-uk Kim #include <contrib/dev/acpica/include/acparser.h> 48a9d8d09cSJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h> 49efcc2a30SJung-uk Kim 50efcc2a30SJung-uk Kim 51efcc2a30SJung-uk Kim #define _COMPONENT ACPI_COMPILER 52efcc2a30SJung-uk Kim ACPI_MODULE_NAME ("aslmethod") 53efcc2a30SJung-uk Kim 54efcc2a30SJung-uk Kim 55a9d8d09cSJung-uk Kim /* Local prototypes */ 56a9d8d09cSJung-uk Kim 57a9d8d09cSJung-uk Kim void 58a9d8d09cSJung-uk Kim MtCheckNamedObjectInMethod ( 59a9d8d09cSJung-uk Kim ACPI_PARSE_OBJECT *Op, 60a9d8d09cSJung-uk Kim ASL_METHOD_INFO *MethodInfo); 61a9d8d09cSJung-uk Kim 62a9d8d09cSJung-uk Kim 63efcc2a30SJung-uk Kim /******************************************************************************* 64efcc2a30SJung-uk Kim * 65efcc2a30SJung-uk Kim * FUNCTION: MtMethodAnalysisWalkBegin 66efcc2a30SJung-uk Kim * 67efcc2a30SJung-uk Kim * PARAMETERS: ASL_WALK_CALLBACK 68efcc2a30SJung-uk Kim * 69efcc2a30SJung-uk Kim * RETURN: Status 70efcc2a30SJung-uk Kim * 71efcc2a30SJung-uk Kim * DESCRIPTION: Descending callback for the analysis walk. Check methods for: 72efcc2a30SJung-uk Kim * 1) Initialized local variables 73efcc2a30SJung-uk Kim * 2) Valid arguments 74efcc2a30SJung-uk Kim * 3) Return types 75efcc2a30SJung-uk Kim * 76efcc2a30SJung-uk Kim ******************************************************************************/ 77efcc2a30SJung-uk Kim 78efcc2a30SJung-uk Kim ACPI_STATUS 79efcc2a30SJung-uk Kim MtMethodAnalysisWalkBegin ( 80efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *Op, 81efcc2a30SJung-uk Kim UINT32 Level, 82efcc2a30SJung-uk Kim void *Context) 83efcc2a30SJung-uk Kim { 84efcc2a30SJung-uk Kim ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 85efcc2a30SJung-uk Kim ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 86efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *Next; 87efcc2a30SJung-uk Kim UINT32 RegisterNumber; 88efcc2a30SJung-uk Kim UINT32 i; 89efcc2a30SJung-uk Kim char LocalName[] = "Local0"; 90efcc2a30SJung-uk Kim char ArgName[] = "Arg0"; 91efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *ArgNode; 92efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *NextType; 93efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *NextParamType; 94efcc2a30SJung-uk Kim UINT8 ActualArgs = 0; 95efcc2a30SJung-uk Kim 96efcc2a30SJung-uk Kim 97efcc2a30SJung-uk Kim switch (Op->Asl.ParseOpcode) 98efcc2a30SJung-uk Kim { 99efcc2a30SJung-uk Kim case PARSEOP_METHOD: 100efcc2a30SJung-uk Kim 101efcc2a30SJung-uk Kim TotalMethods++; 102efcc2a30SJung-uk Kim 103efcc2a30SJung-uk Kim /* Create and init method info */ 104efcc2a30SJung-uk Kim 105efcc2a30SJung-uk Kim MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); 106efcc2a30SJung-uk Kim MethodInfo->Next = WalkInfo->MethodStack; 107efcc2a30SJung-uk Kim MethodInfo->Op = Op; 108efcc2a30SJung-uk Kim 109efcc2a30SJung-uk Kim WalkInfo->MethodStack = MethodInfo; 110efcc2a30SJung-uk Kim 111efcc2a30SJung-uk Kim /* Get the name node, ignored here */ 112efcc2a30SJung-uk Kim 113efcc2a30SJung-uk Kim Next = Op->Asl.Child; 114efcc2a30SJung-uk Kim 115efcc2a30SJung-uk Kim /* Get the NumArguments node */ 116efcc2a30SJung-uk Kim 117efcc2a30SJung-uk Kim Next = Next->Asl.Next; 118efcc2a30SJung-uk Kim MethodInfo->NumArguments = (UINT8) 119efcc2a30SJung-uk Kim (((UINT8) Next->Asl.Value.Integer) & 0x07); 120efcc2a30SJung-uk Kim 121efcc2a30SJung-uk Kim /* Get the SerializeRule and SyncLevel nodes, ignored here */ 122efcc2a30SJung-uk Kim 123efcc2a30SJung-uk Kim Next = Next->Asl.Next; 124a9d8d09cSJung-uk Kim MethodInfo->ShouldBeSerialized = (UINT8) Next->Asl.Value.Integer; 125a9d8d09cSJung-uk Kim 126efcc2a30SJung-uk Kim Next = Next->Asl.Next; 127efcc2a30SJung-uk Kim ArgNode = Next; 128efcc2a30SJung-uk Kim 129efcc2a30SJung-uk Kim /* Get the ReturnType node */ 130efcc2a30SJung-uk Kim 131efcc2a30SJung-uk Kim Next = Next->Asl.Next; 132efcc2a30SJung-uk Kim 133efcc2a30SJung-uk Kim NextType = Next->Asl.Child; 134efcc2a30SJung-uk Kim while (NextType) 135efcc2a30SJung-uk Kim { 136efcc2a30SJung-uk Kim /* Get and map each of the ReturnTypes */ 137efcc2a30SJung-uk Kim 138efcc2a30SJung-uk Kim MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); 139efcc2a30SJung-uk Kim NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 140efcc2a30SJung-uk Kim NextType = NextType->Asl.Next; 141efcc2a30SJung-uk Kim } 142efcc2a30SJung-uk Kim 143efcc2a30SJung-uk Kim /* Get the ParameterType node */ 144efcc2a30SJung-uk Kim 145efcc2a30SJung-uk Kim Next = Next->Asl.Next; 146efcc2a30SJung-uk Kim 147efcc2a30SJung-uk Kim NextType = Next->Asl.Child; 148efcc2a30SJung-uk Kim while (NextType) 149efcc2a30SJung-uk Kim { 150efcc2a30SJung-uk Kim if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 151efcc2a30SJung-uk Kim { 152efcc2a30SJung-uk Kim NextParamType = NextType->Asl.Child; 153efcc2a30SJung-uk Kim while (NextParamType) 154efcc2a30SJung-uk Kim { 155efcc2a30SJung-uk Kim MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType); 156efcc2a30SJung-uk Kim NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 157efcc2a30SJung-uk Kim NextParamType = NextParamType->Asl.Next; 158efcc2a30SJung-uk Kim } 159efcc2a30SJung-uk Kim } 160efcc2a30SJung-uk Kim else 161efcc2a30SJung-uk Kim { 162efcc2a30SJung-uk Kim MethodInfo->ValidArgTypes[ActualArgs] = 163efcc2a30SJung-uk Kim AnMapObjTypeToBtype (NextType); 164efcc2a30SJung-uk Kim NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 165efcc2a30SJung-uk Kim ActualArgs++; 166efcc2a30SJung-uk Kim } 167efcc2a30SJung-uk Kim 168efcc2a30SJung-uk Kim NextType = NextType->Asl.Next; 169efcc2a30SJung-uk Kim } 170efcc2a30SJung-uk Kim 171efcc2a30SJung-uk Kim if ((MethodInfo->NumArguments) && 172efcc2a30SJung-uk Kim (MethodInfo->NumArguments != ActualArgs)) 173efcc2a30SJung-uk Kim { 174efcc2a30SJung-uk Kim /* error: Param list did not match number of args */ 175efcc2a30SJung-uk Kim } 176efcc2a30SJung-uk Kim 177efcc2a30SJung-uk Kim /* Allow numarguments == 0 for Function() */ 178efcc2a30SJung-uk Kim 179efcc2a30SJung-uk Kim if ((!MethodInfo->NumArguments) && (ActualArgs)) 180efcc2a30SJung-uk Kim { 181efcc2a30SJung-uk Kim MethodInfo->NumArguments = ActualArgs; 182efcc2a30SJung-uk Kim ArgNode->Asl.Value.Integer |= ActualArgs; 183efcc2a30SJung-uk Kim } 184efcc2a30SJung-uk Kim 185efcc2a30SJung-uk Kim /* 186efcc2a30SJung-uk Kim * Actual arguments are initialized at method entry. 187efcc2a30SJung-uk Kim * All other ArgX "registers" can be used as locals, so we 188efcc2a30SJung-uk Kim * track their initialization. 189efcc2a30SJung-uk Kim */ 190efcc2a30SJung-uk Kim for (i = 0; i < MethodInfo->NumArguments; i++) 191efcc2a30SJung-uk Kim { 192efcc2a30SJung-uk Kim MethodInfo->ArgInitialized[i] = TRUE; 193efcc2a30SJung-uk Kim } 194efcc2a30SJung-uk Kim break; 195efcc2a30SJung-uk Kim 196efcc2a30SJung-uk Kim case PARSEOP_METHODCALL: 197efcc2a30SJung-uk Kim 198efcc2a30SJung-uk Kim if (MethodInfo && 199efcc2a30SJung-uk Kim (Op->Asl.Node == MethodInfo->Op->Asl.Node)) 200efcc2a30SJung-uk Kim { 201efcc2a30SJung-uk Kim AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); 202efcc2a30SJung-uk Kim } 203efcc2a30SJung-uk Kim break; 204efcc2a30SJung-uk Kim 205efcc2a30SJung-uk Kim case PARSEOP_LOCAL0: 206efcc2a30SJung-uk Kim case PARSEOP_LOCAL1: 207efcc2a30SJung-uk Kim case PARSEOP_LOCAL2: 208efcc2a30SJung-uk Kim case PARSEOP_LOCAL3: 209efcc2a30SJung-uk Kim case PARSEOP_LOCAL4: 210efcc2a30SJung-uk Kim case PARSEOP_LOCAL5: 211efcc2a30SJung-uk Kim case PARSEOP_LOCAL6: 212efcc2a30SJung-uk Kim case PARSEOP_LOCAL7: 213efcc2a30SJung-uk Kim 214efcc2a30SJung-uk Kim if (!MethodInfo) 215efcc2a30SJung-uk Kim { 216efcc2a30SJung-uk Kim /* 217efcc2a30SJung-uk Kim * Local was used outside a control method, or there was an error 218efcc2a30SJung-uk Kim * in the method declaration. 219efcc2a30SJung-uk Kim */ 220efcc2a30SJung-uk Kim AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); 221efcc2a30SJung-uk Kim return (AE_ERROR); 222efcc2a30SJung-uk Kim } 223efcc2a30SJung-uk Kim 224efcc2a30SJung-uk Kim RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); 225efcc2a30SJung-uk Kim 226efcc2a30SJung-uk Kim /* 227efcc2a30SJung-uk Kim * If the local is being used as a target, mark the local 228efcc2a30SJung-uk Kim * initialized 229efcc2a30SJung-uk Kim */ 230efcc2a30SJung-uk Kim if (Op->Asl.CompileFlags & NODE_IS_TARGET) 231efcc2a30SJung-uk Kim { 232efcc2a30SJung-uk Kim MethodInfo->LocalInitialized[RegisterNumber] = TRUE; 233efcc2a30SJung-uk Kim } 234efcc2a30SJung-uk Kim 235efcc2a30SJung-uk Kim /* 236efcc2a30SJung-uk Kim * Otherwise, this is a reference, check if the local 237efcc2a30SJung-uk Kim * has been previously initialized. 238efcc2a30SJung-uk Kim * 239efcc2a30SJung-uk Kim * The only operator that accepts an uninitialized value is ObjectType() 240efcc2a30SJung-uk Kim */ 241efcc2a30SJung-uk Kim else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && 242efcc2a30SJung-uk Kim (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 243efcc2a30SJung-uk Kim { 244efcc2a30SJung-uk Kim LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); 245efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); 246efcc2a30SJung-uk Kim } 247efcc2a30SJung-uk Kim break; 248efcc2a30SJung-uk Kim 249efcc2a30SJung-uk Kim case PARSEOP_ARG0: 250efcc2a30SJung-uk Kim case PARSEOP_ARG1: 251efcc2a30SJung-uk Kim case PARSEOP_ARG2: 252efcc2a30SJung-uk Kim case PARSEOP_ARG3: 253efcc2a30SJung-uk Kim case PARSEOP_ARG4: 254efcc2a30SJung-uk Kim case PARSEOP_ARG5: 255efcc2a30SJung-uk Kim case PARSEOP_ARG6: 256efcc2a30SJung-uk Kim 257efcc2a30SJung-uk Kim if (!MethodInfo) 258efcc2a30SJung-uk Kim { 259efcc2a30SJung-uk Kim /* 260efcc2a30SJung-uk Kim * Arg was used outside a control method, or there was an error 261efcc2a30SJung-uk Kim * in the method declaration. 262efcc2a30SJung-uk Kim */ 263efcc2a30SJung-uk Kim AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); 264efcc2a30SJung-uk Kim return (AE_ERROR); 265efcc2a30SJung-uk Kim } 266efcc2a30SJung-uk Kim 267efcc2a30SJung-uk Kim RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; 268efcc2a30SJung-uk Kim ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); 269efcc2a30SJung-uk Kim 270efcc2a30SJung-uk Kim /* 271efcc2a30SJung-uk Kim * If the Arg is being used as a target, mark the local 272efcc2a30SJung-uk Kim * initialized 273efcc2a30SJung-uk Kim */ 274efcc2a30SJung-uk Kim if (Op->Asl.CompileFlags & NODE_IS_TARGET) 275efcc2a30SJung-uk Kim { 276efcc2a30SJung-uk Kim MethodInfo->ArgInitialized[RegisterNumber] = TRUE; 277efcc2a30SJung-uk Kim } 278efcc2a30SJung-uk Kim 279efcc2a30SJung-uk Kim /* 280efcc2a30SJung-uk Kim * Otherwise, this is a reference, check if the Arg 281efcc2a30SJung-uk Kim * has been previously initialized. 282efcc2a30SJung-uk Kim * 283efcc2a30SJung-uk Kim * The only operator that accepts an uninitialized value is ObjectType() 284efcc2a30SJung-uk Kim */ 285efcc2a30SJung-uk Kim else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && 286efcc2a30SJung-uk Kim (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 287efcc2a30SJung-uk Kim { 288efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); 289efcc2a30SJung-uk Kim } 290efcc2a30SJung-uk Kim 291efcc2a30SJung-uk Kim /* Flag this arg if it is not a "real" argument to the method */ 292efcc2a30SJung-uk Kim 293efcc2a30SJung-uk Kim if (RegisterNumber >= MethodInfo->NumArguments) 294efcc2a30SJung-uk Kim { 295efcc2a30SJung-uk Kim AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); 296efcc2a30SJung-uk Kim } 297efcc2a30SJung-uk Kim break; 298efcc2a30SJung-uk Kim 299efcc2a30SJung-uk Kim case PARSEOP_RETURN: 300efcc2a30SJung-uk Kim 301efcc2a30SJung-uk Kim if (!MethodInfo) 302efcc2a30SJung-uk Kim { 303efcc2a30SJung-uk Kim /* 304efcc2a30SJung-uk Kim * Probably was an error in the method declaration, 305efcc2a30SJung-uk Kim * no additional error here 306efcc2a30SJung-uk Kim */ 307efcc2a30SJung-uk Kim ACPI_WARNING ((AE_INFO, "%p, No parent method", Op)); 308efcc2a30SJung-uk Kim return (AE_ERROR); 309efcc2a30SJung-uk Kim } 310efcc2a30SJung-uk Kim 311efcc2a30SJung-uk Kim /* 312efcc2a30SJung-uk Kim * A child indicates a possible return value. A simple Return or 313efcc2a30SJung-uk Kim * Return() is marked with NODE_IS_NULL_RETURN by the parser so 314efcc2a30SJung-uk Kim * that it is not counted as a "real" return-with-value, although 315efcc2a30SJung-uk Kim * the AML code that is actually emitted is Return(0). The AML 316efcc2a30SJung-uk Kim * definition of Return has a required parameter, so we are 317efcc2a30SJung-uk Kim * forced to convert a null return to Return(0). 318efcc2a30SJung-uk Kim */ 319efcc2a30SJung-uk Kim if ((Op->Asl.Child) && 320efcc2a30SJung-uk Kim (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && 321efcc2a30SJung-uk Kim (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN))) 322efcc2a30SJung-uk Kim { 323efcc2a30SJung-uk Kim MethodInfo->NumReturnWithValue++; 324efcc2a30SJung-uk Kim } 325efcc2a30SJung-uk Kim else 326efcc2a30SJung-uk Kim { 327efcc2a30SJung-uk Kim MethodInfo->NumReturnNoValue++; 328efcc2a30SJung-uk Kim } 329efcc2a30SJung-uk Kim break; 330efcc2a30SJung-uk Kim 331efcc2a30SJung-uk Kim case PARSEOP_BREAK: 332efcc2a30SJung-uk Kim case PARSEOP_CONTINUE: 333efcc2a30SJung-uk Kim 334efcc2a30SJung-uk Kim Next = Op->Asl.Parent; 335efcc2a30SJung-uk Kim while (Next) 336efcc2a30SJung-uk Kim { 337efcc2a30SJung-uk Kim if (Next->Asl.ParseOpcode == PARSEOP_WHILE) 338efcc2a30SJung-uk Kim { 339efcc2a30SJung-uk Kim break; 340efcc2a30SJung-uk Kim } 341efcc2a30SJung-uk Kim Next = Next->Asl.Parent; 342efcc2a30SJung-uk Kim } 343efcc2a30SJung-uk Kim 344efcc2a30SJung-uk Kim if (!Next) 345efcc2a30SJung-uk Kim { 346efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); 347efcc2a30SJung-uk Kim } 348efcc2a30SJung-uk Kim break; 349efcc2a30SJung-uk Kim 350efcc2a30SJung-uk Kim case PARSEOP_STALL: 351efcc2a30SJung-uk Kim 352efcc2a30SJung-uk Kim /* We can range check if the argument is an integer */ 353efcc2a30SJung-uk Kim 354efcc2a30SJung-uk Kim if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 355efcc2a30SJung-uk Kim (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) 356efcc2a30SJung-uk Kim { 357efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); 358efcc2a30SJung-uk Kim } 359efcc2a30SJung-uk Kim break; 360efcc2a30SJung-uk Kim 361efcc2a30SJung-uk Kim case PARSEOP_DEVICE: 362efcc2a30SJung-uk Kim case PARSEOP_EVENT: 363efcc2a30SJung-uk Kim case PARSEOP_MUTEX: 364efcc2a30SJung-uk Kim case PARSEOP_OPERATIONREGION: 365efcc2a30SJung-uk Kim case PARSEOP_POWERRESOURCE: 366efcc2a30SJung-uk Kim case PARSEOP_PROCESSOR: 367efcc2a30SJung-uk Kim case PARSEOP_THERMALZONE: 368efcc2a30SJung-uk Kim 369efcc2a30SJung-uk Kim /* 370efcc2a30SJung-uk Kim * The first operand is a name to be created in the namespace. 371efcc2a30SJung-uk Kim * Check against the reserved list. 372efcc2a30SJung-uk Kim */ 373efcc2a30SJung-uk Kim i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); 374efcc2a30SJung-uk Kim if (i < ACPI_VALID_RESERVED_NAME_MAX) 375efcc2a30SJung-uk Kim { 376efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); 377efcc2a30SJung-uk Kim } 378efcc2a30SJung-uk Kim break; 379efcc2a30SJung-uk Kim 380efcc2a30SJung-uk Kim case PARSEOP_NAME: 381efcc2a30SJung-uk Kim 382efcc2a30SJung-uk Kim /* Typecheck any predefined names statically defined with Name() */ 383efcc2a30SJung-uk Kim 384efcc2a30SJung-uk Kim ApCheckForPredefinedObject (Op, Op->Asl.NameSeg); 385efcc2a30SJung-uk Kim 386efcc2a30SJung-uk Kim /* Special typechecking for _HID */ 387efcc2a30SJung-uk Kim 388efcc2a30SJung-uk Kim if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg)) 389efcc2a30SJung-uk Kim { 390efcc2a30SJung-uk Kim Next = Op->Asl.Child->Asl.Next; 391efcc2a30SJung-uk Kim AnCheckId (Next, ASL_TYPE_HID); 392efcc2a30SJung-uk Kim } 393efcc2a30SJung-uk Kim 394efcc2a30SJung-uk Kim /* Special typechecking for _CID */ 395efcc2a30SJung-uk Kim 396efcc2a30SJung-uk Kim else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg)) 397efcc2a30SJung-uk Kim { 398efcc2a30SJung-uk Kim Next = Op->Asl.Child->Asl.Next; 399efcc2a30SJung-uk Kim 400efcc2a30SJung-uk Kim if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) || 401efcc2a30SJung-uk Kim (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) 402efcc2a30SJung-uk Kim { 403efcc2a30SJung-uk Kim Next = Next->Asl.Child; 404efcc2a30SJung-uk Kim while (Next) 405efcc2a30SJung-uk Kim { 406efcc2a30SJung-uk Kim AnCheckId (Next, ASL_TYPE_CID); 407efcc2a30SJung-uk Kim Next = Next->Asl.Next; 408efcc2a30SJung-uk Kim } 409efcc2a30SJung-uk Kim } 410efcc2a30SJung-uk Kim else 411efcc2a30SJung-uk Kim { 412efcc2a30SJung-uk Kim AnCheckId (Next, ASL_TYPE_CID); 413efcc2a30SJung-uk Kim } 414efcc2a30SJung-uk Kim } 415efcc2a30SJung-uk Kim break; 416efcc2a30SJung-uk Kim 417efcc2a30SJung-uk Kim default: 418a9d8d09cSJung-uk Kim 419efcc2a30SJung-uk Kim break; 420efcc2a30SJung-uk Kim } 421efcc2a30SJung-uk Kim 422a9d8d09cSJung-uk Kim /* Check for named object creation within a non-serialized method */ 423a9d8d09cSJung-uk Kim 424a9d8d09cSJung-uk Kim MtCheckNamedObjectInMethod (Op, MethodInfo); 425efcc2a30SJung-uk Kim return (AE_OK); 426efcc2a30SJung-uk Kim } 427efcc2a30SJung-uk Kim 428efcc2a30SJung-uk Kim 429efcc2a30SJung-uk Kim /******************************************************************************* 430efcc2a30SJung-uk Kim * 431a9d8d09cSJung-uk Kim * FUNCTION: MtCheckNamedObjectInMethod 432a9d8d09cSJung-uk Kim * 433a9d8d09cSJung-uk Kim * PARAMETERS: Op - Current parser op 434a9d8d09cSJung-uk Kim * MethodInfo - Info for method being parsed 435a9d8d09cSJung-uk Kim * 436a9d8d09cSJung-uk Kim * RETURN: None 437a9d8d09cSJung-uk Kim * 438a9d8d09cSJung-uk Kim * DESCRIPTION: Detect if a non-serialized method is creating a named object, 439a9d8d09cSJung-uk Kim * which could possibly cause problems if two threads execute 440a9d8d09cSJung-uk Kim * the method concurrently. Emit a remark in this case. 441a9d8d09cSJung-uk Kim * 442a9d8d09cSJung-uk Kim ******************************************************************************/ 443a9d8d09cSJung-uk Kim 444a9d8d09cSJung-uk Kim void 445a9d8d09cSJung-uk Kim MtCheckNamedObjectInMethod ( 446a9d8d09cSJung-uk Kim ACPI_PARSE_OBJECT *Op, 447a9d8d09cSJung-uk Kim ASL_METHOD_INFO *MethodInfo) 448a9d8d09cSJung-uk Kim { 449a9d8d09cSJung-uk Kim const ACPI_OPCODE_INFO *OpInfo; 450a9d8d09cSJung-uk Kim 451a9d8d09cSJung-uk Kim 452a9d8d09cSJung-uk Kim /* We don't care about actual method declarations */ 453a9d8d09cSJung-uk Kim 454a9d8d09cSJung-uk Kim if (Op->Asl.AmlOpcode == AML_METHOD_OP) 455a9d8d09cSJung-uk Kim { 456a9d8d09cSJung-uk Kim return; 457a9d8d09cSJung-uk Kim } 458a9d8d09cSJung-uk Kim 459a9d8d09cSJung-uk Kim /* Determine if we are creating a named object */ 460a9d8d09cSJung-uk Kim 461a9d8d09cSJung-uk Kim OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 462a9d8d09cSJung-uk Kim if (OpInfo->Class == AML_CLASS_NAMED_OBJECT) 463a9d8d09cSJung-uk Kim { 464a9d8d09cSJung-uk Kim /* 465a9d8d09cSJung-uk Kim * If we have a named object created within a non-serialized method, 466a9d8d09cSJung-uk Kim * emit a remark that the method should be serialized. 467a9d8d09cSJung-uk Kim * 468a9d8d09cSJung-uk Kim * Reason: If a thread blocks within the method for any reason, and 469a9d8d09cSJung-uk Kim * another thread enters the method, the method will fail because an 470a9d8d09cSJung-uk Kim * attempt will be made to create the same object twice. 471a9d8d09cSJung-uk Kim */ 472a9d8d09cSJung-uk Kim if (MethodInfo && !MethodInfo->ShouldBeSerialized) 473a9d8d09cSJung-uk Kim { 474a9d8d09cSJung-uk Kim AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op, 475a9d8d09cSJung-uk Kim "due to creation of named objects within"); 476a9d8d09cSJung-uk Kim 477a9d8d09cSJung-uk Kim /* Emit message only ONCE per method */ 478a9d8d09cSJung-uk Kim 479a9d8d09cSJung-uk Kim MethodInfo->ShouldBeSerialized = TRUE; 480a9d8d09cSJung-uk Kim } 481a9d8d09cSJung-uk Kim } 482a9d8d09cSJung-uk Kim } 483a9d8d09cSJung-uk Kim 484a9d8d09cSJung-uk Kim 485a9d8d09cSJung-uk Kim /******************************************************************************* 486a9d8d09cSJung-uk Kim * 487efcc2a30SJung-uk Kim * FUNCTION: MtMethodAnalysisWalkEnd 488efcc2a30SJung-uk Kim * 489efcc2a30SJung-uk Kim * PARAMETERS: ASL_WALK_CALLBACK 490efcc2a30SJung-uk Kim * 491efcc2a30SJung-uk Kim * RETURN: Status 492efcc2a30SJung-uk Kim * 493efcc2a30SJung-uk Kim * DESCRIPTION: Ascending callback for analysis walk. Complete method 494efcc2a30SJung-uk Kim * return analysis. 495efcc2a30SJung-uk Kim * 496efcc2a30SJung-uk Kim ******************************************************************************/ 497efcc2a30SJung-uk Kim 498efcc2a30SJung-uk Kim ACPI_STATUS 499efcc2a30SJung-uk Kim MtMethodAnalysisWalkEnd ( 500efcc2a30SJung-uk Kim ACPI_PARSE_OBJECT *Op, 501efcc2a30SJung-uk Kim UINT32 Level, 502efcc2a30SJung-uk Kim void *Context) 503efcc2a30SJung-uk Kim { 504efcc2a30SJung-uk Kim ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 505efcc2a30SJung-uk Kim ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 506efcc2a30SJung-uk Kim 507efcc2a30SJung-uk Kim 508efcc2a30SJung-uk Kim switch (Op->Asl.ParseOpcode) 509efcc2a30SJung-uk Kim { 510efcc2a30SJung-uk Kim case PARSEOP_METHOD: 511efcc2a30SJung-uk Kim case PARSEOP_RETURN: 512a9d8d09cSJung-uk Kim 513efcc2a30SJung-uk Kim if (!MethodInfo) 514efcc2a30SJung-uk Kim { 515efcc2a30SJung-uk Kim printf ("No method info for method! [%s]\n", Op->Asl.Namepath); 516efcc2a30SJung-uk Kim AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, 517efcc2a30SJung-uk Kim "No method info for this method"); 518efcc2a30SJung-uk Kim 519efcc2a30SJung-uk Kim CmCleanupAndExit (); 520efcc2a30SJung-uk Kim return (AE_AML_INTERNAL); 521efcc2a30SJung-uk Kim } 522efcc2a30SJung-uk Kim break; 523efcc2a30SJung-uk Kim 524efcc2a30SJung-uk Kim default: 525a9d8d09cSJung-uk Kim 526efcc2a30SJung-uk Kim break; 527efcc2a30SJung-uk Kim } 528efcc2a30SJung-uk Kim 529efcc2a30SJung-uk Kim switch (Op->Asl.ParseOpcode) 530efcc2a30SJung-uk Kim { 531efcc2a30SJung-uk Kim case PARSEOP_METHOD: 532efcc2a30SJung-uk Kim 533efcc2a30SJung-uk Kim WalkInfo->MethodStack = MethodInfo->Next; 534efcc2a30SJung-uk Kim 535efcc2a30SJung-uk Kim /* 536efcc2a30SJung-uk Kim * Check if there is no return statement at the end of the 537efcc2a30SJung-uk Kim * method AND we can actually get there -- i.e., the execution 538efcc2a30SJung-uk Kim * of the method can possibly terminate without a return statement. 539efcc2a30SJung-uk Kim */ 540efcc2a30SJung-uk Kim if ((!AnLastStatementIsReturn (Op)) && 541efcc2a30SJung-uk Kim (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) 542efcc2a30SJung-uk Kim { 543efcc2a30SJung-uk Kim /* 544efcc2a30SJung-uk Kim * No return statement, and execution can possibly exit 545efcc2a30SJung-uk Kim * via this path. This is equivalent to Return () 546efcc2a30SJung-uk Kim */ 547efcc2a30SJung-uk Kim MethodInfo->NumReturnNoValue++; 548efcc2a30SJung-uk Kim } 549efcc2a30SJung-uk Kim 550efcc2a30SJung-uk Kim /* 551efcc2a30SJung-uk Kim * Check for case where some return statements have a return value 552efcc2a30SJung-uk Kim * and some do not. Exit without a return statement is a return with 553efcc2a30SJung-uk Kim * no value 554efcc2a30SJung-uk Kim */ 555efcc2a30SJung-uk Kim if (MethodInfo->NumReturnNoValue && 556efcc2a30SJung-uk Kim MethodInfo->NumReturnWithValue) 557efcc2a30SJung-uk Kim { 558efcc2a30SJung-uk Kim AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, 559efcc2a30SJung-uk Kim Op->Asl.ExternalName); 560efcc2a30SJung-uk Kim } 561efcc2a30SJung-uk Kim 562efcc2a30SJung-uk Kim /* 563efcc2a30SJung-uk Kim * If there are any RETURN() statements with no value, or there is a 564efcc2a30SJung-uk Kim * control path that allows the method to exit without a return value, 565efcc2a30SJung-uk Kim * we mark the method as a method that does not return a value. This 566efcc2a30SJung-uk Kim * knowledge can be used to check method invocations that expect a 567efcc2a30SJung-uk Kim * returned value. 568efcc2a30SJung-uk Kim */ 569efcc2a30SJung-uk Kim if (MethodInfo->NumReturnNoValue) 570efcc2a30SJung-uk Kim { 571efcc2a30SJung-uk Kim if (MethodInfo->NumReturnWithValue) 572efcc2a30SJung-uk Kim { 573efcc2a30SJung-uk Kim Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; 574efcc2a30SJung-uk Kim } 575efcc2a30SJung-uk Kim else 576efcc2a30SJung-uk Kim { 577efcc2a30SJung-uk Kim Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; 578efcc2a30SJung-uk Kim } 579efcc2a30SJung-uk Kim } 580efcc2a30SJung-uk Kim 581efcc2a30SJung-uk Kim /* 582efcc2a30SJung-uk Kim * Check predefined method names for correct return behavior 583efcc2a30SJung-uk Kim * and correct number of arguments. Also, some special checks 584efcc2a30SJung-uk Kim * For GPE and _REG methods. 585efcc2a30SJung-uk Kim */ 586efcc2a30SJung-uk Kim if (ApCheckForPredefinedMethod (Op, MethodInfo)) 587efcc2a30SJung-uk Kim { 588efcc2a30SJung-uk Kim /* Special check for two names like _L01 and _E01 in same scope */ 589efcc2a30SJung-uk Kim 590efcc2a30SJung-uk Kim ApCheckForGpeNameConflict (Op); 591efcc2a30SJung-uk Kim 592efcc2a30SJung-uk Kim /* 593efcc2a30SJung-uk Kim * Special check for _REG: Must have an operation region definition 594efcc2a30SJung-uk Kim * within the same scope! 595efcc2a30SJung-uk Kim */ 596efcc2a30SJung-uk Kim ApCheckRegMethod (Op); 597efcc2a30SJung-uk Kim } 598efcc2a30SJung-uk Kim 599efcc2a30SJung-uk Kim ACPI_FREE (MethodInfo); 600efcc2a30SJung-uk Kim break; 601efcc2a30SJung-uk Kim 602efcc2a30SJung-uk Kim case PARSEOP_NAME: 603efcc2a30SJung-uk Kim 604efcc2a30SJung-uk Kim /* Special check for two names like _L01 and _E01 in same scope */ 605efcc2a30SJung-uk Kim 606efcc2a30SJung-uk Kim ApCheckForGpeNameConflict (Op); 607efcc2a30SJung-uk Kim break; 608efcc2a30SJung-uk Kim 609efcc2a30SJung-uk Kim case PARSEOP_RETURN: 610efcc2a30SJung-uk Kim 611efcc2a30SJung-uk Kim /* 612efcc2a30SJung-uk Kim * If the parent is a predefined method name, attempt to typecheck 613efcc2a30SJung-uk Kim * the return value. Only static types can be validated. 614efcc2a30SJung-uk Kim */ 615efcc2a30SJung-uk Kim ApCheckPredefinedReturnValue (Op, MethodInfo); 616efcc2a30SJung-uk Kim 617efcc2a30SJung-uk Kim /* 618efcc2a30SJung-uk Kim * The parent block does not "exit" and continue execution -- the 619efcc2a30SJung-uk Kim * method is terminated here with the Return() statement. 620efcc2a30SJung-uk Kim */ 621efcc2a30SJung-uk Kim Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 622efcc2a30SJung-uk Kim 623efcc2a30SJung-uk Kim /* Used in the "typing" pass later */ 624efcc2a30SJung-uk Kim 625efcc2a30SJung-uk Kim Op->Asl.ParentMethod = MethodInfo->Op; 626efcc2a30SJung-uk Kim 627efcc2a30SJung-uk Kim /* 628efcc2a30SJung-uk Kim * If there is a peer node after the return statement, then this 629efcc2a30SJung-uk Kim * node is unreachable code -- i.e., it won't be executed because of 630efcc2a30SJung-uk Kim * the preceding Return() statement. 631efcc2a30SJung-uk Kim */ 632efcc2a30SJung-uk Kim if (Op->Asl.Next) 633efcc2a30SJung-uk Kim { 634efcc2a30SJung-uk Kim AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); 635efcc2a30SJung-uk Kim } 636efcc2a30SJung-uk Kim break; 637efcc2a30SJung-uk Kim 638efcc2a30SJung-uk Kim case PARSEOP_IF: 639efcc2a30SJung-uk Kim 640efcc2a30SJung-uk Kim if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 641efcc2a30SJung-uk Kim (Op->Asl.Next) && 642efcc2a30SJung-uk Kim (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) 643efcc2a30SJung-uk Kim { 644efcc2a30SJung-uk Kim /* 645efcc2a30SJung-uk Kim * This IF has a corresponding ELSE. The IF block has no exit, 646efcc2a30SJung-uk Kim * (it contains an unconditional Return) 647efcc2a30SJung-uk Kim * mark the ELSE block to remember this fact. 648efcc2a30SJung-uk Kim */ 649efcc2a30SJung-uk Kim Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; 650efcc2a30SJung-uk Kim } 651efcc2a30SJung-uk Kim break; 652efcc2a30SJung-uk Kim 653efcc2a30SJung-uk Kim case PARSEOP_ELSE: 654efcc2a30SJung-uk Kim 655efcc2a30SJung-uk Kim if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 656efcc2a30SJung-uk Kim (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) 657efcc2a30SJung-uk Kim { 658efcc2a30SJung-uk Kim /* 659efcc2a30SJung-uk Kim * This ELSE block has no exit and the corresponding IF block 660efcc2a30SJung-uk Kim * has no exit either. Therefore, the parent node has no exit. 661efcc2a30SJung-uk Kim */ 662efcc2a30SJung-uk Kim Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 663efcc2a30SJung-uk Kim } 664efcc2a30SJung-uk Kim break; 665efcc2a30SJung-uk Kim 666efcc2a30SJung-uk Kim 667efcc2a30SJung-uk Kim default: 668efcc2a30SJung-uk Kim 669efcc2a30SJung-uk Kim if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 670efcc2a30SJung-uk Kim (Op->Asl.Parent)) 671efcc2a30SJung-uk Kim { 672efcc2a30SJung-uk Kim /* If this node has no exit, then the parent has no exit either */ 673efcc2a30SJung-uk Kim 674efcc2a30SJung-uk Kim Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 675efcc2a30SJung-uk Kim } 676efcc2a30SJung-uk Kim break; 677efcc2a30SJung-uk Kim } 678efcc2a30SJung-uk Kim 679efcc2a30SJung-uk Kim return (AE_OK); 680efcc2a30SJung-uk Kim } 681