1 /******************************************************************************* 2 * 3 * Module Name: nseval - Object evaluation, includes control method execution 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2011, 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 * Pathname - 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 ACPI_NAMESPACE_NODE *Node; 97 98 99 ACPI_FUNCTION_TRACE (NsEvaluate); 100 101 102 if (!Info) 103 { 104 return_ACPI_STATUS (AE_BAD_PARAMETER); 105 } 106 107 /* Initialize the return value to an invalid object */ 108 109 Info->ReturnObject = NULL; 110 Info->ParamCount = 0; 111 112 /* 113 * Get the actual namespace node for the target object. Handles these cases: 114 * 115 * 1) Null node, Pathname (absolute path) 116 * 2) Node, Pathname (path relative to Node) 117 * 3) Node, Null Pathname 118 */ 119 Status = AcpiNsGetNode (Info->PrefixNode, Info->Pathname, 120 ACPI_NS_NO_UPSEARCH, &Info->ResolvedNode); 121 if (ACPI_FAILURE (Status)) 122 { 123 return_ACPI_STATUS (Status); 124 } 125 126 /* 127 * For a method alias, we must grab the actual method node so that proper 128 * scoping context will be established before execution. 129 */ 130 if (AcpiNsGetType (Info->ResolvedNode) == ACPI_TYPE_LOCAL_METHOD_ALIAS) 131 { 132 Info->ResolvedNode = 133 ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Info->ResolvedNode->Object); 134 } 135 136 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", Info->Pathname, 137 Info->ResolvedNode, AcpiNsGetAttachedObject (Info->ResolvedNode))); 138 139 Node = Info->ResolvedNode; 140 141 /* 142 * Two major cases here: 143 * 144 * 1) The object is a control method -- execute it 145 * 2) The object is not a method -- just return it's current value 146 */ 147 if (AcpiNsGetType (Info->ResolvedNode) == ACPI_TYPE_METHOD) 148 { 149 /* 150 * 1) Object is a control method - execute it 151 */ 152 153 /* Verify that there is a method object associated with this node */ 154 155 Info->ObjDesc = AcpiNsGetAttachedObject (Info->ResolvedNode); 156 if (!Info->ObjDesc) 157 { 158 ACPI_ERROR ((AE_INFO, "Control method has no attached sub-object")); 159 return_ACPI_STATUS (AE_NULL_OBJECT); 160 } 161 162 /* Count the number of arguments being passed to the method */ 163 164 if (Info->Parameters) 165 { 166 while (Info->Parameters[Info->ParamCount]) 167 { 168 if (Info->ParamCount > ACPI_METHOD_MAX_ARG) 169 { 170 return_ACPI_STATUS (AE_LIMIT); 171 } 172 Info->ParamCount++; 173 } 174 } 175 176 ACPI_DUMP_PATHNAME (Info->ResolvedNode, "ACPI: Execute Method", 177 ACPI_LV_INFO, _COMPONENT); 178 179 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 180 "Method at AML address %p Length %X\n", 181 Info->ObjDesc->Method.AmlStart + 1, 182 Info->ObjDesc->Method.AmlLength - 1)); 183 184 /* 185 * Any namespace deletion must acquire both the namespace and 186 * interpreter locks to ensure that no thread is using the portion of 187 * the namespace that is being deleted. 188 * 189 * Execute the method via the interpreter. The interpreter is locked 190 * here before calling into the AML parser 191 */ 192 AcpiExEnterInterpreter (); 193 Status = AcpiPsExecuteMethod (Info); 194 AcpiExExitInterpreter (); 195 } 196 else 197 { 198 /* 199 * 2) Object is not a method, return its current value 200 * 201 * Disallow certain object types. For these, "evaluation" is undefined. 202 */ 203 switch (Info->ResolvedNode->Type) 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 ACPI_ERROR ((AE_INFO, 213 "[%4.4s] Evaluation of object type [%s] is not supported", 214 Info->ResolvedNode->Name.Ascii, 215 AcpiUtGetTypeName (Info->ResolvedNode->Type))); 216 217 return_ACPI_STATUS (AE_TYPE); 218 219 default: 220 break; 221 } 222 223 /* 224 * Objects require additional resolution steps (e.g., the Node may be 225 * a field that must be read, etc.) -- we can't just grab the object 226 * out of the node. 227 * 228 * Use ResolveNodeToValue() to get the associated value. 229 * 230 * NOTE: we can get away with passing in NULL for a walk state because 231 * ResolvedNode is guaranteed to not be a reference to either a method 232 * local or a method argument (because this interface is never called 233 * from a running method.) 234 * 235 * Even though we do not directly invoke the interpreter for object 236 * resolution, we must lock it because we could access an opregion. 237 * The opregion access code assumes that the interpreter is locked. 238 */ 239 AcpiExEnterInterpreter (); 240 241 /* Function has a strange interface */ 242 243 Status = AcpiExResolveNodeToValue (&Info->ResolvedNode, NULL); 244 AcpiExExitInterpreter (); 245 246 /* 247 * If AcpiExResolveNodeToValue() succeeded, the return value was placed 248 * in ResolvedNode. 249 */ 250 if (ACPI_SUCCESS (Status)) 251 { 252 Status = AE_CTRL_RETURN_VALUE; 253 Info->ReturnObject = 254 ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->ResolvedNode); 255 256 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n", 257 Info->ReturnObject, 258 AcpiUtGetObjectTypeName (Info->ReturnObject))); 259 } 260 } 261 262 /* 263 * Check input argument count against the ASL-defined count for a method. 264 * Also check predefined names: argument count and return value against 265 * the ACPI specification. Some incorrect return value types are repaired. 266 */ 267 (void) AcpiNsCheckPredefinedNames (Node, Info->ParamCount, 268 Status, &Info->ReturnObject); 269 270 /* Check if there is a return value that must be dealt with */ 271 272 if (Status == AE_CTRL_RETURN_VALUE) 273 { 274 /* If caller does not want the return value, delete it */ 275 276 if (Info->Flags & ACPI_IGNORE_RETURN_VALUE) 277 { 278 AcpiUtRemoveReference (Info->ReturnObject); 279 Info->ReturnObject = NULL; 280 } 281 282 /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ 283 284 Status = AE_OK; 285 } 286 287 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 288 "*** Completed evaluation of object %s ***\n", Info->Pathname)); 289 290 /* 291 * Namespace was unlocked by the handling AcpiNs* function, so we 292 * just return 293 */ 294 return_ACPI_STATUS (Status); 295 } 296 297 298 /******************************************************************************* 299 * 300 * FUNCTION: AcpiNsExecModuleCodeList 301 * 302 * PARAMETERS: None 303 * 304 * RETURN: None. Exceptions during method execution are ignored, since 305 * we cannot abort a table load. 306 * 307 * DESCRIPTION: Execute all elements of the global module-level code list. 308 * Each element is executed as a single control method. 309 * 310 ******************************************************************************/ 311 312 void 313 AcpiNsExecModuleCodeList ( 314 void) 315 { 316 ACPI_OPERAND_OBJECT *Prev; 317 ACPI_OPERAND_OBJECT *Next; 318 ACPI_EVALUATE_INFO *Info; 319 UINT32 MethodCount = 0; 320 321 322 ACPI_FUNCTION_TRACE (NsExecModuleCodeList); 323 324 325 /* Exit now if the list is empty */ 326 327 Next = AcpiGbl_ModuleCodeList; 328 if (!Next) 329 { 330 return_VOID; 331 } 332 333 /* Allocate the evaluation information block */ 334 335 Info = ACPI_ALLOCATE (sizeof (ACPI_EVALUATE_INFO)); 336 if (!Info) 337 { 338 return_VOID; 339 } 340 341 /* Walk the list, executing each "method" */ 342 343 while (Next) 344 { 345 Prev = Next; 346 Next = Next->Method.Mutex; 347 348 /* Clear the link field and execute the method */ 349 350 Prev->Method.Mutex = NULL; 351 AcpiNsExecModuleCode (Prev, Info); 352 MethodCount++; 353 354 /* Delete the (temporary) method object */ 355 356 AcpiUtRemoveReference (Prev); 357 } 358 359 ACPI_INFO ((AE_INFO, 360 "Executed %u blocks of module-level executable AML code", 361 MethodCount)); 362 363 ACPI_FREE (Info); 364 AcpiGbl_ModuleCodeList = NULL; 365 return_VOID; 366 } 367 368 369 /******************************************************************************* 370 * 371 * FUNCTION: AcpiNsExecModuleCode 372 * 373 * PARAMETERS: MethodObj - Object container for the module-level code 374 * Info - Info block for method evaluation 375 * 376 * RETURN: None. Exceptions during method execution are ignored, since 377 * we cannot abort a table load. 378 * 379 * DESCRIPTION: Execute a control method containing a block of module-level 380 * executable AML code. The control method is temporarily 381 * installed to the root node, then evaluated. 382 * 383 ******************************************************************************/ 384 385 static void 386 AcpiNsExecModuleCode ( 387 ACPI_OPERAND_OBJECT *MethodObj, 388 ACPI_EVALUATE_INFO *Info) 389 { 390 ACPI_OPERAND_OBJECT *ParentObj; 391 ACPI_NAMESPACE_NODE *ParentNode; 392 ACPI_OBJECT_TYPE Type; 393 ACPI_STATUS Status; 394 395 396 ACPI_FUNCTION_TRACE (NsExecModuleCode); 397 398 399 /* 400 * Get the parent node. We cheat by using the NextObject field 401 * of the method object descriptor. 402 */ 403 ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 404 MethodObj->Method.NextObject); 405 Type = AcpiNsGetType (ParentNode); 406 407 /* 408 * Get the region handler and save it in the method object. We may need 409 * this if an operation region declaration causes a _REG method to be run. 410 * 411 * We can't do this in AcpiPsLinkModuleCode because 412 * AcpiGbl_RootNode->Object is NULL at PASS1. 413 */ 414 if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object) 415 { 416 MethodObj->Method.Dispatch.Handler = 417 ParentNode->Object->Device.Handler; 418 } 419 420 /* Must clear NextObject (AcpiNsAttachObject needs the field) */ 421 422 MethodObj->Method.NextObject = NULL; 423 424 /* Initialize the evaluation information block */ 425 426 ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO)); 427 Info->PrefixNode = ParentNode; 428 429 /* 430 * Get the currently attached parent object. Add a reference, because the 431 * ref count will be decreased when the method object is installed to 432 * the parent node. 433 */ 434 ParentObj = AcpiNsGetAttachedObject (ParentNode); 435 if (ParentObj) 436 { 437 AcpiUtAddReference (ParentObj); 438 } 439 440 /* Install the method (module-level code) in the parent node */ 441 442 Status = AcpiNsAttachObject (ParentNode, MethodObj, 443 ACPI_TYPE_METHOD); 444 if (ACPI_FAILURE (Status)) 445 { 446 goto Exit; 447 } 448 449 /* Execute the parent node as a control method */ 450 451 Status = AcpiNsEvaluate (Info); 452 453 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n", 454 MethodObj->Method.AmlStart)); 455 456 /* Delete a possible implicit return value (in slack mode) */ 457 458 if (Info->ReturnObject) 459 { 460 AcpiUtRemoveReference (Info->ReturnObject); 461 } 462 463 /* Detach the temporary method object */ 464 465 AcpiNsDetachObject (ParentNode); 466 467 /* Restore the original parent object */ 468 469 if (ParentObj) 470 { 471 Status = AcpiNsAttachObject (ParentNode, ParentObj, Type); 472 } 473 else 474 { 475 ParentNode->Type = (UINT8) Type; 476 } 477 478 Exit: 479 if (ParentObj) 480 { 481 AcpiUtRemoveReference (ParentObj); 482 } 483 return_VOID; 484 } 485