utils.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * acpi_utils.c - ACPI Utility Functions ($Revision: 10 $)
  3. *
  4. * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
  5. * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  6. *
  7. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or (at
  12. * your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program; if not, write to the Free Software Foundation, Inc.,
  21. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  22. *
  23. * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  24. */
  25. #include <linux/kernel.h>
  26. #include <linux/module.h>
  27. #include <linux/init.h>
  28. #include <linux/types.h>
  29. #include <acpi/acpi_bus.h>
  30. #include <acpi/acpi_drivers.h>
  31. #define _COMPONENT ACPI_BUS_COMPONENT
  32. ACPI_MODULE_NAME("acpi_utils")
  33. /* --------------------------------------------------------------------------
  34. Object Evaluation Helpers
  35. -------------------------------------------------------------------------- */
  36. #ifdef ACPI_DEBUG_OUTPUT
  37. #define acpi_util_eval_error(h,p,s) {\
  38. char prefix[80] = {'\0'};\
  39. struct acpi_buffer buffer = {sizeof(prefix), prefix};\
  40. acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\
  41. ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluate [%s.%s]: %s\n",\
  42. (char *) prefix, p, acpi_format_exception(s))); }
  43. #else
  44. #define acpi_util_eval_error(h,p,s)
  45. #endif
  46. acpi_status
  47. acpi_extract_package(union acpi_object *package,
  48. struct acpi_buffer *format, struct acpi_buffer *buffer)
  49. {
  50. u32 size_required = 0;
  51. u32 tail_offset = 0;
  52. char *format_string = NULL;
  53. u32 format_count = 0;
  54. u32 i = 0;
  55. u8 *head = NULL;
  56. u8 *tail = NULL;
  57. ACPI_FUNCTION_TRACE("acpi_extract_package");
  58. if (!package || (package->type != ACPI_TYPE_PACKAGE)
  59. || (package->package.count < 1)) {
  60. ACPI_WARNING((AE_INFO, "Invalid package argument"));
  61. return_ACPI_STATUS(AE_BAD_PARAMETER);
  62. }
  63. if (!format || !format->pointer || (format->length < 1)) {
  64. ACPI_WARNING((AE_INFO, "Invalid format argument"));
  65. return_ACPI_STATUS(AE_BAD_PARAMETER);
  66. }
  67. if (!buffer) {
  68. ACPI_WARNING((AE_INFO, "Invalid buffer argument"));
  69. return_ACPI_STATUS(AE_BAD_PARAMETER);
  70. }
  71. format_count = (format->length / sizeof(char)) - 1;
  72. if (format_count > package->package.count) {
  73. ACPI_WARNING((AE_INFO, "Format specifies more objects [%d]"
  74. " than exist in package [%d].",
  75. format_count, package->package.count));
  76. return_ACPI_STATUS(AE_BAD_DATA);
  77. }
  78. format_string = (char *)format->pointer;
  79. /*
  80. * Calculate size_required.
  81. */
  82. for (i = 0; i < format_count; i++) {
  83. union acpi_object *element = &(package->package.elements[i]);
  84. if (!element) {
  85. return_ACPI_STATUS(AE_BAD_DATA);
  86. }
  87. switch (element->type) {
  88. case ACPI_TYPE_INTEGER:
  89. switch (format_string[i]) {
  90. case 'N':
  91. size_required += sizeof(acpi_integer);
  92. tail_offset += sizeof(acpi_integer);
  93. break;
  94. case 'S':
  95. size_required +=
  96. sizeof(char *) + sizeof(acpi_integer) +
  97. sizeof(char);
  98. tail_offset += sizeof(char *);
  99. break;
  100. default:
  101. ACPI_WARNING((AE_INFO, "Invalid package element"
  102. " [%d]: got number, expecing"
  103. " [%c]",
  104. i, format_string[i]));
  105. return_ACPI_STATUS(AE_BAD_DATA);
  106. break;
  107. }
  108. break;
  109. case ACPI_TYPE_STRING:
  110. case ACPI_TYPE_BUFFER:
  111. switch (format_string[i]) {
  112. case 'S':
  113. size_required +=
  114. sizeof(char *) +
  115. (element->string.length * sizeof(char)) +
  116. sizeof(char);
  117. tail_offset += sizeof(char *);
  118. break;
  119. case 'B':
  120. size_required +=
  121. sizeof(u8 *) +
  122. (element->buffer.length * sizeof(u8));
  123. tail_offset += sizeof(u8 *);
  124. break;
  125. default:
  126. ACPI_WARNING((AE_INFO, "Invalid package element"
  127. " [%d] got string/buffer,"
  128. " expecing [%c]",
  129. i, format_string[i]));
  130. return_ACPI_STATUS(AE_BAD_DATA);
  131. break;
  132. }
  133. break;
  134. case ACPI_TYPE_PACKAGE:
  135. default:
  136. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  137. "Found unsupported element at index=%d\n",
  138. i));
  139. /* TBD: handle nested packages... */
  140. return_ACPI_STATUS(AE_SUPPORT);
  141. break;
  142. }
  143. }
  144. /*
  145. * Validate output buffer.
  146. */
  147. if (buffer->length < size_required) {
  148. buffer->length = size_required;
  149. return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
  150. } else if (buffer->length != size_required || !buffer->pointer) {
  151. return_ACPI_STATUS(AE_BAD_PARAMETER);
  152. }
  153. head = buffer->pointer;
  154. tail = buffer->pointer + tail_offset;
  155. /*
  156. * Extract package data.
  157. */
  158. for (i = 0; i < format_count; i++) {
  159. u8 **pointer = NULL;
  160. union acpi_object *element = &(package->package.elements[i]);
  161. if (!element) {
  162. return_ACPI_STATUS(AE_BAD_DATA);
  163. }
  164. switch (element->type) {
  165. case ACPI_TYPE_INTEGER:
  166. switch (format_string[i]) {
  167. case 'N':
  168. *((acpi_integer *) head) =
  169. element->integer.value;
  170. head += sizeof(acpi_integer);
  171. break;
  172. case 'S':
  173. pointer = (u8 **) head;
  174. *pointer = tail;
  175. *((acpi_integer *) tail) =
  176. element->integer.value;
  177. head += sizeof(acpi_integer *);
  178. tail += sizeof(acpi_integer);
  179. /* NULL terminate string */
  180. *tail = (char)0;
  181. tail += sizeof(char);
  182. break;
  183. default:
  184. /* Should never get here */
  185. break;
  186. }
  187. break;
  188. case ACPI_TYPE_STRING:
  189. case ACPI_TYPE_BUFFER:
  190. switch (format_string[i]) {
  191. case 'S':
  192. pointer = (u8 **) head;
  193. *pointer = tail;
  194. memcpy(tail, element->string.pointer,
  195. element->string.length);
  196. head += sizeof(char *);
  197. tail += element->string.length * sizeof(char);
  198. /* NULL terminate string */
  199. *tail = (char)0;
  200. tail += sizeof(char);
  201. break;
  202. case 'B':
  203. pointer = (u8 **) head;
  204. *pointer = tail;
  205. memcpy(tail, element->buffer.pointer,
  206. element->buffer.length);
  207. head += sizeof(u8 *);
  208. tail += element->buffer.length * sizeof(u8);
  209. break;
  210. default:
  211. /* Should never get here */
  212. break;
  213. }
  214. break;
  215. case ACPI_TYPE_PACKAGE:
  216. /* TBD: handle nested packages... */
  217. default:
  218. /* Should never get here */
  219. break;
  220. }
  221. }
  222. return_ACPI_STATUS(AE_OK);
  223. }
  224. EXPORT_SYMBOL(acpi_extract_package);
  225. acpi_status
  226. acpi_evaluate_integer(acpi_handle handle,
  227. acpi_string pathname,
  228. struct acpi_object_list *arguments, unsigned long *data)
  229. {
  230. acpi_status status = AE_OK;
  231. union acpi_object *element;
  232. struct acpi_buffer buffer = { 0, NULL };
  233. ACPI_FUNCTION_TRACE("acpi_evaluate_integer");
  234. if (!data)
  235. return_ACPI_STATUS(AE_BAD_PARAMETER);
  236. element = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
  237. if (!element)
  238. return_ACPI_STATUS(AE_NO_MEMORY);
  239. memset(element, 0, sizeof(union acpi_object));
  240. buffer.length = sizeof(union acpi_object);
  241. buffer.pointer = element;
  242. status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
  243. if (ACPI_FAILURE(status)) {
  244. acpi_util_eval_error(handle, pathname, status);
  245. kfree(element);
  246. return_ACPI_STATUS(status);
  247. }
  248. if (element->type != ACPI_TYPE_INTEGER) {
  249. acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
  250. kfree(element);
  251. return_ACPI_STATUS(AE_BAD_DATA);
  252. }
  253. *data = element->integer.value;
  254. kfree(element);
  255. ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%lu]\n", *data));
  256. return_ACPI_STATUS(AE_OK);
  257. }
  258. EXPORT_SYMBOL(acpi_evaluate_integer);
  259. #if 0
  260. acpi_status
  261. acpi_evaluate_string(acpi_handle handle,
  262. acpi_string pathname,
  263. acpi_object_list * arguments, acpi_string * data)
  264. {
  265. acpi_status status = AE_OK;
  266. acpi_object *element = NULL;
  267. acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  268. ACPI_FUNCTION_TRACE("acpi_evaluate_string");
  269. if (!data)
  270. return_ACPI_STATUS(AE_BAD_PARAMETER);
  271. status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
  272. if (ACPI_FAILURE(status)) {
  273. acpi_util_eval_error(handle, pathname, status);
  274. return_ACPI_STATUS(status);
  275. }
  276. element = (acpi_object *) buffer.pointer;
  277. if ((element->type != ACPI_TYPE_STRING)
  278. || (element->type != ACPI_TYPE_BUFFER)
  279. || !element->string.length) {
  280. acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
  281. return_ACPI_STATUS(AE_BAD_DATA);
  282. }
  283. *data = kmalloc(element->string.length + 1, GFP_KERNEL);
  284. if (!data) {
  285. ACPI_ERROR((AE_INFO, "Memory allocation"));
  286. return_VALUE(-ENOMEM);
  287. }
  288. memset(*data, 0, element->string.length + 1);
  289. memcpy(*data, element->string.pointer, element->string.length);
  290. ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Return value [%s]\n", *data));
  291. acpi_os_free(buffer.pointer);
  292. return_ACPI_STATUS(AE_OK);
  293. }
  294. #endif
  295. acpi_status
  296. acpi_evaluate_reference(acpi_handle handle,
  297. acpi_string pathname,
  298. struct acpi_object_list *arguments,
  299. struct acpi_handle_list *list)
  300. {
  301. acpi_status status = AE_OK;
  302. union acpi_object *package = NULL;
  303. union acpi_object *element = NULL;
  304. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  305. u32 i = 0;
  306. ACPI_FUNCTION_TRACE("acpi_evaluate_reference");
  307. if (!list) {
  308. return_ACPI_STATUS(AE_BAD_PARAMETER);
  309. }
  310. /* Evaluate object. */
  311. status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
  312. if (ACPI_FAILURE(status))
  313. goto end;
  314. package = (union acpi_object *)buffer.pointer;
  315. if ((buffer.length == 0) || !package) {
  316. ACPI_ERROR((AE_INFO, "No return object (len %X ptr %p)",
  317. (unsigned)buffer.length, package));
  318. status = AE_BAD_DATA;
  319. acpi_util_eval_error(handle, pathname, status);
  320. goto end;
  321. }
  322. if (package->type != ACPI_TYPE_PACKAGE) {
  323. ACPI_ERROR((AE_INFO, "Expecting a [Package], found type %X",
  324. package->type));
  325. status = AE_BAD_DATA;
  326. acpi_util_eval_error(handle, pathname, status);
  327. goto end;
  328. }
  329. if (!package->package.count) {
  330. ACPI_ERROR((AE_INFO, "[Package] has zero elements (%p)",
  331. package));
  332. status = AE_BAD_DATA;
  333. acpi_util_eval_error(handle, pathname, status);
  334. goto end;
  335. }
  336. if (package->package.count > ACPI_MAX_HANDLES) {
  337. return_ACPI_STATUS(AE_NO_MEMORY);
  338. }
  339. list->count = package->package.count;
  340. /* Extract package data. */
  341. for (i = 0; i < list->count; i++) {
  342. element = &(package->package.elements[i]);
  343. if (element->type != ACPI_TYPE_ANY) {
  344. status = AE_BAD_DATA;
  345. ACPI_ERROR((AE_INFO,
  346. "Expecting a [Reference] package element, found type %X",
  347. element->type));
  348. acpi_util_eval_error(handle, pathname, status);
  349. break;
  350. }
  351. /* Get the acpi_handle. */
  352. list->handles[i] = element->reference.handle;
  353. ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found reference [%p]\n",
  354. list->handles[i]));
  355. }
  356. end:
  357. if (ACPI_FAILURE(status)) {
  358. list->count = 0;
  359. //kfree(list->handles);
  360. }
  361. acpi_os_free(buffer.pointer);
  362. return_ACPI_STATUS(status);
  363. }
  364. EXPORT_SYMBOL(acpi_evaluate_reference);