property.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  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. #include <linux/acpi.h>
  16. #include <linux/device.h>
  17. #include <linux/export.h>
  18. #include "internal.h"
  19. /* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
  20. static const u8 prp_uuid[16] = {
  21. 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
  22. 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
  23. };
  24. static bool acpi_property_value_ok(const union acpi_object *value)
  25. {
  26. int j;
  27. /*
  28. * The value must be an integer, a string, a reference, or a package
  29. * whose every element must be an integer, a string, or a reference.
  30. */
  31. switch (value->type) {
  32. case ACPI_TYPE_INTEGER:
  33. case ACPI_TYPE_STRING:
  34. case ACPI_TYPE_LOCAL_REFERENCE:
  35. return true;
  36. case ACPI_TYPE_PACKAGE:
  37. for (j = 0; j < value->package.count; j++)
  38. switch (value->package.elements[j].type) {
  39. case ACPI_TYPE_INTEGER:
  40. case ACPI_TYPE_STRING:
  41. case ACPI_TYPE_LOCAL_REFERENCE:
  42. continue;
  43. default:
  44. return false;
  45. }
  46. return true;
  47. }
  48. return false;
  49. }
  50. static bool acpi_properties_format_valid(const union acpi_object *properties)
  51. {
  52. int i;
  53. for (i = 0; i < properties->package.count; i++) {
  54. const union acpi_object *property;
  55. property = &properties->package.elements[i];
  56. /*
  57. * Only two elements allowed, the first one must be a string and
  58. * the second one has to satisfy certain conditions.
  59. */
  60. if (property->package.count != 2
  61. || property->package.elements[0].type != ACPI_TYPE_STRING
  62. || !acpi_property_value_ok(&property->package.elements[1]))
  63. return false;
  64. }
  65. return true;
  66. }
  67. void acpi_init_properties(struct acpi_device *adev)
  68. {
  69. struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
  70. const union acpi_object *desc;
  71. acpi_status status;
  72. int i;
  73. status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
  74. ACPI_TYPE_PACKAGE);
  75. if (ACPI_FAILURE(status))
  76. return;
  77. desc = buf.pointer;
  78. if (desc->package.count % 2)
  79. goto fail;
  80. /* Look for the device properties UUID. */
  81. for (i = 0; i < desc->package.count; i += 2) {
  82. const union acpi_object *uuid, *properties;
  83. uuid = &desc->package.elements[i];
  84. properties = &desc->package.elements[i + 1];
  85. /*
  86. * The first element must be a UUID and the second one must be
  87. * a package.
  88. */
  89. if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
  90. || properties->type != ACPI_TYPE_PACKAGE)
  91. break;
  92. if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
  93. continue;
  94. /*
  95. * We found the matching UUID. Now validate the format of the
  96. * package immediately following it.
  97. */
  98. if (!acpi_properties_format_valid(properties))
  99. break;
  100. adev->data.pointer = buf.pointer;
  101. adev->data.properties = properties;
  102. return;
  103. }
  104. fail:
  105. dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n");
  106. ACPI_FREE(buf.pointer);
  107. }
  108. void acpi_free_properties(struct acpi_device *adev)
  109. {
  110. ACPI_FREE((void *)adev->data.pointer);
  111. adev->data.pointer = NULL;
  112. adev->data.properties = NULL;
  113. }
  114. /**
  115. * acpi_dev_get_property - return an ACPI property with given name
  116. * @adev: ACPI device to get property
  117. * @name: Name of the property
  118. * @type: Expected property type
  119. * @obj: Location to store the property value (if not %NULL)
  120. *
  121. * Look up a property with @name and store a pointer to the resulting ACPI
  122. * object at the location pointed to by @obj if found.
  123. *
  124. * Callers must not attempt to free the returned objects. These objects will be
  125. * freed by the ACPI core automatically during the removal of @adev.
  126. *
  127. * Return: %0 if property with @name has been found (success),
  128. * %-EINVAL if the arguments are invalid,
  129. * %-ENODATA if the property doesn't exist,
  130. * %-EPROTO if the property value type doesn't match @type.
  131. */
  132. int acpi_dev_get_property(struct acpi_device *adev, const char *name,
  133. acpi_object_type type, const union acpi_object **obj)
  134. {
  135. const union acpi_object *properties;
  136. int i;
  137. if (!adev || !name)
  138. return -EINVAL;
  139. if (!adev->data.pointer || !adev->data.properties)
  140. return -ENODATA;
  141. properties = adev->data.properties;
  142. for (i = 0; i < properties->package.count; i++) {
  143. const union acpi_object *propname, *propvalue;
  144. const union acpi_object *property;
  145. property = &properties->package.elements[i];
  146. propname = &property->package.elements[0];
  147. propvalue = &property->package.elements[1];
  148. if (!strcmp(name, propname->string.pointer)) {
  149. if (type != ACPI_TYPE_ANY && propvalue->type != type)
  150. return -EPROTO;
  151. else if (obj)
  152. *obj = propvalue;
  153. return 0;
  154. }
  155. }
  156. return -ENODATA;
  157. }
  158. EXPORT_SYMBOL_GPL(acpi_dev_get_property);
  159. /**
  160. * acpi_dev_get_property_array - return an ACPI array property with given name
  161. * @adev: ACPI device to get property
  162. * @name: Name of the property
  163. * @type: Expected type of array elements
  164. * @obj: Location to store a pointer to the property value (if not NULL)
  165. *
  166. * Look up an array property with @name and store a pointer to the resulting
  167. * ACPI object at the location pointed to by @obj if found.
  168. *
  169. * Callers must not attempt to free the returned objects. Those objects will be
  170. * freed by the ACPI core automatically during the removal of @adev.
  171. *
  172. * Return: %0 if array property (package) with @name has been found (success),
  173. * %-EINVAL if the arguments are invalid,
  174. * %-ENODATA if the property doesn't exist,
  175. * %-EPROTO if the property is not a package or the type of its elements
  176. * doesn't match @type.
  177. */
  178. int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
  179. acpi_object_type type,
  180. const union acpi_object **obj)
  181. {
  182. const union acpi_object *prop;
  183. int ret, i;
  184. ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop);
  185. if (ret)
  186. return ret;
  187. if (type != ACPI_TYPE_ANY) {
  188. /* Check that all elements are of correct type. */
  189. for (i = 0; i < prop->package.count; i++)
  190. if (prop->package.elements[i].type != type)
  191. return -EPROTO;
  192. }
  193. if (obj)
  194. *obj = prop;
  195. return 0;
  196. }
  197. EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
  198. /**
  199. * acpi_dev_get_property_reference - returns handle to the referenced object
  200. * @adev: ACPI device to get property
  201. * @name: Name of the property
  202. * @size_prop: Name of the "size" property in referenced object
  203. * @index: Index of the reference to return
  204. * @args: Location to store the returned reference with optional arguments
  205. *
  206. * Find property with @name, verifify that it is a package containing at least
  207. * one object reference and if so, store the ACPI device object pointer to the
  208. * target object in @args->adev.
  209. *
  210. * If the reference includes arguments (@size_prop is not %NULL) follow the
  211. * reference and check whether or not there is an integer property @size_prop
  212. * under the target object and if so, whether or not its value matches the
  213. * number of arguments that follow the reference. If there's more than one
  214. * reference in the property value package, @index is used to select the one to
  215. * return.
  216. *
  217. * Return: %0 on success, negative error code on failure.
  218. */
  219. int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
  220. const char *size_prop, size_t index,
  221. struct acpi_reference_args *args)
  222. {
  223. const union acpi_object *element, *end;
  224. const union acpi_object *obj;
  225. struct acpi_device *device;
  226. int ret, idx = 0;
  227. ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj);
  228. if (ret)
  229. return ret;
  230. /*
  231. * The simplest case is when the value is a single reference. Just
  232. * return that reference then.
  233. */
  234. if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
  235. if (size_prop || index)
  236. return -EINVAL;
  237. ret = acpi_bus_get_device(obj->reference.handle, &device);
  238. if (ret)
  239. return ret;
  240. args->adev = device;
  241. args->nargs = 0;
  242. return 0;
  243. }
  244. /*
  245. * If it is not a single reference, then it is a package of
  246. * references followed by number of ints as follows:
  247. *
  248. * Package () { REF, INT, REF, INT, INT }
  249. *
  250. * The index argument is then used to determine which reference
  251. * the caller wants (along with the arguments).
  252. */
  253. if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
  254. return -EPROTO;
  255. element = obj->package.elements;
  256. end = element + obj->package.count;
  257. while (element < end) {
  258. u32 nargs, i;
  259. if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
  260. return -EPROTO;
  261. ret = acpi_bus_get_device(element->reference.handle, &device);
  262. if (ret)
  263. return -ENODEV;
  264. element++;
  265. nargs = 0;
  266. if (size_prop) {
  267. const union acpi_object *prop;
  268. /*
  269. * Find out how many arguments the refenced object
  270. * expects by reading its size_prop property.
  271. */
  272. ret = acpi_dev_get_property(device, size_prop,
  273. ACPI_TYPE_INTEGER, &prop);
  274. if (ret)
  275. return ret;
  276. nargs = prop->integer.value;
  277. if (nargs > MAX_ACPI_REFERENCE_ARGS
  278. || element + nargs > end)
  279. return -EPROTO;
  280. /*
  281. * Skip to the start of the arguments and verify
  282. * that they all are in fact integers.
  283. */
  284. for (i = 0; i < nargs; i++)
  285. if (element[i].type != ACPI_TYPE_INTEGER)
  286. return -EPROTO;
  287. } else {
  288. /* assume following integer elements are all args */
  289. for (i = 0; element + i < end; i++) {
  290. int type = element[i].type;
  291. if (type == ACPI_TYPE_INTEGER)
  292. nargs++;
  293. else if (type == ACPI_TYPE_LOCAL_REFERENCE)
  294. break;
  295. else
  296. return -EPROTO;
  297. }
  298. }
  299. if (idx++ == index) {
  300. args->adev = device;
  301. args->nargs = nargs;
  302. for (i = 0; i < nargs; i++)
  303. args->args[i] = element[i].integer.value;
  304. return 0;
  305. }
  306. element += nargs;
  307. }
  308. return -EPROTO;
  309. }
  310. EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
  311. int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
  312. void **valptr)
  313. {
  314. return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
  315. (const union acpi_object **)valptr);
  316. }
  317. int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
  318. enum dev_prop_type proptype, void *val)
  319. {
  320. const union acpi_object *obj;
  321. int ret;
  322. if (!val)
  323. return -EINVAL;
  324. if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
  325. ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
  326. if (ret)
  327. return ret;
  328. switch (proptype) {
  329. case DEV_PROP_U8:
  330. if (obj->integer.value > U8_MAX)
  331. return -EOVERFLOW;
  332. *(u8 *)val = obj->integer.value;
  333. break;
  334. case DEV_PROP_U16:
  335. if (obj->integer.value > U16_MAX)
  336. return -EOVERFLOW;
  337. *(u16 *)val = obj->integer.value;
  338. break;
  339. case DEV_PROP_U32:
  340. if (obj->integer.value > U32_MAX)
  341. return -EOVERFLOW;
  342. *(u32 *)val = obj->integer.value;
  343. break;
  344. default:
  345. *(u64 *)val = obj->integer.value;
  346. break;
  347. }
  348. } else if (proptype == DEV_PROP_STRING) {
  349. ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
  350. if (ret)
  351. return ret;
  352. *(char **)val = obj->string.pointer;
  353. } else {
  354. ret = -EINVAL;
  355. }
  356. return ret;
  357. }
  358. static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
  359. size_t nval)
  360. {
  361. int i;
  362. for (i = 0; i < nval; i++) {
  363. if (items[i].type != ACPI_TYPE_INTEGER)
  364. return -EPROTO;
  365. if (items[i].integer.value > U8_MAX)
  366. return -EOVERFLOW;
  367. val[i] = items[i].integer.value;
  368. }
  369. return 0;
  370. }
  371. static int acpi_copy_property_array_u16(const union acpi_object *items,
  372. u16 *val, size_t nval)
  373. {
  374. int i;
  375. for (i = 0; i < nval; i++) {
  376. if (items[i].type != ACPI_TYPE_INTEGER)
  377. return -EPROTO;
  378. if (items[i].integer.value > U16_MAX)
  379. return -EOVERFLOW;
  380. val[i] = items[i].integer.value;
  381. }
  382. return 0;
  383. }
  384. static int acpi_copy_property_array_u32(const union acpi_object *items,
  385. u32 *val, size_t nval)
  386. {
  387. int i;
  388. for (i = 0; i < nval; i++) {
  389. if (items[i].type != ACPI_TYPE_INTEGER)
  390. return -EPROTO;
  391. if (items[i].integer.value > U32_MAX)
  392. return -EOVERFLOW;
  393. val[i] = items[i].integer.value;
  394. }
  395. return 0;
  396. }
  397. static int acpi_copy_property_array_u64(const union acpi_object *items,
  398. u64 *val, size_t nval)
  399. {
  400. int i;
  401. for (i = 0; i < nval; i++) {
  402. if (items[i].type != ACPI_TYPE_INTEGER)
  403. return -EPROTO;
  404. val[i] = items[i].integer.value;
  405. }
  406. return 0;
  407. }
  408. static int acpi_copy_property_array_string(const union acpi_object *items,
  409. char **val, size_t nval)
  410. {
  411. int i;
  412. for (i = 0; i < nval; i++) {
  413. if (items[i].type != ACPI_TYPE_STRING)
  414. return -EPROTO;
  415. val[i] = items[i].string.pointer;
  416. }
  417. return 0;
  418. }
  419. int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
  420. enum dev_prop_type proptype, void *val, size_t nval)
  421. {
  422. const union acpi_object *obj;
  423. const union acpi_object *items;
  424. int ret;
  425. if (val && nval == 1) {
  426. ret = acpi_dev_prop_read_single(adev, propname, proptype, val);
  427. if (!ret)
  428. return ret;
  429. }
  430. ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
  431. if (ret)
  432. return ret;
  433. if (!val)
  434. return obj->package.count;
  435. else if (nval <= 0)
  436. return -EINVAL;
  437. if (nval > obj->package.count)
  438. return -EOVERFLOW;
  439. items = obj->package.elements;
  440. switch (proptype) {
  441. case DEV_PROP_U8:
  442. ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
  443. break;
  444. case DEV_PROP_U16:
  445. ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
  446. break;
  447. case DEV_PROP_U32:
  448. ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
  449. break;
  450. case DEV_PROP_U64:
  451. ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
  452. break;
  453. case DEV_PROP_STRING:
  454. ret = acpi_copy_property_array_string(items, (char **)val, nval);
  455. break;
  456. default:
  457. ret = -EINVAL;
  458. break;
  459. }
  460. return ret;
  461. }