Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /*******************************************************************************
3 : : *
4 : : * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
5 : : * ACPI Object evaluation interfaces
6 : : *
7 : : ******************************************************************************/
8 : :
9 : : #define EXPORT_ACPI_INTERFACES
10 : :
11 : : #include <acpi/acpi.h>
12 : : #include "accommon.h"
13 : : #include "acnamesp.h"
14 : : #include "acinterp.h"
15 : :
16 : : #define _COMPONENT ACPI_NAMESPACE
17 : : ACPI_MODULE_NAME("nsxfeval")
18 : :
19 : : /* Local prototypes */
20 : : static void acpi_ns_resolve_references(struct acpi_evaluate_info *info);
21 : :
22 : : /*******************************************************************************
23 : : *
24 : : * FUNCTION: acpi_evaluate_object_typed
25 : : *
26 : : * PARAMETERS: handle - Object handle (optional)
27 : : * pathname - Object pathname (optional)
28 : : * external_params - List of parameters to pass to a method,
29 : : * terminated by NULL. May be NULL
30 : : * if no parameters are being passed.
31 : : * return_buffer - Where to put the object's return value (if
32 : : * any). If NULL, no value is returned.
33 : : * return_type - Expected type of return object
34 : : *
35 : : * RETURN: Status
36 : : *
37 : : * DESCRIPTION: Find and evaluate the given object, passing the given
38 : : * parameters if necessary. One of "Handle" or "Pathname" must
39 : : * be valid (non-null)
40 : : *
41 : : ******************************************************************************/
42 : :
43 : : acpi_status
44 : 1624 : acpi_evaluate_object_typed(acpi_handle handle,
45 : : acpi_string pathname,
46 : : struct acpi_object_list *external_params,
47 : : struct acpi_buffer *return_buffer,
48 : : acpi_object_type return_type)
49 : : {
50 : 1624 : acpi_status status;
51 : 1624 : u8 free_buffer_on_error = FALSE;
52 : 1624 : acpi_handle target_handle;
53 : 1624 : char *full_pathname;
54 : :
55 : 1624 : ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
56 : :
57 : : /* Return buffer must be valid */
58 : :
59 [ + - ]: 1624 : if (!return_buffer) {
60 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
61 : : }
62 : :
63 [ + - ]: 1624 : if (return_buffer->length == ACPI_ALLOCATE_BUFFER) {
64 : 1624 : free_buffer_on_error = TRUE;
65 : : }
66 : :
67 : : /* Get a handle here, in order to build an error message if needed */
68 : :
69 : 1624 : target_handle = handle;
70 [ + - ]: 1624 : if (pathname) {
71 : 1624 : status = acpi_get_handle(handle, pathname, &target_handle);
72 [ - + ]: 1624 : if (ACPI_FAILURE(status)) {
73 : : return_ACPI_STATUS(status);
74 : : }
75 : : }
76 : :
77 : 0 : full_pathname = acpi_ns_get_external_pathname(target_handle);
78 [ # # ]: 0 : if (!full_pathname) {
79 : : return_ACPI_STATUS(AE_NO_MEMORY);
80 : : }
81 : :
82 : : /* Evaluate the object */
83 : :
84 : 0 : status = acpi_evaluate_object(target_handle, NULL, external_params,
85 : : return_buffer);
86 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
87 : 0 : goto exit;
88 : : }
89 : :
90 : : /* Type ANY means "don't care about return value type" */
91 : :
92 [ # # ]: 0 : if (return_type == ACPI_TYPE_ANY) {
93 : 0 : goto exit;
94 : : }
95 : :
96 [ # # ]: 0 : if (return_buffer->length == 0) {
97 : :
98 : : /* Error because caller specifically asked for a return value */
99 : :
100 : 0 : ACPI_ERROR((AE_INFO, "%s did not return any object",
101 : : full_pathname));
102 : 0 : status = AE_NULL_OBJECT;
103 : 0 : goto exit;
104 : : }
105 : :
106 : : /* Examine the object type returned from evaluate_object */
107 : :
108 [ # # ]: 0 : if (((union acpi_object *)return_buffer->pointer)->type == return_type) {
109 : 0 : goto exit;
110 : : }
111 : :
112 : : /* Return object type does not match requested type */
113 : :
114 : 0 : ACPI_ERROR((AE_INFO,
115 : : "Incorrect return type from %s - received [%s], requested [%s]",
116 : : full_pathname,
117 : : acpi_ut_get_type_name(((union acpi_object *)return_buffer->
118 : : pointer)->type),
119 : : acpi_ut_get_type_name(return_type)));
120 : :
121 [ # # ]: 0 : if (free_buffer_on_error) {
122 : : /*
123 : : * Free a buffer created via ACPI_ALLOCATE_BUFFER.
124 : : * Note: We use acpi_os_free here because acpi_os_allocate was used
125 : : * to allocate the buffer. This purposefully bypasses the
126 : : * (optionally enabled) allocation tracking mechanism since we
127 : : * only want to track internal allocations.
128 : : */
129 : 0 : acpi_os_free(return_buffer->pointer);
130 : 0 : return_buffer->pointer = NULL;
131 : : }
132 : :
133 : 0 : return_buffer->length = 0;
134 : 0 : status = AE_TYPE;
135 : :
136 : 0 : exit:
137 : 0 : ACPI_FREE(full_pathname);
138 : 0 : return_ACPI_STATUS(status);
139 : : }
140 : :
141 : : ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
142 : :
143 : : /*******************************************************************************
144 : : *
145 : : * FUNCTION: acpi_evaluate_object
146 : : *
147 : : * PARAMETERS: handle - Object handle (optional)
148 : : * pathname - Object pathname (optional)
149 : : * external_params - List of parameters to pass to method,
150 : : * terminated by NULL. May be NULL
151 : : * if no parameters are being passed.
152 : : * return_buffer - Where to put method's return value (if
153 : : * any). If NULL, no value is returned.
154 : : *
155 : : * RETURN: Status
156 : : *
157 : : * DESCRIPTION: Find and evaluate the given object, passing the given
158 : : * parameters if necessary. One of "Handle" or "Pathname" must
159 : : * be valid (non-null)
160 : : *
161 : : ******************************************************************************/
162 : : acpi_status
163 : 17248 : acpi_evaluate_object(acpi_handle handle,
164 : : acpi_string pathname,
165 : : struct acpi_object_list *external_params,
166 : : struct acpi_buffer *return_buffer)
167 : : {
168 : 17248 : acpi_status status;
169 : 17248 : struct acpi_evaluate_info *info;
170 : 17248 : acpi_size buffer_space_needed;
171 : 17248 : u32 i;
172 : :
173 : 17248 : ACPI_FUNCTION_TRACE(acpi_evaluate_object);
174 : :
175 : : /* Allocate and initialize the evaluation information block */
176 : :
177 : 17248 : info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
178 [ + - ]: 17248 : if (!info) {
179 : : return_ACPI_STATUS(AE_NO_MEMORY);
180 : : }
181 : :
182 : : /* Convert and validate the device handle */
183 : :
184 : 17248 : info->prefix_node = acpi_ns_validate_handle(handle);
185 [ - + ]: 17248 : if (!info->prefix_node) {
186 : 0 : status = AE_BAD_PARAMETER;
187 : 0 : goto cleanup;
188 : : }
189 : :
190 : : /*
191 : : * Get the actual namespace node for the target object.
192 : : * Handles these cases:
193 : : *
194 : : * 1) Null node, valid pathname from root (absolute path)
195 : : * 2) Node and valid pathname (path relative to Node)
196 : : * 3) Node, Null pathname
197 : : */
198 [ + + + + ]: 17248 : if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {
199 : :
200 : : /* The path is fully qualified, just evaluate by name */
201 : :
202 : 28 : info->prefix_node = NULL;
203 [ + + ]: 17220 : } else if (!handle) {
204 : : /*
205 : : * A handle is optional iff a fully qualified pathname is specified.
206 : : * Since we've already handled fully qualified names above, this is
207 : : * an error.
208 : : */
209 : 28 : if (!pathname) {
210 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
211 : : "Both Handle and Pathname are NULL"));
212 : : } else {
213 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
214 : : "Null Handle with relative pathname [%s]",
215 : 28 : pathname));
216 : : }
217 : :
218 : 28 : status = AE_BAD_PARAMETER;
219 : 28 : goto cleanup;
220 : : }
221 : :
222 : 17220 : info->relative_pathname = pathname;
223 : :
224 : : /*
225 : : * Convert all external objects passed as arguments to the
226 : : * internal version(s).
227 : : */
228 [ + + + - ]: 17220 : if (external_params && external_params->count) {
229 : 476 : info->param_count = (u16)external_params->count;
230 : :
231 : : /* Warn on impossible argument count */
232 : :
233 [ - + ]: 476 : if (info->param_count > ACPI_METHOD_NUM_ARGS) {
234 : 0 : ACPI_WARN_PREDEFINED((AE_INFO, pathname,
235 : : ACPI_WARN_ALWAYS,
236 : : "Excess arguments (%u) - using only %u",
237 : : info->param_count,
238 : : ACPI_METHOD_NUM_ARGS));
239 : :
240 : 0 : info->param_count = ACPI_METHOD_NUM_ARGS;
241 : : }
242 : :
243 : : /*
244 : : * Allocate a new parameter block for the internal objects
245 : : * Add 1 to count to allow for null terminated internal list
246 : : */
247 : 476 : info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)info->
248 : : param_count +
249 : : 1) * sizeof(void *));
250 [ - + ]: 476 : if (!info->parameters) {
251 : 0 : status = AE_NO_MEMORY;
252 : 0 : goto cleanup;
253 : : }
254 : :
255 : : /* Convert each external object in the list to an internal object */
256 : :
257 [ + + ]: 2296 : for (i = 0; i < info->param_count; i++) {
258 : 1820 : status =
259 : 1820 : acpi_ut_copy_eobject_to_iobject(&external_params->
260 : 1820 : pointer[i],
261 : 1820 : &info->
262 : 1820 : parameters[i]);
263 [ - + ]: 1820 : if (ACPI_FAILURE(status)) {
264 : 0 : goto cleanup;
265 : : }
266 : : }
267 : :
268 : 476 : info->parameters[info->param_count] = NULL;
269 : : }
270 : :
271 : : #ifdef _FUTURE_FEATURE
272 : :
273 : : /*
274 : : * Begin incoming argument count analysis. Check for too few args
275 : : * and too many args.
276 : : */
277 : : switch (acpi_ns_get_type(info->node)) {
278 : : case ACPI_TYPE_METHOD:
279 : :
280 : : /* Check incoming argument count against the method definition */
281 : :
282 : : if (info->obj_desc->method.param_count > info->param_count) {
283 : : ACPI_ERROR((AE_INFO,
284 : : "Insufficient arguments (%u) - %u are required",
285 : : info->param_count,
286 : : info->obj_desc->method.param_count));
287 : :
288 : : status = AE_MISSING_ARGUMENTS;
289 : : goto cleanup;
290 : : }
291 : :
292 : : else if (info->obj_desc->method.param_count < info->param_count) {
293 : : ACPI_WARNING((AE_INFO,
294 : : "Excess arguments (%u) - only %u are required",
295 : : info->param_count,
296 : : info->obj_desc->method.param_count));
297 : :
298 : : /* Just pass the required number of arguments */
299 : :
300 : : info->param_count = info->obj_desc->method.param_count;
301 : : }
302 : :
303 : : /*
304 : : * Any incoming external objects to be passed as arguments to the
305 : : * method must be converted to internal objects
306 : : */
307 : : if (info->param_count) {
308 : : /*
309 : : * Allocate a new parameter block for the internal objects
310 : : * Add 1 to count to allow for null terminated internal list
311 : : */
312 : : info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
313 : : info->
314 : : param_count +
315 : : 1) *
316 : : sizeof(void *));
317 : : if (!info->parameters) {
318 : : status = AE_NO_MEMORY;
319 : : goto cleanup;
320 : : }
321 : :
322 : : /* Convert each external object in the list to an internal object */
323 : :
324 : : for (i = 0; i < info->param_count; i++) {
325 : : status =
326 : : acpi_ut_copy_eobject_to_iobject
327 : : (&external_params->pointer[i],
328 : : &info->parameters[i]);
329 : : if (ACPI_FAILURE(status)) {
330 : : goto cleanup;
331 : : }
332 : : }
333 : :
334 : : info->parameters[info->param_count] = NULL;
335 : : }
336 : : break;
337 : :
338 : : default:
339 : :
340 : : /* Warn if arguments passed to an object that is not a method */
341 : :
342 : : if (info->param_count) {
343 : : ACPI_WARNING((AE_INFO,
344 : : "%u arguments were passed to a non-method ACPI object",
345 : : info->param_count));
346 : : }
347 : : break;
348 : : }
349 : :
350 : : #endif
351 : :
352 : : /* Now we can evaluate the object */
353 : :
354 : 17220 : status = acpi_ns_evaluate(info);
355 : :
356 : : /*
357 : : * If we are expecting a return value, and all went well above,
358 : : * copy the return value to an external object.
359 : : */
360 [ + + ]: 17220 : if (!return_buffer) {
361 : 168 : goto cleanup_return_object;
362 : : }
363 : :
364 [ + + ]: 17052 : if (!info->return_object) {
365 : 7448 : return_buffer->length = 0;
366 : 7448 : goto cleanup;
367 : : }
368 : :
369 [ - + ]: 9604 : if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
370 : : ACPI_DESC_TYPE_NAMED) {
371 : : /*
372 : : * If we received a NS Node as a return object, this means that
373 : : * the object we are evaluating has nothing interesting to
374 : : * return (such as a mutex, etc.) We return an error because
375 : : * these types are essentially unsupported by this interface.
376 : : * We don't check up front because this makes it easier to add
377 : : * support for various types at a later date if necessary.
378 : : */
379 : 0 : status = AE_TYPE;
380 : 0 : info->return_object = NULL; /* No need to delete a NS Node */
381 : 0 : return_buffer->length = 0;
382 : : }
383 : :
384 [ - + ]: 9604 : if (ACPI_FAILURE(status)) {
385 : 0 : goto cleanup_return_object;
386 : : }
387 : :
388 : : /* Dereference Index and ref_of references */
389 : :
390 : 9604 : acpi_ns_resolve_references(info);
391 : :
392 : : /* Get the size of the returned object */
393 : :
394 : 9604 : status = acpi_ut_get_object_size(info->return_object,
395 : : &buffer_space_needed);
396 [ - + ]: 9604 : if (ACPI_SUCCESS(status)) {
397 : :
398 : : /* Validate/Allocate/Clear caller buffer */
399 : :
400 : 9604 : status = acpi_ut_initialize_buffer(return_buffer,
401 : : buffer_space_needed);
402 [ + - ]: 9604 : if (ACPI_FAILURE(status)) {
403 : : /*
404 : : * Caller's buffer is too small or a new one can't
405 : : * be allocated
406 : : */
407 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
408 : : "Needed buffer size %X, %s\n",
409 : : (u32)buffer_space_needed,
410 : : acpi_format_exception(status)));
411 : : } else {
412 : : /* We have enough space for the object, build it */
413 : :
414 : 9604 : status =
415 : 9604 : acpi_ut_copy_iobject_to_eobject(info->return_object,
416 : : return_buffer);
417 : : }
418 : : }
419 : :
420 : 0 : cleanup_return_object:
421 : :
422 [ + + ]: 9772 : if (info->return_object) {
423 : : /*
424 : : * Delete the internal return object. NOTE: Interpreter must be
425 : : * locked to avoid race condition.
426 : : */
427 : 9744 : acpi_ex_enter_interpreter();
428 : :
429 : : /* Remove one reference on the return object (should delete it) */
430 : :
431 : 9744 : acpi_ut_remove_reference(info->return_object);
432 : 9744 : acpi_ex_exit_interpreter();
433 : : }
434 : :
435 : 28 : cleanup:
436 : :
437 : : /* Free the input parameter list (if we created one) */
438 : :
439 [ + + ]: 17248 : if (info->parameters) {
440 : :
441 : : /* Free the allocated parameter block */
442 : :
443 : 476 : acpi_ut_delete_internal_object_list(info->parameters);
444 : : }
445 : :
446 : 17248 : ACPI_FREE(info);
447 : 17248 : return_ACPI_STATUS(status);
448 : : }
449 : :
450 : : ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
451 : :
452 : : /*******************************************************************************
453 : : *
454 : : * FUNCTION: acpi_ns_resolve_references
455 : : *
456 : : * PARAMETERS: info - Evaluation info block
457 : : *
458 : : * RETURN: Info->return_object is replaced with the dereferenced object
459 : : *
460 : : * DESCRIPTION: Dereference certain reference objects. Called before an
461 : : * internal return object is converted to an external union acpi_object.
462 : : *
463 : : * Performs an automatic dereference of Index and ref_of reference objects.
464 : : * These reference objects are not supported by the union acpi_object, so this is a
465 : : * last resort effort to return something useful. Also, provides compatibility
466 : : * with other ACPI implementations.
467 : : *
468 : : * NOTE: does not handle references within returned package objects or nested
469 : : * references, but this support could be added later if found to be necessary.
470 : : *
471 : : ******************************************************************************/
472 : : static void acpi_ns_resolve_references(struct acpi_evaluate_info *info)
473 : : {
474 : : union acpi_operand_object *obj_desc = NULL;
475 : : struct acpi_namespace_node *node;
476 : :
477 : : /* We are interested in reference objects only */
478 : :
479 : : if ((info->return_object)->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
480 : : return;
481 : : }
482 : :
483 : : /*
484 : : * Two types of references are supported - those created by Index and
485 : : * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted
486 : : * to a union acpi_object, so it is not dereferenced here. A ddb_handle
487 : : * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
488 : : * a union acpi_object.
489 : : */
490 : : switch (info->return_object->reference.class) {
491 : : case ACPI_REFCLASS_INDEX:
492 : :
493 : : obj_desc = *(info->return_object->reference.where);
494 : : break;
495 : :
496 : : case ACPI_REFCLASS_REFOF:
497 : :
498 : : node = info->return_object->reference.object;
499 : : if (node) {
500 : : obj_desc = node->object;
501 : : }
502 : : break;
503 : :
504 : : default:
505 : :
506 : : return;
507 : : }
508 : :
509 : : /* Replace the existing reference object */
510 : :
511 : : if (obj_desc) {
512 : : acpi_ut_add_reference(obj_desc);
513 : : acpi_ut_remove_reference(info->return_object);
514 : : info->return_object = obj_desc;
515 : : }
516 : :
517 : : return;
518 : : }
519 : :
520 : : /*******************************************************************************
521 : : *
522 : : * FUNCTION: acpi_walk_namespace
523 : : *
524 : : * PARAMETERS: type - acpi_object_type to search for
525 : : * start_object - Handle in namespace where search begins
526 : : * max_depth - Depth to which search is to reach
527 : : * descending_callback - Called during tree descent
528 : : * when an object of "Type" is found
529 : : * ascending_callback - Called during tree ascent
530 : : * when an object of "Type" is found
531 : : * context - Passed to user function(s) above
532 : : * return_value - Location where return value of
533 : : * user_function is put if terminated early
534 : : *
535 : : * RETURNS Return value from the user_function if terminated early.
536 : : * Otherwise, returns NULL.
537 : : *
538 : : * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
539 : : * starting (and ending) at the object specified by start_handle.
540 : : * The callback function is called whenever an object that matches
541 : : * the type parameter is found. If the callback function returns
542 : : * a non-zero value, the search is terminated immediately and this
543 : : * value is returned to the caller.
544 : : *
545 : : * The point of this procedure is to provide a generic namespace
546 : : * walk routine that can be called from multiple places to
547 : : * provide multiple services; the callback function(s) can be
548 : : * tailored to each task, whether it is a print function,
549 : : * a compare function, etc.
550 : : *
551 : : ******************************************************************************/
552 : :
553 : : acpi_status
554 : 196 : acpi_walk_namespace(acpi_object_type type,
555 : : acpi_handle start_object,
556 : : u32 max_depth,
557 : : acpi_walk_callback descending_callback,
558 : : acpi_walk_callback ascending_callback,
559 : : void *context, void **return_value)
560 : : {
561 : 196 : acpi_status status;
562 : :
563 : 196 : ACPI_FUNCTION_TRACE(acpi_walk_namespace);
564 : :
565 : : /* Parameter validation */
566 : :
567 : 196 : if ((type > ACPI_TYPE_LOCAL_MAX) ||
568 [ + - + - ]: 196 : (!max_depth) || (!descending_callback && !ascending_callback)) {
569 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
570 : : }
571 : :
572 : : /*
573 : : * Need to acquire the namespace reader lock to prevent interference
574 : : * with any concurrent table unloads (which causes the deletion of
575 : : * namespace objects). We cannot allow the deletion of a namespace node
576 : : * while the user function is using it. The exception to this are the
577 : : * nodes created and deleted during control method execution -- these
578 : : * nodes are marked as temporary nodes and are ignored by the namespace
579 : : * walk. Thus, control methods can be executed while holding the
580 : : * namespace deletion lock (and the user function can execute control
581 : : * methods.)
582 : : */
583 : 196 : status = acpi_ut_acquire_read_lock(&acpi_gbl_namespace_rw_lock);
584 [ + - ]: 196 : if (ACPI_FAILURE(status)) {
585 : : return_ACPI_STATUS(status);
586 : : }
587 : :
588 : : /*
589 : : * Lock the namespace around the walk. The namespace will be
590 : : * unlocked/locked around each call to the user function - since the user
591 : : * function must be allowed to make ACPICA calls itself (for example, it
592 : : * will typically execute control methods during device enumeration.)
593 : : */
594 : 196 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
595 [ - + ]: 196 : if (ACPI_FAILURE(status)) {
596 : 0 : goto unlock_and_exit;
597 : : }
598 : :
599 : : /* Now we can validate the starting node */
600 : :
601 [ - + ]: 196 : if (!acpi_ns_validate_handle(start_object)) {
602 : 0 : status = AE_BAD_PARAMETER;
603 : 0 : goto unlock_and_exit2;
604 : : }
605 : :
606 : 196 : status = acpi_ns_walk_namespace(type, start_object, max_depth,
607 : : ACPI_NS_WALK_UNLOCK,
608 : : descending_callback, ascending_callback,
609 : : context, return_value);
610 : :
611 : 196 : unlock_and_exit2:
612 : 196 : (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
613 : :
614 : 196 : unlock_and_exit:
615 : 196 : (void)acpi_ut_release_read_lock(&acpi_gbl_namespace_rw_lock);
616 : 196 : return_ACPI_STATUS(status);
617 : : }
618 : :
619 : : ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
620 : :
621 : : /*******************************************************************************
622 : : *
623 : : * FUNCTION: acpi_ns_get_device_callback
624 : : *
625 : : * PARAMETERS: Callback from acpi_get_device
626 : : *
627 : : * RETURN: Status
628 : : *
629 : : * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non-
630 : : * present devices, or if they specified a HID, it filters based
631 : : * on that.
632 : : *
633 : : ******************************************************************************/
634 : : static acpi_status
635 : 6160 : acpi_ns_get_device_callback(acpi_handle obj_handle,
636 : : u32 nesting_level,
637 : : void *context, void **return_value)
638 : : {
639 : 6160 : struct acpi_get_devices_info *info = context;
640 : 6160 : acpi_status status;
641 : 6160 : struct acpi_namespace_node *node;
642 : 6160 : u32 flags;
643 : 6160 : struct acpi_pnp_device_id *hid;
644 : 6160 : struct acpi_pnp_device_id_list *cid;
645 : 6160 : u32 i;
646 : 6160 : u8 found;
647 : 6160 : int no_match;
648 : :
649 : 6160 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
650 [ + - ]: 6160 : if (ACPI_FAILURE(status)) {
651 : : return (status);
652 : : }
653 : :
654 : 6160 : node = acpi_ns_validate_handle(obj_handle);
655 : 6160 : status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
656 [ + - ]: 6160 : if (ACPI_FAILURE(status)) {
657 : : return (status);
658 : : }
659 : :
660 [ + - ]: 6160 : if (!node) {
661 : : return (AE_BAD_PARAMETER);
662 : : }
663 : :
664 : : /*
665 : : * First, filter based on the device HID and CID.
666 : : *
667 : : * 01/2010: For this case where a specific HID is requested, we don't
668 : : * want to run _STA until we have an actual HID match. Thus, we will
669 : : * not unnecessarily execute _STA on devices for which the caller
670 : : * doesn't care about. Previously, _STA was executed unconditionally
671 : : * on all devices found here.
672 : : *
673 : : * A side-effect of this change is that now we will continue to search
674 : : * for a matching HID even under device trees where the parent device
675 : : * would have returned a _STA that indicates it is not present or
676 : : * not functioning (thus aborting the search on that branch).
677 : : */
678 [ + + ]: 6160 : if (info->hid != NULL) {
679 : 4620 : status = acpi_ut_execute_HID(node, &hid);
680 [ + + ]: 4620 : if (status == AE_NOT_FOUND) {
681 : : return (AE_OK);
682 [ + - ]: 1596 : } else if (ACPI_FAILURE(status)) {
683 : : return (AE_CTRL_DEPTH);
684 : : }
685 : :
686 : 1596 : no_match = strcmp(hid->string, info->hid);
687 : 1596 : ACPI_FREE(hid);
688 : :
689 [ + - ]: 1596 : if (no_match) {
690 : : /*
691 : : * HID does not match, attempt match within the
692 : : * list of Compatible IDs (CIDs)
693 : : */
694 : 1596 : status = acpi_ut_execute_CID(node, &cid);
695 [ + + ]: 1596 : if (status == AE_NOT_FOUND) {
696 : : return (AE_OK);
697 [ + - ]: 84 : } else if (ACPI_FAILURE(status)) {
698 : : return (AE_CTRL_DEPTH);
699 : : }
700 : :
701 : : /* Walk the CID list */
702 : :
703 : : found = FALSE;
704 [ + + ]: 168 : for (i = 0; i < cid->count; i++) {
705 [ + - ]: 84 : if (strcmp(cid->ids[i].string, info->hid) == 0) {
706 : :
707 : : /* Found a matching CID */
708 : :
709 : : found = TRUE;
710 : : break;
711 : : }
712 : : }
713 : :
714 : 84 : ACPI_FREE(cid);
715 [ - + ]: 84 : if (!found) {
716 : : return (AE_OK);
717 : : }
718 : : }
719 : : }
720 : :
721 : : /* Run _STA to determine if device is present */
722 : :
723 : 1540 : status = acpi_ut_execute_STA(node, &flags);
724 [ + - ]: 1540 : if (ACPI_FAILURE(status)) {
725 : : return (AE_CTRL_DEPTH);
726 : : }
727 : :
728 [ + + ]: 1540 : if (!(flags & ACPI_STA_DEVICE_PRESENT) &&
729 : : !(flags & ACPI_STA_DEVICE_FUNCTIONING)) {
730 : : /*
731 : : * Don't examine the children of the device only when the
732 : : * device is neither present nor functional. See ACPI spec,
733 : : * description of _STA for more information.
734 : : */
735 : : return (AE_CTRL_DEPTH);
736 : : }
737 : :
738 : : /* We have a valid device, invoke the user function */
739 : :
740 : 1512 : status = info->user_function(obj_handle, nesting_level,
741 : : info->context, return_value);
742 : 1512 : return (status);
743 : : }
744 : :
745 : : /*******************************************************************************
746 : : *
747 : : * FUNCTION: acpi_get_devices
748 : : *
749 : : * PARAMETERS: HID - HID to search for. Can be NULL.
750 : : * user_function - Called when a matching object is found
751 : : * context - Passed to user function
752 : : * return_value - Location where return value of
753 : : * user_function is put if terminated early
754 : : *
755 : : * RETURNS Return value from the user_function if terminated early.
756 : : * Otherwise, returns NULL.
757 : : *
758 : : * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
759 : : * starting (and ending) at the object specified by start_handle.
760 : : * The user_function is called whenever an object of type
761 : : * Device is found. If the user function returns
762 : : * a non-zero value, the search is terminated immediately and this
763 : : * value is returned to the caller.
764 : : *
765 : : * This is a wrapper for walk_namespace, but the callback performs
766 : : * additional filtering. Please see acpi_ns_get_device_callback.
767 : : *
768 : : ******************************************************************************/
769 : :
770 : : acpi_status
771 : 112 : acpi_get_devices(const char *HID,
772 : : acpi_walk_callback user_function,
773 : : void *context, void **return_value)
774 : : {
775 : 112 : acpi_status status;
776 : 112 : struct acpi_get_devices_info info;
777 : :
778 : 112 : ACPI_FUNCTION_TRACE(acpi_get_devices);
779 : :
780 : : /* Parameter validation */
781 : :
782 [ + - ]: 112 : if (!user_function) {
783 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
784 : : }
785 : :
786 : : /*
787 : : * We're going to call their callback from OUR callback, so we need
788 : : * to know what it is, and their context parameter.
789 : : */
790 : 112 : info.hid = HID;
791 : 112 : info.context = context;
792 : 112 : info.user_function = user_function;
793 : :
794 : : /*
795 : : * Lock the namespace around the walk.
796 : : * The namespace will be unlocked/locked around each call
797 : : * to the user function - since this function
798 : : * must be allowed to make Acpi calls itself.
799 : : */
800 : 112 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
801 [ + - ]: 112 : if (ACPI_FAILURE(status)) {
802 : : return_ACPI_STATUS(status);
803 : : }
804 : :
805 : 112 : status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
806 : : ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
807 : : acpi_ns_get_device_callback, NULL,
808 : : &info, return_value);
809 : :
810 : 112 : (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
811 : 112 : return_ACPI_STATUS(status);
812 : : }
813 : :
814 : : ACPI_EXPORT_SYMBOL(acpi_get_devices)
815 : :
816 : : /*******************************************************************************
817 : : *
818 : : * FUNCTION: acpi_attach_data
819 : : *
820 : : * PARAMETERS: obj_handle - Namespace node
821 : : * handler - Handler for this attachment
822 : : * data - Pointer to data to be attached
823 : : *
824 : : * RETURN: Status
825 : : *
826 : : * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
827 : : *
828 : : ******************************************************************************/
829 : : acpi_status
830 : 1596 : acpi_attach_data(acpi_handle obj_handle,
831 : : acpi_object_handler handler, void *data)
832 : : {
833 : 1596 : struct acpi_namespace_node *node;
834 : 1596 : acpi_status status;
835 : :
836 : : /* Parameter validation */
837 : :
838 [ + - + - ]: 1596 : if (!obj_handle || !handler || !data) {
839 : : return (AE_BAD_PARAMETER);
840 : : }
841 : :
842 : 1596 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
843 [ + - ]: 1596 : if (ACPI_FAILURE(status)) {
844 : : return (status);
845 : : }
846 : :
847 : : /* Convert and validate the handle */
848 : :
849 : 1596 : node = acpi_ns_validate_handle(obj_handle);
850 [ - + ]: 1596 : if (!node) {
851 : 0 : status = AE_BAD_PARAMETER;
852 : 0 : goto unlock_and_exit;
853 : : }
854 : :
855 : 1596 : status = acpi_ns_attach_data(node, handler, data);
856 : :
857 : 1596 : unlock_and_exit:
858 : 1596 : (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
859 : 1596 : return (status);
860 : : }
861 : :
862 : : ACPI_EXPORT_SYMBOL(acpi_attach_data)
863 : :
864 : : /*******************************************************************************
865 : : *
866 : : * FUNCTION: acpi_detach_data
867 : : *
868 : : * PARAMETERS: obj_handle - Namespace node handle
869 : : * handler - Handler used in call to acpi_attach_data
870 : : *
871 : : * RETURN: Status
872 : : *
873 : : * DESCRIPTION: Remove data that was previously attached to a node.
874 : : *
875 : : ******************************************************************************/
876 : : acpi_status
877 : 0 : acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
878 : : {
879 : 0 : struct acpi_namespace_node *node;
880 : 0 : acpi_status status;
881 : :
882 : : /* Parameter validation */
883 : :
884 [ # # ]: 0 : if (!obj_handle || !handler) {
885 : : return (AE_BAD_PARAMETER);
886 : : }
887 : :
888 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
889 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
890 : : return (status);
891 : : }
892 : :
893 : : /* Convert and validate the handle */
894 : :
895 : 0 : node = acpi_ns_validate_handle(obj_handle);
896 [ # # ]: 0 : if (!node) {
897 : 0 : status = AE_BAD_PARAMETER;
898 : 0 : goto unlock_and_exit;
899 : : }
900 : :
901 : 0 : status = acpi_ns_detach_data(node, handler);
902 : :
903 : 0 : unlock_and_exit:
904 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
905 : 0 : return (status);
906 : : }
907 : :
908 : : ACPI_EXPORT_SYMBOL(acpi_detach_data)
909 : :
910 : : /*******************************************************************************
911 : : *
912 : : * FUNCTION: acpi_get_data_full
913 : : *
914 : : * PARAMETERS: obj_handle - Namespace node
915 : : * handler - Handler used in call to attach_data
916 : : * data - Where the data is returned
917 : : * callback - function to execute before returning
918 : : *
919 : : * RETURN: Status
920 : : *
921 : : * DESCRIPTION: Retrieve data that was previously attached to a namespace node
922 : : * and execute a callback before returning.
923 : : *
924 : : ******************************************************************************/
925 : : acpi_status
926 : 12715 : acpi_get_data_full(acpi_handle obj_handle, acpi_object_handler handler,
927 : : void **data, void (*callback)(void *))
928 : : {
929 : 12715 : struct acpi_namespace_node *node;
930 : 12715 : acpi_status status;
931 : :
932 : : /* Parameter validation */
933 : :
934 [ + - + - ]: 12715 : if (!obj_handle || !handler || !data) {
935 : : return (AE_BAD_PARAMETER);
936 : : }
937 : :
938 : 12715 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
939 [ + - ]: 12715 : if (ACPI_FAILURE(status)) {
940 : : return (status);
941 : : }
942 : :
943 : : /* Convert and validate the handle */
944 : :
945 : 12715 : node = acpi_ns_validate_handle(obj_handle);
946 [ - + ]: 12715 : if (!node) {
947 : 0 : status = AE_BAD_PARAMETER;
948 : 0 : goto unlock_and_exit;
949 : : }
950 : :
951 : 12715 : status = acpi_ns_get_attached_data(node, handler, data);
952 [ + - ]: 12715 : if (ACPI_SUCCESS(status) && callback) {
953 : 0 : callback(*data);
954 : : }
955 : :
956 : 12715 : unlock_and_exit:
957 : 12715 : (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
958 : 12715 : return (status);
959 : : }
960 : :
961 : : ACPI_EXPORT_SYMBOL(acpi_get_data_full)
962 : :
963 : : /*******************************************************************************
964 : : *
965 : : * FUNCTION: acpi_get_data
966 : : *
967 : : * PARAMETERS: obj_handle - Namespace node
968 : : * handler - Handler used in call to attach_data
969 : : * data - Where the data is returned
970 : : *
971 : : * RETURN: Status
972 : : *
973 : : * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
974 : : *
975 : : ******************************************************************************/
976 : : acpi_status
977 : 0 : acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
978 : : {
979 : 0 : return acpi_get_data_full(obj_handle, handler, data, NULL);
980 : : }
981 : :
982 : : ACPI_EXPORT_SYMBOL(acpi_get_data)
|