1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /******************************************************************************* 3 * 4 * Module Name: nseval - Object evaluation, includes control method execution 5 * 6 ******************************************************************************/ 7 8 #include <acpi/acpi.h> 9 #include "accommon.h" 10 #include "acparser.h" 11 #include "acinterp.h" 12 #include "acnamesp.h" 13 14 #define _COMPONENT ACPI_NAMESPACE 15 ACPI_MODULE_NAME("nseval") 16 17 /* Local prototypes */ 18 static void 19 acpi_ns_exec_module_code(union acpi_operand_object *method_obj, 20 struct acpi_evaluate_info *info); 21 22 /******************************************************************************* 23 * 24 * FUNCTION: acpi_ns_evaluate 25 * 26 * PARAMETERS: info - Evaluation info block, contains these fields 27 * and more: 28 * prefix_node - Prefix or Method/Object Node to execute 29 * relative_path - Name of method to execute, If NULL, the 30 * Node is the object to execute 31 * parameters - List of parameters to pass to the method, 32 * terminated by NULL. Params itself may be 33 * NULL if no parameters are being passed. 34 * parameter_type - Type of Parameter list 35 * return_object - Where to put method's return value (if 36 * any). If NULL, no value is returned. 37 * flags - ACPI_IGNORE_RETURN_VALUE to delete return 38 * 39 * RETURN: Status 40 * 41 * DESCRIPTION: Execute a control method or return the current value of an 42 * ACPI namespace object. 43 * 44 * MUTEX: Locks interpreter 45 * 46 ******************************************************************************/ 47 48 acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) 49 { 50 acpi_status status; 51 52 ACPI_FUNCTION_TRACE(ns_evaluate); 53 54 if (!info) { 55 return_ACPI_STATUS(AE_BAD_PARAMETER); 56 } 57 58 if (!info->node) { 59 /* 60 * Get the actual namespace node for the target object if we 61 * need to. Handles these cases: 62 * 63 * 1) Null node, valid pathname from root (absolute path) 64 * 2) Node and valid pathname (path relative to Node) 65 * 3) Node, Null pathname 66 */ 67 status = 68 acpi_ns_get_node(info->prefix_node, info->relative_pathname, 69 ACPI_NS_NO_UPSEARCH, &info->node); 70 if (ACPI_FAILURE(status)) { 71 return_ACPI_STATUS(status); 72 } 73 } 74 75 /* 76 * For a method alias, we must grab the actual method node so that 77 * proper scoping context will be established before execution. 78 */ 79 if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { 80 info->node = 81 ACPI_CAST_PTR(struct acpi_namespace_node, 82 info->node->object); 83 } 84 85 /* Complete the info block initialization */ 86 87 info->return_object = NULL; 88 info->node_flags = info->node->flags; 89 info->obj_desc = acpi_ns_get_attached_object(info->node); 90 91 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", 92 info->relative_pathname, info->node, 93 acpi_ns_get_attached_object(info->node))); 94 95 /* Get info if we have a predefined name (_HID, etc.) */ 96 97 info->predefined = 98 acpi_ut_match_predefined_method(info->node->name.ascii); 99 100 /* Get the full pathname to the object, for use in warning messages */ 101 102 info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE); 103 if (!info->full_pathname) { 104 return_ACPI_STATUS(AE_NO_MEMORY); 105 } 106 107 /* Optional object evaluation log */ 108 109 ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION, 110 "%-26s: %s (%s)\n", " Enter evaluation", 111 &info->full_pathname[1], 112 acpi_ut_get_type_name(info->node->type))); 113 114 /* Count the number of arguments being passed in */ 115 116 info->param_count = 0; 117 if (info->parameters) { 118 while (info->parameters[info->param_count]) { 119 info->param_count++; 120 } 121 122 /* Warn on impossible argument count */ 123 124 if (info->param_count > ACPI_METHOD_NUM_ARGS) { 125 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 126 ACPI_WARN_ALWAYS, 127 "Excess arguments (%u) - using only %u", 128 info->param_count, 129 ACPI_METHOD_NUM_ARGS)); 130 131 info->param_count = ACPI_METHOD_NUM_ARGS; 132 } 133 } 134 135 /* 136 * For predefined names: Check that the declared argument count 137 * matches the ACPI spec -- otherwise this is a BIOS error. 138 */ 139 acpi_ns_check_acpi_compliance(info->full_pathname, info->node, 140 info->predefined); 141 142 /* 143 * For all names: Check that the incoming argument count for 144 * this method/object matches the actual ASL/AML definition. 145 */ 146 acpi_ns_check_argument_count(info->full_pathname, info->node, 147 info->param_count, info->predefined); 148 149 /* For predefined names: Typecheck all incoming arguments */ 150 151 acpi_ns_check_argument_types(info); 152 153 /* 154 * Three major evaluation cases: 155 * 156 * 1) Object types that cannot be evaluated by definition 157 * 2) The object is a control method -- execute it 158 * 3) The object is not a method -- just return it's current value 159 */ 160 switch (acpi_ns_get_type(info->node)) { 161 case ACPI_TYPE_ANY: 162 case ACPI_TYPE_DEVICE: 163 case ACPI_TYPE_EVENT: 164 case ACPI_TYPE_MUTEX: 165 case ACPI_TYPE_REGION: 166 case ACPI_TYPE_THERMAL: 167 case ACPI_TYPE_LOCAL_SCOPE: 168 /* 169 * 1) Disallow evaluation of these object types. For these, 170 * object evaluation is undefined. 171 */ 172 ACPI_ERROR((AE_INFO, 173 "%s: This object type [%s] " 174 "never contains data and cannot be evaluated", 175 info->full_pathname, 176 acpi_ut_get_type_name(info->node->type))); 177 178 status = AE_TYPE; 179 goto cleanup; 180 181 case ACPI_TYPE_METHOD: 182 /* 183 * 2) Object is a control method - execute it 184 */ 185 186 /* Verify that there is a method object associated with this node */ 187 188 if (!info->obj_desc) { 189 ACPI_ERROR((AE_INFO, 190 "%s: Method has no attached sub-object", 191 info->full_pathname)); 192 status = AE_NULL_OBJECT; 193 goto cleanup; 194 } 195 196 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 197 "**** Execute method [%s] at AML address %p length %X\n", 198 info->full_pathname, 199 info->obj_desc->method.aml_start + 1, 200 info->obj_desc->method.aml_length - 1)); 201 202 /* 203 * Any namespace deletion must acquire both the namespace and 204 * interpreter locks to ensure that no thread is using the portion of 205 * the namespace that is being deleted. 206 * 207 * Execute the method via the interpreter. The interpreter is locked 208 * here before calling into the AML parser 209 */ 210 acpi_ex_enter_interpreter(); 211 status = acpi_ps_execute_method(info); 212 acpi_ex_exit_interpreter(); 213 break; 214 215 default: 216 /* 217 * 3) All other non-method objects -- get the current object value 218 */ 219 220 /* 221 * Some objects require additional resolution steps (e.g., the Node 222 * may be a field that must be read, etc.) -- we can't just grab 223 * the object out of the node. 224 * 225 * Use resolve_node_to_value() to get the associated value. 226 * 227 * NOTE: we can get away with passing in NULL for a walk state because 228 * the Node is guaranteed to not be a reference to either a method 229 * local or a method argument (because this interface is never called 230 * from a running method.) 231 * 232 * Even though we do not directly invoke the interpreter for object 233 * resolution, we must lock it because we could access an op_region. 234 * The op_region access code assumes that the interpreter is locked. 235 */ 236 acpi_ex_enter_interpreter(); 237 238 /* TBD: resolve_node_to_value has a strange interface, fix */ 239 240 info->return_object = 241 ACPI_CAST_PTR(union acpi_operand_object, info->node); 242 243 status = 244 acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR 245 (struct acpi_namespace_node, 246 &info->return_object), NULL); 247 acpi_ex_exit_interpreter(); 248 249 if (ACPI_FAILURE(status)) { 250 info->return_object = NULL; 251 goto cleanup; 252 } 253 254 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returned object %p [%s]\n", 255 info->return_object, 256 acpi_ut_get_object_type_name(info-> 257 return_object))); 258 259 status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */ 260 break; 261 } 262 263 /* 264 * For predefined names, check the return value against the ACPI 265 * specification. Some incorrect return value types are repaired. 266 */ 267 (void)acpi_ns_check_return_value(info->node, info, info->param_count, 268 status, &info->return_object); 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 acpi_ut_remove_reference(info->return_object); 278 info->return_object = NULL; 279 } 280 281 /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ 282 283 status = AE_OK; 284 } else if (ACPI_FAILURE(status)) { 285 286 /* If return_object exists, delete it */ 287 288 if (info->return_object) { 289 acpi_ut_remove_reference(info->return_object); 290 info->return_object = NULL; 291 } 292 } 293 294 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 295 "*** Completed evaluation of object %s ***\n", 296 info->relative_pathname)); 297 298 cleanup: 299 /* Optional object evaluation log */ 300 301 ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION, 302 "%-26s: %s\n", " Exit evaluation", 303 &info->full_pathname[1])); 304 305 /* 306 * Namespace was unlocked by the handling acpi_ns* function, so we 307 * just free the pathname and return 308 */ 309 ACPI_FREE(info->full_pathname); 310 info->full_pathname = NULL; 311 return_ACPI_STATUS(status); 312 } 313 314 /******************************************************************************* 315 * 316 * FUNCTION: acpi_ns_exec_module_code_list 317 * 318 * PARAMETERS: None 319 * 320 * RETURN: None. Exceptions during method execution are ignored, since 321 * we cannot abort a table load. 322 * 323 * DESCRIPTION: Execute all elements of the global module-level code list. 324 * Each element is executed as a single control method. 325 * 326 * NOTE: With this option enabled, each block of detected executable AML 327 * code that is outside of any control method is wrapped with a temporary 328 * control method object and placed on a global list. The methods on this 329 * list are executed below. 330 * 331 * This function executes the module-level code for all tables only after 332 * all of the tables have been loaded. It is a legacy option and is 333 * not compatible with other ACPI implementations. See acpi_ns_load_table. 334 * 335 * This function will be removed when the legacy option is removed. 336 * 337 ******************************************************************************/ 338 339 void acpi_ns_exec_module_code_list(void) 340 { 341 union acpi_operand_object *prev; 342 union acpi_operand_object *next; 343 struct acpi_evaluate_info *info; 344 u32 method_count = 0; 345 346 ACPI_FUNCTION_TRACE(ns_exec_module_code_list); 347 348 /* Exit now if the list is empty */ 349 350 next = acpi_gbl_module_code_list; 351 if (!next) { 352 ACPI_DEBUG_PRINT((ACPI_DB_INIT_NAMES, 353 "Legacy MLC block list is empty\n")); 354 355 return_VOID; 356 } 357 358 /* Allocate the evaluation information block */ 359 360 info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info)); 361 if (!info) { 362 return_VOID; 363 } 364 365 /* Walk the list, executing each "method" */ 366 367 while (next) { 368 prev = next; 369 next = next->method.mutex; 370 371 /* Clear the link field and execute the method */ 372 373 prev->method.mutex = NULL; 374 acpi_ns_exec_module_code(prev, info); 375 method_count++; 376 377 /* Delete the (temporary) method object */ 378 379 acpi_ut_remove_reference(prev); 380 } 381 382 ACPI_INFO(("Executed %u blocks of module-level executable AML code", 383 method_count)); 384 385 ACPI_FREE(info); 386 acpi_gbl_module_code_list = NULL; 387 return_VOID; 388 } 389 390 /******************************************************************************* 391 * 392 * FUNCTION: acpi_ns_exec_module_code 393 * 394 * PARAMETERS: method_obj - Object container for the module-level code 395 * info - Info block for method evaluation 396 * 397 * RETURN: None. Exceptions during method execution are ignored, since 398 * we cannot abort a table load. 399 * 400 * DESCRIPTION: Execute a control method containing a block of module-level 401 * executable AML code. The control method is temporarily 402 * installed to the root node, then evaluated. 403 * 404 ******************************************************************************/ 405 406 static void 407 acpi_ns_exec_module_code(union acpi_operand_object *method_obj, 408 struct acpi_evaluate_info *info) 409 { 410 union acpi_operand_object *parent_obj; 411 struct acpi_namespace_node *parent_node; 412 acpi_object_type type; 413 acpi_status status; 414 415 ACPI_FUNCTION_TRACE(ns_exec_module_code); 416 417 /* 418 * Get the parent node. We cheat by using the next_object field 419 * of the method object descriptor. 420 */ 421 parent_node = 422 ACPI_CAST_PTR(struct acpi_namespace_node, 423 method_obj->method.next_object); 424 type = acpi_ns_get_type(parent_node); 425 426 /* 427 * Get the region handler and save it in the method object. We may need 428 * this if an operation region declaration causes a _REG method to be run. 429 * 430 * We can't do this in acpi_ps_link_module_code because 431 * acpi_gbl_root_node->Object is NULL at PASS1. 432 */ 433 if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { 434 method_obj->method.dispatch.handler = 435 parent_node->object->device.handler; 436 } 437 438 /* Must clear next_object (acpi_ns_attach_object needs the field) */ 439 440 method_obj->method.next_object = NULL; 441 442 /* Initialize the evaluation information block */ 443 444 memset(info, 0, sizeof(struct acpi_evaluate_info)); 445 info->prefix_node = parent_node; 446 447 /* 448 * Get the currently attached parent object. Add a reference, 449 * because the ref count will be decreased when the method object 450 * is installed to the parent node. 451 */ 452 parent_obj = acpi_ns_get_attached_object(parent_node); 453 if (parent_obj) { 454 acpi_ut_add_reference(parent_obj); 455 } 456 457 /* Install the method (module-level code) in the parent node */ 458 459 status = 460 acpi_ns_attach_object(parent_node, method_obj, ACPI_TYPE_METHOD); 461 if (ACPI_FAILURE(status)) { 462 goto exit; 463 } 464 465 /* Execute the parent node as a control method */ 466 467 status = acpi_ns_evaluate(info); 468 469 ACPI_DEBUG_PRINT((ACPI_DB_INIT_NAMES, 470 "Executed module-level code at %p\n", 471 method_obj->method.aml_start)); 472 473 /* Delete a possible implicit return value (in slack mode) */ 474 475 if (info->return_object) { 476 acpi_ut_remove_reference(info->return_object); 477 } 478 479 /* Detach the temporary method object */ 480 481 acpi_ns_detach_object(parent_node); 482 483 /* Restore the original parent object */ 484 485 if (parent_obj) { 486 status = acpi_ns_attach_object(parent_node, parent_obj, type); 487 } else { 488 parent_node->type = (u8)type; 489 } 490 491 exit: 492 if (parent_obj) { 493 acpi_ut_remove_reference(parent_obj); 494 } 495 return_VOID; 496 } 497