:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / namespace / nseval.c
1 /*******************************************************************************
2  *
3  * Module Name: nseval - Object evaluation interfaces -- includes control
4  *                       method lookup and execution.
5  *              $Revision$
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
61 ACPI_STATUS
62 acpi_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         /*
76          * Must have a valid object handle
77          */
78         if (!handle) {
79                 return (AE_BAD_PARAMETER);
80         }
81
82         /* Build an internal name string for the method */
83
84         status = acpi_ns_internalize_name (pathname, &internal_path);
85         if (ACPI_FAILURE (status)) {
86                 return (status);
87         }
88
89         /* Get the prefix handle and Node */
90
91         acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
92
93         prefix_node = acpi_ns_convert_handle_to_entry (handle);
94         if (!prefix_node) {
95                 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
96                 status = AE_BAD_PARAMETER;
97                 goto cleanup;
98         }
99
100         /* Lookup the name in the namespace */
101
102         scope_info.scope.node = prefix_node;
103         status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY,
104                          IMODE_EXECUTE, NS_NO_UPSEARCH, NULL,
105                          &node);
106
107         acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
108
109         if (ACPI_FAILURE (status)) {
110                 goto cleanup;
111         }
112
113         /*
114          * Now that we have a handle to the object, we can attempt
115          * to evaluate it.
116          */
117
118         status = acpi_ns_evaluate_by_handle (node, params, return_object);
119
120 cleanup:
121
122         /* Cleanup */
123
124         acpi_cm_free (internal_path);
125
126         return (status);
127 }
128
129
130 /*******************************************************************************
131  *
132  * FUNCTION:    Acpi_ns_evaluate_by_name
133  *
134  * PARAMETERS:  Pathname            - Fully qualified pathname to the object
135  *              *Return_object      - Where to put method's return value (if
136  *                                    any).  If NULL, no value is returned.
137  *              **Params            - List of parameters to pass to the method,
138  *                                    terminated by NULL.  Params itself may be
139  *                                    NULL if no parameters are being passed.
140  *
141  * RETURN:      Status
142  *
143  * DESCRIPTION: Find and execute the requested method passing the given
144  *              parameters
145  *
146  * MUTEX:       Locks Namespace
147  *
148  ******************************************************************************/
149
150 ACPI_STATUS
151 acpi_ns_evaluate_by_name (
152         NATIVE_CHAR             *pathname,
153         ACPI_OPERAND_OBJECT     **params,
154         ACPI_OPERAND_OBJECT     **return_object)
155 {
156         ACPI_STATUS             status;
157         ACPI_NAMESPACE_NODE     *node = NULL;
158         NATIVE_CHAR             *internal_path = NULL;
159
160
161         /* Build an internal name string for the method */
162
163         status = acpi_ns_internalize_name (pathname, &internal_path);
164         if (ACPI_FAILURE (status)) {
165                 return (status);
166         }
167
168         acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
169
170         /* Lookup the name in the namespace */
171
172         status = acpi_ns_lookup (NULL, internal_path, ACPI_TYPE_ANY,
173                          IMODE_EXECUTE, NS_NO_UPSEARCH, NULL,
174                          &node);
175
176         acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
177
178         if (ACPI_FAILURE (status)) {
179                 goto cleanup;
180         }
181
182         /*
183          * Now that we have a handle to the object, we can attempt
184          * to evaluate it.
185          */
186
187         status = acpi_ns_evaluate_by_handle (node, params, return_object);
188
189
190 cleanup:
191
192         /* Cleanup */
193
194         if (internal_path) {
195                 acpi_cm_free (internal_path);
196         }
197
198         return (status);
199 }
200
201
202 /*******************************************************************************
203  *
204  * FUNCTION:    Acpi_ns_evaluate_by_handle
205  *
206  * PARAMETERS:  Handle              - Method Node to execute
207  *              **Params            - List of parameters to pass to the method,
208  *                                    terminated by NULL.  Params itself may be
209  *                                    NULL if no parameters are being passed.
210  *              *Return_object      - Where to put method's return value (if
211  *                                    any).  If NULL, no value is returned.
212  *
213  * RETURN:      Status
214  *
215  * DESCRIPTION: Execute the requested method passing the given parameters
216  *
217  * MUTEX:       Locks Namespace
218  *
219  ******************************************************************************/
220
221 ACPI_STATUS
222 acpi_ns_evaluate_by_handle (
223         ACPI_NAMESPACE_NODE     *handle,
224         ACPI_OPERAND_OBJECT     **params,
225         ACPI_OPERAND_OBJECT     **return_object)
226 {
227         ACPI_NAMESPACE_NODE     *node;
228         ACPI_STATUS             status;
229         ACPI_OPERAND_OBJECT     *local_return_object;
230
231
232         /* Check if namespace has been initialized */
233
234         if (!acpi_gbl_root_node) {
235                 return (AE_NO_NAMESPACE);
236         }
237
238         /* Parameter Validation */
239
240         if (!handle) {
241                 return (AE_BAD_PARAMETER);
242         }
243
244         if (return_object) {
245                 /* Initialize the return value to an invalid object */
246
247                 *return_object = NULL;
248         }
249
250         /* Get the prefix handle and Node */
251
252         acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
253
254         node = acpi_ns_convert_handle_to_entry (handle);
255         if (!node) {
256                 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
257                 return (AE_BAD_PARAMETER);
258         }
259
260
261         /*
262          * Two major cases here:
263          * 1) The object is an actual control method -- execute it.
264          * 2) The object is not a method -- just return it's current
265          *      value
266          *
267          * In both cases, the namespace is unlocked by the
268          *  Acpi_ns* procedure
269          */
270         if (acpi_ns_get_type (node) == ACPI_TYPE_METHOD) {
271                 /*
272                  * Case 1) We have an actual control method to execute
273                  */
274                 status = acpi_ns_execute_control_method (node, params,
275                                  &local_return_object);
276         }
277
278         else {
279                 /*
280                  * Case 2) Object is NOT a method, just return its
281                  * current value
282                  */
283                 status = acpi_ns_get_object_value (node, &local_return_object);
284         }
285
286
287         /*
288          * Check if there is a return value on the stack that must
289          * be dealt with
290          */
291         if (status == AE_CTRL_RETURN_VALUE) {
292                 /*
293                  * If the Method returned a value and the caller
294                  * provided a place to store a returned value, Copy
295                  * the returned value to the object descriptor provided
296                  * by the caller.
297                  */
298                 if (return_object) {
299                         /*
300                          * Valid return object, copy the pointer to
301                          * the returned object
302                          */
303                         *return_object = local_return_object;
304                 }
305
306
307                 /* Map AE_RETURN_VALUE to AE_OK, we are done with it */
308
309                 if (status == AE_CTRL_RETURN_VALUE) {
310                         status = AE_OK;
311                 }
312         }
313
314         /*
315          * Namespace was unlocked by the handling Acpi_ns* function,
316          * so we just return
317          */
318         return (status);
319 }
320
321
322 /*******************************************************************************
323  *
324  * FUNCTION:    Acpi_ns_execute_control_method
325  *
326  * PARAMETERS:  Method_node     - The object/method
327  *              **Params            - List of parameters to pass to the method,
328  *                                    terminated by NULL.  Params itself may be
329  *                                    NULL if no parameters are being passed.
330  *              **Return_obj_desc   - List of result objects to be returned
331  *                                    from the method.
332  *
333  * RETURN:      Status
334  *
335  * DESCRIPTION: Execute the requested method passing the given parameters
336  *
337  * MUTEX:       Assumes namespace is locked
338  *
339  ******************************************************************************/
340
341 ACPI_STATUS
342 acpi_ns_execute_control_method (
343         ACPI_NAMESPACE_NODE     *method_node,
344         ACPI_OPERAND_OBJECT     **params,
345         ACPI_OPERAND_OBJECT     **return_obj_desc)
346 {
347         ACPI_STATUS             status;
348         ACPI_OPERAND_OBJECT     *obj_desc;
349
350
351         /* Verify that there is a method associated with this object */
352
353         obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_node);
354         if (!obj_desc) {
355                 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
356                 return (AE_ERROR);
357         }
358
359
360         /*
361          * Unlock the namespace before execution.  This allows namespace access
362          * via the external Acpi* interfaces while a method is being executed.
363          * However, any namespace deletion must acquire both the namespace and
364          * interpreter locks to ensure that no thread is using the portion of the
365          * namespace that is being deleted.
366          */
367         acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
368
369         /*
370          * Execute the method via the interpreter
371          */
372         status = acpi_aml_execute_method (method_node, params, return_obj_desc);
373
374         return (status);
375 }
376
377
378 /*******************************************************************************
379  *
380  * FUNCTION:    Acpi_ns_get_object_value
381  *
382  * PARAMETERS:  Node         - The object
383  *
384  * RETURN:      Status
385  *
386  * DESCRIPTION: Return the current value of the object
387  *
388  * MUTEX:       Assumes namespace is locked
389  *
390  ******************************************************************************/
391
392 ACPI_STATUS
393 acpi_ns_get_object_value (
394         ACPI_NAMESPACE_NODE     *node,
395         ACPI_OPERAND_OBJECT     **return_obj_desc)
396 {
397         ACPI_STATUS             status = AE_OK;
398         ACPI_OPERAND_OBJECT     *obj_desc;
399         ACPI_OPERAND_OBJECT     *val_desc;
400
401
402         /*
403          *  We take the value from certain objects directly
404          */
405
406         if ((node->type == ACPI_TYPE_PROCESSOR) ||
407                 (node->type == ACPI_TYPE_POWER)) {
408                 /*
409                  *  Create a Reference object to contain the object
410                  */
411                 obj_desc = acpi_cm_create_internal_object (node->type);
412                 if (!obj_desc) {
413                    status = AE_NO_MEMORY;
414                    goto unlock_and_exit;
415                 }
416
417                 /*
418                  *  Get the attached object
419                  */
420
421                 val_desc = acpi_ns_get_attached_object (node);
422                 if (!val_desc) {
423                         status = AE_NULL_OBJECT;
424                         goto unlock_and_exit;
425                 }
426
427                 /*
428                  * Just copy from the original to the return object
429                  *
430                  * TBD: [Future] - need a low-level object copy that handles
431                  * the reference count automatically.  (Don't want to copy it)
432                  */
433
434                 MEMCPY (obj_desc, val_desc, sizeof (ACPI_OPERAND_OBJECT));
435                 obj_desc->common.reference_count = 1;
436                 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
437         }
438
439
440         /*
441          * Other objects require a reference object wrapper which we
442          * then attempt to resolve.
443          */
444         else {
445                 /* Create an Reference object to contain the object */
446
447                 obj_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
448                 if (!obj_desc) {
449                    status = AE_NO_MEMORY;
450                    goto unlock_and_exit;
451                 }
452
453                 /* Construct a descriptor pointing to the name */
454
455                 obj_desc->reference.opcode = (u8) AML_NAME_OP;
456                 obj_desc->reference.object = (void *) node;
457
458                 /*
459                  * Use Resolve_to_value() to get the associated value. This call
460                  * always deletes Obj_desc (allocated above).
461                  *
462                  * NOTE: we can get away with passing in NULL for a walk state
463                  * because Obj_desc is guaranteed to not be a reference to either
464                  * a method local or a method argument
465                  *
466                  * Even though we do not directly invoke the interpreter
467                  * for this, we must enter it because we could access an opregion.
468                  * The opregion access code assumes that the interpreter
469                  * is locked.
470                  *
471                  * We must release the namespace lock before entering the
472                  * intepreter.
473                  */
474
475                 acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
476                 status = acpi_aml_enter_interpreter ();
477                 if (ACPI_SUCCESS (status)) {
478                         status = acpi_aml_resolve_to_value (&obj_desc, NULL);
479
480                         acpi_aml_exit_interpreter ();
481                 }
482         }
483
484         /*
485          * If Acpi_aml_resolve_to_value() succeeded, the return value was
486          * placed in Obj_desc.
487          */
488
489         if (ACPI_SUCCESS (status)) {
490                 status = AE_CTRL_RETURN_VALUE;
491
492                 *return_obj_desc = obj_desc;
493         }
494
495         /* Namespace is unlocked */
496
497         return (status);
498
499
500 unlock_and_exit:
501
502         /* Unlock the namespace */
503
504         acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
505         return (status);
506 }