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