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