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