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 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "acinterp.h" 48 #include "acnamesp.h" 49 50 #define _COMPONENT ACPI_NAMESPACE 51 ACPI_MODULE_NAME("nseval") 52 53 /* Local prototypes */ 54 static void 55 acpi_ns_exec_module_code(union acpi_operand_object *method_obj, 56 struct acpi_evaluate_info *info); 57 58 /******************************************************************************* 59 * 60 * FUNCTION: acpi_ns_evaluate 61 * 62 * PARAMETERS: info - Evaluation info block, contains: 63 * prefix_node - Prefix or Method/Object Node to execute 64 * pathname - Name of method to execute, If NULL, the 65 * Node is the object to execute 66 * parameters - List of parameters to pass to the method, 67 * terminated by NULL. Params itself may be 68 * NULL if no parameters are being passed. 69 * return_object - Where to put method's return value (if 70 * any). If NULL, no value is returned. 71 * parameter_type - Type of Parameter list 72 * return_object - Where to put method's return value (if 73 * any). If NULL, no value is returned. 74 * flags - ACPI_IGNORE_RETURN_VALUE to delete return 75 * 76 * RETURN: Status 77 * 78 * DESCRIPTION: Execute a control method or return the current value of an 79 * ACPI namespace object. 80 * 81 * MUTEX: Locks interpreter 82 * 83 ******************************************************************************/ 84 85 acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) 86 { 87 acpi_status status; 88 struct acpi_namespace_node *node; 89 90 ACPI_FUNCTION_TRACE(ns_evaluate); 91 92 if (!info) { 93 return_ACPI_STATUS(AE_BAD_PARAMETER); 94 } 95 96 /* Initialize the return value to an invalid object */ 97 98 info->return_object = NULL; 99 info->param_count = 0; 100 101 if (!info->resolved_node) { 102 /* 103 * Get the actual namespace node for the target object if we need to. 104 * Handles these cases: 105 * 106 * 1) Null node, Pathname (absolute path) 107 * 2) Node, Pathname (path relative to Node) 108 * 3) Node, Null Pathname 109 */ 110 status = acpi_ns_get_node(info->prefix_node, info->pathname, 111 ACPI_NS_NO_UPSEARCH, 112 &info->resolved_node); 113 if (ACPI_FAILURE(status)) { 114 return_ACPI_STATUS(status); 115 } 116 } 117 118 /* 119 * For a method alias, we must grab the actual method node so that proper 120 * scoping context will be established before execution. 121 */ 122 if (acpi_ns_get_type(info->resolved_node) == 123 ACPI_TYPE_LOCAL_METHOD_ALIAS) { 124 info->resolved_node = 125 ACPI_CAST_PTR(struct acpi_namespace_node, 126 info->resolved_node->object); 127 } 128 129 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, 130 info->resolved_node, 131 acpi_ns_get_attached_object(info->resolved_node))); 132 133 node = info->resolved_node; 134 135 /* 136 * Two major cases here: 137 * 138 * 1) The object is a control method -- execute it 139 * 2) The object is not a method -- just return it's current value 140 */ 141 if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { 142 /* 143 * 1) Object is a control method - execute it 144 */ 145 146 /* Verify that there is a method object associated with this node */ 147 148 info->obj_desc = 149 acpi_ns_get_attached_object(info->resolved_node); 150 if (!info->obj_desc) { 151 ACPI_ERROR((AE_INFO, 152 "Control method has no attached sub-object")); 153 return_ACPI_STATUS(AE_NULL_OBJECT); 154 } 155 156 /* Count the number of arguments being passed to the method */ 157 158 if (info->parameters) { 159 while (info->parameters[info->param_count]) { 160 if (info->param_count > ACPI_METHOD_MAX_ARG) { 161 return_ACPI_STATUS(AE_LIMIT); 162 } 163 info->param_count++; 164 } 165 } 166 167 168 ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method", 169 ACPI_LV_INFO, _COMPONENT); 170 171 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 172 "Method at AML address %p Length %X\n", 173 info->obj_desc->method.aml_start + 1, 174 info->obj_desc->method.aml_length - 1)); 175 176 /* 177 * Any namespace deletion must acquire both the namespace and 178 * interpreter locks to ensure that no thread is using the portion of 179 * the namespace that is being deleted. 180 * 181 * Execute the method via the interpreter. The interpreter is locked 182 * here before calling into the AML parser 183 */ 184 acpi_ex_enter_interpreter(); 185 status = acpi_ps_execute_method(info); 186 acpi_ex_exit_interpreter(); 187 } else { 188 /* 189 * 2) Object is not a method, return its current value 190 * 191 * Disallow certain object types. For these, "evaluation" is undefined. 192 */ 193 switch (info->resolved_node->type) { 194 case ACPI_TYPE_DEVICE: 195 case ACPI_TYPE_EVENT: 196 case ACPI_TYPE_MUTEX: 197 case ACPI_TYPE_REGION: 198 case ACPI_TYPE_THERMAL: 199 case ACPI_TYPE_LOCAL_SCOPE: 200 201 ACPI_ERROR((AE_INFO, 202 "[%4.4s] Evaluation of object type [%s] is not supported", 203 info->resolved_node->name.ascii, 204 acpi_ut_get_type_name(info->resolved_node-> 205 type))); 206 207 return_ACPI_STATUS(AE_TYPE); 208 209 default: 210 break; 211 } 212 213 /* 214 * Objects require additional resolution steps (e.g., the Node may be 215 * a field that must be read, etc.) -- we can't just grab the object 216 * 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 * resolved_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 opregion. 227 * The opregion access code assumes that the interpreter is locked. 228 */ 229 acpi_ex_enter_interpreter(); 230 231 /* Function has a strange interface */ 232 233 status = 234 acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); 235 acpi_ex_exit_interpreter(); 236 237 /* 238 * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed 239 * in resolved_node. 240 */ 241 if (ACPI_SUCCESS(status)) { 242 status = AE_CTRL_RETURN_VALUE; 243 info->return_object = 244 ACPI_CAST_PTR(union acpi_operand_object, 245 info->resolved_node); 246 247 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 248 "Returning object %p [%s]\n", 249 info->return_object, 250 acpi_ut_get_object_type_name(info-> 251 return_object))); 252 } 253 } 254 255 /* 256 * Check input argument count against the ASL-defined count for a method. 257 * Also check predefined names: argument count and return value against 258 * the ACPI specification. Some incorrect return value types are repaired. 259 */ 260 (void)acpi_ns_check_predefined_names(node, 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 } 278 279 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 280 "*** Completed evaluation of object %s ***\n", 281 info->pathname)); 282 283 /* 284 * Namespace was unlocked by the handling acpi_ns* function, so we 285 * just return 286 */ 287 return_ACPI_STATUS(status); 288 } 289 290 /******************************************************************************* 291 * 292 * FUNCTION: acpi_ns_exec_module_code_list 293 * 294 * PARAMETERS: None 295 * 296 * RETURN: None. Exceptions during method execution are ignored, since 297 * we cannot abort a table load. 298 * 299 * DESCRIPTION: Execute all elements of the global module-level code list. 300 * Each element is executed as a single control method. 301 * 302 ******************************************************************************/ 303 304 void acpi_ns_exec_module_code_list(void) 305 { 306 union acpi_operand_object *prev; 307 union acpi_operand_object *next; 308 struct acpi_evaluate_info *info; 309 u32 method_count = 0; 310 311 ACPI_FUNCTION_TRACE(ns_exec_module_code_list); 312 313 /* Exit now if the list is empty */ 314 315 next = acpi_gbl_module_code_list; 316 if (!next) { 317 return_VOID; 318 } 319 320 /* Allocate the evaluation information block */ 321 322 info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info)); 323 if (!info) { 324 return_VOID; 325 } 326 327 /* Walk the list, executing each "method" */ 328 329 while (next) { 330 prev = next; 331 next = next->method.mutex; 332 333 /* Clear the link field and execute the method */ 334 335 prev->method.mutex = NULL; 336 acpi_ns_exec_module_code(prev, info); 337 method_count++; 338 339 /* Delete the (temporary) method object */ 340 341 acpi_ut_remove_reference(prev); 342 } 343 344 ACPI_INFO((AE_INFO, 345 "Executed %u blocks of module-level executable AML code", 346 method_count)); 347 348 ACPI_FREE(info); 349 acpi_gbl_module_code_list = NULL; 350 return_VOID; 351 } 352 353 /******************************************************************************* 354 * 355 * FUNCTION: acpi_ns_exec_module_code 356 * 357 * PARAMETERS: method_obj - Object container for the module-level code 358 * info - Info block for method evaluation 359 * 360 * RETURN: None. Exceptions during method execution are ignored, since 361 * we cannot abort a table load. 362 * 363 * DESCRIPTION: Execute a control method containing a block of module-level 364 * executable AML code. The control method is temporarily 365 * installed to the root node, then evaluated. 366 * 367 ******************************************************************************/ 368 369 static void 370 acpi_ns_exec_module_code(union acpi_operand_object *method_obj, 371 struct acpi_evaluate_info *info) 372 { 373 union acpi_operand_object *parent_obj; 374 struct acpi_namespace_node *parent_node; 375 acpi_object_type type; 376 acpi_status status; 377 378 ACPI_FUNCTION_TRACE(ns_exec_module_code); 379 380 /* 381 * Get the parent node. We cheat by using the next_object field 382 * of the method object descriptor. 383 */ 384 parent_node = ACPI_CAST_PTR(struct acpi_namespace_node, 385 method_obj->method.next_object); 386 type = acpi_ns_get_type(parent_node); 387 388 /* 389 * Get the region handler and save it in the method object. We may need 390 * this if an operation region declaration causes a _REG method to be run. 391 * 392 * We can't do this in acpi_ps_link_module_code because 393 * acpi_gbl_root_node->Object is NULL at PASS1. 394 */ 395 if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { 396 method_obj->method.dispatch.handler = 397 parent_node->object->device.handler; 398 } 399 400 /* Must clear next_object (acpi_ns_attach_object needs the field) */ 401 402 method_obj->method.next_object = NULL; 403 404 /* Initialize the evaluation information block */ 405 406 ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); 407 info->prefix_node = parent_node; 408 409 /* 410 * Get the currently attached parent object. Add a reference, because the 411 * ref count will be decreased when the method object is installed to 412 * the parent node. 413 */ 414 parent_obj = acpi_ns_get_attached_object(parent_node); 415 if (parent_obj) { 416 acpi_ut_add_reference(parent_obj); 417 } 418 419 /* Install the method (module-level code) in the parent node */ 420 421 status = acpi_ns_attach_object(parent_node, method_obj, 422 ACPI_TYPE_METHOD); 423 if (ACPI_FAILURE(status)) { 424 goto exit; 425 } 426 427 /* Execute the parent node as a control method */ 428 429 status = acpi_ns_evaluate(info); 430 431 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n", 432 method_obj->method.aml_start)); 433 434 /* Delete a possible implicit return value (in slack mode) */ 435 436 if (info->return_object) { 437 acpi_ut_remove_reference(info->return_object); 438 } 439 440 /* Detach the temporary method object */ 441 442 acpi_ns_detach_object(parent_node); 443 444 /* Restore the original parent object */ 445 446 if (parent_obj) { 447 status = acpi_ns_attach_object(parent_node, parent_obj, type); 448 } else { 449 parent_node->type = (u8)type; 450 } 451 452 exit: 453 if (parent_obj) { 454 acpi_ut_remove_reference(parent_obj); 455 } 456 return_VOID; 457 } 458