utils.c 23.7 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-or-later
L
Linus Torvalds 已提交
2 3 4 5 6 7 8 9 10
/*
 *  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>
 */

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

18
#include "internal.h"
19
#include "sleep.h"
20

L
Linus Torvalds 已提交
21
#define _COMPONENT		ACPI_BUS_COMPONENT
22
ACPI_MODULE_NAME("utils");
L
Linus Torvalds 已提交
23 24 25 26

/* --------------------------------------------------------------------------
                            Object Evaluation Helpers
   -------------------------------------------------------------------------- */
27 28 29
static void
acpi_util_eval_error(acpi_handle h, acpi_string p, acpi_status s)
{
L
Linus Torvalds 已提交
30
#ifdef ACPI_DEBUG_OUTPUT
31 32 33 34 35
	char prefix[80] = {'\0'};
	struct acpi_buffer buffer = {sizeof(prefix), prefix};
	acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",
		(char *) prefix, p, acpi_format_exception(s)));
L
Linus Torvalds 已提交
36
#else
37
	return;
L
Linus Torvalds 已提交
38
#endif
39 40
}

L
Linus Torvalds 已提交
41
acpi_status
L
Len Brown 已提交
42 43
acpi_extract_package(union acpi_object *package,
		     struct acpi_buffer *format, struct acpi_buffer *buffer)
L
Linus Torvalds 已提交
44
{
L
Len Brown 已提交
45 46 47 48 49 50 51
	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 已提交
52 53


L
Len Brown 已提交
54 55
	if (!package || (package->type != ACPI_TYPE_PACKAGE)
	    || (package->package.count < 1)) {
56
		printk(KERN_WARNING PREFIX "Invalid package argument\n");
57
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
58 59 60
	}

	if (!format || !format->pointer || (format->length < 1)) {
61
		printk(KERN_WARNING PREFIX "Invalid format argument\n");
62
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
63 64 65
	}

	if (!buffer) {
66
		printk(KERN_WARNING PREFIX "Invalid buffer argument\n");
67
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
68 69
	}

L
Len Brown 已提交
70
	format_count = (format->length / sizeof(char)) - 1;
L
Linus Torvalds 已提交
71
	if (format_count > package->package.count) {
72 73 74
		printk(KERN_WARNING PREFIX "Format specifies more objects [%d]"
			      " than exist in package [%d].\n",
			      format_count, package->package.count);
75
		return AE_BAD_DATA;
L
Linus Torvalds 已提交
76 77
	}

78
	format_string = format->pointer;
L
Linus Torvalds 已提交
79 80 81 82

	/*
	 * Calculate size_required.
	 */
L
Len Brown 已提交
83
	for (i = 0; i < format_count; i++) {
L
Linus Torvalds 已提交
84 85 86 87 88 89 90 91

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

		switch (element->type) {

		case ACPI_TYPE_INTEGER:
			switch (format_string[i]) {
			case 'N':
L
Lin Ming 已提交
92 93
				size_required += sizeof(u64);
				tail_offset += sizeof(u64);
L
Linus Torvalds 已提交
94 95
				break;
			case 'S':
L
Len Brown 已提交
96
				size_required +=
L
Lin Ming 已提交
97
				    sizeof(char *) + sizeof(u64) +
L
Len Brown 已提交
98 99
				    sizeof(char);
				tail_offset += sizeof(char *);
L
Linus Torvalds 已提交
100 101
				break;
			default:
102
				printk(KERN_WARNING PREFIX "Invalid package element"
103
					      " [%d]: got number, expecting"
104 105
					      " [%c]\n",
					      i, format_string[i]);
106
				return AE_BAD_DATA;
L
Linus Torvalds 已提交
107 108 109 110 111 112 113
			}
			break;

		case ACPI_TYPE_STRING:
		case ACPI_TYPE_BUFFER:
			switch (format_string[i]) {
			case 'S':
L
Len Brown 已提交
114 115 116 117 118
				size_required +=
				    sizeof(char *) +
				    (element->string.length * sizeof(char)) +
				    sizeof(char);
				tail_offset += sizeof(char *);
L
Linus Torvalds 已提交
119 120
				break;
			case 'B':
L
Len Brown 已提交
121
				size_required +=
122
				    sizeof(u8 *) + element->buffer.length;
L
Len Brown 已提交
123
				tail_offset += sizeof(u8 *);
L
Linus Torvalds 已提交
124 125
				break;
			default:
126
				printk(KERN_WARNING PREFIX "Invalid package element"
127
					      " [%d] got string/buffer,"
128
					      " expecting [%c]\n",
129
					      i, format_string[i]);
130
				return AE_BAD_DATA;
L
Linus Torvalds 已提交
131 132
			}
			break;
133 134 135 136 137 138 139 140 141 142 143 144 145 146
		case ACPI_TYPE_LOCAL_REFERENCE:
			switch (format_string[i]) {
			case 'R':
				size_required += sizeof(void *);
				tail_offset += sizeof(void *);
				break;
			default:
				printk(KERN_WARNING PREFIX "Invalid package element"
					      " [%d] got reference,"
					      " expecting [%c]\n",
					      i, format_string[i]);
				return AE_BAD_DATA;
			}
			break;
L
Linus Torvalds 已提交
147 148 149

		case ACPI_TYPE_PACKAGE:
		default:
L
Len Brown 已提交
150 151 152
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Found unsupported element at index=%d\n",
					  i));
L
Linus Torvalds 已提交
153
			/* TBD: handle nested packages... */
154
			return AE_SUPPORT;
L
Linus Torvalds 已提交
155 156 157 158 159 160
		}
	}

	/*
	 * Validate output buffer.
	 */
161
	if (buffer->length == ACPI_ALLOCATE_BUFFER) {
162
		buffer->pointer = ACPI_ALLOCATE_ZEROED(size_required);
163 164
		if (!buffer->pointer)
			return AE_NO_MEMORY;
L
Linus Torvalds 已提交
165
		buffer->length = size_required;
166 167 168 169 170 171 172 173
	} 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 已提交
174 175 176 177 178 179 180 181
	}

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

	/*
	 * Extract package data.
	 */
L
Len Brown 已提交
182
	for (i = 0; i < format_count; i++) {
L
Linus Torvalds 已提交
183 184 185 186 187 188 189 190 191

		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 已提交
192
				*((u64 *) head) =
L
Len Brown 已提交
193
				    element->integer.value;
L
Lin Ming 已提交
194
				head += sizeof(u64);
L
Linus Torvalds 已提交
195 196
				break;
			case 'S':
L
Len Brown 已提交
197
				pointer = (u8 **) head;
L
Linus Torvalds 已提交
198
				*pointer = tail;
L
Lin Ming 已提交
199
				*((u64 *) tail) =
L
Len Brown 已提交
200
				    element->integer.value;
L
Lin Ming 已提交
201 202
				head += sizeof(u64 *);
				tail += sizeof(u64);
L
Linus Torvalds 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216
				/* 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 已提交
217
				pointer = (u8 **) head;
L
Linus Torvalds 已提交
218
				*pointer = tail;
L
Len Brown 已提交
219 220 221
				memcpy(tail, element->string.pointer,
				       element->string.length);
				head += sizeof(char *);
L
Linus Torvalds 已提交
222 223 224 225 226 227
				tail += element->string.length * sizeof(char);
				/* NULL terminate string */
				*tail = (char)0;
				tail += sizeof(char);
				break;
			case 'B':
L
Len Brown 已提交
228
				pointer = (u8 **) head;
L
Linus Torvalds 已提交
229
				*pointer = tail;
L
Len Brown 已提交
230 231 232
				memcpy(tail, element->buffer.pointer,
				       element->buffer.length);
				head += sizeof(u8 *);
233
				tail += element->buffer.length;
L
Linus Torvalds 已提交
234 235 236 237 238 239
				break;
			default:
				/* Should never get here */
				break;
			}
			break;
240 241 242 243 244 245 246 247 248 249 250 251
		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 已提交
252 253 254 255 256 257 258 259
		case ACPI_TYPE_PACKAGE:
			/* TBD: handle nested packages... */
		default:
			/* Should never get here */
			break;
		}
	}

260
	return AE_OK;
L
Linus Torvalds 已提交
261 262
}

L
Len Brown 已提交
263
EXPORT_SYMBOL(acpi_extract_package);
L
Linus Torvalds 已提交
264 265

acpi_status
L
Len Brown 已提交
266 267
acpi_evaluate_integer(acpi_handle handle,
		      acpi_string pathname,
268
		      struct acpi_object_list *arguments, unsigned long long *data)
L
Linus Torvalds 已提交
269
{
L
Len Brown 已提交
270
	acpi_status status = AE_OK;
271
	union acpi_object element;
L
Len Brown 已提交
272
	struct acpi_buffer buffer = { 0, NULL };
L
Linus Torvalds 已提交
273 274

	if (!data)
275
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
276 277

	buffer.length = sizeof(union acpi_object);
278
	buffer.pointer = &element;
L
Linus Torvalds 已提交
279 280 281
	status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
	if (ACPI_FAILURE(status)) {
		acpi_util_eval_error(handle, pathname, status);
282
		return status;
L
Linus Torvalds 已提交
283 284
	}

285
	if (element.type != ACPI_TYPE_INTEGER) {
L
Linus Torvalds 已提交
286
		acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
287
		return AE_BAD_DATA;
L
Linus Torvalds 已提交
288 289
	}

290
	*data = element.integer.value;
L
Linus Torvalds 已提交
291

292
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%llu]\n", *data));
L
Linus Torvalds 已提交
293

294
	return AE_OK;
L
Linus Torvalds 已提交
295 296
}

L
Len Brown 已提交
297
EXPORT_SYMBOL(acpi_evaluate_integer);
L
Linus Torvalds 已提交
298 299

acpi_status
L
Len Brown 已提交
300 301 302 303
acpi_evaluate_reference(acpi_handle handle,
			acpi_string pathname,
			struct acpi_object_list *arguments,
			struct acpi_handle_list *list)
L
Linus Torvalds 已提交
304
{
L
Len Brown 已提交
305 306 307 308 309
	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 已提交
310 311 312


	if (!list) {
313
		return AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
314 315 316 317 318 319 320 321
	}

	/* Evaluate object. */

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

322
	package = buffer.pointer;
L
Linus Torvalds 已提交
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340

	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) {
341
		kfree(package);
342
		return AE_NO_MEMORY;
L
Linus Torvalds 已提交
343 344 345 346 347 348 349 350 351
	}
	list->count = package->package.count;

	/* Extract package data. */

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

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

352
		if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
L
Linus Torvalds 已提交
353 354 355 356 357
			status = AE_BAD_DATA;
			acpi_util_eval_error(handle, pathname, status);
			break;
		}

358 359
		if (!element->reference.handle) {
			status = AE_NULL_ENTRY;
360
			acpi_util_eval_error(handle, pathname, status);
361 362
			break;
		}
L
Linus Torvalds 已提交
363 364 365 366
		/* Get the  acpi_handle. */

		list->handles[i] = element->reference.handle;
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
L
Len Brown 已提交
367
				  list->handles[i]));
L
Linus Torvalds 已提交
368 369
	}

L
Len Brown 已提交
370
      end:
L
Linus Torvalds 已提交
371 372 373 374 375
	if (ACPI_FAILURE(status)) {
		list->count = 0;
		//kfree(list->handles);
	}

376
	kfree(buffer.pointer);
L
Linus Torvalds 已提交
377

378
	return status;
L
Linus Torvalds 已提交
379 380
}

L
Len Brown 已提交
381
EXPORT_SYMBOL(acpi_evaluate_reference);
M
Matthew Garrett 已提交
382 383

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

405 406 407 408 409
	status = acpi_decode_pld_buffer(
			output->package.elements[0].buffer.pointer,
			output->package.elements[0].buffer.length,
			pld);

M
Matthew Garrett 已提交
410 411 412 413 414
out:
	kfree(buffer.pointer);
	return status;
}
EXPORT_SYMBOL(acpi_get_physical_device_location);
415 416

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

448
	return acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
449
}
450
EXPORT_SYMBOL(acpi_evaluate_ost);
451

B
Bjørn Mork 已提交
452 453
/**
 * acpi_handle_path: Return the object path of handle
454
 * @handle: ACPI device handle
B
Bjørn Mork 已提交
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
 *
 * 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;
}

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

	va_end(args);
B
Bjørn Mork 已提交
497
	kfree(path);
498 499
}
EXPORT_SYMBOL(acpi_handle_printk);
500

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

534 535 536 537 538 539 540 541 542 543 544 545 546 547
/**
 * 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);
548 549 550 551 552 553 554 555 556 557 558 559

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);
560 561 562 563 564 565 566 567 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

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

604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
/**
 * 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);

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

D
Dan Williams 已提交
699 700 701
	if (funcs == 0)
		return false;

702
	obj = acpi_evaluate_dsm(handle, guid, rev, 0, NULL);
703 704 705 706 707 708 709 710
	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++)
711
			mask |= (((u64)obj->buffer.pointer[i]) << (i * 8));
712 713 714 715
	ACPI_FREE(obj);

	/*
	 * Bit 0 indicates whether there's support for any functions other than
716
	 * function 0 for the specified GUID and revision.
717 718 719 720 721 722 723
	 */
	if ((mask & 0x1) && (mask & funcs) == funcs)
		return true;

	return false;
}
EXPORT_SYMBOL(acpi_check_dsm);
724

725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
/**
 * 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);

750
/**
751
 * acpi_dev_found - Detect presence of a given ACPI device in the namespace.
752 753 754 755 756 757 758 759 760 761 762
 * @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()).
 */
763
bool acpi_dev_found(const char *hid)
764 765 766 767 768 769 770 771 772 773 774 775 776 777
{
	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;
}
778
EXPORT_SYMBOL(acpi_dev_found);
779

780
struct acpi_dev_match_info {
781 782 783 784 785
	struct acpi_device_id hid[2];
	const char *uid;
	s64 hrv;
};

786
static int acpi_dev_match_cb(struct device *dev, const void *data)
787 788
{
	struct acpi_device *adev = to_acpi_device(dev);
789
	const struct acpi_dev_match_info *match = data;
790 791 792 793 794 795 796 797 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 828 829 830 831
	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)
{
832
	struct acpi_dev_match_info match = {};
833 834 835 836 837 838
	struct device *dev;

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

839
	dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
840
	put_device(dev);
841 842 843 844
	return !!dev;
}
EXPORT_SYMBOL(acpi_dev_present);

845
/**
846
 * acpi_dev_get_first_match_dev - Return the first match of ACPI device
847 848 849 850
 * @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
 *
851
 * Return the first match of ACPI device if a matching device was present
852 853
 * at the moment of invocation, or NULL otherwise.
 *
854 855
 * The caller is responsible to call put_device() on the returned device.
 *
856 857
 * See additional information in acpi_dev_present() as well.
 */
858 859 860 861 862 863 864 865 866 867 868
struct acpi_device *
acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
{
	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;

	dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
869
	return dev ? to_acpi_device(dev) : NULL;
870 871 872
}
EXPORT_SYMBOL(acpi_dev_get_first_match_dev);

873 874 875 876 877 878 879 880 881 882 883 884 885 886
/*
 * 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);
887 888 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

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