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