1 /*******************************************************************************
2  *
3  * Module Name: nseval - Object evaluation interfaces -- includes control
4  *                       method lookup and execution.
5  *
6  ******************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2004, 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 
46 #include <acpi/acpi.h>
47 #include <acpi/acparser.h>
48 #include <acpi/acinterp.h>
49 #include <acpi/acnamesp.h>
50 
51 
52 #define _COMPONENT          ACPI_NAMESPACE
53 	 ACPI_MODULE_NAME    ("nseval")
54 
55 
56 /*******************************************************************************
57  *
58  * FUNCTION:    acpi_ns_evaluate_relative
59  *
60  * PARAMETERS:  Handle              - The relative containing object
61  *              Pathname            - Name of method to execute, If NULL, the
62  *                                    handle is the object to execute
63  *              Params              - List of parameters to pass to the method,
64  *                                    terminated by NULL.  Params itself may be
65  *                                    NULL if no parameters are being passed.
66  *              return_object       - Where to put method's return value (if
67  *                                    any).  If NULL, no value is returned.
68  *
69  * RETURN:      Status
70  *
71  * DESCRIPTION: Find and execute the requested method using the handle as a
72  *              scope
73  *
74  * MUTEX:       Locks Namespace
75  *
76  ******************************************************************************/
77 
78 acpi_status
acpi_ns_evaluate_relative(struct acpi_namespace_node * handle,char * pathname,union acpi_operand_object ** params,union acpi_operand_object ** return_object)79 acpi_ns_evaluate_relative (
80 	struct acpi_namespace_node      *handle,
81 	char                            *pathname,
82 	union acpi_operand_object       **params,
83 	union acpi_operand_object       **return_object)
84 {
85 	acpi_status                     status;
86 	struct acpi_namespace_node      *prefix_node;
87 	struct acpi_namespace_node      *node = NULL;
88 	union acpi_generic_state        *scope_info;
89 	char                            *internal_path = NULL;
90 
91 
92 	ACPI_FUNCTION_TRACE ("ns_evaluate_relative");
93 
94 
95 	/*
96 	 * Must have a valid object handle
97 	 */
98 	if (!handle) {
99 		return_ACPI_STATUS (AE_BAD_PARAMETER);
100 	}
101 
102 	/* Build an internal name string for the method */
103 
104 	status = acpi_ns_internalize_name (pathname, &internal_path);
105 	if (ACPI_FAILURE (status)) {
106 		return_ACPI_STATUS (status);
107 	}
108 
109 	scope_info = acpi_ut_create_generic_state ();
110 	if (!scope_info) {
111 		goto cleanup1;
112 	}
113 
114 	/* Get the prefix handle and Node */
115 
116 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
117 	if (ACPI_FAILURE (status)) {
118 		goto cleanup;
119 	}
120 
121 	prefix_node = acpi_ns_map_handle_to_node (handle);
122 	if (!prefix_node) {
123 		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
124 		status = AE_BAD_PARAMETER;
125 		goto cleanup;
126 	}
127 
128 	/* Lookup the name in the namespace */
129 
130 	scope_info->scope.node = prefix_node;
131 	status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
132 			 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
133 			 &node);
134 
135 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
136 
137 	if (ACPI_FAILURE (status)) {
138 		ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
139 			pathname, acpi_format_exception (status)));
140 		goto cleanup;
141 	}
142 
143 	/*
144 	 * Now that we have a handle to the object, we can attempt
145 	 * to evaluate it.
146 	 */
147 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
148 		pathname, node, acpi_ns_get_attached_object (node)));
149 
150 	status = acpi_ns_evaluate_by_handle (node, params, return_object);
151 
152 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
153 		pathname));
154 
155 cleanup:
156 	acpi_ut_delete_generic_state (scope_info);
157 
158 cleanup1:
159 	ACPI_MEM_FREE (internal_path);
160 	return_ACPI_STATUS (status);
161 }
162 
163 
164 /*******************************************************************************
165  *
166  * FUNCTION:    acpi_ns_evaluate_by_name
167  *
168  * PARAMETERS:  Pathname            - Fully qualified pathname to the object
169  *              return_object       - Where to put method's return value (if
170  *                                    any).  If NULL, no value is returned.
171  *              Params              - List of parameters to pass to the method,
172  *                                    terminated by NULL.  Params itself may be
173  *                                    NULL if no parameters are being passed.
174  *
175  * RETURN:      Status
176  *
177  * DESCRIPTION: Find and execute the requested method passing the given
178  *              parameters
179  *
180  * MUTEX:       Locks Namespace
181  *
182  ******************************************************************************/
183 
184 acpi_status
acpi_ns_evaluate_by_name(char * pathname,union acpi_operand_object ** params,union acpi_operand_object ** return_object)185 acpi_ns_evaluate_by_name (
186 	char                            *pathname,
187 	union acpi_operand_object       **params,
188 	union acpi_operand_object       **return_object)
189 {
190 	acpi_status                     status;
191 	struct acpi_namespace_node      *node = NULL;
192 	char                            *internal_path = NULL;
193 
194 
195 	ACPI_FUNCTION_TRACE ("ns_evaluate_by_name");
196 
197 
198 	/* Build an internal name string for the method */
199 
200 	status = acpi_ns_internalize_name (pathname, &internal_path);
201 	if (ACPI_FAILURE (status)) {
202 		return_ACPI_STATUS (status);
203 	}
204 
205 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
206 	if (ACPI_FAILURE (status)) {
207 		goto cleanup;
208 	}
209 
210 	/* Lookup the name in the namespace */
211 
212 	status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
213 			 ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
214 			 &node);
215 
216 	(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
217 
218 	if (ACPI_FAILURE (status)) {
219 		ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Object at [%s] was not found, status=%.4X\n",
220 			pathname, status));
221 		goto cleanup;
222 	}
223 
224 	/*
225 	 * Now that we have a handle to the object, we can attempt
226 	 * to evaluate it.
227 	 */
228 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n",
229 		pathname, node, acpi_ns_get_attached_object (node)));
230 
231 	status = acpi_ns_evaluate_by_handle (node, params, return_object);
232 
233 	ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n",
234 		pathname));
235 
236 
237 cleanup:
238 
239 	/* Cleanup */
240 
241 	if (internal_path) {
242 		ACPI_MEM_FREE (internal_path);
243 	}
244 
245 	return_ACPI_STATUS (status);
246 }
247 
248 
249 /*******************************************************************************
250  *
251  * FUNCTION:    acpi_ns_evaluate_by_handle
252  *
253  * PARAMETERS:  Handle              - Method Node to execute
254  *              Params              - List of parameters to pass to the method,
255  *                                    terminated by NULL.  Params itself may be
256  *                                    NULL if no parameters are being passed.
257  *              return_object       - Where to put method's return value (if
258  *                                    any).  If NULL, no value is returned.
259  *
260  * RETURN:      Status
261  *
262  * DESCRIPTION: Execute the requested method passing the given parameters
263  *
264  * MUTEX:       Locks Namespace
265  *
266  ******************************************************************************/
267 
268 acpi_status
acpi_ns_evaluate_by_handle(struct acpi_namespace_node * handle,union acpi_operand_object ** params,union acpi_operand_object ** return_object)269 acpi_ns_evaluate_by_handle (
270 	struct acpi_namespace_node      *handle,
271 	union acpi_operand_object       **params,
272 	union acpi_operand_object       **return_object)
273 {
274 	struct acpi_namespace_node      *node;
275 	acpi_status                     status;
276 	union acpi_operand_object       *local_return_object;
277 
278 
279 	ACPI_FUNCTION_TRACE ("ns_evaluate_by_handle");
280 
281 
282 	/* Check if namespace has been initialized */
283 
284 	if (!acpi_gbl_root_node) {
285 		return_ACPI_STATUS (AE_NO_NAMESPACE);
286 	}
287 
288 	/* Parameter Validation */
289 
290 	if (!handle) {
291 		return_ACPI_STATUS (AE_BAD_PARAMETER);
292 	}
293 
294 	if (return_object) {
295 		/* Initialize the return value to an invalid object */
296 
297 		*return_object = NULL;
298 	}
299 
300 	/* Get the prefix handle and Node */
301 
302 	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
303 	if (ACPI_FAILURE (status)) {
304 		return_ACPI_STATUS (status);
305 	}
306 
307 	node = acpi_ns_map_handle_to_node (handle);
308 	if (!node) {
309 		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
310 		return_ACPI_STATUS (AE_BAD_PARAMETER);
311 	}
312 
313 	/*
314 	 * For a method alias, we must grab the actual method node
315 	 * so that proper scoping context will be established
316 	 * before execution.
317 	 */
318 	if (acpi_ns_get_type (node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
319 		node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
320 	}
321 
322 	/*
323 	 * Two major cases here:
324 	 * 1) The object is an actual control method -- execute it.
325 	 * 2) The object is not a method -- just return it's current
326 	 *      value
327 	 *
328 	 * In both cases, the namespace is unlocked by the
329 	 *  acpi_ns* procedure
330 	 */
331 	if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) {
332 		/*
333 		 * Case 1) We have an actual control method to execute
334 		 */
335 		status = acpi_ns_execute_control_method (node, params,
336 				 &local_return_object);
337 	}
338 	else {
339 		/*
340 		 * Case 2) Object is NOT a method, just return its
341 		 * current value
342 		 */
343 		status = acpi_ns_get_object_value (node, &local_return_object);
344 	}
345 
346 	/*
347 	 * Check if there is a return value on the stack that must
348 	 * be dealt with
349 	 */
350 	if (status == AE_CTRL_RETURN_VALUE) {
351 		/*
352 		 * If the Method returned a value and the caller
353 		 * provided a place to store a returned value, Copy
354 		 * the returned value to the object descriptor provided
355 		 * by the caller.
356 		 */
357 		if (return_object) {
358 			/*
359 			 * Valid return object, copy the pointer to
360 			 * the returned object
361 			 */
362 			*return_object = local_return_object;
363 		}
364 
365 		/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
366 
367 		status = AE_OK;
368 	}
369 
370 	/*
371 	 * Namespace was unlocked by the handling acpi_ns* function,
372 	 * so we just return
373 	 */
374 	return_ACPI_STATUS (status);
375 }
376 
377 
378 /*******************************************************************************
379  *
380  * FUNCTION:    acpi_ns_execute_control_method
381  *
382  * PARAMETERS:  method_node         - The method to execute
383  *              Params              - List of parameters to pass to the method,
384  *                                    terminated by NULL.  Params itself may be
385  *                                    NULL if no parameters are being passed.
386  *              return_obj_desc     - List of result objects to be returned
387  *                                    from the method.
388  *
389  * RETURN:      Status
390  *
391  * DESCRIPTION: Execute the requested method passing the given parameters
392  *
393  * MUTEX:       Assumes namespace is locked
394  *
395  ******************************************************************************/
396 
397 acpi_status
acpi_ns_execute_control_method(struct acpi_namespace_node * method_node,union acpi_operand_object ** params,union acpi_operand_object ** return_obj_desc)398 acpi_ns_execute_control_method (
399 	struct acpi_namespace_node      *method_node,
400 	union acpi_operand_object       **params,
401 	union acpi_operand_object       **return_obj_desc)
402 {
403 	acpi_status                     status;
404 	union acpi_operand_object       *obj_desc;
405 
406 
407 	ACPI_FUNCTION_TRACE ("ns_execute_control_method");
408 
409 
410 	/* Verify that there is a method associated with this object */
411 
412 	obj_desc = acpi_ns_get_attached_object (method_node);
413 	if (!obj_desc) {
414 		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n"));
415 
416 		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
417 		return_ACPI_STATUS (AE_NULL_OBJECT);
418 	}
419 
420 	ACPI_DUMP_PATHNAME (method_node, "Execute Method:",
421 		ACPI_LV_INFO, _COMPONENT);
422 
423 	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
424 		obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1));
425 
426 	/*
427 	 * Unlock the namespace before execution.  This allows namespace access
428 	 * via the external Acpi* interfaces while a method is being executed.
429 	 * However, any namespace deletion must acquire both the namespace and
430 	 * interpreter locks to ensure that no thread is using the portion of the
431 	 * namespace that is being deleted.
432 	 */
433 	status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
434 	if (ACPI_FAILURE (status)) {
435 		return_ACPI_STATUS (status);
436 	}
437 
438 	/*
439 	 * Execute the method via the interpreter.  The interpreter is locked
440 	 * here before calling into the AML parser
441 	 */
442 	status = acpi_ex_enter_interpreter ();
443 	if (ACPI_FAILURE (status)) {
444 		return_ACPI_STATUS (status);
445 	}
446 
447 	status = acpi_psx_execute (method_node, params, return_obj_desc);
448 	acpi_ex_exit_interpreter ();
449 
450 	return_ACPI_STATUS (status);
451 }
452 
453 
454 /*******************************************************************************
455  *
456  * FUNCTION:    acpi_ns_get_object_value
457  *
458  * PARAMETERS:  Node                - The object
459  *              return_obj_desc     - Where the objects value is returned
460  *
461  * RETURN:      Status
462  *
463  * DESCRIPTION: Return the current value of the object
464  *
465  * MUTEX:       Assumes namespace is locked, leaves namespace unlocked
466  *
467  ******************************************************************************/
468 
469 acpi_status
acpi_ns_get_object_value(struct acpi_namespace_node * node,union acpi_operand_object ** return_obj_desc)470 acpi_ns_get_object_value (
471 	struct acpi_namespace_node      *node,
472 	union acpi_operand_object       **return_obj_desc)
473 {
474 	acpi_status                     status = AE_OK;
475 	struct acpi_namespace_node      *resolved_node = node;
476 
477 
478 	ACPI_FUNCTION_TRACE ("ns_get_object_value");
479 
480 
481 	/*
482 	 * Objects require additional resolution steps (e.g., the
483 	 * Node may be a field that must be read, etc.) -- we can't just grab
484 	 * the object out of the node.
485 	 */
486 
487 	/*
488 	 * Use resolve_node_to_value() to get the associated value. This call
489 	 * always deletes obj_desc (allocated above).
490 	 *
491 	 * NOTE: we can get away with passing in NULL for a walk state
492 	 * because obj_desc is guaranteed to not be a reference to either
493 	 * a method local or a method argument (because this interface can only be
494 	 * called from the acpi_evaluate external interface, never called from
495 	 * a running control method.)
496 	 *
497 	 * Even though we do not directly invoke the interpreter
498 	 * for this, we must enter it because we could access an opregion.
499 	 * The opregion access code assumes that the interpreter
500 	 * is locked.
501 	 *
502 	 * We must release the namespace lock before entering the
503 	 * intepreter.
504 	 */
505 	status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
506 	if (ACPI_FAILURE (status)) {
507 		return_ACPI_STATUS (status);
508 	}
509 
510 	status = acpi_ex_enter_interpreter ();
511 	if (ACPI_SUCCESS (status)) {
512 		status = acpi_ex_resolve_node_to_value (&resolved_node, NULL);
513 		/*
514 		 * If acpi_ex_resolve_node_to_value() succeeded, the return value was
515 		 * placed in resolved_node.
516 		 */
517 		acpi_ex_exit_interpreter ();
518 
519 		if (ACPI_SUCCESS (status)) {
520 			status = AE_CTRL_RETURN_VALUE;
521 			*return_obj_desc = ACPI_CAST_PTR (union acpi_operand_object, resolved_node);
522 			ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n",
523 				*return_obj_desc, acpi_ut_get_object_type_name (*return_obj_desc)));
524 		}
525 	}
526 
527 	/* Namespace is unlocked */
528 
529 	return_ACPI_STATUS (status);
530 }
531 
532