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