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 /* Count the number of arguments being passed in */ 108 109 info->param_count = 0; 110 if (info->parameters) { 111 while (info->parameters[info->param_count]) { 112 info->param_count++; 113 } 114 115 /* Warn on impossible argument count */ 116 117 if (info->param_count > ACPI_METHOD_NUM_ARGS) { 118 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 119 ACPI_WARN_ALWAYS, 120 "Excess arguments (%u) - using only %u", 121 info->param_count, 122 ACPI_METHOD_NUM_ARGS)); 123 124 info->param_count = ACPI_METHOD_NUM_ARGS; 125 } 126 } 127 128 /* 129 * For predefined names: Check that the declared argument count 130 * matches the ACPI spec -- otherwise this is a BIOS error. 131 */ 132 acpi_ns_check_acpi_compliance(info->full_pathname, info->node, 133 info->predefined); 134 135 /* 136 * For all names: Check that the incoming argument count for 137 * this method/object matches the actual ASL/AML definition. 138 */ 139 acpi_ns_check_argument_count(info->full_pathname, info->node, 140 info->param_count, info->predefined); 141 142 /* For predefined names: Typecheck all incoming arguments */ 143 144 acpi_ns_check_argument_types(info); 145 146 /* 147 * Three major evaluation cases: 148 * 149 * 1) Object types that cannot be evaluated by definition 150 * 2) The object is a control method -- execute it 151 * 3) The object is not a method -- just return it's current value 152 */ 153 switch (acpi_ns_get_type(info->node)) { 154 case ACPI_TYPE_ANY: 155 case ACPI_TYPE_DEVICE: 156 case ACPI_TYPE_EVENT: 157 case ACPI_TYPE_MUTEX: 158 case ACPI_TYPE_REGION: 159 case ACPI_TYPE_THERMAL: 160 case ACPI_TYPE_LOCAL_SCOPE: 161 /* 162 * 1) Disallow evaluation of these object types. For these, 163 * object evaluation is undefined. 164 */ 165 ACPI_ERROR((AE_INFO, 166 "%s: This object type [%s] " 167 "never contains data and cannot be evaluated", 168 info->full_pathname, 169 acpi_ut_get_type_name(info->node->type))); 170 171 status = AE_TYPE; 172 goto cleanup; 173 174 case ACPI_TYPE_METHOD: 175 /* 176 * 2) Object is a control method - execute it 177 */ 178 179 /* Verify that there is a method object associated with this node */ 180 181 if (!info->obj_desc) { 182 ACPI_ERROR((AE_INFO, 183 "%s: Method has no attached sub-object", 184 info->full_pathname)); 185 status = AE_NULL_OBJECT; 186 goto cleanup; 187 } 188 189 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 190 "**** Execute method [%s] at AML address %p length %X\n", 191 info->full_pathname, 192 info->obj_desc->method.aml_start + 1, 193 info->obj_desc->method.aml_length - 1)); 194 195 /* 196 * Any namespace deletion must acquire both the namespace and 197 * interpreter locks to ensure that no thread is using the portion of 198 * the namespace that is being deleted. 199 * 200 * Execute the method via the interpreter. The interpreter is locked 201 * here before calling into the AML parser 202 */ 203 acpi_ex_enter_interpreter(); 204 status = acpi_ps_execute_method(info); 205 acpi_ex_exit_interpreter(); 206 break; 207 208 default: 209 /* 210 * 3) All other non-method objects -- get the current object value 211 */ 212 213 /* 214 * Some objects require additional resolution steps (e.g., the Node 215 * may be a field that must be read, etc.) -- we can't just grab 216 * the object out of the node. 217 * 218 * Use resolve_node_to_value() to get the associated value. 219 * 220 * NOTE: we can get away with passing in NULL for a walk state because 221 * the Node is guaranteed to not be a reference to either a method 222 * local or a method argument (because this interface is never called 223 * from a running method.) 224 * 225 * Even though we do not directly invoke the interpreter for object 226 * resolution, we must lock it because we could access an op_region. 227 * The op_region access code assumes that the interpreter is locked. 228 */ 229 acpi_ex_enter_interpreter(); 230 231 /* TBD: resolve_node_to_value has a strange interface, fix */ 232 233 info->return_object = 234 ACPI_CAST_PTR(union acpi_operand_object, info->node); 235 236 status = 237 acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR 238 (struct acpi_namespace_node, 239 &info->return_object), NULL); 240 acpi_ex_exit_interpreter(); 241 242 if (ACPI_FAILURE(status)) { 243 info->return_object = NULL; 244 goto cleanup; 245 } 246 247 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returned object %p [%s]\n", 248 info->return_object, 249 acpi_ut_get_object_type_name(info-> 250 return_object))); 251 252 status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */ 253 break; 254 } 255 256 /* 257 * For predefined names, check the return value against the ACPI 258 * specification. Some incorrect return value types are repaired. 259 */ 260 (void)acpi_ns_check_return_value(info->node, info, info->param_count, 261 status, &info->return_object); 262 263 /* Check if there is a return value that must be dealt with */ 264 265 if (status == AE_CTRL_RETURN_VALUE) { 266 267 /* If caller does not want the return value, delete it */ 268 269 if (info->flags & ACPI_IGNORE_RETURN_VALUE) { 270 acpi_ut_remove_reference(info->return_object); 271 info->return_object = NULL; 272 } 273 274 /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ 275 276 status = AE_OK; 277 } else if (ACPI_FAILURE(status)) { 278 279 /* If return_object exists, delete it */ 280 281 if (info->return_object) { 282 acpi_ut_remove_reference(info->return_object); 283 info->return_object = NULL; 284 } 285 } 286 287 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 288 "*** Completed evaluation of object %s ***\n", 289 info->relative_pathname)); 290 291 cleanup: 292 /* 293 * Namespace was unlocked by the handling acpi_ns* function, so we 294 * just free the pathname and return 295 */ 296 ACPI_FREE(info->full_pathname); 297 info->full_pathname = NULL; 298 return_ACPI_STATUS(status); 299 } 300 301 /******************************************************************************* 302 * 303 * FUNCTION: acpi_ns_exec_module_code_list 304 * 305 * PARAMETERS: None 306 * 307 * RETURN: None. Exceptions during method execution are ignored, since 308 * we cannot abort a table load. 309 * 310 * DESCRIPTION: Execute all elements of the global module-level code list. 311 * Each element is executed as a single control method. 312 * 313 * NOTE: With this option enabled, each block of detected executable AML 314 * code that is outside of any control method is wrapped with a temporary 315 * control method object and placed on a global list. The methods on this 316 * list are executed below. 317 * 318 * This function executes the module-level code for all tables only after 319 * all of the tables have been loaded. It is a legacy option and is 320 * not compatible with other ACPI implementations. See acpi_ns_load_table. 321 * 322 * This function will be removed when the legacy option is removed. 323 * 324 ******************************************************************************/ 325 326 void acpi_ns_exec_module_code_list(void) 327 { 328 union acpi_operand_object *prev; 329 union acpi_operand_object *next; 330 struct acpi_evaluate_info *info; 331 u32 method_count = 0; 332 333 ACPI_FUNCTION_TRACE(ns_exec_module_code_list); 334 335 /* Exit now if the list is empty */ 336 337 next = acpi_gbl_module_code_list; 338 if (!next) { 339 ACPI_DEBUG_PRINT((ACPI_DB_INIT_NAMES, 340 "Legacy MLC block list is empty\n")); 341 342 return_VOID; 343 } 344 345 /* Allocate the evaluation information block */ 346 347 info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info)); 348 if (!info) { 349 return_VOID; 350 } 351 352 /* Walk the list, executing each "method" */ 353 354 while (next) { 355 prev = next; 356 next = next->method.mutex; 357 358 /* Clear the link field and execute the method */ 359 360 prev->method.mutex = NULL; 361 acpi_ns_exec_module_code(prev, info); 362 method_count++; 363 364 /* Delete the (temporary) method object */ 365 366 acpi_ut_remove_reference(prev); 367 } 368 369 ACPI_INFO(("Executed %u blocks of module-level executable AML code", 370 method_count)); 371 372 ACPI_FREE(info); 373 acpi_gbl_module_code_list = NULL; 374 return_VOID; 375 } 376 377 /******************************************************************************* 378 * 379 * FUNCTION: acpi_ns_exec_module_code 380 * 381 * PARAMETERS: method_obj - Object container for the module-level code 382 * info - Info block for method evaluation 383 * 384 * RETURN: None. Exceptions during method execution are ignored, since 385 * we cannot abort a table load. 386 * 387 * DESCRIPTION: Execute a control method containing a block of module-level 388 * executable AML code. The control method is temporarily 389 * installed to the root node, then evaluated. 390 * 391 ******************************************************************************/ 392 393 static void 394 acpi_ns_exec_module_code(union acpi_operand_object *method_obj, 395 struct acpi_evaluate_info *info) 396 { 397 union acpi_operand_object *parent_obj; 398 struct acpi_namespace_node *parent_node; 399 acpi_object_type type; 400 acpi_status status; 401 402 ACPI_FUNCTION_TRACE(ns_exec_module_code); 403 404 /* 405 * Get the parent node. We cheat by using the next_object field 406 * of the method object descriptor. 407 */ 408 parent_node = 409 ACPI_CAST_PTR(struct acpi_namespace_node, 410 method_obj->method.next_object); 411 type = acpi_ns_get_type(parent_node); 412 413 /* 414 * Get the region handler and save it in the method object. We may need 415 * this if an operation region declaration causes a _REG method to be run. 416 * 417 * We can't do this in acpi_ps_link_module_code because 418 * acpi_gbl_root_node->Object is NULL at PASS1. 419 */ 420 if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { 421 method_obj->method.dispatch.handler = 422 parent_node->object->device.handler; 423 } 424 425 /* Must clear next_object (acpi_ns_attach_object needs the field) */ 426 427 method_obj->method.next_object = NULL; 428 429 /* Initialize the evaluation information block */ 430 431 memset(info, 0, sizeof(struct acpi_evaluate_info)); 432 info->prefix_node = parent_node; 433 434 /* 435 * Get the currently attached parent object. Add a reference, 436 * because the ref count will be decreased when the method object 437 * is installed to the parent node. 438 */ 439 parent_obj = acpi_ns_get_attached_object(parent_node); 440 if (parent_obj) { 441 acpi_ut_add_reference(parent_obj); 442 } 443 444 /* Install the method (module-level code) in the parent node */ 445 446 status = 447 acpi_ns_attach_object(parent_node, method_obj, ACPI_TYPE_METHOD); 448 if (ACPI_FAILURE(status)) { 449 goto exit; 450 } 451 452 /* Execute the parent node as a control method */ 453 454 status = acpi_ns_evaluate(info); 455 456 ACPI_DEBUG_PRINT((ACPI_DB_INIT_NAMES, 457 "Executed module-level code at %p\n", 458 method_obj->method.aml_start)); 459 460 /* Delete a possible implicit return value (in slack mode) */ 461 462 if (info->return_object) { 463 acpi_ut_remove_reference(info->return_object); 464 } 465 466 /* Detach the temporary method object */ 467 468 acpi_ns_detach_object(parent_node); 469 470 /* Restore the original parent object */ 471 472 if (parent_obj) { 473 status = acpi_ns_attach_object(parent_node, parent_obj, type); 474 } else { 475 parent_node->type = (u8)type; 476 } 477 478 exit: 479 if (parent_obj) { 480 acpi_ut_remove_reference(parent_obj); 481 } 482 return_VOID; 483 } 484