1 /******************************************************************************* 2 * 3 * Module Name: nseval - Object evaluation, includes control method execution 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 #define __NSEVAL_C__ 45 46 #include "acpi.h" 47 #include "accommon.h" 48 #include "acparser.h" 49 #include "acinterp.h" 50 #include "acnamesp.h" 51 52 53 #define _COMPONENT ACPI_NAMESPACE 54 ACPI_MODULE_NAME ("nseval") 55 56 /* Local prototypes */ 57 58 static void 59 AcpiNsExecModuleCode ( 60 ACPI_OPERAND_OBJECT *MethodObj, 61 ACPI_EVALUATE_INFO *Info); 62 63 64 /******************************************************************************* 65 * 66 * FUNCTION: AcpiNsEvaluate 67 * 68 * PARAMETERS: Info - Evaluation info block, contains: 69 * PrefixNode - Prefix or Method/Object Node to execute 70 * RelativePath - Name of method to execute, If NULL, the 71 * Node is the object to execute 72 * Parameters - List of parameters to pass to the method, 73 * terminated by NULL. Params itself may be 74 * NULL if no parameters are being passed. 75 * ReturnObject - Where to put method's return value (if 76 * any). If NULL, no value is returned. 77 * ParameterType - Type of Parameter list 78 * ReturnObject - Where to put method's return value (if 79 * any). If NULL, no value is returned. 80 * Flags - ACPI_IGNORE_RETURN_VALUE to delete return 81 * 82 * RETURN: Status 83 * 84 * DESCRIPTION: Execute a control method or return the current value of an 85 * ACPI namespace object. 86 * 87 * MUTEX: Locks interpreter 88 * 89 ******************************************************************************/ 90 91 ACPI_STATUS 92 AcpiNsEvaluate ( 93 ACPI_EVALUATE_INFO *Info) 94 { 95 ACPI_STATUS Status; 96 97 98 ACPI_FUNCTION_TRACE (NsEvaluate); 99 100 101 if (!Info) 102 { 103 return_ACPI_STATUS (AE_BAD_PARAMETER); 104 } 105 106 if (!Info->Node) 107 { 108 /* 109 * Get the actual namespace node for the target object if we 110 * need to. Handles these cases: 111 * 112 * 1) Null node, valid pathname from root (absolute path) 113 * 2) Node and valid pathname (path relative to Node) 114 * 3) Node, Null pathname 115 */ 116 Status = AcpiNsGetNode (Info->PrefixNode, Info->RelativePathname, 117 ACPI_NS_NO_UPSEARCH, &Info->Node); 118 if (ACPI_FAILURE (Status)) 119 { 120 return_ACPI_STATUS (Status); 121 } 122 } 123 124 /* 125 * For a method alias, we must grab the actual method node so that 126 * proper scoping context will be established before execution. 127 */ 128 if (AcpiNsGetType (Info->Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) 129 { 130 Info->Node = ACPI_CAST_PTR ( 131 ACPI_NAMESPACE_NODE, Info->Node->Object); 132 } 133 134 /* Complete the info block initialization */ 135 136 Info->ReturnObject = NULL; 137 Info->NodeFlags = Info->Node->Flags; 138 Info->ObjDesc = AcpiNsGetAttachedObject (Info->Node); 139 140 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", 141 Info->RelativePathname, Info->Node, 142 AcpiNsGetAttachedObject (Info->Node))); 143 144 /* Get info if we have a predefined name (_HID, etc.) */ 145 146 Info->Predefined = AcpiUtMatchPredefinedMethod (Info->Node->Name.Ascii); 147 148 /* Get the full pathname to the object, for use in warning messages */ 149 150 Info->FullPathname = AcpiNsGetExternalPathname (Info->Node); 151 if (!Info->FullPathname) 152 { 153 return_ACPI_STATUS (AE_NO_MEMORY); 154 } 155 156 /* Count the number of arguments being passed in */ 157 158 Info->ParamCount = 0; 159 if (Info->Parameters) 160 { 161 while (Info->Parameters[Info->ParamCount]) 162 { 163 Info->ParamCount++; 164 } 165 166 /* Warn on impossible argument count */ 167 168 if (Info->ParamCount > ACPI_METHOD_NUM_ARGS) 169 { 170 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS, 171 "Excess arguments (%u) - using only %u", 172 Info->ParamCount, ACPI_METHOD_NUM_ARGS)); 173 174 Info->ParamCount = ACPI_METHOD_NUM_ARGS; 175 } 176 } 177 178 /* 179 * For predefined names: Check that the declared argument count 180 * matches the ACPI spec -- otherwise this is a BIOS error. 181 */ 182 AcpiNsCheckAcpiCompliance (Info->FullPathname, Info->Node, 183 Info->Predefined); 184 185 /* 186 * For all names: Check that the incoming argument count for 187 * this method/object matches the actual ASL/AML definition. 188 */ 189 AcpiNsCheckArgumentCount (Info->FullPathname, Info->Node, 190 Info->ParamCount, Info->Predefined); 191 192 /* For predefined names: Typecheck all incoming arguments */ 193 194 AcpiNsCheckArgumentTypes (Info); 195 196 /* 197 * Three major evaluation cases: 198 * 199 * 1) Object types that cannot be evaluated by definition 200 * 2) The object is a control method -- execute it 201 * 3) The object is not a method -- just return it's current value 202 */ 203 switch (AcpiNsGetType (Info->Node)) 204 { 205 case ACPI_TYPE_DEVICE: 206 case ACPI_TYPE_EVENT: 207 case ACPI_TYPE_MUTEX: 208 case ACPI_TYPE_REGION: 209 case ACPI_TYPE_THERMAL: 210 case ACPI_TYPE_LOCAL_SCOPE: 211 /* 212 * 1) Disallow evaluation of certain object types. For these, 213 * object evaluation is undefined and not supported. 214 */ 215 ACPI_ERROR ((AE_INFO, 216 "%s: Evaluation of object type [%s] is not supported", 217 Info->FullPathname, 218 AcpiUtGetTypeName (Info->Node->Type))); 219 220 Status = AE_TYPE; 221 goto Cleanup; 222 223 case ACPI_TYPE_METHOD: 224 /* 225 * 2) Object is a control method - execute it 226 */ 227 228 /* Verify that there is a method object associated with this node */ 229 230 if (!Info->ObjDesc) 231 { 232 ACPI_ERROR ((AE_INFO, "%s: Method has no attached sub-object", 233 Info->FullPathname)); 234 Status = AE_NULL_OBJECT; 235 goto Cleanup; 236 } 237 238 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 239 "**** Execute method [%s] at AML address %p length %X\n", 240 Info->FullPathname, 241 Info->ObjDesc->Method.AmlStart + 1, 242 Info->ObjDesc->Method.AmlLength - 1)); 243 244 /* 245 * Any namespace deletion must acquire both the namespace and 246 * interpreter locks to ensure that no thread is using the portion of 247 * the namespace that is being deleted. 248 * 249 * Execute the method via the interpreter. The interpreter is locked 250 * here before calling into the AML parser 251 */ 252 AcpiExEnterInterpreter (); 253 Status = AcpiPsExecuteMethod (Info); 254 AcpiExExitInterpreter (); 255 break; 256 257 default: 258 /* 259 * 3) All other non-method objects -- get the current object value 260 */ 261 262 /* 263 * Some objects require additional resolution steps (e.g., the Node 264 * may be a field that must be read, etc.) -- we can't just grab 265 * the object out of the node. 266 * 267 * Use ResolveNodeToValue() to get the associated value. 268 * 269 * NOTE: we can get away with passing in NULL for a walk state because 270 * the Node is guaranteed to not be a reference to either a method 271 * local or a method argument (because this interface is never called 272 * from a running method.) 273 * 274 * Even though we do not directly invoke the interpreter for object 275 * resolution, we must lock it because we could access an OpRegion. 276 * The OpRegion access code assumes that the interpreter is locked. 277 */ 278 AcpiExEnterInterpreter (); 279 280 /* TBD: ResolveNodeToValue has a strange interface, fix */ 281 282 Info->ReturnObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->Node); 283 284 Status = AcpiExResolveNodeToValue (ACPI_CAST_INDIRECT_PTR ( 285 ACPI_NAMESPACE_NODE, &Info->ReturnObject), NULL); 286 AcpiExExitInterpreter (); 287 288 if (ACPI_FAILURE (Status)) 289 { 290 goto Cleanup; 291 } 292 293 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returned object %p [%s]\n", 294 Info->ReturnObject, 295 AcpiUtGetObjectTypeName (Info->ReturnObject))); 296 297 Status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */ 298 break; 299 } 300 301 /* 302 * For predefined names, check the return value against the ACPI 303 * specification. Some incorrect return value types are repaired. 304 */ 305 (void) AcpiNsCheckReturnValue (Info->Node, Info, Info->ParamCount, 306 Status, &Info->ReturnObject); 307 308 /* Check if there is a return value that must be dealt with */ 309 310 if (Status == AE_CTRL_RETURN_VALUE) 311 { 312 /* If caller does not want the return value, delete it */ 313 314 if (Info->Flags & ACPI_IGNORE_RETURN_VALUE) 315 { 316 AcpiUtRemoveReference (Info->ReturnObject); 317 Info->ReturnObject = NULL; 318 } 319 320 /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ 321 322 Status = AE_OK; 323 } 324 325 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 326 "*** Completed evaluation of object %s ***\n", 327 Info->RelativePathname)); 328 329 Cleanup: 330 /* 331 * Namespace was unlocked by the handling AcpiNs* function, so we 332 * just free the pathname and return 333 */ 334 ACPI_FREE (Info->FullPathname); 335 Info->FullPathname = NULL; 336 return_ACPI_STATUS (Status); 337 } 338 339 340 /******************************************************************************* 341 * 342 * FUNCTION: AcpiNsExecModuleCodeList 343 * 344 * PARAMETERS: None 345 * 346 * RETURN: None. Exceptions during method execution are ignored, since 347 * we cannot abort a table load. 348 * 349 * DESCRIPTION: Execute all elements of the global module-level code list. 350 * Each element is executed as a single control method. 351 * 352 ******************************************************************************/ 353 354 void 355 AcpiNsExecModuleCodeList ( 356 void) 357 { 358 ACPI_OPERAND_OBJECT *Prev; 359 ACPI_OPERAND_OBJECT *Next; 360 ACPI_EVALUATE_INFO *Info; 361 UINT32 MethodCount = 0; 362 363 364 ACPI_FUNCTION_TRACE (NsExecModuleCodeList); 365 366 367 /* Exit now if the list is empty */ 368 369 Next = AcpiGbl_ModuleCodeList; 370 if (!Next) 371 { 372 return_VOID; 373 } 374 375 /* Allocate the evaluation information block */ 376 377 Info = ACPI_ALLOCATE (sizeof (ACPI_EVALUATE_INFO)); 378 if (!Info) 379 { 380 return_VOID; 381 } 382 383 /* Walk the list, executing each "method" */ 384 385 while (Next) 386 { 387 Prev = Next; 388 Next = Next->Method.Mutex; 389 390 /* Clear the link field and execute the method */ 391 392 Prev->Method.Mutex = NULL; 393 AcpiNsExecModuleCode (Prev, Info); 394 MethodCount++; 395 396 /* Delete the (temporary) method object */ 397 398 AcpiUtRemoveReference (Prev); 399 } 400 401 ACPI_INFO ((AE_INFO, 402 "Executed %u blocks of module-level executable AML code", 403 MethodCount)); 404 405 ACPI_FREE (Info); 406 AcpiGbl_ModuleCodeList = NULL; 407 return_VOID; 408 } 409 410 411 /******************************************************************************* 412 * 413 * FUNCTION: AcpiNsExecModuleCode 414 * 415 * PARAMETERS: MethodObj - Object container for the module-level code 416 * Info - Info block for method evaluation 417 * 418 * RETURN: None. Exceptions during method execution are ignored, since 419 * we cannot abort a table load. 420 * 421 * DESCRIPTION: Execute a control method containing a block of module-level 422 * executable AML code. The control method is temporarily 423 * installed to the root node, then evaluated. 424 * 425 ******************************************************************************/ 426 427 static void 428 AcpiNsExecModuleCode ( 429 ACPI_OPERAND_OBJECT *MethodObj, 430 ACPI_EVALUATE_INFO *Info) 431 { 432 ACPI_OPERAND_OBJECT *ParentObj; 433 ACPI_NAMESPACE_NODE *ParentNode; 434 ACPI_OBJECT_TYPE Type; 435 ACPI_STATUS Status; 436 437 438 ACPI_FUNCTION_TRACE (NsExecModuleCode); 439 440 441 /* 442 * Get the parent node. We cheat by using the NextObject field 443 * of the method object descriptor. 444 */ 445 ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 446 MethodObj->Method.NextObject); 447 Type = AcpiNsGetType (ParentNode); 448 449 /* 450 * Get the region handler and save it in the method object. We may need 451 * this if an operation region declaration causes a _REG method to be run. 452 * 453 * We can't do this in AcpiPsLinkModuleCode because 454 * AcpiGbl_RootNode->Object is NULL at PASS1. 455 */ 456 if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object) 457 { 458 MethodObj->Method.Dispatch.Handler = 459 ParentNode->Object->Device.Handler; 460 } 461 462 /* Must clear NextObject (AcpiNsAttachObject needs the field) */ 463 464 MethodObj->Method.NextObject = NULL; 465 466 /* Initialize the evaluation information block */ 467 468 ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO)); 469 Info->PrefixNode = ParentNode; 470 471 /* 472 * Get the currently attached parent object. Add a reference, because the 473 * ref count will be decreased when the method object is installed to 474 * the parent node. 475 */ 476 ParentObj = AcpiNsGetAttachedObject (ParentNode); 477 if (ParentObj) 478 { 479 AcpiUtAddReference (ParentObj); 480 } 481 482 /* Install the method (module-level code) in the parent node */ 483 484 Status = AcpiNsAttachObject (ParentNode, MethodObj, 485 ACPI_TYPE_METHOD); 486 if (ACPI_FAILURE (Status)) 487 { 488 goto Exit; 489 } 490 491 /* Execute the parent node as a control method */ 492 493 Status = AcpiNsEvaluate (Info); 494 495 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n", 496 MethodObj->Method.AmlStart)); 497 498 /* Delete a possible implicit return value (in slack mode) */ 499 500 if (Info->ReturnObject) 501 { 502 AcpiUtRemoveReference (Info->ReturnObject); 503 } 504 505 /* Detach the temporary method object */ 506 507 AcpiNsDetachObject (ParentNode); 508 509 /* Restore the original parent object */ 510 511 if (ParentObj) 512 { 513 Status = AcpiNsAttachObject (ParentNode, ParentObj, Type); 514 } 515 else 516 { 517 ParentNode->Type = (UINT8) Type; 518 } 519 520 Exit: 521 if (ParentObj) 522 { 523 AcpiUtRemoveReference (ParentObj); 524 } 525 return_VOID; 526 }