1/******************************************************************************* 2 * 3 * Module Name: nseval - Object evaluation interfaces -- includes control 4 * method lookup and execution. 5 * $Revision: 1.1.1.1 $ 6 * 7 ******************************************************************************/ 8 9/* 10 * Copyright (C) 2000, 2001 R. Byron Moore 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 */ 26 27 28#include "acpi.h" 29#include "amlcode.h" 30#include "acparser.h" 31#include "acinterp.h" 32#include "acnamesp.h" 33 34 35#define _COMPONENT ACPI_NAMESPACE 36 MODULE_NAME ("nseval") 37 38 39/******************************************************************************* 40 * 41 * FUNCTION: Acpi_ns_evaluate_relative 42 * 43 * PARAMETERS: Handle - The relative containing object 44 * *Pathname - Name of method to execute, If NULL, the 45 * handle is the object to execute 46 * **Params - List of parameters to pass to the method, 47 * terminated by NULL. Params itself may be 48 * NULL if no parameters are being passed. 49 * *Return_object - Where to put method's return value (if 50 * any). If NULL, no value is returned. 51 * 52 * RETURN: Status 53 * 54 * DESCRIPTION: Find and execute the requested method using the handle as a 55 * scope 56 * 57 * MUTEX: Locks Namespace 58 * 59 ******************************************************************************/ 60 61acpi_status 62acpi_ns_evaluate_relative ( 63 acpi_namespace_node *handle, 64 NATIVE_CHAR *pathname, 65 acpi_operand_object **params, 66 acpi_operand_object **return_object) 67{ 68 acpi_namespace_node *prefix_node; 69 acpi_status status; 70 acpi_namespace_node *node = NULL; 71 NATIVE_CHAR *internal_path = NULL; 72 acpi_generic_state scope_info; 73 74 75 FUNCTION_TRACE ("Ns_evaluate_relative"); 76 77 78 /* 79 * Must have a valid object handle 80 */ 81 if (!handle) { 82 return_ACPI_STATUS (AE_BAD_PARAMETER); 83 } 84 85 /* Build an internal name string for the method */ 86 87 status = acpi_ns_internalize_name (pathname, &internal_path); 88 if (ACPI_FAILURE (status)) { 89 return_ACPI_STATUS (status); 90 } 91 92 /* Get the prefix handle and Node */ 93 94 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 95 96 prefix_node = acpi_ns_map_handle_to_node (handle); 97 if (!prefix_node) { 98 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 99 status = AE_BAD_PARAMETER; 100 goto cleanup; 101 } 102 103 /* Lookup the name in the namespace */ 104 105 scope_info.scope.node = prefix_node; 106 status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY, 107 IMODE_EXECUTE, NS_NO_UPSEARCH, NULL, 108 &node); 109 110 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 111 112 if (ACPI_FAILURE (status)) { 113 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object [%s] not found [%s]\n", 114 pathname, acpi_format_exception (status))); 115 goto cleanup; 116 } 117 118 /* 119 * Now that we have a handle to the object, we can attempt 120 * to evaluate it. 121 */ 122 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s [%p] Value %p\n", 123 pathname, node, node->object)); 124 125 status = acpi_ns_evaluate_by_handle (node, params, return_object); 126 127 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "*** Completed eval of object %s ***\n", 128 pathname)); 129 130cleanup: 131 132 ACPI_MEM_FREE (internal_path); 133 return_ACPI_STATUS (status); 134} 135 136 137/******************************************************************************* 138 * 139 * FUNCTION: Acpi_ns_evaluate_by_name 140 * 141 * PARAMETERS: Pathname - Fully qualified pathname to the object 142 * *Return_object - Where to put method's return value (if 143 * any). If NULL, no value is returned. 144 * **Params - List of parameters to pass to the method, 145 * terminated by NULL. Params itself may be 146 * NULL if no parameters are being passed. 147 * 148 * RETURN: Status 149 * 150 * DESCRIPTION: Find and execute the requested method passing the given 151 * parameters 152 * 153 * MUTEX: Locks Namespace 154 * 155 ******************************************************************************/ 156 157acpi_status 158acpi_ns_evaluate_by_name ( 159 NATIVE_CHAR *pathname, 160 acpi_operand_object **params, 161 acpi_operand_object **return_object) 162{ 163 acpi_status status; 164 acpi_namespace_node *node = NULL; 165 NATIVE_CHAR *internal_path = NULL; 166 167 168 FUNCTION_TRACE ("Ns_evaluate_by_name"); 169 170 171 /* Build an internal name string for the method */ 172 173 status = acpi_ns_internalize_name (pathname, &internal_path); 174 if (ACPI_FAILURE (status)) { 175 return_ACPI_STATUS (status); 176 } 177 178 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 179 180 /* Lookup the name in the namespace */ 181 182 status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY, 183 IMODE_EXECUTE, NS_NO_UPSEARCH, NULL, 184 &node); 185 186 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 187 188 if (ACPI_FAILURE (status)) { 189 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Object at [%s] was not found, status=%.4X\n", 190 pathname, status)); 191 goto cleanup; 192 } 193 194 /* 195 * Now that we have a handle to the object, we can attempt 196 * to evaluate it. 197 */ 198 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s [%p] Value %p\n", 199 pathname, node, node->object)); 200 201 status = acpi_ns_evaluate_by_handle (node, params, return_object); 202 203 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "*** Completed eval of object %s ***\n", 204 pathname)); 205 206 207cleanup: 208 209 /* Cleanup */ 210 211 if (internal_path) { 212 ACPI_MEM_FREE (internal_path); 213 } 214 215 return_ACPI_STATUS (status); 216} 217 218 219/******************************************************************************* 220 * 221 * FUNCTION: Acpi_ns_evaluate_by_handle 222 * 223 * PARAMETERS: Handle - Method Node to execute 224 * **Params - List of parameters to pass to the method, 225 * terminated by NULL. Params itself may be 226 * NULL if no parameters are being passed. 227 * *Return_object - Where to put method's return value (if 228 * any). If NULL, no value is returned. 229 * 230 * RETURN: Status 231 * 232 * DESCRIPTION: Execute the requested method passing the given parameters 233 * 234 * MUTEX: Locks Namespace 235 * 236 ******************************************************************************/ 237 238acpi_status 239acpi_ns_evaluate_by_handle ( 240 acpi_namespace_node *handle, 241 acpi_operand_object **params, 242 acpi_operand_object **return_object) 243{ 244 acpi_namespace_node *node; 245 acpi_status status; 246 acpi_operand_object *local_return_object; 247 248 249 FUNCTION_TRACE ("Ns_evaluate_by_handle"); 250 251 252 /* Check if namespace has been initialized */ 253 254 if (!acpi_gbl_root_node) { 255 return_ACPI_STATUS (AE_NO_NAMESPACE); 256 } 257 258 /* Parameter Validation */ 259 260 if (!handle) { 261 return_ACPI_STATUS (AE_BAD_PARAMETER); 262 } 263 264 if (return_object) { 265 /* Initialize the return value to an invalid object */ 266 267 *return_object = NULL; 268 } 269 270 /* Get the prefix handle and Node */ 271 272 acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); 273 274 node = acpi_ns_map_handle_to_node (handle); 275 if (!node) { 276 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 277 return_ACPI_STATUS (AE_BAD_PARAMETER); 278 } 279 280 281 /* 282 * Two major cases here: 283 * 1) The object is an actual control method -- execute it. 284 * 2) The object is not a method -- just return it's current 285 * value 286 * 287 * In both cases, the namespace is unlocked by the 288 * Acpi_ns* procedure 289 */ 290 if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) { 291 /* 292 * Case 1) We have an actual control method to execute 293 */ 294 status = acpi_ns_execute_control_method (node, params, 295 &local_return_object); 296 } 297 298 else { 299 /* 300 * Case 2) Object is NOT a method, just return its 301 * current value 302 */ 303 status = acpi_ns_get_object_value (node, &local_return_object); 304 } 305 306 307 /* 308 * Check if there is a return value on the stack that must 309 * be dealt with 310 */ 311 if (status == AE_CTRL_RETURN_VALUE) { 312 /* 313 * If the Method returned a value and the caller 314 * provided a place to store a returned value, Copy 315 * the returned value to the object descriptor provided 316 * by the caller. 317 */ 318 if (return_object) { 319 /* 320 * Valid return object, copy the pointer to 321 * the returned object 322 */ 323 *return_object = local_return_object; 324 } 325 326 327 /* Map AE_RETURN_VALUE to AE_OK, we are done with it */ 328 329 if (status == AE_CTRL_RETURN_VALUE) { 330 status = AE_OK; 331 } 332 } 333 334 /* 335 * Namespace was unlocked by the handling Acpi_ns* function, 336 * so we just return 337 */ 338 return_ACPI_STATUS (status); 339} 340 341 342/******************************************************************************* 343 * 344 * FUNCTION: Acpi_ns_execute_control_method 345 * 346 * PARAMETERS: Method_node - The object/method 347 * **Params - List of parameters to pass to the method, 348 * terminated by NULL. Params itself may be 349 * NULL if no parameters are being passed. 350 * **Return_obj_desc - List of result objects to be returned 351 * from the method. 352 * 353 * RETURN: Status 354 * 355 * DESCRIPTION: Execute the requested method passing the given parameters 356 * 357 * MUTEX: Assumes namespace is locked 358 * 359 ******************************************************************************/ 360 361acpi_status 362acpi_ns_execute_control_method ( 363 acpi_namespace_node *method_node, 364 acpi_operand_object **params, 365 acpi_operand_object **return_obj_desc) 366{ 367 acpi_status status; 368 acpi_operand_object *obj_desc; 369 370 371 FUNCTION_TRACE ("Ns_execute_control_method"); 372 373 374 /* Verify that there is a method associated with this object */ 375 376 obj_desc = acpi_ns_get_attached_object (method_node); 377 if (!obj_desc) { 378 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n")); 379 380 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 381 return_ACPI_STATUS (AE_NULL_OBJECT); 382 } 383 384 385 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Control method at Offset %p Length %x]\n", 386 obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1)); 387 388 DUMP_PATHNAME (method_node, "Ns_execute_control_method: Executing", 389 ACPI_LV_NAMES, _COMPONENT); 390 391 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "At offset %p\n", 392 obj_desc->method.aml_start + 1)); 393 394 395 /* 396 * Unlock the namespace before execution. This allows namespace access 397 * via the external Acpi* interfaces while a method is being executed. 398 * However, any namespace deletion must acquire both the namespace and 399 * interpreter locks to ensure that no thread is using the portion of the 400 * namespace that is being deleted. 401 */ 402 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 403 404 /* 405 * Execute the method via the interpreter. The interpreter is locked 406 * here before calling into the AML parser 407 */ 408 status = acpi_ex_enter_interpreter (); 409 if (ACPI_FAILURE (status)) { 410 return_ACPI_STATUS (status); 411 } 412 413 status = acpi_psx_execute (method_node, params, return_obj_desc); 414 acpi_ex_exit_interpreter (); 415 416 return_ACPI_STATUS (status); 417} 418 419 420/******************************************************************************* 421 * 422 * FUNCTION: Acpi_ns_get_object_value 423 * 424 * PARAMETERS: Node - The object 425 * 426 * RETURN: Status 427 * 428 * DESCRIPTION: Return the current value of the object 429 * 430 * MUTEX: Assumes namespace is locked 431 * 432 ******************************************************************************/ 433 434acpi_status 435acpi_ns_get_object_value ( 436 acpi_namespace_node *node, 437 acpi_operand_object **return_obj_desc) 438{ 439 acpi_status status = AE_OK; 440 acpi_operand_object *obj_desc; 441 acpi_operand_object *source_desc; 442 443 444 FUNCTION_TRACE ("Ns_get_object_value"); 445 446 447 /* 448 * We take the value from certain objects directly 449 */ 450 if ((node->type == ACPI_TYPE_PROCESSOR) || 451 (node->type == ACPI_TYPE_POWER)) { 452 /* 453 * Create a Reference object to contain the object 454 */ 455 obj_desc = acpi_ut_create_internal_object (node->type); 456 if (!obj_desc) { 457 status = AE_NO_MEMORY; 458 goto unlock_and_exit; 459 } 460 461 /* 462 * Get the attached object 463 */ 464 source_desc = acpi_ns_get_attached_object (node); 465 if (!source_desc) { 466 status = AE_NULL_OBJECT; 467 goto unlock_and_exit; 468 } 469 470 /* 471 * Just copy from the original to the return object 472 * 473 * TBD: [Future] - need a low-level object copy that handles 474 * the reference count automatically. (Don't want to copy it) 475 */ 476 MEMCPY (obj_desc, source_desc, sizeof (acpi_operand_object)); 477 obj_desc->common.reference_count = 1; 478 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 479 } 480 481 482 /* 483 * Other objects require a reference object wrapper which we 484 * then attempt to resolve. 485 */ 486 else { 487 /* Create an Reference object to contain the object */ 488 489 obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); 490 if (!obj_desc) { 491 status = AE_NO_MEMORY; 492 goto unlock_and_exit; 493 } 494 495 /* Construct a descriptor pointing to the name */ 496 497 obj_desc->reference.opcode = (u8) AML_NAME_OP; 498 obj_desc->reference.object = (void *) node; 499 500 /* 501 * Use Resolve_to_value() to get the associated value. This call 502 * always deletes Obj_desc (allocated above). 503 * 504 * NOTE: we can get away with passing in NULL for a walk state 505 * because Obj_desc is guaranteed to not be a reference to either 506 * a method local or a method argument 507 * 508 * Even though we do not directly invoke the interpreter 509 * for this, we must enter it because we could access an opregion. 510 * The opregion access code assumes that the interpreter 511 * is locked. 512 * 513 * We must release the namespace lock before entering the 514 * intepreter. 515 */ 516 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 517 status = acpi_ex_enter_interpreter (); 518 if (ACPI_SUCCESS (status)) { 519 status = acpi_ex_resolve_to_value (&obj_desc, NULL); 520 521 acpi_ex_exit_interpreter (); 522 } 523 } 524 525 /* 526 * If Acpi_ex_resolve_to_value() succeeded, the return value was 527 * placed in Obj_desc. 528 */ 529 if (ACPI_SUCCESS (status)) { 530 status = AE_CTRL_RETURN_VALUE; 531 532 *return_obj_desc = obj_desc; 533 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Returning obj %p\n", *return_obj_desc)); 534 } 535 536 /* Namespace is unlocked */ 537 538 return_ACPI_STATUS (status); 539 540 541unlock_and_exit: 542 543 /* Unlock the namespace */ 544 545 acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); 546 return_ACPI_STATUS (status); 547} 548