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 */ 23static 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 28static 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 59static 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 79static 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 115void 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 168void 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 */ 194int 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} 227EXPORT_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 */ 248int 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} 270EXPORT_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 */ 289int 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} 373EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference); 374 375int 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 382int 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 428static 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 444static 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 460static 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 476static 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 490static 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 504int 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