nseval.c 15.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8
/*******************************************************************************
 *
 * Module Name: nseval - Object evaluation interfaces -- includes control
 *                       method lookup and execution.
 *
 ******************************************************************************/

/*
B
Bob Moore 已提交
9
 * Copyright (C) 2000 - 2006, R. Byron Moore
L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
#include <acpi/acparser.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>

#define _COMPONENT          ACPI_NAMESPACE
L
Len Brown 已提交
51
ACPI_MODULE_NAME("nseval")
L
Linus Torvalds 已提交
52

R
Robert Moore 已提交
53 54
/* Local prototypes */
static acpi_status
L
Len Brown 已提交
55
acpi_ns_execute_control_method(struct acpi_parameter_info *info);
R
Robert Moore 已提交
56

L
Len Brown 已提交
57
static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info);
L
Linus Torvalds 已提交
58 59 60 61 62

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_evaluate_relative
 *
R
Robert Moore 已提交
63 64 65 66 67 68 69 70
 * PARAMETERS:  Pathname        - Name of method to execute, If NULL, the
 *                                handle is the object to execute
 *              Info            - Method info block, contains:
 *                  return_object   - Where to put method's return value (if
 *                                    any).  If NULL, no value is returned.
 *                  Params          - List of parameters to pass to the method,
 *                                    terminated by NULL.  Params itself may be
 *                                    NULL if no parameters are being passed.
L
Linus Torvalds 已提交
71 72 73
 *
 * RETURN:      Status
 *
R
Robert Moore 已提交
74
 * DESCRIPTION: Evaluate the object or find and execute the requested method
L
Linus Torvalds 已提交
75 76 77 78 79 80
 *
 * MUTEX:       Locks Namespace
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
81
acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info)
L
Linus Torvalds 已提交
82
{
L
Len Brown 已提交
83 84 85 86
	acpi_status status;
	struct acpi_namespace_node *node = NULL;
	union acpi_generic_state *scope_info;
	char *internal_path = NULL;
L
Linus Torvalds 已提交
87

L
Len Brown 已提交
88
	ACPI_FUNCTION_TRACE("ns_evaluate_relative");
L
Linus Torvalds 已提交
89 90 91 92 93

	/*
	 * Must have a valid object handle
	 */
	if (!info || !info->node) {
L
Len Brown 已提交
94
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
95 96 97 98
	}

	/* Build an internal name string for the method */

L
Len Brown 已提交
99 100 101
	status = acpi_ns_internalize_name(pathname, &internal_path);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
102 103
	}

L
Len Brown 已提交
104
	scope_info = acpi_ut_create_generic_state();
L
Linus Torvalds 已提交
105 106 107 108 109 110
	if (!scope_info) {
		goto cleanup1;
	}

	/* Get the prefix handle and Node */

L
Len Brown 已提交
111 112
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
113 114 115
		goto cleanup;
	}

L
Len Brown 已提交
116
	info->node = acpi_ns_map_handle_to_node(info->node);
L
Linus Torvalds 已提交
117
	if (!info->node) {
L
Len Brown 已提交
118
		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
L
Linus Torvalds 已提交
119 120 121 122 123 124 125
		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	/* Lookup the name in the namespace */

	scope_info->scope.node = info->node;
L
Len Brown 已提交
126 127 128
	status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY,
				ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
				&node);
L
Linus Torvalds 已提交
129

L
Len Brown 已提交
130
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
L
Linus Torvalds 已提交
131

L
Len Brown 已提交
132 133 134
	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
				  pathname, acpi_format_exception(status)));
L
Linus Torvalds 已提交
135 136 137 138 139 140
		goto cleanup;
	}

	/*
	 * Now that we have a handle to the object, we can attempt to evaluate it.
	 */
L
Len Brown 已提交
141 142
	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
			  pathname, node, acpi_ns_get_attached_object(node)));
L
Linus Torvalds 已提交
143 144

	info->node = node;
L
Len Brown 已提交
145
	status = acpi_ns_evaluate_by_handle(info);
L
Linus Torvalds 已提交
146

L
Len Brown 已提交
147 148
	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
			  "*** Completed eval of object %s ***\n", pathname));
L
Linus Torvalds 已提交
149

L
Len Brown 已提交
150 151
      cleanup:
	acpi_ut_delete_generic_state(scope_info);
L
Linus Torvalds 已提交
152

L
Len Brown 已提交
153 154 155
      cleanup1:
	ACPI_MEM_FREE(internal_path);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
156 157 158 159 160 161
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_evaluate_by_name
 *
R
Robert Moore 已提交
162 163
 * PARAMETERS:  Pathname        - Fully qualified pathname to the object
 *              Info                - Method info block, contains:
L
Linus Torvalds 已提交
164 165 166 167 168 169 170 171
 *                  return_object   - Where to put method's return value (if
 *                                    any).  If NULL, no value is returned.
 *                  Params          - List of parameters to pass to the method,
 *                                    terminated by NULL.  Params itself may be
 *                                    NULL if no parameters are being passed.
 *
 * RETURN:      Status
 *
R
Robert Moore 已提交
172 173
 * DESCRIPTION: Evaluate the object or rind and execute the requested method
 *              passing the given parameters
L
Linus Torvalds 已提交
174 175 176 177 178 179
 *
 * MUTEX:       Locks Namespace
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
180
acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info)
L
Linus Torvalds 已提交
181
{
L
Len Brown 已提交
182 183
	acpi_status status;
	char *internal_path = NULL;
L
Linus Torvalds 已提交
184

L
Len Brown 已提交
185
	ACPI_FUNCTION_TRACE("ns_evaluate_by_name");
L
Linus Torvalds 已提交
186 187 188

	/* Build an internal name string for the method */

L
Len Brown 已提交
189 190 191
	status = acpi_ns_internalize_name(pathname, &internal_path);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
192 193
	}

L
Len Brown 已提交
194 195
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
196 197 198 199 200
		goto cleanup;
	}

	/* Lookup the name in the namespace */

L
Len Brown 已提交
201 202 203
	status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
				ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
				&info->node);
L
Linus Torvalds 已提交
204

L
Len Brown 已提交
205
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
L
Linus Torvalds 已提交
206

L
Len Brown 已提交
207 208 209 210
	if (ACPI_FAILURE(status)) {
		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
				  "Object at [%s] was not found, status=%.4X\n",
				  pathname, status));
L
Linus Torvalds 已提交
211 212 213 214 215 216
		goto cleanup;
	}

	/*
	 * Now that we have a handle to the object, we can attempt to evaluate it.
	 */
L
Len Brown 已提交
217 218 219
	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
			  pathname, info->node,
			  acpi_ns_get_attached_object(info->node)));
L
Linus Torvalds 已提交
220

L
Len Brown 已提交
221
	status = acpi_ns_evaluate_by_handle(info);
L
Linus Torvalds 已提交
222

L
Len Brown 已提交
223 224
	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
			  "*** Completed eval of object %s ***\n", pathname));
L
Linus Torvalds 已提交
225

L
Len Brown 已提交
226
      cleanup:
L
Linus Torvalds 已提交
227 228 229 230

	/* Cleanup */

	if (internal_path) {
L
Len Brown 已提交
231
		ACPI_MEM_FREE(internal_path);
L
Linus Torvalds 已提交
232 233
	}

L
Len Brown 已提交
234
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
235 236 237 238 239 240
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_evaluate_by_handle
 *
R
Robert Moore 已提交
241 242 243 244
 * PARAMETERS:  Info            - Method info block, contains:
 *                  Node            - Method/Object Node to execute
 *                  Parameters      - List of parameters to pass to the method,
 *                                    terminated by NULL. Params itself may be
L
Linus Torvalds 已提交
245
 *                                    NULL if no parameters are being passed.
R
Robert Moore 已提交
246 247 248 249 250
 *                  return_object   - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
 *                  parameter_type  - Type of Parameter list
 *                  return_object   - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
L
Linus Torvalds 已提交
251 252 253
 *
 * RETURN:      Status
 *
R
Robert Moore 已提交
254 255
 * DESCRIPTION: Evaluate object or execute the requested method passing the
 *              given parameters
L
Linus Torvalds 已提交
256 257 258 259 260
 *
 * MUTEX:       Locks Namespace
 *
 ******************************************************************************/

L
Len Brown 已提交
261
acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info)
L
Linus Torvalds 已提交
262
{
L
Len Brown 已提交
263
	acpi_status status;
L
Linus Torvalds 已提交
264

L
Len Brown 已提交
265
	ACPI_FUNCTION_TRACE("ns_evaluate_by_handle");
L
Linus Torvalds 已提交
266 267 268 269

	/* Check if namespace has been initialized */

	if (!acpi_gbl_root_node) {
L
Len Brown 已提交
270
		return_ACPI_STATUS(AE_NO_NAMESPACE);
L
Linus Torvalds 已提交
271 272 273 274 275
	}

	/* Parameter Validation */

	if (!info) {
L
Len Brown 已提交
276
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
277 278 279 280 281 282 283 284
	}

	/* Initialize the return value to an invalid object */

	info->return_object = NULL;

	/* Get the prefix handle and Node */

L
Len Brown 已提交
285 286 287
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
288 289
	}

L
Len Brown 已提交
290
	info->node = acpi_ns_map_handle_to_node(info->node);
L
Linus Torvalds 已提交
291
	if (!info->node) {
L
Len Brown 已提交
292 293
		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
294 295 296 297 298 299
	}

	/*
	 * For a method alias, we must grab the actual method node so that proper
	 * scoping context will be established before execution.
	 */
L
Len Brown 已提交
300 301 302 303
	if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
		info->node =
		    ACPI_CAST_PTR(struct acpi_namespace_node,
				  info->node->object);
L
Linus Torvalds 已提交
304 305 306 307 308 309 310 311 312
	}

	/*
	 * Two major cases here:
	 * 1) The object is an actual control method -- execute it.
	 * 2) The object is not a method -- just return it's current value
	 *
	 * In both cases, the namespace is unlocked by the acpi_ns* procedure
	 */
L
Len Brown 已提交
313
	if (acpi_ns_get_type(info->node) == ACPI_TYPE_METHOD) {
L
Linus Torvalds 已提交
314 315 316
		/*
		 * Case 1) We have an actual control method to execute
		 */
L
Len Brown 已提交
317 318
		status = acpi_ns_execute_control_method(info);
	} else {
L
Linus Torvalds 已提交
319 320 321
		/*
		 * Case 2) Object is NOT a method, just return its current value
		 */
L
Len Brown 已提交
322
		status = acpi_ns_get_object_value(info);
L
Linus Torvalds 已提交
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
	}

	/*
	 * Check if there is a return value on the stack that must be dealt with
	 */
	if (status == AE_CTRL_RETURN_VALUE) {
		/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */

		status = AE_OK;
	}

	/*
	 * Namespace was unlocked by the handling acpi_ns* function, so we
	 * just return
	 */
L
Len Brown 已提交
338
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
339 340 341 342 343 344
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_execute_control_method
 *
R
Robert Moore 已提交
345 346
 * PARAMETERS:  Info            - Method info block, contains:
 *                  Node            - Method Node to execute
347
 *                  obj_desc        - Method object
R
Robert Moore 已提交
348 349 350 351 352 353 354 355
 *                  Parameters      - List of parameters to pass to the method,
 *                                    terminated by NULL. Params itself may be
 *                                    NULL if no parameters are being passed.
 *                  return_object   - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
 *                  parameter_type  - Type of Parameter list
 *                  return_object   - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
L
Linus Torvalds 已提交
356 357 358 359 360 361 362 363 364
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute the requested method passing the given parameters
 *
 * MUTEX:       Assumes namespace is locked
 *
 ******************************************************************************/

R
Robert Moore 已提交
365
static acpi_status
L
Len Brown 已提交
366
acpi_ns_execute_control_method(struct acpi_parameter_info *info)
L
Linus Torvalds 已提交
367
{
L
Len Brown 已提交
368
	acpi_status status;
L
Linus Torvalds 已提交
369

L
Len Brown 已提交
370
	ACPI_FUNCTION_TRACE("ns_execute_control_method");
L
Linus Torvalds 已提交
371 372 373

	/* Verify that there is a method associated with this object */

L
Len Brown 已提交
374
	info->obj_desc = acpi_ns_get_attached_object(info->node);
375
	if (!info->obj_desc) {
B
Bob Moore 已提交
376
		ACPI_ERROR((AE_INFO, "No attached method object"));
L
Linus Torvalds 已提交
377

L
Len Brown 已提交
378 379
		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
		return_ACPI_STATUS(AE_NULL_OBJECT);
L
Linus Torvalds 已提交
380 381
	}

L
Len Brown 已提交
382 383
	ACPI_DUMP_PATHNAME(info->node, "Execute Method:",
			   ACPI_LV_INFO, _COMPONENT);
L
Linus Torvalds 已提交
384

L
Len Brown 已提交
385 386 387
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
			  info->obj_desc->method.aml_start + 1,
			  info->obj_desc->method.aml_length - 1));
L
Linus Torvalds 已提交
388 389 390 391 392 393 394 395

	/*
	 * Unlock the namespace before execution.  This allows namespace access
	 * via the external Acpi* interfaces while a method is being executed.
	 * However, any namespace deletion must acquire both the namespace and
	 * interpreter locks to ensure that no thread is using the portion of the
	 * namespace that is being deleted.
	 */
L
Len Brown 已提交
396 397 398
	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
399 400 401 402 403 404
	}

	/*
	 * Execute the method via the interpreter.  The interpreter is locked
	 * here before calling into the AML parser
	 */
L
Len Brown 已提交
405 406 407
	status = acpi_ex_enter_interpreter();
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
408 409
	}

L
Len Brown 已提交
410 411
	status = acpi_ps_execute_method(info);
	acpi_ex_exit_interpreter();
L
Linus Torvalds 已提交
412

L
Len Brown 已提交
413
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
414 415 416 417 418 419
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_object_value
 *
R
Robert Moore 已提交
420 421 422 423
 * PARAMETERS:  Info            - Method info block, contains:
 *                  Node            - Object's NS node
 *                  return_object   - Where to put object value (if
 *                                    any). If NULL, no value is returned.
L
Linus Torvalds 已提交
424 425 426 427 428 429 430 431 432
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Return the current value of the object
 *
 * MUTEX:       Assumes namespace is locked, leaves namespace unlocked
 *
 ******************************************************************************/

L
Len Brown 已提交
433
static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info)
L
Linus Torvalds 已提交
434
{
L
Len Brown 已提交
435 436
	acpi_status status = AE_OK;
	struct acpi_namespace_node *resolved_node = info->node;
L
Linus Torvalds 已提交
437

L
Len Brown 已提交
438
	ACPI_FUNCTION_TRACE("ns_get_object_value");
L
Linus Torvalds 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460

	/*
	 * Objects require additional resolution steps (e.g., the Node may be a
	 * field that must be read, etc.) -- we can't just grab the object out of
	 * the node.
	 */

	/*
	 * Use resolve_node_to_value() to get the associated value. This call always
	 * deletes obj_desc (allocated above).
	 *
	 * NOTE: we can get away with passing in NULL for a walk state because
	 * obj_desc is guaranteed to not be a reference to either a method local or
	 * a method argument (because this interface can only be called from the
	 * acpi_evaluate external interface, never called from a running method.)
	 *
	 * Even though we do not directly invoke the interpreter for this, we must
	 * enter it because we could access an opregion. The opregion access code
	 * assumes that the interpreter is locked.
	 *
	 * We must release the namespace lock before entering the intepreter.
	 */
L
Len Brown 已提交
461 462 463
	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
464 465
	}

L
Len Brown 已提交
466 467 468
	status = acpi_ex_enter_interpreter();
	if (ACPI_SUCCESS(status)) {
		status = acpi_ex_resolve_node_to_value(&resolved_node, NULL);
L
Linus Torvalds 已提交
469 470 471 472
		/*
		 * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed
		 * in resolved_node.
		 */
L
Len Brown 已提交
473
		acpi_ex_exit_interpreter();
L
Linus Torvalds 已提交
474

L
Len Brown 已提交
475
		if (ACPI_SUCCESS(status)) {
L
Linus Torvalds 已提交
476 477
			status = AE_CTRL_RETURN_VALUE;
			info->return_object = ACPI_CAST_PTR
L
Len Brown 已提交
478 479 480 481 482 483
			    (union acpi_operand_object, resolved_node);
			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
					  "Returning object %p [%s]\n",
					  info->return_object,
					  acpi_ut_get_object_type_name(info->
								       return_object)));
L
Linus Torvalds 已提交
484 485 486 487 488
		}
	}

	/* Namespace is unlocked */

L
Len Brown 已提交
489
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
490
}