Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
4 : : *
5 : : * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
6 : : * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 : : */
8 : :
9 : : #include <linux/kernel.h>
10 : : #include <linux/module.h>
11 : : #include <linux/slab.h>
12 : : #include <linux/init.h>
13 : : #include <linux/types.h>
14 : : #include <linux/hardirq.h>
15 : : #include <linux/acpi.h>
16 : : #include <linux/dynamic_debug.h>
17 : :
18 : : #include "internal.h"
19 : : #include "sleep.h"
20 : :
21 : : #define _COMPONENT ACPI_BUS_COMPONENT
22 : : ACPI_MODULE_NAME("utils");
23 : :
24 : : /* --------------------------------------------------------------------------
25 : : Object Evaluation Helpers
26 : : -------------------------------------------------------------------------- */
27 : : static void
28 : 0 : acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s)
29 : : {
30 : : #ifdef ACPI_DEBUG_OUTPUT
31 : : char prefix[80] = {'\0'};
32 : : struct acpi_buffer buffer = {sizeof(prefix), prefix};
33 : : acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);
34 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",
35 : : (char *) prefix, p, acpi_format_exception(s)));
36 : : #else
37 : 0 : return;
38 : : #endif
39 : : }
40 : :
41 : : acpi_status
42 : 0 : acpi_extract_package(union acpi_object *package,
43 : : struct acpi_buffer *format, struct acpi_buffer *buffer)
44 : : {
45 : 0 : u32 size_required = 0;
46 : 0 : u32 tail_offset = 0;
47 : 0 : char *format_string = NULL;
48 : 0 : u32 format_count = 0;
49 : 0 : u32 i = 0;
50 : 0 : u8 *head = NULL;
51 : 0 : u8 *tail = NULL;
52 : :
53 : :
54 [ # # # # ]: 0 : if (!package || (package->type != ACPI_TYPE_PACKAGE)
55 [ # # ]: 0 : || (package->package.count < 1)) {
56 : 0 : printk(KERN_WARNING PREFIX "Invalid package argument\n");
57 : 0 : return AE_BAD_PARAMETER;
58 : : }
59 : :
60 [ # # # # : 0 : if (!format || !format->pointer || (format->length < 1)) {
# # ]
61 : 0 : printk(KERN_WARNING PREFIX "Invalid format argument\n");
62 : 0 : return AE_BAD_PARAMETER;
63 : : }
64 : :
65 [ # # ]: 0 : if (!buffer) {
66 : 0 : printk(KERN_WARNING PREFIX "Invalid buffer argument\n");
67 : 0 : return AE_BAD_PARAMETER;
68 : : }
69 : :
70 : 0 : format_count = (format->length / sizeof(char)) - 1;
71 [ # # ]: 0 : if (format_count > package->package.count) {
72 : 0 : printk(KERN_WARNING PREFIX "Format specifies more objects [%d]"
73 : : " than exist in package [%d].\n",
74 : : format_count, package->package.count);
75 : 0 : return AE_BAD_DATA;
76 : : }
77 : :
78 : : format_string = format->pointer;
79 : :
80 : : /*
81 : : * Calculate size_required.
82 : : */
83 [ # # ]: 0 : for (i = 0; i < format_count; i++) {
84 : :
85 : 0 : union acpi_object *element = &(package->package.elements[i]);
86 : :
87 [ # # # # ]: 0 : switch (element->type) {
88 : :
89 : 0 : case ACPI_TYPE_INTEGER:
90 [ # # # ]: 0 : switch (format_string[i]) {
91 : 0 : case 'N':
92 : 0 : size_required += sizeof(u64);
93 : 0 : tail_offset += sizeof(u64);
94 : 0 : break;
95 : 0 : case 'S':
96 : 0 : size_required +=
97 : : sizeof(char *) + sizeof(u64) +
98 : : sizeof(char);
99 : 0 : tail_offset += sizeof(char *);
100 : 0 : break;
101 : 0 : default:
102 : 0 : printk(KERN_WARNING PREFIX "Invalid package element"
103 : : " [%d]: got number, expecting"
104 : : " [%c]\n",
105 : : i, format_string[i]);
106 : 0 : return AE_BAD_DATA;
107 : : break;
108 : : }
109 : : break;
110 : :
111 : 0 : case ACPI_TYPE_STRING:
112 : : case ACPI_TYPE_BUFFER:
113 [ # # # ]: 0 : switch (format_string[i]) {
114 : 0 : case 'S':
115 : 0 : size_required +=
116 : : sizeof(char *) +
117 : 0 : (element->string.length * sizeof(char)) +
118 : : sizeof(char);
119 : 0 : tail_offset += sizeof(char *);
120 : 0 : break;
121 : 0 : case 'B':
122 : 0 : size_required +=
123 : 0 : sizeof(u8 *) + element->buffer.length;
124 : 0 : tail_offset += sizeof(u8 *);
125 : 0 : break;
126 : 0 : default:
127 : 0 : printk(KERN_WARNING PREFIX "Invalid package element"
128 : : " [%d] got string/buffer,"
129 : : " expecting [%c]\n",
130 : : i, format_string[i]);
131 : 0 : return AE_BAD_DATA;
132 : : break;
133 : : }
134 : : break;
135 : 0 : case ACPI_TYPE_LOCAL_REFERENCE:
136 [ # # ]: 0 : switch (format_string[i]) {
137 : 0 : case 'R':
138 : 0 : size_required += sizeof(void *);
139 : 0 : tail_offset += sizeof(void *);
140 : 0 : break;
141 : 0 : default:
142 : 0 : printk(KERN_WARNING PREFIX "Invalid package element"
143 : : " [%d] got reference,"
144 : : " expecting [%c]\n",
145 : : i, format_string[i]);
146 : 0 : return AE_BAD_DATA;
147 : 0 : break;
148 : : }
149 : 0 : break;
150 : :
151 : : case ACPI_TYPE_PACKAGE:
152 : : default:
153 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
154 : : "Found unsupported element at index=%d\n",
155 : : i));
156 : : /* TBD: handle nested packages... */
157 : : return AE_SUPPORT;
158 : 0 : break;
159 : : }
160 : : }
161 : :
162 : : /*
163 : : * Validate output buffer.
164 : : */
165 [ # # ]: 0 : if (buffer->length == ACPI_ALLOCATE_BUFFER) {
166 : 0 : buffer->pointer = ACPI_ALLOCATE_ZEROED(size_required);
167 [ # # ]: 0 : if (!buffer->pointer)
168 : : return AE_NO_MEMORY;
169 : 0 : buffer->length = size_required;
170 : : } else {
171 [ # # ]: 0 : if (buffer->length < size_required) {
172 : 0 : buffer->length = size_required;
173 : 0 : return AE_BUFFER_OVERFLOW;
174 [ # # ]: 0 : } else if (buffer->length != size_required ||
175 [ # # ]: 0 : !buffer->pointer) {
176 : : return AE_BAD_PARAMETER;
177 : : }
178 : : }
179 : :
180 : 0 : head = buffer->pointer;
181 : 0 : tail = buffer->pointer + tail_offset;
182 : :
183 : : /*
184 : : * Extract package data.
185 : : */
186 [ # # ]: 0 : for (i = 0; i < format_count; i++) {
187 : :
188 : 0 : u8 **pointer = NULL;
189 : 0 : union acpi_object *element = &(package->package.elements[i]);
190 : :
191 [ # # # # ]: 0 : switch (element->type) {
192 : :
193 : 0 : case ACPI_TYPE_INTEGER:
194 [ # # # ]: 0 : switch (format_string[i]) {
195 : 0 : case 'N':
196 : 0 : *((u64 *) head) =
197 : 0 : element->integer.value;
198 : 0 : head += sizeof(u64);
199 : 0 : break;
200 : 0 : case 'S':
201 : 0 : pointer = (u8 **) head;
202 : 0 : *pointer = tail;
203 : 0 : *((u64 *) tail) =
204 : 0 : element->integer.value;
205 : 0 : head += sizeof(u64 *);
206 : 0 : tail += sizeof(u64);
207 : : /* NULL terminate string */
208 : 0 : *tail = (char)0;
209 : 0 : tail += sizeof(char);
210 : 0 : break;
211 : : default:
212 : : /* Should never get here */
213 : : break;
214 : : }
215 : : break;
216 : :
217 : 0 : case ACPI_TYPE_STRING:
218 : : case ACPI_TYPE_BUFFER:
219 [ # # # ]: 0 : switch (format_string[i]) {
220 : 0 : case 'S':
221 : 0 : pointer = (u8 **) head;
222 : 0 : *pointer = tail;
223 : 0 : memcpy(tail, element->string.pointer,
224 : 0 : element->string.length);
225 : 0 : head += sizeof(char *);
226 : 0 : tail += element->string.length * sizeof(char);
227 : : /* NULL terminate string */
228 : 0 : *tail = (char)0;
229 : 0 : tail += sizeof(char);
230 : 0 : break;
231 : 0 : case 'B':
232 : 0 : pointer = (u8 **) head;
233 : 0 : *pointer = tail;
234 : 0 : memcpy(tail, element->buffer.pointer,
235 : 0 : element->buffer.length);
236 : 0 : head += sizeof(u8 *);
237 : 0 : tail += element->buffer.length;
238 : 0 : break;
239 : : default:
240 : : /* Should never get here */
241 : : break;
242 : : }
243 : : break;
244 : 0 : case ACPI_TYPE_LOCAL_REFERENCE:
245 [ # # ]: 0 : switch (format_string[i]) {
246 : 0 : case 'R':
247 : 0 : *(void **)head =
248 : 0 : (void *)element->reference.handle;
249 : 0 : head += sizeof(void *);
250 : 0 : break;
251 : : default:
252 : : /* Should never get here */
253 : : break;
254 : : }
255 : : break;
256 : : case ACPI_TYPE_PACKAGE:
257 : : /* TBD: handle nested packages... */
258 : : default:
259 : : /* Should never get here */
260 : : break;
261 : : }
262 : : }
263 : :
264 : : return AE_OK;
265 : : }
266 : :
267 : : EXPORT_SYMBOL(acpi_extract_package);
268 : :
269 : : acpi_status
270 : 1716 : acpi_evaluate_integer(acpi_handle handle,
271 : : acpi_string pathname,
272 : : struct acpi_object_list *arguments, unsigned long long *data)
273 : : {
274 : 1716 : acpi_status status = AE_OK;
275 : 1716 : union acpi_object element;
276 : 1716 : struct acpi_buffer buffer = { 0, NULL };
277 : :
278 [ + - ]: 1716 : if (!data)
279 : : return AE_BAD_PARAMETER;
280 : :
281 : 1716 : buffer.length = sizeof(union acpi_object);
282 : 1716 : buffer.pointer = &element;
283 : 1716 : status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
284 [ + + ]: 1716 : if (ACPI_FAILURE(status)) {
285 : : acpi_util_eval_error(handle, pathname, status);
286 : : return status;
287 : : }
288 : :
289 [ + - ]: 1014 : if (element.type != ACPI_TYPE_INTEGER) {
290 : : acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
291 : : return AE_BAD_DATA;
292 : : }
293 : :
294 : 1014 : *data = element.integer.value;
295 : :
296 : 1014 : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
297 : :
298 : 1014 : return AE_OK;
299 : : }
300 : :
301 : : EXPORT_SYMBOL(acpi_evaluate_integer);
302 : :
303 : : acpi_status
304 : 0 : acpi_evaluate_reference(acpi_handle handle,
305 : : acpi_string pathname,
306 : : struct acpi_object_list *arguments,
307 : : struct acpi_handle_list *list)
308 : : {
309 : 0 : acpi_status status = AE_OK;
310 : 0 : union acpi_object *package = NULL;
311 : 0 : union acpi_object *element = NULL;
312 : 0 : struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
313 : 0 : u32 i = 0;
314 : :
315 : :
316 [ # # ]: 0 : if (!list) {
317 : : return AE_BAD_PARAMETER;
318 : : }
319 : :
320 : : /* Evaluate object. */
321 : :
322 : 0 : status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
323 [ # # ]: 0 : if (ACPI_FAILURE(status))
324 : 0 : goto end;
325 : :
326 : 0 : package = buffer.pointer;
327 : :
328 [ # # # # ]: 0 : if ((buffer.length == 0) || !package) {
329 : 0 : status = AE_BAD_DATA;
330 : 0 : acpi_util_eval_error(handle, pathname, status);
331 : 0 : goto end;
332 : : }
333 [ # # ]: 0 : if (package->type != ACPI_TYPE_PACKAGE) {
334 : 0 : status = AE_BAD_DATA;
335 : 0 : acpi_util_eval_error(handle, pathname, status);
336 : 0 : goto end;
337 : : }
338 [ # # ]: 0 : if (!package->package.count) {
339 : 0 : status = AE_BAD_DATA;
340 : 0 : acpi_util_eval_error(handle, pathname, status);
341 : 0 : goto end;
342 : : }
343 : :
344 [ # # ]: 0 : if (package->package.count > ACPI_MAX_HANDLES) {
345 : 0 : kfree(package);
346 : 0 : return AE_NO_MEMORY;
347 : : }
348 : 0 : list->count = package->package.count;
349 : :
350 : : /* Extract package data. */
351 : :
352 [ # # ]: 0 : for (i = 0; i < list->count; i++) {
353 : :
354 : 0 : element = &(package->package.elements[i]);
355 : :
356 [ # # ]: 0 : if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
357 : : status = AE_BAD_DATA;
358 : : acpi_util_eval_error(handle, pathname, status);
359 : : break;
360 : : }
361 : :
362 [ # # ]: 0 : if (!element->reference.handle) {
363 : : status = AE_NULL_ENTRY;
364 : : acpi_util_eval_error(handle, pathname, status);
365 : : break;
366 : : }
367 : : /* Get the acpi_handle. */
368 : :
369 : 0 : list->handles[i] = element->reference.handle;
370 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
371 : 0 : list->handles[i]));
372 : : }
373 : :
374 : 0 : end:
375 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
376 : 0 : list->count = 0;
377 : : //kfree(list->handles);
378 : : }
379 : :
380 : 0 : kfree(buffer.pointer);
381 : :
382 : 0 : return status;
383 : : }
384 : :
385 : : EXPORT_SYMBOL(acpi_evaluate_reference);
386 : :
387 : : acpi_status
388 : 0 : acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld)
389 : : {
390 : 0 : acpi_status status;
391 : 0 : struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
392 : 0 : union acpi_object *output;
393 : :
394 : 0 : status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer);
395 : :
396 [ # # ]: 0 : if (ACPI_FAILURE(status))
397 : : return status;
398 : :
399 : 0 : output = buffer.pointer;
400 : :
401 [ # # # # ]: 0 : if (!output || output->type != ACPI_TYPE_PACKAGE
402 [ # # ]: 0 : || !output->package.count
403 [ # # ]: 0 : || output->package.elements[0].type != ACPI_TYPE_BUFFER
404 [ # # ]: 0 : || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) {
405 : 0 : status = AE_TYPE;
406 : 0 : goto out;
407 : : }
408 : :
409 : 0 : status = acpi_decode_pld_buffer(
410 : : output->package.elements[0].buffer.pointer,
411 : : output->package.elements[0].buffer.length,
412 : : pld);
413 : :
414 : 0 : out:
415 : 0 : kfree(buffer.pointer);
416 : 0 : return status;
417 : : }
418 : : EXPORT_SYMBOL(acpi_get_physical_device_location);
419 : :
420 : : /**
421 : : * acpi_evaluate_ost: Evaluate _OST for hotplug operations
422 : : * @handle: ACPI device handle
423 : : * @source_event: source event code
424 : : * @status_code: status code
425 : : * @status_buf: optional detailed information (NULL if none)
426 : : *
427 : : * Evaluate _OST for hotplug operations. All ACPI hotplug handlers
428 : : * must call this function when evaluating _OST for hotplug operations.
429 : : * When the platform does not support _OST, this function has no effect.
430 : : */
431 : : acpi_status
432 : 0 : acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code,
433 : : struct acpi_buffer *status_buf)
434 : : {
435 : 0 : union acpi_object params[3] = {
436 : : {.type = ACPI_TYPE_INTEGER,},
437 : : {.type = ACPI_TYPE_INTEGER,},
438 : : {.type = ACPI_TYPE_BUFFER,}
439 : : };
440 : 0 : struct acpi_object_list arg_list = {3, params};
441 : :
442 : 0 : params[0].integer.value = source_event;
443 : 0 : params[1].integer.value = status_code;
444 [ # # ]: 0 : if (status_buf != NULL) {
445 : 0 : params[2].buffer.pointer = status_buf->pointer;
446 : 0 : params[2].buffer.length = status_buf->length;
447 : : } else {
448 : 0 : params[2].buffer.pointer = NULL;
449 : 0 : params[2].buffer.length = 0;
450 : : }
451 : :
452 : 0 : return acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
453 : : }
454 : : EXPORT_SYMBOL(acpi_evaluate_ost);
455 : :
456 : : /**
457 : : * acpi_handle_path: Return the object path of handle
458 : : * @handle: ACPI device handle
459 : : *
460 : : * Caller must free the returned buffer
461 : : */
462 : 0 : static char *acpi_handle_path(acpi_handle handle)
463 : : {
464 : 0 : struct acpi_buffer buffer = {
465 : : .length = ACPI_ALLOCATE_BUFFER,
466 : : .pointer = NULL
467 : : };
468 : :
469 [ # # # # ]: 0 : if (in_interrupt() ||
470 : 0 : acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK)
471 : 0 : return NULL;
472 : 0 : return buffer.pointer;
473 : : }
474 : :
475 : : /**
476 : : * acpi_handle_printk: Print message with ACPI prefix and object path
477 : : * @level: log level
478 : : * @handle: ACPI device handle
479 : : * @fmt: format string
480 : : *
481 : : * This function is called through acpi_handle_<level> macros and prints
482 : : * a message with ACPI prefix and object path. This function acquires
483 : : * the global namespace mutex to obtain an object path. In interrupt
484 : : * context, it shows the object path as <n/a>.
485 : : */
486 : : void
487 : 0 : acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
488 : : {
489 : 0 : struct va_format vaf;
490 : 0 : va_list args;
491 : 0 : const char *path;
492 : :
493 : 0 : va_start(args, fmt);
494 : 0 : vaf.fmt = fmt;
495 : 0 : vaf.va = &args;
496 : :
497 : 0 : path = acpi_handle_path(handle);
498 [ # # ]: 0 : printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf);
499 : :
500 : 0 : va_end(args);
501 : 0 : kfree(path);
502 : 0 : }
503 : : EXPORT_SYMBOL(acpi_handle_printk);
504 : :
505 : : #if defined(CONFIG_DYNAMIC_DEBUG)
506 : : /**
507 : : * __acpi_handle_debug: pr_debug with ACPI prefix and object path
508 : : * @descriptor: Dynamic Debug descriptor
509 : : * @handle: ACPI device handle
510 : : * @fmt: format string
511 : : *
512 : : * This function is called through acpi_handle_debug macro and debug
513 : : * prints a message with ACPI prefix and object path. This function
514 : : * acquires the global namespace mutex to obtain an object path. In
515 : : * interrupt context, it shows the object path as <n/a>.
516 : : */
517 : : void
518 : : __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle,
519 : : const char *fmt, ...)
520 : : {
521 : : struct va_format vaf;
522 : : va_list args;
523 : : const char *path;
524 : :
525 : : va_start(args, fmt);
526 : : vaf.fmt = fmt;
527 : : vaf.va = &args;
528 : :
529 : : path = acpi_handle_path(handle);
530 : : __dynamic_pr_debug(descriptor, "ACPI: %s: %pV", path ? path : "<n/a>", &vaf);
531 : :
532 : : va_end(args);
533 : : kfree(path);
534 : : }
535 : : EXPORT_SYMBOL(__acpi_handle_debug);
536 : : #endif
537 : :
538 : : /**
539 : : * acpi_has_method: Check whether @handle has a method named @name
540 : : * @handle: ACPI device handle
541 : : * @name: name of object or method
542 : : *
543 : : * Check whether @handle has a method named @name.
544 : : */
545 : 5940 : bool acpi_has_method(acpi_handle handle, char *name)
546 : : {
547 : 5940 : acpi_handle tmp;
548 : :
549 : 5940 : return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp));
550 : : }
551 : : EXPORT_SYMBOL(acpi_has_method);
552 : :
553 : 3 : acpi_status acpi_execute_simple_method(acpi_handle handle, char *method,
554 : : u64 arg)
555 : : {
556 : 3 : union acpi_object obj = { .type = ACPI_TYPE_INTEGER };
557 : 3 : struct acpi_object_list arg_list = { .count = 1, .pointer = &obj, };
558 : :
559 : 3 : obj.integer.value = arg;
560 : :
561 : 3 : return acpi_evaluate_object(handle, method, &arg_list, NULL);
562 : : }
563 : : EXPORT_SYMBOL(acpi_execute_simple_method);
564 : :
565 : : /**
566 : : * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations
567 : : * @handle: ACPI device handle
568 : : *
569 : : * Evaluate device's _EJ0 method for hotplug operations.
570 : : */
571 : 0 : acpi_status acpi_evaluate_ej0(acpi_handle handle)
572 : : {
573 : 0 : acpi_status status;
574 : :
575 : 0 : status = acpi_execute_simple_method(handle, "_EJ0", 1);
576 [ # # ]: 0 : if (status == AE_NOT_FOUND)
577 : 0 : acpi_handle_warn(handle, "No _EJ0 support for device\n");
578 [ # # ]: 0 : else if (ACPI_FAILURE(status))
579 : 0 : acpi_handle_warn(handle, "Eject failed (0x%x)\n", status);
580 : :
581 : 0 : return status;
582 : : }
583 : :
584 : : /**
585 : : * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device
586 : : * @handle: ACPI device handle
587 : : * @lock: lock device if non-zero, otherwise unlock device
588 : : *
589 : : * Evaluate device's _LCK method if present to lock/unlock device
590 : : */
591 : 0 : acpi_status acpi_evaluate_lck(acpi_handle handle, int lock)
592 : : {
593 : 0 : acpi_status status;
594 : :
595 : 0 : status = acpi_execute_simple_method(handle, "_LCK", !!lock);
596 [ # # ]: 0 : if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
597 [ # # ]: 0 : if (lock)
598 : 0 : acpi_handle_warn(handle,
599 : : "Locking device failed (0x%x)\n", status);
600 : : else
601 : 0 : acpi_handle_warn(handle,
602 : : "Unlocking device failed (0x%x)\n", status);
603 : : }
604 : :
605 : 0 : return status;
606 : : }
607 : :
608 : : /**
609 : : * acpi_evaluate_dsm - evaluate device's _DSM method
610 : : * @handle: ACPI device handle
611 : : * @guid: GUID of requested functions, should be 16 bytes
612 : : * @rev: revision number of requested function
613 : : * @func: requested function number
614 : : * @argv4: the function specific parameter
615 : : *
616 : : * Evaluate device's _DSM method with specified GUID, revision id and
617 : : * function number. Caller needs to free the returned object.
618 : : *
619 : : * Though ACPI defines the fourth parameter for _DSM should be a package,
620 : : * some old BIOSes do expect a buffer or an integer etc.
621 : : */
622 : : union acpi_object *
623 : 42 : acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 func,
624 : : union acpi_object *argv4)
625 : : {
626 : 42 : acpi_status ret;
627 : 42 : struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
628 : 42 : union acpi_object params[4];
629 : 42 : struct acpi_object_list input = {
630 : : .count = 4,
631 : : .pointer = params,
632 : : };
633 : :
634 : 42 : params[0].type = ACPI_TYPE_BUFFER;
635 : 42 : params[0].buffer.length = 16;
636 : 42 : params[0].buffer.pointer = (u8 *)guid;
637 : 42 : params[1].type = ACPI_TYPE_INTEGER;
638 : 42 : params[1].integer.value = rev;
639 : 42 : params[2].type = ACPI_TYPE_INTEGER;
640 : 42 : params[2].integer.value = func;
641 [ - + ]: 42 : if (argv4) {
642 : 0 : params[3] = *argv4;
643 : : } else {
644 : 42 : params[3].type = ACPI_TYPE_PACKAGE;
645 : 42 : params[3].package.count = 0;
646 : 42 : params[3].package.elements = NULL;
647 : : }
648 : :
649 : 42 : ret = acpi_evaluate_object(handle, "_DSM", &input, &buf);
650 [ - + ]: 42 : if (ACPI_SUCCESS(ret))
651 : 0 : return (union acpi_object *)buf.pointer;
652 : :
653 [ - + ]: 42 : if (ret != AE_NOT_FOUND)
654 : 0 : acpi_handle_warn(handle,
655 : : "failed to evaluate _DSM (0x%x)\n", ret);
656 : :
657 : : return NULL;
658 : : }
659 : : EXPORT_SYMBOL(acpi_evaluate_dsm);
660 : :
661 : : /**
662 : : * acpi_check_dsm - check if _DSM method supports requested functions.
663 : : * @handle: ACPI device handle
664 : : * @guid: GUID of requested functions, should be 16 bytes at least
665 : : * @rev: revision number of requested functions
666 : : * @funcs: bitmap of requested functions
667 : : *
668 : : * Evaluate device's _DSM method to check whether it supports requested
669 : : * functions. Currently only support 64 functions at maximum, should be
670 : : * enough for now.
671 : : */
672 : 18 : bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs)
673 : : {
674 : 18 : int i;
675 : 18 : u64 mask = 0;
676 : 18 : union acpi_object *obj;
677 : :
678 [ + - ]: 18 : if (funcs == 0)
679 : : return false;
680 : :
681 : 18 : obj = acpi_evaluate_dsm(handle, guid, rev, 0, NULL);
682 [ - + ]: 18 : if (!obj)
683 : : return false;
684 : :
685 : : /* For compatibility, old BIOSes may return an integer */
686 [ # # ]: 0 : if (obj->type == ACPI_TYPE_INTEGER)
687 : 0 : mask = obj->integer.value;
688 [ # # ]: 0 : else if (obj->type == ACPI_TYPE_BUFFER)
689 [ # # # # ]: 0 : for (i = 0; i < obj->buffer.length && i < 8; i++)
690 : 0 : mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));
691 : 0 : ACPI_FREE(obj);
692 : :
693 : : /*
694 : : * Bit 0 indicates whether there's support for any functions other than
695 : : * function 0 for the specified GUID and revision.
696 : : */
697 [ # # # # ]: 0 : if ((mask & 0x1) && (mask & funcs) == funcs)
698 : 0 : return true;
699 : :
700 : : return false;
701 : : }
702 : : EXPORT_SYMBOL(acpi_check_dsm);
703 : :
704 : : /**
705 : : * acpi_dev_hid_uid_match - Match device by supplied HID and UID
706 : : * @adev: ACPI device to match.
707 : : * @hid2: Hardware ID of the device.
708 : : * @uid2: Unique ID of the device, pass NULL to not check _UID.
709 : : *
710 : : * Matches HID and UID in @adev with given @hid2 and @uid2.
711 : : * Returns true if matches.
712 : : */
713 : 0 : bool acpi_dev_hid_uid_match(struct acpi_device *adev,
714 : : const char *hid2, const char *uid2)
715 : : {
716 : 0 : const char *hid1 = acpi_device_hid(adev);
717 : 0 : const char *uid1 = acpi_device_uid(adev);
718 : :
719 [ # # ]: 0 : if (strcmp(hid1, hid2))
720 : : return false;
721 : :
722 [ # # ]: 0 : if (!uid2)
723 : : return true;
724 : :
725 [ # # # # ]: 0 : return uid1 && !strcmp(uid1, uid2);
726 : : }
727 : : EXPORT_SYMBOL(acpi_dev_hid_uid_match);
728 : :
729 : : /**
730 : : * acpi_dev_found - Detect presence of a given ACPI device in the namespace.
731 : : * @hid: Hardware ID of the device.
732 : : *
733 : : * Return %true if the device was present at the moment of invocation.
734 : : * Note that if the device is pluggable, it may since have disappeared.
735 : : *
736 : : * For this function to work, acpi_bus_scan() must have been executed
737 : : * which happens in the subsys_initcall() subsection. Hence, do not
738 : : * call from a subsys_initcall() or earlier (use acpi_get_devices()
739 : : * instead). Calling from module_init() is fine (which is synonymous
740 : : * with device_initcall()).
741 : : */
742 : 0 : bool acpi_dev_found(const char *hid)
743 : : {
744 : 0 : struct acpi_device_bus_id *acpi_device_bus_id;
745 : 0 : bool found = false;
746 : :
747 : 0 : mutex_lock(&acpi_device_lock);
748 [ # # ]: 0 : list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
749 [ # # ]: 0 : if (!strcmp(acpi_device_bus_id->bus_id, hid)) {
750 : : found = true;
751 : : break;
752 : : }
753 : 0 : mutex_unlock(&acpi_device_lock);
754 : :
755 : 0 : return found;
756 : : }
757 : : EXPORT_SYMBOL(acpi_dev_found);
758 : :
759 : : struct acpi_dev_match_info {
760 : : struct acpi_device_id hid[2];
761 : : const char *uid;
762 : : s64 hrv;
763 : : };
764 : :
765 : 522 : static int acpi_dev_match_cb(struct device *dev, const void *data)
766 : : {
767 : 522 : struct acpi_device *adev = to_acpi_device(dev);
768 : 522 : const struct acpi_dev_match_info *match = data;
769 : 522 : unsigned long long hrv;
770 : 522 : acpi_status status;
771 : :
772 [ - + ]: 522 : if (acpi_match_device_ids(adev, match->hid))
773 : : return 0;
774 : :
775 [ # # # # ]: 0 : if (match->uid && (!adev->pnp.unique_id ||
776 [ # # ]: 0 : strcmp(adev->pnp.unique_id, match->uid)))
777 : : return 0;
778 : :
779 [ # # ]: 0 : if (match->hrv == -1)
780 : : return 1;
781 : :
782 : 0 : status = acpi_evaluate_integer(adev->handle, "_HRV", NULL, &hrv);
783 [ # # ]: 0 : if (ACPI_FAILURE(status))
784 : : return 0;
785 : :
786 : 0 : return hrv == match->hrv;
787 : : }
788 : :
789 : : /**
790 : : * acpi_dev_present - Detect that a given ACPI device is present
791 : : * @hid: Hardware ID of the device.
792 : : * @uid: Unique ID of the device, pass NULL to not check _UID
793 : : * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
794 : : *
795 : : * Return %true if a matching device was present at the moment of invocation.
796 : : * Note that if the device is pluggable, it may since have disappeared.
797 : : *
798 : : * Note that unlike acpi_dev_found() this function checks the status
799 : : * of the device. So for devices which are present in the dsdt, but
800 : : * which are disabled (their _STA callback returns 0) this function
801 : : * will return false.
802 : : *
803 : : * For this function to work, acpi_bus_scan() must have been executed
804 : : * which happens in the subsys_initcall() subsection. Hence, do not
805 : : * call from a subsys_initcall() or earlier (use acpi_get_devices()
806 : : * instead). Calling from module_init() is fine (which is synonymous
807 : : * with device_initcall()).
808 : : */
809 : 9 : bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
810 : : {
811 : 9 : struct acpi_dev_match_info match = {};
812 : 9 : struct device *dev;
813 : :
814 : 9 : strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
815 : 9 : match.uid = uid;
816 : 9 : match.hrv = hrv;
817 : :
818 : 9 : dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
819 : 9 : put_device(dev);
820 : 9 : return !!dev;
821 : : }
822 : : EXPORT_SYMBOL(acpi_dev_present);
823 : :
824 : : /**
825 : : * acpi_dev_get_first_match_dev - Return the first match of ACPI device
826 : : * @hid: Hardware ID of the device.
827 : : * @uid: Unique ID of the device, pass NULL to not check _UID
828 : : * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
829 : : *
830 : : * Return the first match of ACPI device if a matching device was present
831 : : * at the moment of invocation, or NULL otherwise.
832 : : *
833 : : * The caller is responsible to call put_device() on the returned device.
834 : : *
835 : : * See additional information in acpi_dev_present() as well.
836 : : */
837 : : struct acpi_device *
838 : 0 : acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
839 : : {
840 : 0 : struct acpi_dev_match_info match = {};
841 : 0 : struct device *dev;
842 : :
843 : 0 : strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
844 : 0 : match.uid = uid;
845 : 0 : match.hrv = hrv;
846 : :
847 : 0 : dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
848 [ # # ]: 0 : return dev ? to_acpi_device(dev) : NULL;
849 : : }
850 : : EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
851 : :
852 : : /*
853 : : * acpi_backlight= handling, this is done here rather then in video_detect.c
854 : : * because __setup cannot be used in modules.
855 : : */
856 : : char acpi_video_backlight_string[16];
857 : : EXPORT_SYMBOL(acpi_video_backlight_string);
858 : :
859 : 0 : static int __init acpi_backlight(char *str)
860 : : {
861 : 0 : strlcpy(acpi_video_backlight_string, str,
862 : : sizeof(acpi_video_backlight_string));
863 : 0 : return 1;
864 : : }
865 : : __setup("acpi_backlight=", acpi_backlight);
866 : :
867 : : /**
868 : : * acpi_match_platform_list - Check if the system matches with a given list
869 : : * @plat: pointer to acpi_platform_list table terminated by a NULL entry
870 : : *
871 : : * Return the matched index if the system is found in the platform list.
872 : : * Otherwise, return a negative error code.
873 : : */
874 : 3 : int acpi_match_platform_list(const struct acpi_platform_list *plat)
875 : : {
876 : 3 : struct acpi_table_header hdr;
877 : 3 : int idx = 0;
878 : :
879 [ + - ]: 3 : if (acpi_disabled)
880 : : return -ENODEV;
881 : :
882 [ + + ]: 15 : for (; plat->oem_id[0]; plat++, idx++) {
883 [ - + ]: 12 : if (ACPI_FAILURE(acpi_get_table_header(plat->table, 0, &hdr)))
884 : 0 : continue;
885 : :
886 [ + - ]: 12 : if (strncmp(plat->oem_id, hdr.oem_id, ACPI_OEM_ID_SIZE))
887 : 12 : continue;
888 : :
889 [ # # ]: 0 : if (strncmp(plat->oem_table_id, hdr.oem_table_id, ACPI_OEM_TABLE_ID_SIZE))
890 : 0 : continue;
891 : :
892 [ # # # # ]: 0 : if ((plat->pred == all_versions) ||
893 [ # # # # ]: 0 : (plat->pred == less_than_or_equal && hdr.oem_revision <= plat->oem_revision) ||
894 [ # # # # ]: 0 : (plat->pred == greater_than_or_equal && hdr.oem_revision >= plat->oem_revision) ||
895 [ # # ]: 0 : (plat->pred == equal && hdr.oem_revision == plat->oem_revision))
896 : 0 : return idx;
897 : : }
898 : :
899 : : return -ENODEV;
900 : : }
901 : : EXPORT_SYMBOL(acpi_match_platform_list);
|