xref: /openbmc/linux/drivers/acpi/property.c (revision 93df8a1e)
1 /*
2  * ACPI device specific properties support.
3  *
4  * Copyright (C) 2014, Intel Corporation
5  * All rights reserved.
6  *
7  * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
8  *          Darren Hart <dvhart@linux.intel.com>
9  *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15 
16 #include <linux/acpi.h>
17 #include <linux/device.h>
18 #include <linux/export.h>
19 
20 #include "internal.h"
21 
22 /* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
23 static const u8 prp_uuid[16] = {
24 	0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
25 	0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
26 };
27 
28 static bool acpi_property_value_ok(const union acpi_object *value)
29 {
30 	int j;
31 
32 	/*
33 	 * The value must be an integer, a string, a reference, or a package
34 	 * whose every element must be an integer, a string, or a reference.
35 	 */
36 	switch (value->type) {
37 	case ACPI_TYPE_INTEGER:
38 	case ACPI_TYPE_STRING:
39 	case ACPI_TYPE_LOCAL_REFERENCE:
40 		return true;
41 
42 	case ACPI_TYPE_PACKAGE:
43 		for (j = 0; j < value->package.count; j++)
44 			switch (value->package.elements[j].type) {
45 			case ACPI_TYPE_INTEGER:
46 			case ACPI_TYPE_STRING:
47 			case ACPI_TYPE_LOCAL_REFERENCE:
48 				continue;
49 
50 			default:
51 				return false;
52 			}
53 
54 		return true;
55 	}
56 	return false;
57 }
58 
59 static bool acpi_properties_format_valid(const union acpi_object *properties)
60 {
61 	int i;
62 
63 	for (i = 0; i < properties->package.count; i++) {
64 		const union acpi_object *property;
65 
66 		property = &properties->package.elements[i];
67 		/*
68 		 * Only two elements allowed, the first one must be a string and
69 		 * the second one has to satisfy certain conditions.
70 		 */
71 		if (property->package.count != 2
72 		    || property->package.elements[0].type != ACPI_TYPE_STRING
73 		    || !acpi_property_value_ok(&property->package.elements[1]))
74 			return false;
75 	}
76 	return true;
77 }
78 
79 static void acpi_init_of_compatible(struct acpi_device *adev)
80 {
81 	const union acpi_object *of_compatible;
82 	int ret;
83 
84 	ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
85 					  &of_compatible);
86 	if (ret) {
87 		ret = acpi_dev_get_property(adev, "compatible",
88 					    ACPI_TYPE_STRING, &of_compatible);
89 		if (ret) {
90 			if (adev->parent
91 			    && adev->parent->flags.of_compatible_ok)
92 				goto out;
93 
94 			return;
95 		}
96 	}
97 	adev->data.of_compatible = of_compatible;
98 
99  out:
100 	adev->flags.of_compatible_ok = 1;
101 }
102 
103 void acpi_init_properties(struct acpi_device *adev)
104 {
105 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
106 	bool acpi_of = false;
107 	struct acpi_hardware_id *hwid;
108 	const union acpi_object *desc;
109 	acpi_status status;
110 	int i;
111 
112 	/*
113 	 * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
114 	 * Device Tree compatible properties for this device.
115 	 */
116 	list_for_each_entry(hwid, &adev->pnp.ids, list) {
117 		if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
118 			acpi_of = true;
119 			break;
120 		}
121 	}
122 
123 	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
124 					    ACPI_TYPE_PACKAGE);
125 	if (ACPI_FAILURE(status))
126 		goto out;
127 
128 	desc = buf.pointer;
129 	if (desc->package.count % 2)
130 		goto fail;
131 
132 	/* Look for the device properties UUID. */
133 	for (i = 0; i < desc->package.count; i += 2) {
134 		const union acpi_object *uuid, *properties;
135 
136 		uuid = &desc->package.elements[i];
137 		properties = &desc->package.elements[i + 1];
138 
139 		/*
140 		 * The first element must be a UUID and the second one must be
141 		 * a package.
142 		 */
143 		if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
144 		    || properties->type != ACPI_TYPE_PACKAGE)
145 			break;
146 
147 		if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
148 			continue;
149 
150 		/*
151 		 * We found the matching UUID. Now validate the format of the
152 		 * package immediately following it.
153 		 */
154 		if (!acpi_properties_format_valid(properties))
155 			break;
156 
157 		adev->data.pointer = buf.pointer;
158 		adev->data.properties = properties;
159 
160 		if (acpi_of)
161 			acpi_init_of_compatible(adev);
162 
163 		goto out;
164 	}
165 
166  fail:
167 	dev_dbg(&adev->dev, "Returned _DSD data is not valid, skipping\n");
168 	ACPI_FREE(buf.pointer);
169 
170  out:
171 	if (acpi_of && !adev->flags.of_compatible_ok)
172 		acpi_handle_info(adev->handle,
173 			 ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
174 }
175 
176 void acpi_free_properties(struct acpi_device *adev)
177 {
178 	ACPI_FREE((void *)adev->data.pointer);
179 	adev->data.of_compatible = NULL;
180 	adev->data.pointer = NULL;
181 	adev->data.properties = NULL;
182 }
183 
184 /**
185  * acpi_dev_get_property - return an ACPI property with given name
186  * @adev: ACPI device to get property
187  * @name: Name of the property
188  * @type: Expected property type
189  * @obj: Location to store the property value (if not %NULL)
190  *
191  * Look up a property with @name and store a pointer to the resulting ACPI
192  * object at the location pointed to by @obj if found.
193  *
194  * Callers must not attempt to free the returned objects.  These objects will be
195  * freed by the ACPI core automatically during the removal of @adev.
196  *
197  * Return: %0 if property with @name has been found (success),
198  *         %-EINVAL if the arguments are invalid,
199  *         %-ENODATA if the property doesn't exist,
200  *         %-EPROTO if the property value type doesn't match @type.
201  */
202 int acpi_dev_get_property(struct acpi_device *adev, const char *name,
203 			  acpi_object_type type, const union acpi_object **obj)
204 {
205 	const union acpi_object *properties;
206 	int i;
207 
208 	if (!adev || !name)
209 		return -EINVAL;
210 
211 	if (!adev->data.pointer || !adev->data.properties)
212 		return -ENODATA;
213 
214 	properties = adev->data.properties;
215 	for (i = 0; i < properties->package.count; i++) {
216 		const union acpi_object *propname, *propvalue;
217 		const union acpi_object *property;
218 
219 		property = &properties->package.elements[i];
220 
221 		propname = &property->package.elements[0];
222 		propvalue = &property->package.elements[1];
223 
224 		if (!strcmp(name, propname->string.pointer)) {
225 			if (type != ACPI_TYPE_ANY && propvalue->type != type)
226 				return -EPROTO;
227 			else if (obj)
228 				*obj = propvalue;
229 
230 			return 0;
231 		}
232 	}
233 	return -ENODATA;
234 }
235 EXPORT_SYMBOL_GPL(acpi_dev_get_property);
236 
237 /**
238  * acpi_dev_get_property_array - return an ACPI array property with given name
239  * @adev: ACPI device to get property
240  * @name: Name of the property
241  * @type: Expected type of array elements
242  * @obj: Location to store a pointer to the property value (if not NULL)
243  *
244  * Look up an array property with @name and store a pointer to the resulting
245  * ACPI object at the location pointed to by @obj if found.
246  *
247  * Callers must not attempt to free the returned objects.  Those objects will be
248  * freed by the ACPI core automatically during the removal of @adev.
249  *
250  * Return: %0 if array property (package) with @name has been found (success),
251  *         %-EINVAL if the arguments are invalid,
252  *         %-ENODATA if the property doesn't exist,
253  *         %-EPROTO if the property is not a package or the type of its elements
254  *           doesn't match @type.
255  */
256 int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
257 				acpi_object_type type,
258 				const union acpi_object **obj)
259 {
260 	const union acpi_object *prop;
261 	int ret, i;
262 
263 	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop);
264 	if (ret)
265 		return ret;
266 
267 	if (type != ACPI_TYPE_ANY) {
268 		/* Check that all elements are of correct type. */
269 		for (i = 0; i < prop->package.count; i++)
270 			if (prop->package.elements[i].type != type)
271 				return -EPROTO;
272 	}
273 	if (obj)
274 		*obj = prop;
275 
276 	return 0;
277 }
278 EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
279 
280 /**
281  * acpi_dev_get_property_reference - returns handle to the referenced object
282  * @adev: ACPI device to get property
283  * @name: Name of the property
284  * @index: Index of the reference to return
285  * @args: Location to store the returned reference with optional arguments
286  *
287  * Find property with @name, verifify that it is a package containing at least
288  * one object reference and if so, store the ACPI device object pointer to the
289  * target object in @args->adev.  If the reference includes arguments, store
290  * them in the @args->args[] array.
291  *
292  * If there's more than one reference in the property value package, @index is
293  * used to select the one to return.
294  *
295  * Return: %0 on success, negative error code on failure.
296  */
297 int acpi_dev_get_property_reference(struct acpi_device *adev,
298 				    const char *name, size_t index,
299 				    struct acpi_reference_args *args)
300 {
301 	const union acpi_object *element, *end;
302 	const union acpi_object *obj;
303 	struct acpi_device *device;
304 	int ret, idx = 0;
305 
306 	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj);
307 	if (ret)
308 		return ret;
309 
310 	/*
311 	 * The simplest case is when the value is a single reference.  Just
312 	 * return that reference then.
313 	 */
314 	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
315 		if (index)
316 			return -EINVAL;
317 
318 		ret = acpi_bus_get_device(obj->reference.handle, &device);
319 		if (ret)
320 			return ret;
321 
322 		args->adev = device;
323 		args->nargs = 0;
324 		return 0;
325 	}
326 
327 	/*
328 	 * If it is not a single reference, then it is a package of
329 	 * references followed by number of ints as follows:
330 	 *
331 	 *  Package () { REF, INT, REF, INT, INT }
332 	 *
333 	 * The index argument is then used to determine which reference
334 	 * the caller wants (along with the arguments).
335 	 */
336 	if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
337 		return -EPROTO;
338 
339 	element = obj->package.elements;
340 	end = element + obj->package.count;
341 
342 	while (element < end) {
343 		u32 nargs, i;
344 
345 		if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
346 			return -EPROTO;
347 
348 		ret = acpi_bus_get_device(element->reference.handle, &device);
349 		if (ret)
350 			return -ENODEV;
351 
352 		element++;
353 		nargs = 0;
354 
355 		/* assume following integer elements are all args */
356 		for (i = 0; element + i < end; i++) {
357 			int type = element[i].type;
358 
359 			if (type == ACPI_TYPE_INTEGER)
360 				nargs++;
361 			else if (type == ACPI_TYPE_LOCAL_REFERENCE)
362 				break;
363 			else
364 				return -EPROTO;
365 		}
366 
367 		if (idx++ == index) {
368 			args->adev = device;
369 			args->nargs = nargs;
370 			for (i = 0; i < nargs; i++)
371 				args->args[i] = element[i].integer.value;
372 
373 			return 0;
374 		}
375 
376 		element += nargs;
377 	}
378 
379 	return -EPROTO;
380 }
381 EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
382 
383 int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
384 		      void **valptr)
385 {
386 	return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
387 				     (const union acpi_object **)valptr);
388 }
389 
390 int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
391 			      enum dev_prop_type proptype, void *val)
392 {
393 	const union acpi_object *obj;
394 	int ret;
395 
396 	if (!val)
397 		return -EINVAL;
398 
399 	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
400 		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
401 		if (ret)
402 			return ret;
403 
404 		switch (proptype) {
405 		case DEV_PROP_U8:
406 			if (obj->integer.value > U8_MAX)
407 				return -EOVERFLOW;
408 			*(u8 *)val = obj->integer.value;
409 			break;
410 		case DEV_PROP_U16:
411 			if (obj->integer.value > U16_MAX)
412 				return -EOVERFLOW;
413 			*(u16 *)val = obj->integer.value;
414 			break;
415 		case DEV_PROP_U32:
416 			if (obj->integer.value > U32_MAX)
417 				return -EOVERFLOW;
418 			*(u32 *)val = obj->integer.value;
419 			break;
420 		default:
421 			*(u64 *)val = obj->integer.value;
422 			break;
423 		}
424 	} else if (proptype == DEV_PROP_STRING) {
425 		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
426 		if (ret)
427 			return ret;
428 
429 		*(char **)val = obj->string.pointer;
430 	} else {
431 		ret = -EINVAL;
432 	}
433 	return ret;
434 }
435 
436 static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
437 				       size_t nval)
438 {
439 	int i;
440 
441 	for (i = 0; i < nval; i++) {
442 		if (items[i].type != ACPI_TYPE_INTEGER)
443 			return -EPROTO;
444 		if (items[i].integer.value > U8_MAX)
445 			return -EOVERFLOW;
446 
447 		val[i] = items[i].integer.value;
448 	}
449 	return 0;
450 }
451 
452 static int acpi_copy_property_array_u16(const union acpi_object *items,
453 					u16 *val, size_t nval)
454 {
455 	int i;
456 
457 	for (i = 0; i < nval; i++) {
458 		if (items[i].type != ACPI_TYPE_INTEGER)
459 			return -EPROTO;
460 		if (items[i].integer.value > U16_MAX)
461 			return -EOVERFLOW;
462 
463 		val[i] = items[i].integer.value;
464 	}
465 	return 0;
466 }
467 
468 static int acpi_copy_property_array_u32(const union acpi_object *items,
469 					u32 *val, size_t nval)
470 {
471 	int i;
472 
473 	for (i = 0; i < nval; i++) {
474 		if (items[i].type != ACPI_TYPE_INTEGER)
475 			return -EPROTO;
476 		if (items[i].integer.value > U32_MAX)
477 			return -EOVERFLOW;
478 
479 		val[i] = items[i].integer.value;
480 	}
481 	return 0;
482 }
483 
484 static int acpi_copy_property_array_u64(const union acpi_object *items,
485 					u64 *val, size_t nval)
486 {
487 	int i;
488 
489 	for (i = 0; i < nval; i++) {
490 		if (items[i].type != ACPI_TYPE_INTEGER)
491 			return -EPROTO;
492 
493 		val[i] = items[i].integer.value;
494 	}
495 	return 0;
496 }
497 
498 static int acpi_copy_property_array_string(const union acpi_object *items,
499 					   char **val, size_t nval)
500 {
501 	int i;
502 
503 	for (i = 0; i < nval; i++) {
504 		if (items[i].type != ACPI_TYPE_STRING)
505 			return -EPROTO;
506 
507 		val[i] = items[i].string.pointer;
508 	}
509 	return 0;
510 }
511 
512 int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
513 		       enum dev_prop_type proptype, void *val, size_t nval)
514 {
515 	const union acpi_object *obj;
516 	const union acpi_object *items;
517 	int ret;
518 
519 	if (val && nval == 1) {
520 		ret = acpi_dev_prop_read_single(adev, propname, proptype, val);
521 		if (!ret)
522 			return ret;
523 	}
524 
525 	ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
526 	if (ret)
527 		return ret;
528 
529 	if (!val)
530 		return obj->package.count;
531 	else if (nval <= 0)
532 		return -EINVAL;
533 
534 	if (nval > obj->package.count)
535 		return -EOVERFLOW;
536 
537 	items = obj->package.elements;
538 	switch (proptype) {
539 	case DEV_PROP_U8:
540 		ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
541 		break;
542 	case DEV_PROP_U16:
543 		ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
544 		break;
545 	case DEV_PROP_U32:
546 		ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
547 		break;
548 	case DEV_PROP_U64:
549 		ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
550 		break;
551 	case DEV_PROP_STRING:
552 		ret = acpi_copy_property_array_string(items, (char **)val, nval);
553 		break;
554 	default:
555 		ret = -EINVAL;
556 		break;
557 	}
558 	return ret;
559 }
560