utils.c 25.2 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 281 282 283 284 285 286 287 288 289 290 291 292 293
int acpi_get_local_address(acpi_handle handle, u32 *addr)
{
	unsigned long long adr;
	acpi_status status;

	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
	if (ACPI_FAILURE(status))
		return -ENODATA;

	*addr = (u32)adr;
	return 0;
}
EXPORT_SYMBOL(acpi_get_local_address);

L
Linus Torvalds 已提交
294
acpi_status
L
Len Brown 已提交
295 296 297 298
acpi_evaluate_reference(acpi_handle handle,
			acpi_string pathname,
			struct acpi_object_list *arguments,
			struct acpi_handle_list *list)
L
Linus Torvalds 已提交
299
{
L
Len Brown 已提交
300 301 302 303 304
	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 已提交
305 306 307


	if (!list) {
308
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
309 310 311 312 313 314 315 316
	}

	/* Evaluate object. */

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

317
	package = buffer.pointer;
L
Linus Torvalds 已提交
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335

	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) {
336
		kfree(package);
337
		return AE_NO_MEMORY;
L
Linus Torvalds 已提交
338 339 340 341 342 343 344 345 346
	}
	list->count = package->package.count;

	/* Extract package data. */

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

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

347
		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
L
Linus Torvalds 已提交
348 349 350 351 352
			status = AE_BAD_DATA;
			acpi_util_eval_error(handle, pathname, status);
			break;
		}

353 354
		if (!element->reference.handle) {
			status = AE_NULL_ENTRY;
355
			acpi_util_eval_error(handle, pathname, status);
356 357
			break;
		}
L
Linus Torvalds 已提交
358 359 360
		/* Get the  acpi_handle. */

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

L
Len Brown 已提交
364
      end:
L
Linus Torvalds 已提交
365 366 367 368 369
	if (ACPI_FAILURE(status)) {
		list->count = 0;
		//kfree(list->handles);
	}

370
	kfree(buffer.pointer);
L
Linus Torvalds 已提交
371

372
	return status;
L
Linus Torvalds 已提交
373 374
}

L
Len Brown 已提交
375
EXPORT_SYMBOL(acpi_evaluate_reference);
M
Matthew Garrett 已提交
376 377

acpi_status
378
acpi_get_physical_device_location(acpi_handle handle, struct acpi_pld_info **pld)
M
Matthew Garrett 已提交
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
{
	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
394
	    || output->package.elements[0].buffer.length < ACPI_PLD_REV1_BUFFER_SIZE) {
M
Matthew Garrett 已提交
395 396 397 398
		status = AE_TYPE;
		goto out;
	}

399 400 401 402 403
	status = acpi_decode_pld_buffer(
			output->package.elements[0].buffer.pointer,
			output->package.elements[0].buffer.length,
			pld);

M
Matthew Garrett 已提交
404 405 406 407 408
out:
	kfree(buffer.pointer);
	return status;
}
EXPORT_SYMBOL(acpi_get_physical_device_location);
409 410

/**
411
 * acpi_evaluate_ost: Evaluate _OST for hotplug operations
412 413 414 415 416 417 418 419 420 421
 * @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
422 423
acpi_evaluate_ost(acpi_handle handle, u32 source_event, u32 status_code,
		  struct acpi_buffer *status_buf)
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
{
	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;
	}

442
	return acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
443
}
444
EXPORT_SYMBOL(acpi_evaluate_ost);
445

B
Bjørn Mork 已提交
446 447
/**
 * acpi_handle_path: Return the object path of handle
448
 * @handle: ACPI device handle
B
Bjørn Mork 已提交
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
 *
 * 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;
}

465 466
/**
 * acpi_handle_printk: Print message with ACPI prefix and object path
467 468 469
 * @level: log level
 * @handle: ACPI device handle
 * @fmt: format string
470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
 *
 * 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 已提交
487 488
	path = acpi_handle_path(handle);
	printk("%sACPI: %s: %pV", level, path ? path : "<n/a>" , &vaf);
489 490

	va_end(args);
B
Bjørn Mork 已提交
491
	kfree(path);
492 493
}
EXPORT_SYMBOL(acpi_handle_printk);
494

B
Bjørn Mork 已提交
495 496 497
#if defined(CONFIG_DYNAMIC_DEBUG)
/**
 * __acpi_handle_debug: pr_debug with ACPI prefix and object path
498 499 500
 * @descriptor: Dynamic Debug descriptor
 * @handle: ACPI device handle
 * @fmt: format string
B
Bjørn Mork 已提交
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
 *
 * 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

528 529 530 531 532 533 534 535 536 537 538 539 540 541
/**
 * acpi_evaluation_failure_warn - Log evaluation failure warning.
 * @handle: Parent object handle.
 * @name: Name of the object whose evaluation has failed.
 * @status: Status value returned by the failing object evaluation.
 */
void acpi_evaluation_failure_warn(acpi_handle handle, const char *name,
				  acpi_status status)
{
	acpi_handle_warn(handle, "%s evaluation failed: %s\n", name,
			 acpi_format_exception(status));
}
EXPORT_SYMBOL_GPL(acpi_evaluation_failure_warn);

542 543 544 545 546 547 548 549 550 551 552 553 554 555
/**
 * 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);
556 557 558 559 560 561 562 563 564 565 566 567

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);
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 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 609 610

/**
 * 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;
}
611

612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636
/**
 * 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);

637 638 639
/**
 * acpi_evaluate_dsm - evaluate device's _DSM method
 * @handle: ACPI device handle
640
 * @guid: GUID of requested functions, should be 16 bytes
641 642 643 644
 * @rev: revision number of requested function
 * @func: requested function number
 * @argv4: the function specific parameter
 *
645
 * Evaluate device's _DSM method with specified GUID, revision id and
646 647 648 649 650 651
 * 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 *
652
acpi_evaluate_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 func,
653 654 655 656 657 658 659 660 661 662 663 664
		  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;
665
	params[0].buffer.pointer = (u8 *)guid;
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
	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
693
 * @guid: GUID of requested functions, should be 16 bytes at least
694 695 696 697 698 699 700
 * @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.
 */
701
bool acpi_check_dsm(acpi_handle handle, const guid_t *guid, u64 rev, u64 funcs)
702 703 704 705 706
{
	int i;
	u64 mask = 0;
	union acpi_object *obj;

D
Dan Williams 已提交
707 708 709
	if (funcs == 0)
		return false;

710
	obj = acpi_evaluate_dsm(handle, guid, rev, 0, NULL);
711 712 713 714 715 716 717 718
	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++)
719
			mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));
720 721 722 723
	ACPI_FREE(obj);

	/*
	 * Bit 0 indicates whether there's support for any functions other than
724
	 * function 0 for the specified GUID and revision.
725 726 727 728 729 730 731
	 */
	if ((mask & 0x1) && (mask & funcs) == funcs)
		return true;

	return false;
}
EXPORT_SYMBOL(acpi_check_dsm);
732

733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
/**
 * 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);

758
/**
759
 * acpi_dev_found - Detect presence of a given ACPI device in the namespace.
760 761 762 763 764 765 766 767 768 769 770
 * @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()).
 */
771
bool acpi_dev_found(const char *hid)
772 773 774 775 776 777 778 779 780 781 782 783 784 785
{
	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;
}
786
EXPORT_SYMBOL(acpi_dev_found);
787

788
struct acpi_dev_match_info {
789 790 791 792 793
	struct acpi_device_id hid[2];
	const char *uid;
	s64 hrv;
};

794
static int acpi_dev_match_cb(struct device *dev, const void *data)
795 796
{
	struct acpi_device *adev = to_acpi_device(dev);
797
	const struct acpi_dev_match_info *match = data;
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
	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
828
 * of the device. So for devices which are present in the DSDT, but
829 830 831 832 833 834 835 836 837 838 839
 * 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)
{
840
	struct acpi_dev_match_info match = {};
841 842 843 844 845 846
	struct device *dev;

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

847
	dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
848
	put_device(dev);
849 850 851 852
	return !!dev;
}
EXPORT_SYMBOL(acpi_dev_present);

853
/**
854
 * acpi_dev_get_next_match_dev - Return the next match of ACPI device
855
 * @adev: Pointer to the previous ACPI device matching this @hid, @uid and @hrv
856 857 858 859
 * @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
 *
860
 * Return the next match of ACPI device if another matching device was present
861 862
 * at the moment of invocation, or NULL otherwise.
 *
863
 * The caller is responsible for invoking acpi_dev_put() on the returned device.
864 865
 * On the other hand the function invokes  acpi_dev_put() on the given @adev
 * assuming that its reference counter had been increased beforehand.
866
 *
867 868
 * See additional information in acpi_dev_present() as well.
 */
869
struct acpi_device *
870
acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv)
871
{
872
	struct device *start = adev ? &adev->dev : NULL;
873 874 875 876 877 878 879
	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;

880
	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
881
	acpi_dev_put(adev);
882
	return dev ? to_acpi_device(dev) : NULL;
883
}
884 885 886 887 888 889 890 891 892 893 894
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.
 *
895
 * The caller is responsible for invoking acpi_dev_put() on the returned device.
896 897 898 899 900 901 902 903
 *
 * 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);
}
904 905
EXPORT_SYMBOL(acpi_dev_get_first_match_dev);

906 907 908 909 910 911 912 913 914 915 916
/**
 * acpi_reduced_hardware - Return if this is an ACPI-reduced-hw machine
 *
 * Return true when running on an ACPI-reduced-hw machine, false otherwise.
 */
bool acpi_reduced_hardware(void)
{
	return acpi_gbl_reduced_hardware;
}
EXPORT_SYMBOL_GPL(acpi_reduced_hardware);

917 918 919 920 921 922 923 924 925 926 927 928 929 930
/*
 * 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);
931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966

/**
 * 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);