utils.c 24.0 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
L
Linus Torvalds 已提交
2 3 4 5 6 7 8
/*
 *  acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
 *
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 */

9 10
#define pr_fmt(fmt) "ACPI: utils: " fmt

L
Linus Torvalds 已提交
11 12
#include <linux/kernel.h>
#include <linux/module.h>
13
#include <linux/slab.h>
L
Linus Torvalds 已提交
14 15
#include <linux/init.h>
#include <linux/types.h>
16 17
#include <linux/hardirq.h>
#include <linux/acpi.h>
B
Bjørn Mork 已提交
18
#include <linux/dynamic_debug.h>
L
Linus Torvalds 已提交
19

20
#include "internal.h"
21
#include "sleep.h"
22

L
Linus Torvalds 已提交
23 24 25
/* --------------------------------------------------------------------------
                            Object Evaluation Helpers
   -------------------------------------------------------------------------- */
26
static void acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s)
27
{
28
	acpi_handle_debug(h, "Evaluate [%s]: %s\n", p, acpi_format_exception(s));
29 30
}

L
Linus Torvalds 已提交
31
acpi_status
L
Len Brown 已提交
32 33
acpi_extract_package(union acpi_object *package,
		     struct acpi_buffer *format, struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
34
{
L
Len Brown 已提交
35 36 37 38 39 40 41
	u32 size_required = 0;
	u32 tail_offset = 0;
	char *format_string = NULL;
	u32 format_count = 0;
	u32 i = 0;
	u8 *head = NULL;
	u8 *tail = NULL;
L
Linus Torvalds 已提交
42 43


L
Len Brown 已提交
44 45
	if (!package || (package->type != ACPI_TYPE_PACKAGE)
	    || (package->package.count < 1)) {
46
		pr_debug("Invalid package argument\n");
47
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
48 49 50
	}

	if (!format || !format->pointer || (format->length < 1)) {
51
		pr_debug("Invalid format argument\n");
52
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
53 54 55
	}

	if (!buffer) {
56
		pr_debug("Invalid buffer argument\n");
57
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
58 59
	}

L
Len Brown 已提交
60
	format_count = (format->length / sizeof(char)) - 1;
L
Linus Torvalds 已提交
61
	if (format_count > package->package.count) {
62 63
		pr_debug("Format specifies more objects [%d] than present [%d]\n",
			 format_count, package->package.count);
64
		return AE_BAD_DATA;
L
Linus Torvalds 已提交
65 66
	}

67
	format_string = format->pointer;
L
Linus Torvalds 已提交
68 69 70 71

	/*
	 * Calculate size_required.
	 */
L
Len Brown 已提交
72
	for (i = 0; i < format_count; i++) {
L
Linus Torvalds 已提交
73 74 75 76 77 78 79 80

		union acpi_object *element = &(package->package.elements[i]);

		switch (element->type) {

		case ACPI_TYPE_INTEGER:
			switch (format_string[i]) {
			case 'N':
L
Lin Ming 已提交
81 82
				size_required += sizeof(u64);
				tail_offset += sizeof(u64);
L
Linus Torvalds 已提交
83 84
				break;
			case 'S':
L
Len Brown 已提交
85
				size_required +=
L
Lin Ming 已提交
86
				    sizeof(char *) + sizeof(u64) +
L
Len Brown 已提交
87 88
				    sizeof(char);
				tail_offset += sizeof(char *);
L
Linus Torvalds 已提交
89 90
				break;
			default:
91 92
				pr_debug("Invalid package element [%d]: got number, expected [%c]\n",
					 i, format_string[i]);
93
				return AE_BAD_DATA;
L
Linus Torvalds 已提交
94 95 96 97 98 99 100
			}
			break;

		case ACPI_TYPE_STRING:
		case ACPI_TYPE_BUFFER:
			switch (format_string[i]) {
			case 'S':
L
Len Brown 已提交
101 102 103 104 105
				size_required +=
				    sizeof(char *) +
				    (element->string.length * sizeof(char)) +
				    sizeof(char);
				tail_offset += sizeof(char *);
L
Linus Torvalds 已提交
106 107
				break;
			case 'B':
L
Len Brown 已提交
108
				size_required +=
109
				    sizeof(u8 *) + element->buffer.length;
L
Len Brown 已提交
110
				tail_offset += sizeof(u8 *);
L
Linus Torvalds 已提交
111 112
				break;
			default:
113 114
				pr_debug("Invalid package element [%d] got string/buffer, expected [%c]\n",
					 i, format_string[i]);
115
				return AE_BAD_DATA;
L
Linus Torvalds 已提交
116 117
			}
			break;
118 119 120 121 122 123 124
		case ACPI_TYPE_LOCAL_REFERENCE:
			switch (format_string[i]) {
			case 'R':
				size_required += sizeof(void *);
				tail_offset += sizeof(void *);
				break;
			default:
125 126
				pr_debug("Invalid package element [%d] got reference, expected [%c]\n",
					 i, format_string[i]);
127 128 129
				return AE_BAD_DATA;
			}
			break;
L
Linus Torvalds 已提交
130 131 132

		case ACPI_TYPE_PACKAGE:
		default:
133
			pr_debug("Unsupported element at index=%d\n", i);
L
Linus Torvalds 已提交
134
			/* TBD: handle nested packages... */
135
			return AE_SUPPORT;
L
Linus Torvalds 已提交
136 137 138 139 140 141
		}
	}

	/*
	 * Validate output buffer.
	 */
142
	if (buffer->length == ACPI_ALLOCATE_BUFFER) {
143
		buffer->pointer = ACPI_ALLOCATE_ZEROED(size_required);
144 145
		if (!buffer->pointer)
			return AE_NO_MEMORY;
L
Linus Torvalds 已提交
146
		buffer->length = size_required;
147 148 149 150 151 152 153 154
	} else {
		if (buffer->length < size_required) {
			buffer->length = size_required;
			return AE_BUFFER_OVERFLOW;
		} else if (buffer->length != size_required ||
			   !buffer->pointer) {
			return AE_BAD_PARAMETER;
		}
L
Linus Torvalds 已提交
155 156 157 158 159 160 161 162
	}

	head = buffer->pointer;
	tail = buffer->pointer + tail_offset;

	/*
	 * Extract package data.
	 */
L
Len Brown 已提交
163
	for (i = 0; i < format_count; i++) {
L
Linus Torvalds 已提交
164 165 166 167 168 169 170 171 172

		u8 **pointer = NULL;
		union acpi_object *element = &(package->package.elements[i]);

		switch (element->type) {

		case ACPI_TYPE_INTEGER:
			switch (format_string[i]) {
			case 'N':
L
Lin Ming 已提交
173
				*((u64 *) head) =
L
Len Brown 已提交
174
				    element->integer.value;
L
Lin Ming 已提交
175
				head += sizeof(u64);
L
Linus Torvalds 已提交
176 177
				break;
			case 'S':
L
Len Brown 已提交
178
				pointer = (u8 **) head;
L
Linus Torvalds 已提交
179
				*pointer = tail;
L
Lin Ming 已提交
180
				*((u64 *) tail) =
L
Len Brown 已提交
181
				    element->integer.value;
L
Lin Ming 已提交
182 183
				head += sizeof(u64 *);
				tail += sizeof(u64);
L
Linus Torvalds 已提交
184 185 186 187 188 189 190 191 192 193 194 195 196 197
				/* NULL terminate string */
				*tail = (char)0;
				tail += sizeof(char);
				break;
			default:
				/* Should never get here */
				break;
			}
			break;

		case ACPI_TYPE_STRING:
		case ACPI_TYPE_BUFFER:
			switch (format_string[i]) {
			case 'S':
L
Len Brown 已提交
198
				pointer = (u8 **) head;
L
Linus Torvalds 已提交
199
				*pointer = tail;
L
Len Brown 已提交
200 201 202
				memcpy(tail, element->string.pointer,
				       element->string.length);
				head += sizeof(char *);
L
Linus Torvalds 已提交
203 204 205 206 207 208
				tail += element->string.length * sizeof(char);
				/* NULL terminate string */
				*tail = (char)0;
				tail += sizeof(char);
				break;
			case 'B':
L
Len Brown 已提交
209
				pointer = (u8 **) head;
L
Linus Torvalds 已提交
210
				*pointer = tail;
L
Len Brown 已提交
211 212 213
				memcpy(tail, element->buffer.pointer,
				       element->buffer.length);
				head += sizeof(u8 *);
214
				tail += element->buffer.length;
L
Linus Torvalds 已提交
215 216 217 218 219 220
				break;
			default:
				/* Should never get here */
				break;
			}
			break;
221 222 223 224 225 226 227 228 229 230 231 232
		case ACPI_TYPE_LOCAL_REFERENCE:
			switch (format_string[i]) {
			case 'R':
				*(void **)head =
				    (void *)element->reference.handle;
				head += sizeof(void *);
				break;
			default:
				/* Should never get here */
				break;
			}
			break;
L
Linus Torvalds 已提交
233 234 235 236 237 238 239 240
		case ACPI_TYPE_PACKAGE:
			/* TBD: handle nested packages... */
		default:
			/* Should never get here */
			break;
		}
	}

241
	return AE_OK;
L
Linus Torvalds 已提交
242 243
}

L
Len Brown 已提交
244
EXPORT_SYMBOL(acpi_extract_package);
L
Linus Torvalds 已提交
245 246

acpi_status
L
Len Brown 已提交
247 248
acpi_evaluate_integer(acpi_handle handle,
		      acpi_string pathname,
249
		      struct acpi_object_list *arguments, unsigned long long *data)
L
Linus Torvalds 已提交
250
{
L
Len Brown 已提交
251
	acpi_status status = AE_OK;
252
	union acpi_object element;
L
Len Brown 已提交
253
	struct acpi_buffer buffer = { 0, NULL };
L
Linus Torvalds 已提交
254 255

	if (!data)
256
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
257 258

	buffer.length = sizeof(union acpi_object);
259
	buffer.pointer = &element;
L
Linus Torvalds 已提交
260 261 262
	status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
	if (ACPI_FAILURE(status)) {
		acpi_util_eval_error(handle, pathname, status);
263
		return status;
L
Linus Torvalds 已提交
264 265
	}

266
	if (element.type != ACPI_TYPE_INTEGER) {
L
Linus Torvalds 已提交
267
		acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
268
		return AE_BAD_DATA;
L
Linus Torvalds 已提交
269 270
	}

271
	*data = element.integer.value;
L
Linus Torvalds 已提交
272

273
	acpi_handle_debug(handle, "Return value [%llu]\n", *data);
L
Linus Torvalds 已提交
274

275
	return AE_OK;
L
Linus Torvalds 已提交
276 277
}

L
Len Brown 已提交
278
EXPORT_SYMBOL(acpi_evaluate_integer);
L
Linus Torvalds 已提交
279 280

acpi_status
L
Len Brown 已提交
281 282 283 284
acpi_evaluate_reference(acpi_handle handle,
			acpi_string pathname,
			struct acpi_object_list *arguments,
			struct acpi_handle_list *list)
L
Linus Torvalds 已提交
285
{
L
Len Brown 已提交
286 287 288 289 290
	acpi_status status = AE_OK;
	union acpi_object *package = NULL;
	union acpi_object *element = NULL;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	u32 i = 0;
L
Linus Torvalds 已提交
291 292 293


	if (!list) {
294
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
295 296 297 298 299 300 301 302
	}

	/* Evaluate object. */

	status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
	if (ACPI_FAILURE(status))
		goto end;

303
	package = buffer.pointer;
L
Linus Torvalds 已提交
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321

	if ((buffer.length == 0) || !package) {
		status = AE_BAD_DATA;
		acpi_util_eval_error(handle, pathname, status);
		goto end;
	}
	if (package->type != ACPI_TYPE_PACKAGE) {
		status = AE_BAD_DATA;
		acpi_util_eval_error(handle, pathname, status);
		goto end;
	}
	if (!package->package.count) {
		status = AE_BAD_DATA;
		acpi_util_eval_error(handle, pathname, status);
		goto end;
	}

	if (package->package.count > ACPI_MAX_HANDLES) {
322
		kfree(package);
323
		return AE_NO_MEMORY;
L
Linus Torvalds 已提交
324 325 326 327 328 329 330 331 332
	}
	list->count = package->package.count;

	/* Extract package data. */

	for (i = 0; i < list->count; i++) {

		element = &(package->package.elements[i]);

333
		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
L
Linus Torvalds 已提交
334 335 336 337 338
			status = AE_BAD_DATA;
			acpi_util_eval_error(handle, pathname, status);
			break;
		}

339 340
		if (!element->reference.handle) {
			status = AE_NULL_ENTRY;
341
			acpi_util_eval_error(handle, pathname, status);
342 343
			break;
		}
L
Linus Torvalds 已提交
344 345 346
		/* Get the  acpi_handle. */

		list->handles[i] = element->reference.handle;
347
		acpi_handle_debug(list->handles[i], "Found in reference list\n");
L
Linus Torvalds 已提交
348 349
	}

L
Len Brown 已提交
350
      end:
L
Linus Torvalds 已提交
351 352 353 354 355
	if (ACPI_FAILURE(status)) {
		list->count = 0;
		//kfree(list->handles);
	}

356
	kfree(buffer.pointer);
L
Linus Torvalds 已提交
357

358
	return status;
L
Linus Torvalds 已提交
359 360
}

L
Len Brown 已提交
361
EXPORT_SYMBOL(acpi_evaluate_reference);
M
Matthew Garrett 已提交
362 363

acpi_status
364
acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld)
M
Matthew Garrett 已提交
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
{
	acpi_status status;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *output;

	status = acpi_evaluate_object(handle, "_PLD", NULL, &buffer);

	if (ACPI_FAILURE(status))
		return status;

	output = buffer.pointer;

	if (!output || output->type != ACPI_TYPE_PACKAGE
	    || !output->package.count
	    || output->package.elements[0].type != ACPI_TYPE_BUFFER
380
	    || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) {
M
Matthew Garrett 已提交
381 382 383 384
		status = AE_TYPE;
		goto out;
	}

385 386 387 388 389
	status = acpi_decode_pld_buffer(
			output->package.elements[0].buffer.pointer,
			output->package.elements[0].buffer.length,
			pld);

M
Matthew Garrett 已提交
390 391 392 393 394
out:
	kfree(buffer.pointer);
	return status;
}
EXPORT_SYMBOL(acpi_get_physical_device_location);
395 396

/**
397
 * acpi_evaluate_ost: Evaluate _OST for hotplug operations
398 399 400 401 402 403 404 405 406 407
 * @handle: ACPI device handle
 * @source_event: source event code
 * @status_code: status code
 * @status_buf: optional detailed information (NULL if none)
 *
 * Evaluate _OST for hotplug operations. All ACPI hotplug handlers
 * must call this function when evaluating _OST for hotplug operations.
 * When the platform does not support _OST, this function has no effect.
 */
acpi_status
408 409
acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code,
		  struct acpi_buffer *status_buf)
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
{
	union acpi_object params[3] = {
		{.type = ACPI_TYPE_INTEGER,},
		{.type = ACPI_TYPE_INTEGER,},
		{.type = ACPI_TYPE_BUFFER,}
	};
	struct acpi_object_list arg_list = {3, params};

	params[0].integer.value = source_event;
	params[1].integer.value = status_code;
	if (status_buf != NULL) {
		params[2].buffer.pointer = status_buf->pointer;
		params[2].buffer.length = status_buf->length;
	} else {
		params[2].buffer.pointer = NULL;
		params[2].buffer.length = 0;
	}

428
	return acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
429
}
430
EXPORT_SYMBOL(acpi_evaluate_ost);
431

B
Bjørn Mork 已提交
432 433
/**
 * acpi_handle_path: Return the object path of handle
434
 * @handle: ACPI device handle
B
Bjørn Mork 已提交
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
 *
 * Caller must free the returned buffer
 */
static char *acpi_handle_path(acpi_handle handle)
{
	struct acpi_buffer buffer = {
		.length = ACPI_ALLOCATE_BUFFER,
		.pointer = NULL
	};

	if (in_interrupt() ||
	    acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer) != AE_OK)
		return NULL;
	return buffer.pointer;
}

451 452
/**
 * acpi_handle_printk: Print message with ACPI prefix and object path
453 454 455
 * @level: log level
 * @handle: ACPI device handle
 * @fmt: format string
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
 *
 * This function is called through acpi_handle_<level> macros and prints
 * a message with ACPI prefix and object path.  This function acquires
 * the global namespace mutex to obtain an object path.  In interrupt
 * context, it shows the object path as <n/a>.
 */
void
acpi_handle_printk(const char *level, acpi_handle handle, const char *fmt, ...)
{
	struct va_format vaf;
	va_list args;
	const char *path;

	va_start(args, fmt);
	vaf.fmt = fmt;
	vaf.va = &args;

B
Bjørn Mork 已提交
473 474
	path = acpi_handle_path(handle);
	printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf);
475 476

	va_end(args);
B
Bjørn Mork 已提交
477
	kfree(path);
478 479
}
EXPORT_SYMBOL(acpi_handle_printk);
480

B
Bjørn Mork 已提交
481 482 483
#if defined(CONFIG_DYNAMIC_DEBUG)
/**
 * __acpi_handle_debug: pr_debug with ACPI prefix and object path
484 485 486
 * @descriptor: Dynamic Debug descriptor
 * @handle: ACPI device handle
 * @fmt: format string
B
Bjørn Mork 已提交
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
 *
 * This function is called through acpi_handle_debug macro and debug
 * prints a message with ACPI prefix and object path. This function
 * acquires the global namespace mutex to obtain an object path.  In
 * interrupt context, it shows the object path as <n/a>.
 */
void
__acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle,
		    const char *fmt, ...)
{
	struct va_format vaf;
	va_list args;
	const char *path;

	va_start(args, fmt);
	vaf.fmt = fmt;
	vaf.va = &args;

	path = acpi_handle_path(handle);
	__dynamic_pr_debug(descriptor, "ACPI: %s: %pV", path ? path : "<n/a>", &vaf);

	va_end(args);
	kfree(path);
}
EXPORT_SYMBOL(__acpi_handle_debug);
#endif

514 515 516 517 518 519 520 521 522 523 524 525 526 527
/**
 * acpi_has_method: Check whether @handle has a method named @name
 * @handle: ACPI device handle
 * @name: name of object or method
 *
 * Check whether @handle has a method named @name.
 */
bool acpi_has_method(acpi_handle handle, char *name)
{
	acpi_handle tmp;

	return ACPI_SUCCESS(acpi_get_handle(handle, name, &tmp));
}
EXPORT_SYMBOL(acpi_has_method);
528 529 530 531 532 533 534 535 536 537 538 539

acpi_status acpi_execute_simple_method(acpi_handle handle, char *method,
				       u64 arg)
{
	union acpi_object obj = { .type = ACPI_TYPE_INTEGER };
	struct acpi_object_list arg_list = { .count = 1, .pointer = &obj, };

	obj.integer.value = arg;

	return acpi_evaluate_object(handle, method, &arg_list, NULL);
}
EXPORT_SYMBOL(acpi_execute_simple_method);
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582

/**
 * acpi_evaluate_ej0: Evaluate _EJ0 method for hotplug operations
 * @handle: ACPI device handle
 *
 * Evaluate device's _EJ0 method for hotplug operations.
 */
acpi_status acpi_evaluate_ej0(acpi_handle handle)
{
	acpi_status status;

	status = acpi_execute_simple_method(handle, "_EJ0", 1);
	if (status == AE_NOT_FOUND)
		acpi_handle_warn(handle, "No _EJ0 support for device\n");
	else if (ACPI_FAILURE(status))
		acpi_handle_warn(handle, "Eject failed (0x%x)\n", status);

	return status;
}

/**
 * acpi_evaluate_lck: Evaluate _LCK method to lock/unlock device
 * @handle: ACPI device handle
 * @lock: lock device if non-zero, otherwise unlock device
 *
 * Evaluate device's _LCK method if present to lock/unlock device
 */
acpi_status acpi_evaluate_lck(acpi_handle handle, int lock)
{
	acpi_status status;

	status = acpi_execute_simple_method(handle, "_LCK", !!lock);
	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
		if (lock)
			acpi_handle_warn(handle,
				"Locking device failed (0x%x)\n", status);
		else
			acpi_handle_warn(handle,
				"Unlocking device failed (0x%x)\n", status);
	}

	return status;
}
583

584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
/**
 * acpi_evaluate_reg: Evaluate _REG method to register OpRegion presence
 * @handle: ACPI device handle
 * @space_id: ACPI address space id to register OpRegion presence for
 * @function: Parameter to pass to _REG one of ACPI_REG_CONNECT or
 *            ACPI_REG_DISCONNECT
 *
 * Evaluate device's _REG method to register OpRegion presence.
 */
acpi_status acpi_evaluate_reg(acpi_handle handle, u8 space_id, u32 function)
{
	struct acpi_object_list arg_list;
	union acpi_object params[2];

	params[0].type = ACPI_TYPE_INTEGER;
	params[0].integer.value = space_id;
	params[1].type = ACPI_TYPE_INTEGER;
	params[1].integer.value = function;
	arg_list.count = 2;
	arg_list.pointer = params;

	return acpi_evaluate_object(handle, "_REG", &arg_list, NULL);
}
EXPORT_SYMBOL(acpi_evaluate_reg);

609 610 611
/**
 * acpi_evaluate_dsm - evaluate device's _DSM method
 * @handle: ACPI device handle
612
 * @guid: GUID of requested functions, should be 16 bytes
613 614 615 616
 * @rev: revision number of requested function
 * @func: requested function number
 * @argv4: the function specific parameter
 *
617
 * Evaluate device's _DSM method with specified GUID, revision id and
618 619 620 621 622 623
 * function number. Caller needs to free the returned object.
 *
 * Though ACPI defines the fourth parameter for _DSM should be a package,
 * some old BIOSes do expect a buffer or an integer etc.
 */
union acpi_object *
624
acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 func,
625 626 627 628 629 630 631 632 633 634 635 636
		  union acpi_object *argv4)
{
	acpi_status ret;
	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
	union acpi_object params[4];
	struct acpi_object_list input = {
		.count = 4,
		.pointer = params,
	};

	params[0].type = ACPI_TYPE_BUFFER;
	params[0].buffer.length = 16;
637
	params[0].buffer.pointer = (u8 *)guid;
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
	params[1].type = ACPI_TYPE_INTEGER;
	params[1].integer.value = rev;
	params[2].type = ACPI_TYPE_INTEGER;
	params[2].integer.value = func;
	if (argv4) {
		params[3] = *argv4;
	} else {
		params[3].type = ACPI_TYPE_PACKAGE;
		params[3].package.count = 0;
		params[3].package.elements = NULL;
	}

	ret = acpi_evaluate_object(handle, "_DSM", &input, &buf);
	if (ACPI_SUCCESS(ret))
		return (union acpi_object *)buf.pointer;

	if (ret != AE_NOT_FOUND)
		acpi_handle_warn(handle,
				"failed to evaluate _DSM (0x%x)\n", ret);

	return NULL;
}
EXPORT_SYMBOL(acpi_evaluate_dsm);

/**
 * acpi_check_dsm - check if _DSM method supports requested functions.
 * @handle: ACPI device handle
665
 * @guid: GUID of requested functions, should be 16 bytes at least
666 667 668 669 670 671 672
 * @rev: revision number of requested functions
 * @funcs: bitmap of requested functions
 *
 * Evaluate device's _DSM method to check whether it supports requested
 * functions. Currently only support 64 functions at maximum, should be
 * enough for now.
 */
673
bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs)
674 675 676 677 678
{
	int i;
	u64 mask = 0;
	union acpi_object *obj;

D
Dan Williams 已提交
679 680 681
	if (funcs == 0)
		return false;

682
	obj = acpi_evaluate_dsm(handle, guid, rev, 0, NULL);
683 684 685 686 687 688 689 690
	if (!obj)
		return false;

	/* For compatibility, old BIOSes may return an integer */
	if (obj->type == ACPI_TYPE_INTEGER)
		mask = obj->integer.value;
	else if (obj->type == ACPI_TYPE_BUFFER)
		for (i = 0; i < obj->buffer.length && i < 8; i++)
691
			mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));
692 693 694 695
	ACPI_FREE(obj);

	/*
	 * Bit 0 indicates whether there's support for any functions other than
696
	 * function 0 for the specified GUID and revision.
697 698 699 700 701 702 703
	 */
	if ((mask & 0x1) && (mask & funcs) == funcs)
		return true;

	return false;
}
EXPORT_SYMBOL(acpi_check_dsm);
704

705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
/**
 * acpi_dev_hid_uid_match - Match device by supplied HID and UID
 * @adev: ACPI device to match.
 * @hid2: Hardware ID of the device.
 * @uid2: Unique ID of the device, pass NULL to not check _UID.
 *
 * Matches HID and UID in @adev with given @hid2 and @uid2.
 * Returns true if matches.
 */
bool acpi_dev_hid_uid_match(struct acpi_device *adev,
			    const char *hid2, const char *uid2)
{
	const char *hid1 = acpi_device_hid(adev);
	const char *uid1 = acpi_device_uid(adev);

	if (strcmp(hid1, hid2))
		return false;

	if (!uid2)
		return true;

	return uid1 && !strcmp(uid1, uid2);
}
EXPORT_SYMBOL(acpi_dev_hid_uid_match);

730
/**
731
 * acpi_dev_found - Detect presence of a given ACPI device in the namespace.
732 733 734 735 736 737 738 739 740 741 742
 * @hid: Hardware ID of the device.
 *
 * Return %true if the device was present at the moment of invocation.
 * Note that if the device is pluggable, it may since have disappeared.
 *
 * For this function to work, acpi_bus_scan() must have been executed
 * which happens in the subsys_initcall() subsection. Hence, do not
 * call from a subsys_initcall() or earlier (use acpi_get_devices()
 * instead). Calling from module_init() is fine (which is synonymous
 * with device_initcall()).
 */
743
bool acpi_dev_found(const char *hid)
744 745 746 747 748 749 750 751 752 753 754 755 756 757
{
	struct acpi_device_bus_id *acpi_device_bus_id;
	bool found = false;

	mutex_lock(&acpi_device_lock);
	list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
		if (!strcmp(acpi_device_bus_id->bus_id, hid)) {
			found = true;
			break;
		}
	mutex_unlock(&acpi_device_lock);

	return found;
}
758
EXPORT_SYMBOL(acpi_dev_found);
759

760
struct acpi_dev_match_info {
761 762 763 764 765
	struct acpi_device_id hid[2];
	const char *uid;
	s64 hrv;
};

766
static int acpi_dev_match_cb(struct device *dev, const void *data)
767 768
{
	struct acpi_device *adev = to_acpi_device(dev);
769
	const struct acpi_dev_match_info *match = data;
770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
	unsigned long long hrv;
	acpi_status status;

	if (acpi_match_device_ids(adev, match->hid))
		return 0;

	if (match->uid && (!adev->pnp.unique_id ||
	    strcmp(adev->pnp.unique_id, match->uid)))
		return 0;

	if (match->hrv == -1)
		return 1;

	status = acpi_evaluate_integer(adev->handle, "_HRV", NULL, &hrv);
	if (ACPI_FAILURE(status))
		return 0;

	return hrv == match->hrv;
}

/**
 * acpi_dev_present - Detect that a given ACPI device is present
 * @hid: Hardware ID of the device.
 * @uid: Unique ID of the device, pass NULL to not check _UID
 * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
 *
 * Return %true if a matching device was present at the moment of invocation.
 * Note that if the device is pluggable, it may since have disappeared.
 *
 * Note that unlike acpi_dev_found() this function checks the status
 * of the device. So for devices which are present in the dsdt, but
 * which are disabled (their _STA callback returns 0) this function
 * will return false.
 *
 * For this function to work, acpi_bus_scan() must have been executed
 * which happens in the subsys_initcall() subsection. Hence, do not
 * call from a subsys_initcall() or earlier (use acpi_get_devices()
 * instead). Calling from module_init() is fine (which is synonymous
 * with device_initcall()).
 */
bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
{
812
	struct acpi_dev_match_info match = {};
813 814 815 816 817 818
	struct device *dev;

	strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
	match.uid = uid;
	match.hrv = hrv;

819
	dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
820
	put_device(dev);
821 822 823 824
	return !!dev;
}
EXPORT_SYMBOL(acpi_dev_present);

825
/**
826 827
 * acpi_dev_get_next_match_dev - Return the next match of ACPI device
 * @adev: Pointer to the previous acpi_device matching this @hid, @uid and @hrv
828 829 830 831
 * @hid: Hardware ID of the device.
 * @uid: Unique ID of the device, pass NULL to not check _UID
 * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
 *
832
 * Return the next match of ACPI device if another matching device was present
833 834
 * at the moment of invocation, or NULL otherwise.
 *
835 836
 * The caller is responsible to call put_device() on the returned device.
 *
837 838
 * See additional information in acpi_dev_present() as well.
 */
839
struct acpi_device *
840
acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv)
841
{
842
	struct device *start = adev ? &adev->dev : NULL;
843 844 845 846 847 848 849
	struct acpi_dev_match_info match = {};
	struct device *dev;

	strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
	match.uid = uid;
	match.hrv = hrv;

850
	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
851
	return dev ? to_acpi_device(dev) : NULL;
852
}
853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872
EXPORT_SYMBOL(acpi_dev_get_next_match_dev);

/**
 * acpi_dev_get_first_match_dev - Return the first match of ACPI device
 * @hid: Hardware ID of the device.
 * @uid: Unique ID of the device, pass NULL to not check _UID
 * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
 *
 * Return the first match of ACPI device if a matching device was present
 * at the moment of invocation, or NULL otherwise.
 *
 * The caller is responsible to call put_device() on the returned device.
 *
 * See additional information in acpi_dev_present() as well.
 */
struct acpi_device *
acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
{
	return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
}
873 874
EXPORT_SYMBOL(acpi_dev_get_first_match_dev);

875 876 877 878 879 880 881 882 883 884 885 886 887 888
/*
 * acpi_backlight= handling, this is done here rather then in video_detect.c
 * because __setup cannot be used in modules.
 */
char acpi_video_backlight_string[16];
EXPORT_SYMBOL(acpi_video_backlight_string);

static int __init acpi_backlight(char *str)
{
	strlcpy(acpi_video_backlight_string, str,
		sizeof(acpi_video_backlight_string));
	return 1;
}
__setup("acpi_backlight=", acpi_backlight);
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924

/**
 * acpi_match_platform_list - Check if the system matches with a given list
 * @plat: pointer to acpi_platform_list table terminated by a NULL entry
 *
 * Return the matched index if the system is found in the platform list.
 * Otherwise, return a negative error code.
 */
int acpi_match_platform_list(const struct acpi_platform_list *plat)
{
	struct acpi_table_header hdr;
	int idx = 0;

	if (acpi_disabled)
		return -ENODEV;

	for (; plat->oem_id[0]; plat++, idx++) {
		if (ACPI_FAILURE(acpi_get_table_header(plat->table, 0, &hdr)))
			continue;

		if (strncmp(plat->oem_id, hdr.oem_id, ACPI_OEM_ID_SIZE))
			continue;

		if (strncmp(plat->oem_table_id, hdr.oem_table_id, ACPI_OEM_TABLE_ID_SIZE))
			continue;

		if ((plat->pred == all_versions) ||
		    (plat->pred == less_than_or_equal && hdr.oem_revision <= plat->oem_revision) ||
		    (plat->pred == greater_than_or_equal && hdr.oem_revision >= plat->oem_revision) ||
		    (plat->pred == equal && hdr.oem_revision == plat->oem_revision))
			return idx;
	}

	return -ENODEV;
}
EXPORT_SYMBOL(acpi_match_platform_list);