property.c 35.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0-only
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * ACPI device specific properties support.
 *
 * Copyright (C) 2014, Intel Corporation
 * All rights reserved.
 *
 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
 *          Darren Hart <dvhart@linux.intel.com>
 *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
 */

#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/export.h>

#include "internal.h"

19
static int acpi_data_get_property_array(const struct acpi_device_data *data,
20 21 22 23
					const char *name,
					acpi_object_type type,
					const union acpi_object **obj);

24 25 26 27 28 29 30 31
/*
 * The GUIDs here are made equivalent to each other in order to avoid extra
 * complexity in the properties handling code, with the caveat that the
 * kernel will accept certain combinations of GUID and properties that are
 * not defined without a warning. For instance if any of the properties
 * from different GUID appear in a property list of another, it will be
 * accepted by the kernel. Firmware validation tools should catch these.
 */
32 33
static const guid_t prp_guids[] = {
	/* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
34
	GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
35
		  0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01),
36 37 38
	/* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */
	GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3,
		  0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4),
39 40 41
	/* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */
	GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
		  0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
42 43
};

44
/* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
45 46 47
static const guid_t ads_guid =
	GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
		  0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
48 49 50

static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
					   const union acpi_object *desc,
51 52
					   struct acpi_device_data *data,
					   struct fwnode_handle *parent);
53 54 55
static bool acpi_extract_properties(const union acpi_object *desc,
				    struct acpi_device_data *data);

56 57 58
static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
					acpi_handle handle,
					const union acpi_object *link,
59 60
					struct list_head *list,
					struct fwnode_handle *parent)
61 62
{
	struct acpi_data_node *dn;
63
	bool result;
64 65 66 67 68 69

	dn = kzalloc(sizeof(*dn), GFP_KERNEL);
	if (!dn)
		return false;

	dn->name = link->package.elements[0].string.pointer;
70
	dn->fwnode.ops = &acpi_data_fwnode_ops;
71
	dn->parent = parent;
72
	INIT_LIST_HEAD(&dn->data.properties);
73 74
	INIT_LIST_HEAD(&dn->data.subnodes);

75
	result = acpi_extract_properties(desc, &dn->data);
76

77 78 79
	if (handle) {
		acpi_handle scope;
		acpi_status status;
80

81 82 83 84 85 86 87 88
		/*
		 * The scope for the subnode object lookup is the one of the
		 * namespace node (device) containing the object that has
		 * returned the package.  That is, it's the scope of that
		 * object's parent.
		 */
		status = acpi_get_parent(handle, &scope);
		if (ACPI_SUCCESS(status)
89 90
		    && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data,
						      &dn->fwnode))
91
			result = true;
92 93
	} else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data,
						  &dn->fwnode)) {
94 95
		result = true;
	}
96

97
	if (result) {
98
		dn->handle = handle;
99
		dn->data.pointer = desc;
100 101 102 103
		list_add_tail(&dn->sibling, list);
		return true;
	}

104
	kfree(dn);
105
	acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
106 107 108 109 110
	return false;
}

static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
					const union acpi_object *link,
111 112
					struct list_head *list,
					struct fwnode_handle *parent)
113 114 115 116 117 118 119 120 121
{
	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
	acpi_status status;

	status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
					    ACPI_TYPE_PACKAGE);
	if (ACPI_FAILURE(status))
		return false;

122 123
	if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list,
					parent))
124
		return true;
125 126 127 128 129

	ACPI_FREE(buf.pointer);
	return false;
}

130 131
static bool acpi_nondev_subnode_ok(acpi_handle scope,
				   const union acpi_object *link,
132 133
				   struct list_head *list,
				   struct fwnode_handle *parent)
134 135 136 137 138 139 140 141 142 143 144 145
{
	acpi_handle handle;
	acpi_status status;

	if (!scope)
		return false;

	status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
				 &handle);
	if (ACPI_FAILURE(status))
		return false;

146
	return acpi_nondev_subnode_data_ok(handle, link, list, parent);
147 148
}

149 150
static int acpi_add_nondev_subnodes(acpi_handle scope,
				    const union acpi_object *links,
151 152
				    struct list_head *list,
				    struct fwnode_handle *parent)
153 154 155 156 157
{
	bool ret = false;
	int i;

	for (i = 0; i < links->package.count; i++) {
158 159 160
		const union acpi_object *link, *desc;
		acpi_handle handle;
		bool result;
161 162

		link = &links->package.elements[i];
163 164 165 166 167 168 169 170 171 172 173
		/* Only two elements allowed. */
		if (link->package.count != 2)
			continue;

		/* The first one must be a string. */
		if (link->package.elements[0].type != ACPI_TYPE_STRING)
			continue;

		/* The second one may be a string, a reference or a package. */
		switch (link->package.elements[1].type) {
		case ACPI_TYPE_STRING:
174 175
			result = acpi_nondev_subnode_ok(scope, link, list,
							 parent);
176 177 178
			break;
		case ACPI_TYPE_LOCAL_REFERENCE:
			handle = link->package.elements[1].reference.handle;
179 180
			result = acpi_nondev_subnode_data_ok(handle, link, list,
							     parent);
181 182 183
			break;
		case ACPI_TYPE_PACKAGE:
			desc = &link->package.elements[1];
184 185
			result = acpi_nondev_subnode_extract(desc, NULL, link,
							     list, parent);
186 187 188 189 190 191
			break;
		default:
			result = false;
			break;
		}
		ret = ret || result;
192 193 194 195 196 197 198
	}

	return ret;
}

static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
					   const union acpi_object *desc,
199 200
					   struct acpi_device_data *data,
					   struct fwnode_handle *parent)
201 202 203
{
	int i;

204
	/* Look for the ACPI data subnodes GUID. */
205
	for (i = 0; i < desc->package.count; i += 2) {
206
		const union acpi_object *guid, *links;
207

208
		guid = &desc->package.elements[i];
209 210 211
		links = &desc->package.elements[i + 1];

		/*
212
		 * The first element must be a GUID and the second one must be
213 214
		 * a package.
		 */
215 216 217
		if (guid->type != ACPI_TYPE_BUFFER ||
		    guid->buffer.length != 16 ||
		    links->type != ACPI_TYPE_PACKAGE)
218 219
			break;

220
		if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
221 222
			continue;

223 224
		return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
						parent);
225 226 227 228
	}

	return false;
}
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280

static bool acpi_property_value_ok(const union acpi_object *value)
{
	int j;

	/*
	 * The value must be an integer, a string, a reference, or a package
	 * whose every element must be an integer, a string, or a reference.
	 */
	switch (value->type) {
	case ACPI_TYPE_INTEGER:
	case ACPI_TYPE_STRING:
	case ACPI_TYPE_LOCAL_REFERENCE:
		return true;

	case ACPI_TYPE_PACKAGE:
		for (j = 0; j < value->package.count; j++)
			switch (value->package.elements[j].type) {
			case ACPI_TYPE_INTEGER:
			case ACPI_TYPE_STRING:
			case ACPI_TYPE_LOCAL_REFERENCE:
				continue;

			default:
				return false;
			}

		return true;
	}
	return false;
}

static bool acpi_properties_format_valid(const union acpi_object *properties)
{
	int i;

	for (i = 0; i < properties->package.count; i++) {
		const union acpi_object *property;

		property = &properties->package.elements[i];
		/*
		 * Only two elements allowed, the first one must be a string and
		 * the second one has to satisfy certain conditions.
		 */
		if (property->package.count != 2
		    || property->package.elements[0].type != ACPI_TYPE_STRING
		    || !acpi_property_value_ok(&property->package.elements[1]))
			return false;
	}
	return true;
}

281 282 283 284 285
static void acpi_init_of_compatible(struct acpi_device *adev)
{
	const union acpi_object *of_compatible;
	int ret;

286 287
	ret = acpi_data_get_property_array(&adev->data, "compatible",
					   ACPI_TYPE_STRING, &of_compatible);
288 289 290 291
	if (ret) {
		ret = acpi_dev_get_property(adev, "compatible",
					    ACPI_TYPE_STRING, &of_compatible);
		if (ret) {
292 293 294 295
			if (adev->parent
			    && adev->parent->flags.of_compatible_ok)
				goto out;

296 297 298 299
			return;
		}
	}
	adev->data.of_compatible = of_compatible;
300 301 302

 out:
	adev->flags.of_compatible_ok = 1;
303 304
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
static bool acpi_is_property_guid(const guid_t *guid)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(prp_guids); i++) {
		if (guid_equal(guid, &prp_guids[i]))
			return true;
	}

	return false;
}

struct acpi_device_properties *
acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
		    const union acpi_object *properties)
{
	struct acpi_device_properties *props;

	props = kzalloc(sizeof(*props), GFP_KERNEL);
	if (props) {
		INIT_LIST_HEAD(&props->list);
		props->guid = guid;
		props->properties = properties;
		list_add_tail(&props->list, &data->properties);
	}

	return props;
}

334 335
static bool acpi_extract_properties(const union acpi_object *desc,
				    struct acpi_device_data *data)
336 337 338 339
{
	int i;

	if (desc->package.count % 2)
340
		return false;
341

342
	/* Look for the device properties GUID. */
343
	for (i = 0; i < desc->package.count; i += 2) {
344
		const union acpi_object *guid, *properties;
345

346
		guid = &desc->package.elements[i];
347 348 349
		properties = &desc->package.elements[i + 1];

		/*
350
		 * The first element must be a GUID and the second one must be
351 352
		 * a package.
		 */
353 354 355
		if (guid->type != ACPI_TYPE_BUFFER ||
		    guid->buffer.length != 16 ||
		    properties->type != ACPI_TYPE_PACKAGE)
356 357
			break;

358
		if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
359 360 361
			continue;

		/*
362
		 * We found the matching GUID. Now validate the format of the
363 364 365
		 * package immediately following it.
		 */
		if (!acpi_properties_format_valid(properties))
366
			continue;
367

368 369
		acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
				    properties);
370
	}
371

372
	return !list_empty(&data->properties);
373
}
374

375 376 377 378 379 380 381
void acpi_init_properties(struct acpi_device *adev)
{
	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
	struct acpi_hardware_id *hwid;
	acpi_status status;
	bool acpi_of = false;

382
	INIT_LIST_HEAD(&adev->data.properties);
383 384
	INIT_LIST_HEAD(&adev->data.subnodes);

385 386 387
	if (!adev->handle)
		return;

388 389 390 391 392 393 394 395 396
	/*
	 * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
	 * Device Tree compatible properties for this device.
	 */
	list_for_each_entry(hwid, &adev->pnp.ids, list) {
		if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
			acpi_of = true;
			break;
		}
397 398
	}

399 400 401 402 403 404 405 406 407
	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
					    ACPI_TYPE_PACKAGE);
	if (ACPI_FAILURE(status))
		goto out;

	if (acpi_extract_properties(buf.pointer, &adev->data)) {
		adev->data.pointer = buf.pointer;
		if (acpi_of)
			acpi_init_of_compatible(adev);
408
	}
409 410
	if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer,
					&adev->data, acpi_fwnode_handle(adev)))
411 412 413
		adev->data.pointer = buf.pointer;

	if (!adev->data.pointer) {
414 415 416
		acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
		ACPI_FREE(buf.pointer);
	}
417 418 419 420

 out:
	if (acpi_of && !adev->flags.of_compatible_ok)
		acpi_handle_info(adev->handle,
421
			 ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
422 423 424

	if (!adev->data.pointer)
		acpi_extract_apple_properties(adev);
425 426
}

427 428 429 430 431 432 433 434 435
static void acpi_destroy_nondev_subnodes(struct list_head *list)
{
	struct acpi_data_node *dn, *next;

	if (list_empty(list))
		return;

	list_for_each_entry_safe_reverse(dn, next, list, sibling) {
		acpi_destroy_nondev_subnodes(&dn->data.subnodes);
436
		wait_for_completion(&dn->kobj_done);
437 438 439 440 441 442
		list_del(&dn->sibling);
		ACPI_FREE((void *)dn->data.pointer);
		kfree(dn);
	}
}

443 444
void acpi_free_properties(struct acpi_device *adev)
{
445 446
	struct acpi_device_properties *props, *tmp;

447
	acpi_destroy_nondev_subnodes(&adev->data.subnodes);
448
	ACPI_FREE((void *)adev->data.pointer);
449
	adev->data.of_compatible = NULL;
450
	adev->data.pointer = NULL;
451 452 453 454
	list_for_each_entry_safe(props, tmp, &adev->data.properties, list) {
		list_del(&props->list);
		kfree(props);
	}
455 456 457
}

/**
458 459
 * acpi_data_get_property - return an ACPI property with given name
 * @data: ACPI device deta object to get the property from
460 461 462 463 464 465 466 467
 * @name: Name of the property
 * @type: Expected property type
 * @obj: Location to store the property value (if not %NULL)
 *
 * Look up a property with @name and store a pointer to the resulting ACPI
 * object at the location pointed to by @obj if found.
 *
 * Callers must not attempt to free the returned objects.  These objects will be
468
 * freed by the ACPI core automatically during the removal of @data.
469 470 471
 *
 * Return: %0 if property with @name has been found (success),
 *         %-EINVAL if the arguments are invalid,
472
 *         %-EINVAL if the property doesn't exist,
473 474
 *         %-EPROTO if the property value type doesn't match @type.
 */
475
static int acpi_data_get_property(const struct acpi_device_data *data,
476 477
				  const char *name, acpi_object_type type,
				  const union acpi_object **obj)
478
{
479
	const struct acpi_device_properties *props;
480

481
	if (!data || !name)
482 483
		return -EINVAL;

484
	if (!data->pointer || list_empty(&data->properties))
485
		return -EINVAL;
486

487 488 489
	list_for_each_entry(props, &data->properties, list) {
		const union acpi_object *properties;
		unsigned int i;
490

491 492 493 494 495 496
		properties = props->properties;
		for (i = 0; i < properties->package.count; i++) {
			const union acpi_object *propname, *propvalue;
			const union acpi_object *property;

			property = &properties->package.elements[i];
497

498 499
			propname = &property->package.elements[0];
			propvalue = &property->package.elements[1];
500

501 502 503 504 505 506
			if (!strcmp(name, propname->string.pointer)) {
				if (type != ACPI_TYPE_ANY &&
				    propvalue->type != type)
					return -EPROTO;
				if (obj)
					*obj = propvalue;
507

508 509
				return 0;
			}
510 511
		}
	}
512
	return -EINVAL;
513
}
514 515 516 517 518 519 520 521

/**
 * acpi_dev_get_property - return an ACPI property with given name.
 * @adev: ACPI device to get the property from.
 * @name: Name of the property.
 * @type: Expected property type.
 * @obj: Location to store the property value (if not %NULL).
 */
522
int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
523 524 525 526
			  acpi_object_type type, const union acpi_object **obj)
{
	return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
}
527 528
EXPORT_SYMBOL_GPL(acpi_dev_get_property);

529 530
static const struct acpi_device_data *
acpi_device_data_of_node(const struct fwnode_handle *fwnode)
531
{
532
	if (is_acpi_device_node(fwnode)) {
533
		const struct acpi_device *adev = to_acpi_device_node(fwnode);
534
		return &adev->data;
535
	} else if (is_acpi_data_node(fwnode)) {
536
		const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
537 538 539 540 541
		return &dn->data;
	}
	return NULL;
}

542
/**
543 544 545 546 547
 * acpi_node_prop_get - return an ACPI property with given name.
 * @fwnode: Firmware node to get the property from.
 * @propname: Name of the property.
 * @valptr: Location to store a pointer to the property value (if not %NULL).
 */
548 549
int acpi_node_prop_get(const struct fwnode_handle *fwnode,
		       const char *propname, void **valptr)
550 551 552 553 554 555 556 557 558
{
	return acpi_data_get_property(acpi_device_data_of_node(fwnode),
				      propname, ACPI_TYPE_ANY,
				      (const union acpi_object **)valptr);
}

/**
 * acpi_data_get_property_array - return an ACPI array property with given name
 * @adev: ACPI data object to get the property from
559 560 561 562 563 564 565 566
 * @name: Name of the property
 * @type: Expected type of array elements
 * @obj: Location to store a pointer to the property value (if not NULL)
 *
 * Look up an array property with @name and store a pointer to the resulting
 * ACPI object at the location pointed to by @obj if found.
 *
 * Callers must not attempt to free the returned objects.  Those objects will be
567
 * freed by the ACPI core automatically during the removal of @data.
568 569 570
 *
 * Return: %0 if array property (package) with @name has been found (success),
 *         %-EINVAL if the arguments are invalid,
571
 *         %-EINVAL if the property doesn't exist,
572 573 574
 *         %-EPROTO if the property is not a package or the type of its elements
 *           doesn't match @type.
 */
575
static int acpi_data_get_property_array(const struct acpi_device_data *data,
576 577 578
					const char *name,
					acpi_object_type type,
					const union acpi_object **obj)
579 580 581 582
{
	const union acpi_object *prop;
	int ret, i;

583
	ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
	if (ret)
		return ret;

	if (type != ACPI_TYPE_ANY) {
		/* Check that all elements are of correct type. */
		for (i = 0; i < prop->package.count; i++)
			if (prop->package.elements[i].type != type)
				return -EPROTO;
	}
	if (obj)
		*obj = prop;

	return 0;
}

599 600 601 602
static struct fwnode_handle *
acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
				 const char *childname)
{
603
	char name[ACPI_PATH_SEGMENT_LENGTH];
604
	struct fwnode_handle *child;
605 606
	struct acpi_buffer path;
	acpi_status status;
607

608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
	path.length = sizeof(name);
	path.pointer = name;

	fwnode_for_each_child_node(fwnode, child) {
		if (is_acpi_data_node(child)) {
			if (acpi_data_node_match(child, childname))
				return child;
			continue;
		}

		status = acpi_get_name(ACPI_HANDLE_FWNODE(child),
				       ACPI_SINGLE_NAME, &path);
		if (ACPI_FAILURE(status))
			break;

		if (!strncmp(name, childname, ACPI_NAMESEG_SIZE))
624
			return child;
625
	}
626 627 628 629

	return NULL;
}

630
/**
631 632
 * __acpi_node_get_property_reference - returns handle to the referenced object
 * @fwnode: Firmware node to get the property from
633
 * @propname: Name of the property
634
 * @index: Index of the reference to return
635
 * @num_args: Maximum number of arguments after each reference
636 637 638 639
 * @args: Location to store the returned reference with optional arguments
 *
 * Find property with @name, verifify that it is a package containing at least
 * one object reference and if so, store the ACPI device object pointer to the
640 641
 * target object in @args->adev.  If the reference includes arguments, store
 * them in the @args->args[] array.
642
 *
643 644
 * If there's more than one reference in the property value package, @index is
 * used to select the one to return.
645
 *
646 647 648 649 650 651 652 653 654 655 656 657 658
 * It is possible to leave holes in the property value set like in the
 * example below:
 *
 * Package () {
 *     "cs-gpios",
 *     Package () {
 *        ^GPIO, 19, 0, 0,
 *        ^GPIO, 20, 0, 0,
 *        0,
 *        ^GPIO, 21, 0, 0,
 *     }
 * }
 *
659 660 661
 * Calling this function with index %2 or index %3 return %-ENOENT. If the
 * property does not contain any more values %-ENOENT is returned. The NULL
 * entry must be single integer and preferably contain value %0.
662
 *
663 664
 * Return: %0 on success, negative error code on failure.
 */
665
int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
666
	const char *propname, size_t index, size_t num_args,
667
	struct fwnode_reference_args *args)
668 669 670
{
	const union acpi_object *element, *end;
	const union acpi_object *obj;
671
	const struct acpi_device_data *data;
672 673 674
	struct acpi_device *device;
	int ret, idx = 0;

675 676
	data = acpi_device_data_of_node(fwnode);
	if (!data)
677
		return -ENOENT;
678

679
	ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
680
	if (ret)
681
		return ret == -EINVAL ? -ENOENT : -EINVAL;
682 683 684 685 686 687

	/*
	 * The simplest case is when the value is a single reference.  Just
	 * return that reference then.
	 */
	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
688
		if (index)
689 690 691 692
			return -EINVAL;

		ret = acpi_bus_get_device(obj->reference.handle, &device);
		if (ret)
693
			return ret == -ENODEV ? -EINVAL : ret;
694

695
		args->fwnode = acpi_fwnode_handle(device);
696 697 698 699 700 701 702 703 704 705 706 707 708
		args->nargs = 0;
		return 0;
	}

	/*
	 * If it is not a single reference, then it is a package of
	 * references followed by number of ints as follows:
	 *
	 *  Package () { REF, INT, REF, INT, INT }
	 *
	 * The index argument is then used to determine which reference
	 * the caller wants (along with the arguments).
	 */
709 710 711 712
	if (obj->type != ACPI_TYPE_PACKAGE)
		return -EINVAL;
	if (index >= obj->package.count)
		return -ENOENT;
713 714 715 716 717 718 719

	element = obj->package.elements;
	end = element + obj->package.count;

	while (element < end) {
		u32 nargs, i;

720
		if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
721 722
			struct fwnode_handle *ref_fwnode;

723 724 725
			ret = acpi_bus_get_device(element->reference.handle,
						  &device);
			if (ret)
726
				return -EINVAL;
727 728 729 730

			nargs = 0;
			element++;

731 732 733 734 735 736 737 738 739 740 741 742 743
			/*
			 * Find the referred data extension node under the
			 * referred device node.
			 */
			for (ref_fwnode = acpi_fwnode_handle(device);
			     element < end && element->type == ACPI_TYPE_STRING;
			     element++) {
				ref_fwnode = acpi_fwnode_get_named_child_node(
					ref_fwnode, element->string.pointer);
				if (!ref_fwnode)
					return -EINVAL;
			}

744 745 746 747 748 749 750 751 752
			/* assume following integer elements are all args */
			for (i = 0; element + i < end && i < num_args; i++) {
				int type = element[i].type;

				if (type == ACPI_TYPE_INTEGER)
					nargs++;
				else if (type == ACPI_TYPE_LOCAL_REFERENCE)
					break;
				else
753
					return -EINVAL;
754
			}
755

756
			if (nargs > NR_FWNODE_REFERENCE_ARGS)
757
				return -EINVAL;
758

759
			if (idx == index) {
760
				args->fwnode = ref_fwnode;
761 762 763
				args->nargs = nargs;
				for (i = 0; i < nargs; i++)
					args->args[i] = element[i].integer.value;
764

765 766 767 768 769 770 771 772 773
				return 0;
			}

			element += nargs;
		} else if (element->type == ACPI_TYPE_INTEGER) {
			if (idx == index)
				return -ENOENT;
			element++;
		} else {
774
			return -EINVAL;
775 776
		}

777
		idx++;
778 779
	}

780
	return -ENOENT;
781
}
782
EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
783

784
static int acpi_data_prop_read_single(const struct acpi_device_data *data,
785 786
				      const char *propname,
				      enum dev_prop_type proptype, void *val)
787 788 789 790 791 792 793 794
{
	const union acpi_object *obj;
	int ret;

	if (!val)
		return -EINVAL;

	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
795
		ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
		if (ret)
			return ret;

		switch (proptype) {
		case DEV_PROP_U8:
			if (obj->integer.value > U8_MAX)
				return -EOVERFLOW;
			*(u8 *)val = obj->integer.value;
			break;
		case DEV_PROP_U16:
			if (obj->integer.value > U16_MAX)
				return -EOVERFLOW;
			*(u16 *)val = obj->integer.value;
			break;
		case DEV_PROP_U32:
			if (obj->integer.value > U32_MAX)
				return -EOVERFLOW;
			*(u32 *)val = obj->integer.value;
			break;
		default:
			*(u64 *)val = obj->integer.value;
			break;
		}
	} else if (proptype == DEV_PROP_STRING) {
820
		ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
821 822 823 824
		if (ret)
			return ret;

		*(char **)val = obj->string.pointer;
825 826

		return 1;
827 828 829 830 831 832
	} else {
		ret = -EINVAL;
	}
	return ret;
}

833 834 835
int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
			      enum dev_prop_type proptype, void *val)
{
836 837 838 839 840 841 842 843 844
	int ret;

	if (!adev)
		return -EINVAL;

	ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val);
	if (ret < 0 || proptype != ACPI_TYPE_STRING)
		return ret;
	return 0;
845 846
}

847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 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
static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
				       size_t nval)
{
	int i;

	for (i = 0; i < nval; i++) {
		if (items[i].type != ACPI_TYPE_INTEGER)
			return -EPROTO;
		if (items[i].integer.value > U8_MAX)
			return -EOVERFLOW;

		val[i] = items[i].integer.value;
	}
	return 0;
}

static int acpi_copy_property_array_u16(const union acpi_object *items,
					u16 *val, size_t nval)
{
	int i;

	for (i = 0; i < nval; i++) {
		if (items[i].type != ACPI_TYPE_INTEGER)
			return -EPROTO;
		if (items[i].integer.value > U16_MAX)
			return -EOVERFLOW;

		val[i] = items[i].integer.value;
	}
	return 0;
}

static int acpi_copy_property_array_u32(const union acpi_object *items,
					u32 *val, size_t nval)
{
	int i;

	for (i = 0; i < nval; i++) {
		if (items[i].type != ACPI_TYPE_INTEGER)
			return -EPROTO;
		if (items[i].integer.value > U32_MAX)
			return -EOVERFLOW;

		val[i] = items[i].integer.value;
	}
	return 0;
}

static int acpi_copy_property_array_u64(const union acpi_object *items,
					u64 *val, size_t nval)
{
	int i;

	for (i = 0; i < nval; i++) {
		if (items[i].type != ACPI_TYPE_INTEGER)
			return -EPROTO;

		val[i] = items[i].integer.value;
	}
	return 0;
}

static int acpi_copy_property_array_string(const union acpi_object *items,
					   char **val, size_t nval)
{
	int i;

	for (i = 0; i < nval; i++) {
		if (items[i].type != ACPI_TYPE_STRING)
			return -EPROTO;

		val[i] = items[i].string.pointer;
	}
920
	return nval;
921 922
}

923
static int acpi_data_prop_read(const struct acpi_device_data *data,
924 925 926
			       const char *propname,
			       enum dev_prop_type proptype,
			       void *val, size_t nval)
927 928 929 930 931 932
{
	const union acpi_object *obj;
	const union acpi_object *items;
	int ret;

	if (val && nval == 1) {
933
		ret = acpi_data_prop_read_single(data, propname, proptype, val);
934
		if (ret >= 0)
935 936 937
			return ret;
	}

938
	ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
939 940 941 942 943 944
	if (ret)
		return ret;

	if (!val)
		return obj->package.count;

945
	if (proptype != DEV_PROP_STRING && nval > obj->package.count)
946
		return -EOVERFLOW;
947 948
	else if (nval <= 0)
		return -EINVAL;
949 950

	items = obj->package.elements;
951

952 953 954 955 956 957 958 959 960 961 962 963 964 965
	switch (proptype) {
	case DEV_PROP_U8:
		ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
		break;
	case DEV_PROP_U16:
		ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
		break;
	case DEV_PROP_U32:
		ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
		break;
	case DEV_PROP_U64:
		ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
		break;
	case DEV_PROP_STRING:
966 967 968
		ret = acpi_copy_property_array_string(
			items, (char **)val,
			min_t(u32, nval, obj->package.count));
969 970 971 972 973 974 975
		break;
	default:
		ret = -EINVAL;
		break;
	}
	return ret;
}
976

977
int acpi_dev_prop_read(const struct acpi_device *adev, const char *propname,
978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
		       enum dev_prop_type proptype, void *val, size_t nval)
{
	return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
}

/**
 * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
 * @fwnode: Firmware node to get the property from.
 * @propname: Name of the property.
 * @proptype: Expected property type.
 * @val: Location to store the property value (if not %NULL).
 * @nval: Size of the array pointed to by @val.
 *
 * If @val is %NULL, return the number of array elements comprising the value
 * of the property.  Otherwise, read at most @nval values to the array at the
 * location pointed to by @val.
 */
995 996 997
int acpi_node_prop_read(const struct fwnode_handle *fwnode,
			const char *propname, enum dev_prop_type proptype,
			void *val, size_t nval)
998 999 1000 1001
{
	return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
				   propname, proptype, val, nval);
}
1002 1003

/**
1004 1005
 * acpi_get_next_subnode - Return the next child node handle for a fwnode
 * @fwnode: Firmware node to find the next child node for.
1006 1007
 * @child: Handle to one of the device's child nodes or a null handle.
 */
1008
struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
1009 1010
					    struct fwnode_handle *child)
{
1011 1012 1013
	const struct acpi_device *adev = to_acpi_device_node(fwnode);
	const struct list_head *head;
	struct list_head *next;
1014

1015
	if (!child || is_acpi_device_node(child)) {
1016 1017
		struct acpi_device *child_adev;

1018 1019 1020 1021 1022
		if (adev)
			head = &adev->children;
		else
			goto nondev;

1023 1024 1025 1026
		if (list_empty(head))
			goto nondev;

		if (child) {
1027 1028
			adev = to_acpi_device_node(child);
			next = adev->node.next;
1029 1030 1031 1032
			if (next == head) {
				child = NULL;
				goto nondev;
			}
1033
			child_adev = list_entry(next, struct acpi_device, node);
1034
		} else {
1035 1036
			child_adev = list_first_entry(head, struct acpi_device,
						      node);
1037
		}
1038
		return acpi_fwnode_handle(child_adev);
1039 1040 1041
	}

 nondev:
1042
	if (!child || is_acpi_data_node(child)) {
1043
		const struct acpi_data_node *data = to_acpi_data_node(fwnode);
1044 1045
		struct acpi_data_node *dn;

1046 1047 1048 1049 1050 1051 1052 1053
		/*
		 * We can have a combination of device and data nodes, e.g. with
		 * hierarchical _DSD properties. Make sure the adev pointer is
		 * restored before going through data nodes, otherwise we will
		 * be looking for data_nodes below the last device found instead
		 * of the common fwnode shared by device_nodes and data_nodes.
		 */
		adev = to_acpi_device_node(fwnode);
1054 1055
		if (adev)
			head = &adev->data.subnodes;
1056 1057 1058 1059 1060
		else if (data)
			head = &data->data.subnodes;
		else
			return NULL;

1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
		if (list_empty(head))
			return NULL;

		if (child) {
			dn = to_acpi_data_node(child);
			next = dn->sibling.next;
			if (next == head)
				return NULL;

			dn = list_entry(next, struct acpi_data_node, sibling);
		} else {
			dn = list_first_entry(head, struct acpi_data_node, sibling);
		}
		return &dn->fwnode;
	}
	return NULL;
}
1078 1079 1080 1081 1082 1083 1084 1085

/**
 * acpi_node_get_parent - Return parent fwnode of this fwnode
 * @fwnode: Firmware node whose parent to get
 *
 * Returns parent node of an ACPI device or data firmware node or %NULL if
 * not available.
 */
1086
struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode)
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
{
	if (is_acpi_data_node(fwnode)) {
		/* All data nodes have parent pointer so just return that */
		return to_acpi_data_node(fwnode)->parent;
	} else if (is_acpi_device_node(fwnode)) {
		acpi_handle handle, parent_handle;

		handle = to_acpi_device_node(fwnode)->handle;
		if (ACPI_SUCCESS(acpi_get_parent(handle, &parent_handle))) {
			struct acpi_device *adev;

			if (!acpi_bus_get_device(parent_handle, &adev))
				return acpi_fwnode_handle(adev);
		}
	}

	return NULL;
}
1105

1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
/*
 * Return true if the node is an ACPI graph node. Called on either ports
 * or endpoints.
 */
static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
			       const char *str)
{
	unsigned int len = strlen(str);
	const char *name;

	if (!len || !is_acpi_data_node(fwnode))
		return false;

	name = to_acpi_data_node(fwnode)->name;

	return (fwnode_property_present(fwnode, "reg") &&
		!strncmp(name, str, len) && name[len] == '@') ||
		fwnode_property_present(fwnode, str);
}

1126 1127 1128 1129 1130 1131
/**
 * acpi_graph_get_next_endpoint - Get next endpoint ACPI firmware node
 * @fwnode: Pointer to the parent firmware node
 * @prev: Previous endpoint node or %NULL to get the first
 *
 * Looks up next endpoint ACPI firmware node below a given @fwnode. Returns
1132 1133
 * %NULL if there is no next endpoint or in case of error. In case of success
 * the next endpoint is returned.
1134
 */
1135
static struct fwnode_handle *acpi_graph_get_next_endpoint(
1136
	const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
1137 1138 1139 1140 1141 1142 1143
{
	struct fwnode_handle *port = NULL;
	struct fwnode_handle *endpoint;

	if (!prev) {
		do {
			port = fwnode_get_next_child_node(fwnode, port);
1144 1145 1146 1147 1148 1149 1150 1151
			/*
			 * The names of the port nodes begin with "port@"
			 * followed by the number of the port node and they also
			 * have a "reg" property that also has the number of the
			 * port node. For compatibility reasons a node is also
			 * recognised as a port node from the "port" property.
			 */
			if (is_acpi_graph_node(port, "port"))
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
				break;
		} while (port);
	} else {
		port = fwnode_get_parent(prev);
	}

	if (!port)
		return NULL;

	endpoint = fwnode_get_next_child_node(port, prev);
	while (!endpoint) {
		port = fwnode_get_next_child_node(fwnode, port);
		if (!port)
			break;
1166
		if (is_acpi_graph_node(port, "port"))
1167 1168 1169
			endpoint = fwnode_get_next_child_node(port, NULL);
	}

1170 1171 1172 1173 1174 1175 1176 1177
	/*
	 * The names of the endpoint nodes begin with "endpoint@" followed by
	 * the number of the endpoint node and they also have a "reg" property
	 * that also has the number of the endpoint node. For compatibility
	 * reasons a node is also recognised as an endpoint node from the
	 * "endpoint" property.
	 */
	if (!is_acpi_graph_node(endpoint, "endpoint"))
1178
		return NULL;
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192

	return endpoint;
}

/**
 * acpi_graph_get_child_prop_value - Return a child with a given property value
 * @fwnode: device fwnode
 * @prop_name: The name of the property to look for
 * @val: the desired property value
 *
 * Return the port node corresponding to a given port number. Returns
 * the child node on success, NULL otherwise.
 */
static struct fwnode_handle *acpi_graph_get_child_prop_value(
1193 1194
	const struct fwnode_handle *fwnode, const char *prop_name,
	unsigned int val)
1195 1196 1197 1198 1199 1200
{
	struct fwnode_handle *child;

	fwnode_for_each_child_node(fwnode, child) {
		u32 nr;

1201
		if (fwnode_property_read_u32(child, prop_name, &nr))
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
			continue;

		if (val == nr)
			return child;
	}

	return NULL;
}


/**
 * acpi_graph_get_remote_enpoint - Parses and returns remote end of an endpoint
 * @fwnode: Endpoint firmware node pointing to a remote device
 * @endpoint: Firmware node of remote endpoint is filled here if not %NULL
 *
1217
 * Returns the remote endpoint corresponding to @__fwnode. NULL on error.
1218
 */
1219 1220
static struct fwnode_handle *
acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
1221
{
1222
	struct fwnode_handle *fwnode;
1223
	unsigned int port_nr, endpoint_nr;
1224
	struct fwnode_reference_args args;
1225 1226 1227
	int ret;

	memset(&args, 0, sizeof(args));
1228
	ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
1229 1230
					       &args);
	if (ret)
1231
		return NULL;
1232

1233
	/* Direct endpoint reference? */
1234
	if (!is_acpi_device_node(args.fwnode))
1235
		return args.nargs ? NULL : args.fwnode;
1236

1237 1238 1239 1240 1241
	/*
	 * Always require two arguments with the reference: port and
	 * endpoint indices.
	 */
	if (args.nargs != 2)
1242
		return NULL;
1243

1244
	fwnode = args.fwnode;
1245 1246 1247 1248 1249
	port_nr = args.args[0];
	endpoint_nr = args.args[1];

	fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);

1250
	return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
1251
}
1252

1253
static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
1254 1255 1256 1257 1258 1259 1260
{
	if (!is_acpi_device_node(fwnode))
		return false;

	return acpi_device_is_present(to_acpi_device_node(fwnode));
}

1261
static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
1262 1263 1264 1265 1266
					 const char *propname)
{
	return !acpi_node_prop_get(fwnode, propname, NULL);
}

1267 1268 1269 1270 1271
static int
acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
				    const char *propname,
				    unsigned int elem_size, void *val,
				    size_t nval)
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
{
	enum dev_prop_type type;

	switch (elem_size) {
	case sizeof(u8):
		type = DEV_PROP_U8;
		break;
	case sizeof(u16):
		type = DEV_PROP_U16;
		break;
	case sizeof(u32):
		type = DEV_PROP_U32;
		break;
	case sizeof(u64):
		type = DEV_PROP_U64;
		break;
	default:
		return -ENXIO;
	}

	return acpi_node_prop_read(fwnode, propname, type, val, nval);
}

1295 1296 1297 1298
static int
acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
				       const char *propname, const char **val,
				       size_t nval)
1299 1300 1301 1302 1303
{
	return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
				   val, nval);
}

1304 1305 1306 1307 1308 1309
static int
acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
			       const char *prop, const char *nargs_prop,
			       unsigned int args_count, unsigned int index,
			       struct fwnode_reference_args *args)
{
1310 1311
	return __acpi_node_get_property_reference(fwnode, prop, index,
						  args_count, args);
1312 1313
}

1314 1315 1316 1317 1318 1319 1320
static struct fwnode_handle *
acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
{
	return acpi_node_get_parent(fwnode);
}

static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
1321 1322 1323 1324 1325 1326
					    struct fwnode_endpoint *endpoint)
{
	struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);

	endpoint->local_fwnode = fwnode;

1327 1328 1329 1330
	if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
		fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
	if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
		fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
1331 1332 1333 1334

	return 0;
}

1335
static const void *
1336 1337 1338
acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
				  const struct device *dev)
{
1339
	return acpi_device_get_match_data(dev);
1340 1341
}

1342 1343 1344
#define DECLARE_ACPI_FWNODE_OPS(ops) \
	const struct fwnode_operations ops = {				\
		.device_is_available = acpi_fwnode_device_is_available, \
1345
		.device_get_match_data = acpi_fwnode_device_get_match_data, \
1346 1347 1348 1349 1350 1351 1352 1353
		.property_present = acpi_fwnode_property_present,	\
		.property_read_int_array =				\
			acpi_fwnode_property_read_int_array,		\
		.property_read_string_array =				\
			acpi_fwnode_property_read_string_array,		\
		.get_parent = acpi_node_get_parent,			\
		.get_next_child_node = acpi_get_next_subnode,		\
		.get_named_child_node = acpi_fwnode_get_named_child_node, \
1354
		.get_reference_args = acpi_fwnode_get_reference_args,	\
1355
		.graph_get_next_endpoint =				\
1356
			acpi_graph_get_next_endpoint,			\
1357
		.graph_get_remote_endpoint =				\
1358
			acpi_graph_get_remote_endpoint,			\
1359
		.graph_get_port_parent = acpi_fwnode_get_parent,	\
1360 1361 1362 1363 1364 1365 1366
		.graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
	};								\
	EXPORT_SYMBOL_GPL(ops)

DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
const struct fwnode_operations acpi_static_fwnode_ops;
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379

bool is_acpi_device_node(const struct fwnode_handle *fwnode)
{
	return !IS_ERR_OR_NULL(fwnode) &&
		fwnode->ops == &acpi_device_fwnode_ops;
}
EXPORT_SYMBOL(is_acpi_device_node);

bool is_acpi_data_node(const struct fwnode_handle *fwnode)
{
	return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
}
EXPORT_SYMBOL(is_acpi_data_node);