nsconvert.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: nsconvert - Object conversions for objects returned by
  5. * predefined methods
  6. *
  7. * Copyright (C) 2000 - 2022, Intel Corp.
  8. *
  9. *****************************************************************************/
  10. #include <acpi/acpi.h>
  11. #include "accommon.h"
  12. #include "acnamesp.h"
  13. #include "acinterp.h"
  14. #include "acpredef.h"
  15. #include "amlresrc.h"
  16. #define _COMPONENT ACPI_NAMESPACE
  17. ACPI_MODULE_NAME("nsconvert")
  18. /*******************************************************************************
  19. *
  20. * FUNCTION: acpi_ns_convert_to_integer
  21. *
  22. * PARAMETERS: original_object - Object to be converted
  23. * return_object - Where the new converted object is returned
  24. *
  25. * RETURN: Status. AE_OK if conversion was successful.
  26. *
  27. * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
  28. *
  29. ******************************************************************************/
  30. acpi_status
  31. acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
  32. union acpi_operand_object **return_object)
  33. {
  34. union acpi_operand_object *new_object;
  35. acpi_status status;
  36. u64 value = 0;
  37. u32 i;
  38. switch (original_object->common.type) {
  39. case ACPI_TYPE_STRING:
  40. /* String-to-Integer conversion */
  41. status =
  42. acpi_ut_strtoul64(original_object->string.pointer, &value);
  43. if (ACPI_FAILURE(status)) {
  44. return (status);
  45. }
  46. break;
  47. case ACPI_TYPE_BUFFER:
  48. /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
  49. if (original_object->buffer.length > 8) {
  50. return (AE_AML_OPERAND_TYPE);
  51. }
  52. /* Extract each buffer byte to create the integer */
  53. for (i = 0; i < original_object->buffer.length; i++) {
  54. value |= ((u64)
  55. original_object->buffer.pointer[i] << (i *
  56. 8));
  57. }
  58. break;
  59. default:
  60. return (AE_AML_OPERAND_TYPE);
  61. }
  62. new_object = acpi_ut_create_integer_object(value);
  63. if (!new_object) {
  64. return (AE_NO_MEMORY);
  65. }
  66. *return_object = new_object;
  67. return (AE_OK);
  68. }
  69. /*******************************************************************************
  70. *
  71. * FUNCTION: acpi_ns_convert_to_string
  72. *
  73. * PARAMETERS: original_object - Object to be converted
  74. * return_object - Where the new converted object is returned
  75. *
  76. * RETURN: Status. AE_OK if conversion was successful.
  77. *
  78. * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
  79. *
  80. ******************************************************************************/
  81. acpi_status
  82. acpi_ns_convert_to_string(union acpi_operand_object *original_object,
  83. union acpi_operand_object **return_object)
  84. {
  85. union acpi_operand_object *new_object;
  86. acpi_size length;
  87. acpi_status status;
  88. switch (original_object->common.type) {
  89. case ACPI_TYPE_INTEGER:
  90. /*
  91. * Integer-to-String conversion. Commonly, convert
  92. * an integer of value 0 to a NULL string. The last element of
  93. * _BIF and _BIX packages occasionally need this fix.
  94. */
  95. if (original_object->integer.value == 0) {
  96. /* Allocate a new NULL string object */
  97. new_object = acpi_ut_create_string_object(0);
  98. if (!new_object) {
  99. return (AE_NO_MEMORY);
  100. }
  101. } else {
  102. status = acpi_ex_convert_to_string(original_object,
  103. &new_object,
  104. ACPI_IMPLICIT_CONVERT_HEX);
  105. if (ACPI_FAILURE(status)) {
  106. return (status);
  107. }
  108. }
  109. break;
  110. case ACPI_TYPE_BUFFER:
  111. /*
  112. * Buffer-to-String conversion. Use a to_string
  113. * conversion, no transform performed on the buffer data. The best
  114. * example of this is the _BIF method, where the string data from
  115. * the battery is often (incorrectly) returned as buffer object(s).
  116. */
  117. length = 0;
  118. while ((length < original_object->buffer.length) &&
  119. (original_object->buffer.pointer[length])) {
  120. length++;
  121. }
  122. /* Allocate a new string object */
  123. new_object = acpi_ut_create_string_object(length);
  124. if (!new_object) {
  125. return (AE_NO_MEMORY);
  126. }
  127. /*
  128. * Copy the raw buffer data with no transform. String is already NULL
  129. * terminated at Length+1.
  130. */
  131. memcpy(new_object->string.pointer,
  132. original_object->buffer.pointer, length);
  133. break;
  134. default:
  135. return (AE_AML_OPERAND_TYPE);
  136. }
  137. *return_object = new_object;
  138. return (AE_OK);
  139. }
  140. /*******************************************************************************
  141. *
  142. * FUNCTION: acpi_ns_convert_to_buffer
  143. *
  144. * PARAMETERS: original_object - Object to be converted
  145. * return_object - Where the new converted object is returned
  146. *
  147. * RETURN: Status. AE_OK if conversion was successful.
  148. *
  149. * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
  150. *
  151. ******************************************************************************/
  152. acpi_status
  153. acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
  154. union acpi_operand_object **return_object)
  155. {
  156. union acpi_operand_object *new_object;
  157. acpi_status status;
  158. union acpi_operand_object **elements;
  159. u32 *dword_buffer;
  160. u32 count;
  161. u32 i;
  162. switch (original_object->common.type) {
  163. case ACPI_TYPE_INTEGER:
  164. /*
  165. * Integer-to-Buffer conversion.
  166. * Convert the Integer to a packed-byte buffer. _MAT and other
  167. * objects need this sometimes, if a read has been performed on a
  168. * Field object that is less than or equal to the global integer
  169. * size (32 or 64 bits).
  170. */
  171. status =
  172. acpi_ex_convert_to_buffer(original_object, &new_object);
  173. if (ACPI_FAILURE(status)) {
  174. return (status);
  175. }
  176. break;
  177. case ACPI_TYPE_STRING:
  178. /* String-to-Buffer conversion. Simple data copy */
  179. new_object = acpi_ut_create_buffer_object
  180. (original_object->string.length);
  181. if (!new_object) {
  182. return (AE_NO_MEMORY);
  183. }
  184. memcpy(new_object->buffer.pointer,
  185. original_object->string.pointer,
  186. original_object->string.length);
  187. break;
  188. case ACPI_TYPE_PACKAGE:
  189. /*
  190. * This case is often seen for predefined names that must return a
  191. * Buffer object with multiple DWORD integers within. For example,
  192. * _FDE and _GTM. The Package can be converted to a Buffer.
  193. */
  194. /* All elements of the Package must be integers */
  195. elements = original_object->package.elements;
  196. count = original_object->package.count;
  197. for (i = 0; i < count; i++) {
  198. if ((!*elements) ||
  199. ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
  200. return (AE_AML_OPERAND_TYPE);
  201. }
  202. elements++;
  203. }
  204. /* Create the new buffer object to replace the Package */
  205. new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
  206. if (!new_object) {
  207. return (AE_NO_MEMORY);
  208. }
  209. /* Copy the package elements (integers) to the buffer as DWORDs */
  210. elements = original_object->package.elements;
  211. dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
  212. for (i = 0; i < count; i++) {
  213. *dword_buffer = (u32)(*elements)->integer.value;
  214. dword_buffer++;
  215. elements++;
  216. }
  217. break;
  218. default:
  219. return (AE_AML_OPERAND_TYPE);
  220. }
  221. *return_object = new_object;
  222. return (AE_OK);
  223. }
  224. /*******************************************************************************
  225. *
  226. * FUNCTION: acpi_ns_convert_to_unicode
  227. *
  228. * PARAMETERS: scope - Namespace node for the method/object
  229. * original_object - ASCII String Object to be converted
  230. * return_object - Where the new converted object is returned
  231. *
  232. * RETURN: Status. AE_OK if conversion was successful.
  233. *
  234. * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
  235. *
  236. ******************************************************************************/
  237. acpi_status
  238. acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,
  239. union acpi_operand_object *original_object,
  240. union acpi_operand_object **return_object)
  241. {
  242. union acpi_operand_object *new_object;
  243. char *ascii_string;
  244. u16 *unicode_buffer;
  245. u32 unicode_length;
  246. u32 i;
  247. if (!original_object) {
  248. return (AE_OK);
  249. }
  250. /* If a Buffer was returned, it must be at least two bytes long */
  251. if (original_object->common.type == ACPI_TYPE_BUFFER) {
  252. if (original_object->buffer.length < 2) {
  253. return (AE_AML_OPERAND_VALUE);
  254. }
  255. *return_object = NULL;
  256. return (AE_OK);
  257. }
  258. /*
  259. * The original object is an ASCII string. Convert this string to
  260. * a unicode buffer.
  261. */
  262. ascii_string = original_object->string.pointer;
  263. unicode_length = (original_object->string.length * 2) + 2;
  264. /* Create a new buffer object for the Unicode data */
  265. new_object = acpi_ut_create_buffer_object(unicode_length);
  266. if (!new_object) {
  267. return (AE_NO_MEMORY);
  268. }
  269. unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
  270. /* Convert ASCII to Unicode */
  271. for (i = 0; i < original_object->string.length; i++) {
  272. unicode_buffer[i] = (u16)ascii_string[i];
  273. }
  274. *return_object = new_object;
  275. return (AE_OK);
  276. }
  277. /*******************************************************************************
  278. *
  279. * FUNCTION: acpi_ns_convert_to_resource
  280. *
  281. * PARAMETERS: scope - Namespace node for the method/object
  282. * original_object - Object to be converted
  283. * return_object - Where the new converted object is returned
  284. *
  285. * RETURN: Status. AE_OK if conversion was successful
  286. *
  287. * DESCRIPTION: Attempt to convert a Integer object to a resource_template
  288. * Buffer.
  289. *
  290. ******************************************************************************/
  291. acpi_status
  292. acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,
  293. union acpi_operand_object *original_object,
  294. union acpi_operand_object **return_object)
  295. {
  296. union acpi_operand_object *new_object;
  297. u8 *buffer;
  298. /*
  299. * We can fix the following cases for an expected resource template:
  300. * 1. No return value (interpreter slack mode is disabled)
  301. * 2. A "Return (Zero)" statement
  302. * 3. A "Return empty buffer" statement
  303. *
  304. * We will return a buffer containing a single end_tag
  305. * resource descriptor.
  306. */
  307. if (original_object) {
  308. switch (original_object->common.type) {
  309. case ACPI_TYPE_INTEGER:
  310. /* We can only repair an Integer==0 */
  311. if (original_object->integer.value) {
  312. return (AE_AML_OPERAND_TYPE);
  313. }
  314. break;
  315. case ACPI_TYPE_BUFFER:
  316. if (original_object->buffer.length) {
  317. /* Additional checks can be added in the future */
  318. *return_object = NULL;
  319. return (AE_OK);
  320. }
  321. break;
  322. case ACPI_TYPE_STRING:
  323. default:
  324. return (AE_AML_OPERAND_TYPE);
  325. }
  326. }
  327. /* Create the new buffer object for the resource descriptor */
  328. new_object = acpi_ut_create_buffer_object(2);
  329. if (!new_object) {
  330. return (AE_NO_MEMORY);
  331. }
  332. buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
  333. /* Initialize the Buffer with a single end_tag descriptor */
  334. buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
  335. buffer[1] = 0x00;
  336. *return_object = new_object;
  337. return (AE_OK);
  338. }
  339. /*******************************************************************************
  340. *
  341. * FUNCTION: acpi_ns_convert_to_reference
  342. *
  343. * PARAMETERS: scope - Namespace node for the method/object
  344. * original_object - Object to be converted
  345. * return_object - Where the new converted object is returned
  346. *
  347. * RETURN: Status. AE_OK if conversion was successful
  348. *
  349. * DESCRIPTION: Attempt to convert a Integer object to a object_reference.
  350. * Buffer.
  351. *
  352. ******************************************************************************/
  353. acpi_status
  354. acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,
  355. union acpi_operand_object *original_object,
  356. union acpi_operand_object **return_object)
  357. {
  358. union acpi_operand_object *new_object = NULL;
  359. acpi_status status;
  360. struct acpi_namespace_node *node;
  361. union acpi_generic_state scope_info;
  362. char *name;
  363. ACPI_FUNCTION_NAME(ns_convert_to_reference);
  364. /* Convert path into internal presentation */
  365. status =
  366. acpi_ns_internalize_name(original_object->string.pointer, &name);
  367. if (ACPI_FAILURE(status)) {
  368. return_ACPI_STATUS(status);
  369. }
  370. /* Find the namespace node */
  371. scope_info.scope.node =
  372. ACPI_CAST_PTR(struct acpi_namespace_node, scope);
  373. status =
  374. acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
  375. ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
  376. NULL, &node);
  377. if (ACPI_FAILURE(status)) {
  378. /* Check if we are resolving a named reference within a package */
  379. ACPI_ERROR_NAMESPACE(&scope_info,
  380. original_object->string.pointer, status);
  381. goto error_exit;
  382. }
  383. /* Create and init a new internal ACPI object */
  384. new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
  385. if (!new_object) {
  386. status = AE_NO_MEMORY;
  387. goto error_exit;
  388. }
  389. new_object->reference.node = node;
  390. new_object->reference.object = node->object;
  391. new_object->reference.class = ACPI_REFCLASS_NAME;
  392. /*
  393. * Increase reference of the object if needed (the object is likely a
  394. * null for device nodes).
  395. */
  396. acpi_ut_add_reference(node->object);
  397. error_exit:
  398. ACPI_FREE(name);
  399. *return_object = new_object;
  400. return (status);
  401. }