Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 77b2555b52a894a2e39a42e43d993df875c46a6a 491 lines 16 kB view raw
1/******************************************************************************* 2 * 3 * Module Name: nseval - Object evaluation interfaces -- includes control 4 * method lookup and execution. 5 * 6 ******************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2005, R. Byron Moore 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45#include <acpi/acpi.h> 46#include <acpi/acparser.h> 47#include <acpi/acinterp.h> 48#include <acpi/acnamesp.h> 49 50#define _COMPONENT ACPI_NAMESPACE 51ACPI_MODULE_NAME("nseval") 52 53/* Local prototypes */ 54static acpi_status 55acpi_ns_execute_control_method(struct acpi_parameter_info *info); 56 57static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info); 58 59/******************************************************************************* 60 * 61 * FUNCTION: acpi_ns_evaluate_relative 62 * 63 * PARAMETERS: Pathname - Name of method to execute, If NULL, the 64 * handle is the object to execute 65 * Info - Method info block, contains: 66 * return_object - Where to put method's return value (if 67 * any). If NULL, no value is returned. 68 * Params - List of parameters to pass to the method, 69 * terminated by NULL. Params itself may be 70 * NULL if no parameters are being passed. 71 * 72 * RETURN: Status 73 * 74 * DESCRIPTION: Evaluate the object or find and execute the requested method 75 * 76 * MUTEX: Locks Namespace 77 * 78 ******************************************************************************/ 79 80acpi_status 81acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info) 82{ 83 acpi_status status; 84 struct acpi_namespace_node *node = NULL; 85 union acpi_generic_state *scope_info; 86 char *internal_path = NULL; 87 88 ACPI_FUNCTION_TRACE("ns_evaluate_relative"); 89 90 /* 91 * Must have a valid object handle 92 */ 93 if (!info || !info->node) { 94 return_ACPI_STATUS(AE_BAD_PARAMETER); 95 } 96 97 /* Build an internal name string for the method */ 98 99 status = acpi_ns_internalize_name(pathname, &internal_path); 100 if (ACPI_FAILURE(status)) { 101 return_ACPI_STATUS(status); 102 } 103 104 scope_info = acpi_ut_create_generic_state(); 105 if (!scope_info) { 106 goto cleanup1; 107 } 108 109 /* Get the prefix handle and Node */ 110 111 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 112 if (ACPI_FAILURE(status)) { 113 goto cleanup; 114 } 115 116 info->node = acpi_ns_map_handle_to_node(info->node); 117 if (!info->node) { 118 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 119 status = AE_BAD_PARAMETER; 120 goto cleanup; 121 } 122 123 /* Lookup the name in the namespace */ 124 125 scope_info->scope.node = info->node; 126 status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY, 127 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, 128 &node); 129 130 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 131 132 if (ACPI_FAILURE(status)) { 133 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n", 134 pathname, acpi_format_exception(status))); 135 goto cleanup; 136 } 137 138 /* 139 * Now that we have a handle to the object, we can attempt to evaluate it. 140 */ 141 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", 142 pathname, node, acpi_ns_get_attached_object(node))); 143 144 info->node = node; 145 status = acpi_ns_evaluate_by_handle(info); 146 147 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 148 "*** Completed eval of object %s ***\n", pathname)); 149 150 cleanup: 151 acpi_ut_delete_generic_state(scope_info); 152 153 cleanup1: 154 ACPI_MEM_FREE(internal_path); 155 return_ACPI_STATUS(status); 156} 157 158/******************************************************************************* 159 * 160 * FUNCTION: acpi_ns_evaluate_by_name 161 * 162 * PARAMETERS: Pathname - Fully qualified pathname to the object 163 * Info - Method info block, contains: 164 * return_object - Where to put method's return value (if 165 * any). If NULL, no value is returned. 166 * Params - List of parameters to pass to the method, 167 * terminated by NULL. Params itself may be 168 * NULL if no parameters are being passed. 169 * 170 * RETURN: Status 171 * 172 * DESCRIPTION: Evaluate the object or rind and execute the requested method 173 * passing the given parameters 174 * 175 * MUTEX: Locks Namespace 176 * 177 ******************************************************************************/ 178 179acpi_status 180acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) 181{ 182 acpi_status status; 183 char *internal_path = NULL; 184 185 ACPI_FUNCTION_TRACE("ns_evaluate_by_name"); 186 187 /* Build an internal name string for the method */ 188 189 status = acpi_ns_internalize_name(pathname, &internal_path); 190 if (ACPI_FAILURE(status)) { 191 return_ACPI_STATUS(status); 192 } 193 194 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 195 if (ACPI_FAILURE(status)) { 196 goto cleanup; 197 } 198 199 /* Lookup the name in the namespace */ 200 201 status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY, 202 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, 203 &info->node); 204 205 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 206 207 if (ACPI_FAILURE(status)) { 208 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 209 "Object at [%s] was not found, status=%.4X\n", 210 pathname, status)); 211 goto cleanup; 212 } 213 214 /* 215 * Now that we have a handle to the object, we can attempt to evaluate it. 216 */ 217 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", 218 pathname, info->node, 219 acpi_ns_get_attached_object(info->node))); 220 221 status = acpi_ns_evaluate_by_handle(info); 222 223 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 224 "*** Completed eval of object %s ***\n", pathname)); 225 226 cleanup: 227 228 /* Cleanup */ 229 230 if (internal_path) { 231 ACPI_MEM_FREE(internal_path); 232 } 233 234 return_ACPI_STATUS(status); 235} 236 237/******************************************************************************* 238 * 239 * FUNCTION: acpi_ns_evaluate_by_handle 240 * 241 * PARAMETERS: Info - Method info block, contains: 242 * Node - Method/Object Node to execute 243 * Parameters - List of parameters to pass to the method, 244 * terminated by NULL. Params itself may be 245 * NULL if no parameters are being passed. 246 * return_object - Where to put method's return value (if 247 * any). If NULL, no value is returned. 248 * parameter_type - Type of Parameter list 249 * return_object - Where to put method's return value (if 250 * any). If NULL, no value is returned. 251 * 252 * RETURN: Status 253 * 254 * DESCRIPTION: Evaluate object or execute the requested method passing the 255 * given parameters 256 * 257 * MUTEX: Locks Namespace 258 * 259 ******************************************************************************/ 260 261acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info) 262{ 263 acpi_status status; 264 265 ACPI_FUNCTION_TRACE("ns_evaluate_by_handle"); 266 267 /* Check if namespace has been initialized */ 268 269 if (!acpi_gbl_root_node) { 270 return_ACPI_STATUS(AE_NO_NAMESPACE); 271 } 272 273 /* Parameter Validation */ 274 275 if (!info) { 276 return_ACPI_STATUS(AE_BAD_PARAMETER); 277 } 278 279 /* Initialize the return value to an invalid object */ 280 281 info->return_object = NULL; 282 283 /* Get the prefix handle and Node */ 284 285 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 286 if (ACPI_FAILURE(status)) { 287 return_ACPI_STATUS(status); 288 } 289 290 info->node = acpi_ns_map_handle_to_node(info->node); 291 if (!info->node) { 292 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 293 return_ACPI_STATUS(AE_BAD_PARAMETER); 294 } 295 296 /* 297 * For a method alias, we must grab the actual method node so that proper 298 * scoping context will be established before execution. 299 */ 300 if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { 301 info->node = 302 ACPI_CAST_PTR(struct acpi_namespace_node, 303 info->node->object); 304 } 305 306 /* 307 * Two major cases here: 308 * 1) The object is an actual control method -- execute it. 309 * 2) The object is not a method -- just return it's current value 310 * 311 * In both cases, the namespace is unlocked by the acpi_ns* procedure 312 */ 313 if (acpi_ns_get_type(info->node) == ACPI_TYPE_METHOD) { 314 /* 315 * Case 1) We have an actual control method to execute 316 */ 317 status = acpi_ns_execute_control_method(info); 318 } else { 319 /* 320 * Case 2) Object is NOT a method, just return its current value 321 */ 322 status = acpi_ns_get_object_value(info); 323 } 324 325 /* 326 * Check if there is a return value on the stack that must be dealt with 327 */ 328 if (status == AE_CTRL_RETURN_VALUE) { 329 /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ 330 331 status = AE_OK; 332 } 333 334 /* 335 * Namespace was unlocked by the handling acpi_ns* function, so we 336 * just return 337 */ 338 return_ACPI_STATUS(status); 339} 340 341/******************************************************************************* 342 * 343 * FUNCTION: acpi_ns_execute_control_method 344 * 345 * PARAMETERS: Info - Method info block, contains: 346 * Node - Method Node to execute 347 * obj_desc - Method object 348 * Parameters - List of parameters to pass to the method, 349 * terminated by NULL. Params itself may be 350 * NULL if no parameters are being passed. 351 * return_object - Where to put method's return value (if 352 * any). If NULL, no value is returned. 353 * parameter_type - Type of Parameter list 354 * return_object - Where to put method's return value (if 355 * any). If NULL, no value is returned. 356 * 357 * RETURN: Status 358 * 359 * DESCRIPTION: Execute the requested method passing the given parameters 360 * 361 * MUTEX: Assumes namespace is locked 362 * 363 ******************************************************************************/ 364 365static acpi_status 366acpi_ns_execute_control_method(struct acpi_parameter_info *info) 367{ 368 acpi_status status; 369 370 ACPI_FUNCTION_TRACE("ns_execute_control_method"); 371 372 /* Verify that there is a method associated with this object */ 373 374 info->obj_desc = acpi_ns_get_attached_object(info->node); 375 if (!info->obj_desc) { 376 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 377 "No attached method object\n")); 378 379 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 380 return_ACPI_STATUS(AE_NULL_OBJECT); 381 } 382 383 ACPI_DUMP_PATHNAME(info->node, "Execute Method:", 384 ACPI_LV_INFO, _COMPONENT); 385 386 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", 387 info->obj_desc->method.aml_start + 1, 388 info->obj_desc->method.aml_length - 1)); 389 390 /* 391 * Unlock the namespace before execution. This allows namespace access 392 * via the external Acpi* interfaces while a method is being executed. 393 * However, any namespace deletion must acquire both the namespace and 394 * interpreter locks to ensure that no thread is using the portion of the 395 * namespace that is being deleted. 396 */ 397 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 398 if (ACPI_FAILURE(status)) { 399 return_ACPI_STATUS(status); 400 } 401 402 /* 403 * Execute the method via the interpreter. The interpreter is locked 404 * here before calling into the AML parser 405 */ 406 status = acpi_ex_enter_interpreter(); 407 if (ACPI_FAILURE(status)) { 408 return_ACPI_STATUS(status); 409 } 410 411 status = acpi_ps_execute_method(info); 412 acpi_ex_exit_interpreter(); 413 414 return_ACPI_STATUS(status); 415} 416 417/******************************************************************************* 418 * 419 * FUNCTION: acpi_ns_get_object_value 420 * 421 * PARAMETERS: Info - Method info block, contains: 422 * Node - Object's NS node 423 * return_object - Where to put object value (if 424 * any). If NULL, no value is returned. 425 * 426 * RETURN: Status 427 * 428 * DESCRIPTION: Return the current value of the object 429 * 430 * MUTEX: Assumes namespace is locked, leaves namespace unlocked 431 * 432 ******************************************************************************/ 433 434static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info) 435{ 436 acpi_status status = AE_OK; 437 struct acpi_namespace_node *resolved_node = info->node; 438 439 ACPI_FUNCTION_TRACE("ns_get_object_value"); 440 441 /* 442 * Objects require additional resolution steps (e.g., the Node may be a 443 * field that must be read, etc.) -- we can't just grab the object out of 444 * the node. 445 */ 446 447 /* 448 * Use resolve_node_to_value() to get the associated value. This call always 449 * deletes obj_desc (allocated above). 450 * 451 * NOTE: we can get away with passing in NULL for a walk state because 452 * obj_desc is guaranteed to not be a reference to either a method local or 453 * a method argument (because this interface can only be called from the 454 * acpi_evaluate external interface, never called from a running method.) 455 * 456 * Even though we do not directly invoke the interpreter for this, we must 457 * enter it because we could access an opregion. The opregion access code 458 * assumes that the interpreter is locked. 459 * 460 * We must release the namespace lock before entering the intepreter. 461 */ 462 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 463 if (ACPI_FAILURE(status)) { 464 return_ACPI_STATUS(status); 465 } 466 467 status = acpi_ex_enter_interpreter(); 468 if (ACPI_SUCCESS(status)) { 469 status = acpi_ex_resolve_node_to_value(&resolved_node, NULL); 470 /* 471 * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed 472 * in resolved_node. 473 */ 474 acpi_ex_exit_interpreter(); 475 476 if (ACPI_SUCCESS(status)) { 477 status = AE_CTRL_RETURN_VALUE; 478 info->return_object = ACPI_CAST_PTR 479 (union acpi_operand_object, resolved_node); 480 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 481 "Returning object %p [%s]\n", 482 info->return_object, 483 acpi_ut_get_object_type_name(info-> 484 return_object))); 485 } 486 } 487 488 /* Namespace is unlocked */ 489 490 return_ACPI_STATUS(status); 491}