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