utstrsuppt.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /*******************************************************************************
  3. *
  4. * Module Name: utstrsuppt - Support functions for string-to-integer conversion
  5. *
  6. ******************************************************************************/
  7. #include <acpi/acpi.h>
  8. #include "accommon.h"
  9. #define _COMPONENT ACPI_UTILITIES
  10. ACPI_MODULE_NAME("utstrsuppt")
  11. /* Local prototypes */
  12. static acpi_status
  13. acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit);
  14. static acpi_status
  15. acpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product);
  16. static acpi_status acpi_ut_strtoul_add64(u64 addend1, u32 digit, u64 *out_sum);
  17. /*******************************************************************************
  18. *
  19. * FUNCTION: acpi_ut_convert_octal_string
  20. *
  21. * PARAMETERS: string - Null terminated input string
  22. * return_value_ptr - Where the converted value is returned
  23. *
  24. * RETURN: Status and 64-bit converted integer
  25. *
  26. * DESCRIPTION: Performs a base 8 conversion of the input string to an
  27. * integer value, either 32 or 64 bits.
  28. *
  29. * NOTE: Maximum 64-bit unsigned octal value is 01777777777777777777777
  30. * Maximum 32-bit unsigned octal value is 037777777777
  31. *
  32. ******************************************************************************/
  33. acpi_status acpi_ut_convert_octal_string(char *string, u64 *return_value_ptr)
  34. {
  35. u64 accumulated_value = 0;
  36. acpi_status status = AE_OK;
  37. /* Convert each ASCII byte in the input string */
  38. while (*string) {
  39. /*
  40. * Character must be ASCII 0-7, otherwise:
  41. * 1) Runtime: terminate with no error, per the ACPI spec
  42. * 2) Compiler: return an error
  43. */
  44. if (!(ACPI_IS_OCTAL_DIGIT(*string))) {
  45. #ifdef ACPI_ASL_COMPILER
  46. status = AE_BAD_OCTAL_CONSTANT;
  47. #endif
  48. break;
  49. }
  50. /* Convert and insert this octal digit into the accumulator */
  51. status = acpi_ut_insert_digit(&accumulated_value, 8, *string);
  52. if (ACPI_FAILURE(status)) {
  53. status = AE_OCTAL_OVERFLOW;
  54. break;
  55. }
  56. string++;
  57. }
  58. /* Always return the value that has been accumulated */
  59. *return_value_ptr = accumulated_value;
  60. return (status);
  61. }
  62. /*******************************************************************************
  63. *
  64. * FUNCTION: acpi_ut_convert_decimal_string
  65. *
  66. * PARAMETERS: string - Null terminated input string
  67. * return_value_ptr - Where the converted value is returned
  68. *
  69. * RETURN: Status and 64-bit converted integer
  70. *
  71. * DESCRIPTION: Performs a base 10 conversion of the input string to an
  72. * integer value, either 32 or 64 bits.
  73. *
  74. * NOTE: Maximum 64-bit unsigned decimal value is 18446744073709551615
  75. * Maximum 32-bit unsigned decimal value is 4294967295
  76. *
  77. ******************************************************************************/
  78. acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr)
  79. {
  80. u64 accumulated_value = 0;
  81. acpi_status status = AE_OK;
  82. /* Convert each ASCII byte in the input string */
  83. while (*string) {
  84. /*
  85. * Character must be ASCII 0-9, otherwise:
  86. * 1) Runtime: terminate with no error, per the ACPI spec
  87. * 2) Compiler: return an error
  88. */
  89. if (!isdigit((int)*string)) {
  90. #ifdef ACPI_ASL_COMPILER
  91. status = AE_BAD_DECIMAL_CONSTANT;
  92. #endif
  93. break;
  94. }
  95. /* Convert and insert this decimal digit into the accumulator */
  96. status = acpi_ut_insert_digit(&accumulated_value, 10, *string);
  97. if (ACPI_FAILURE(status)) {
  98. status = AE_DECIMAL_OVERFLOW;
  99. break;
  100. }
  101. string++;
  102. }
  103. /* Always return the value that has been accumulated */
  104. *return_value_ptr = accumulated_value;
  105. return (status);
  106. }
  107. /*******************************************************************************
  108. *
  109. * FUNCTION: acpi_ut_convert_hex_string
  110. *
  111. * PARAMETERS: string - Null terminated input string
  112. * return_value_ptr - Where the converted value is returned
  113. *
  114. * RETURN: Status and 64-bit converted integer
  115. *
  116. * DESCRIPTION: Performs a base 16 conversion of the input string to an
  117. * integer value, either 32 or 64 bits.
  118. *
  119. * NOTE: Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF
  120. * Maximum 32-bit unsigned hex value is 0xFFFFFFFF
  121. *
  122. ******************************************************************************/
  123. acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr)
  124. {
  125. u64 accumulated_value = 0;
  126. acpi_status status = AE_OK;
  127. /* Convert each ASCII byte in the input string */
  128. while (*string) {
  129. /*
  130. * Character must be ASCII A-F, a-f, or 0-9, otherwise:
  131. * 1) Runtime: terminate with no error, per the ACPI spec
  132. * 2) Compiler: return an error
  133. */
  134. if (!isxdigit((int)*string)) {
  135. #ifdef ACPI_ASL_COMPILER
  136. status = AE_BAD_HEX_CONSTANT;
  137. #endif
  138. break;
  139. }
  140. /* Convert and insert this hex digit into the accumulator */
  141. status = acpi_ut_insert_digit(&accumulated_value, 16, *string);
  142. if (ACPI_FAILURE(status)) {
  143. status = AE_HEX_OVERFLOW;
  144. break;
  145. }
  146. string++;
  147. }
  148. /* Always return the value that has been accumulated */
  149. *return_value_ptr = accumulated_value;
  150. return (status);
  151. }
  152. /*******************************************************************************
  153. *
  154. * FUNCTION: acpi_ut_remove_leading_zeros
  155. *
  156. * PARAMETERS: string - Pointer to input ASCII string
  157. *
  158. * RETURN: Next character after any leading zeros. This character may be
  159. * used by the caller to detect end-of-string.
  160. *
  161. * DESCRIPTION: Remove any leading zeros in the input string. Return the
  162. * next character after the final ASCII zero to enable the caller
  163. * to check for the end of the string (NULL terminator).
  164. *
  165. ******************************************************************************/
  166. char acpi_ut_remove_leading_zeros(char **string)
  167. {
  168. while (**string == ACPI_ASCII_ZERO) {
  169. *string += 1;
  170. }
  171. return (**string);
  172. }
  173. /*******************************************************************************
  174. *
  175. * FUNCTION: acpi_ut_remove_whitespace
  176. *
  177. * PARAMETERS: string - Pointer to input ASCII string
  178. *
  179. * RETURN: Next character after any whitespace. This character may be
  180. * used by the caller to detect end-of-string.
  181. *
  182. * DESCRIPTION: Remove any leading whitespace in the input string. Return the
  183. * next character after the final ASCII zero to enable the caller
  184. * to check for the end of the string (NULL terminator).
  185. *
  186. ******************************************************************************/
  187. char acpi_ut_remove_whitespace(char **string)
  188. {
  189. while (isspace((u8)**string)) {
  190. *string += 1;
  191. }
  192. return (**string);
  193. }
  194. /*******************************************************************************
  195. *
  196. * FUNCTION: acpi_ut_detect_hex_prefix
  197. *
  198. * PARAMETERS: string - Pointer to input ASCII string
  199. *
  200. * RETURN: TRUE if a "0x" prefix was found at the start of the string
  201. *
  202. * DESCRIPTION: Detect and remove a hex "0x" prefix
  203. *
  204. ******************************************************************************/
  205. u8 acpi_ut_detect_hex_prefix(char **string)
  206. {
  207. char *initial_position = *string;
  208. acpi_ut_remove_hex_prefix(string);
  209. if (*string != initial_position) {
  210. return (TRUE); /* String is past leading 0x */
  211. }
  212. return (FALSE); /* Not a hex string */
  213. }
  214. /*******************************************************************************
  215. *
  216. * FUNCTION: acpi_ut_remove_hex_prefix
  217. *
  218. * PARAMETERS: string - Pointer to input ASCII string
  219. *
  220. * RETURN: none
  221. *
  222. * DESCRIPTION: Remove a hex "0x" prefix
  223. *
  224. ******************************************************************************/
  225. void acpi_ut_remove_hex_prefix(char **string)
  226. {
  227. if ((**string == ACPI_ASCII_ZERO) &&
  228. (tolower((int)*(*string + 1)) == 'x')) {
  229. *string += 2; /* Go past the leading 0x */
  230. }
  231. }
  232. /*******************************************************************************
  233. *
  234. * FUNCTION: acpi_ut_detect_octal_prefix
  235. *
  236. * PARAMETERS: string - Pointer to input ASCII string
  237. *
  238. * RETURN: True if an octal "0" prefix was found at the start of the
  239. * string
  240. *
  241. * DESCRIPTION: Detect and remove an octal prefix (zero)
  242. *
  243. ******************************************************************************/
  244. u8 acpi_ut_detect_octal_prefix(char **string)
  245. {
  246. if (**string == ACPI_ASCII_ZERO) {
  247. *string += 1; /* Go past the leading 0 */
  248. return (TRUE);
  249. }
  250. return (FALSE); /* Not an octal string */
  251. }
  252. /*******************************************************************************
  253. *
  254. * FUNCTION: acpi_ut_insert_digit
  255. *
  256. * PARAMETERS: accumulated_value - Current value of the integer value
  257. * accumulator. The new value is
  258. * returned here.
  259. * base - Radix, either 8/10/16
  260. * ascii_digit - ASCII single digit to be inserted
  261. *
  262. * RETURN: Status and result of the convert/insert operation. The only
  263. * possible returned exception code is numeric overflow of
  264. * either the multiply or add conversion operations.
  265. *
  266. * DESCRIPTION: Generic conversion and insertion function for all bases:
  267. *
  268. * 1) Multiply the current accumulated/converted value by the
  269. * base in order to make room for the new character.
  270. *
  271. * 2) Convert the new character to binary and add it to the
  272. * current accumulated value.
  273. *
  274. * Note: The only possible exception indicates an integer
  275. * overflow (AE_NUMERIC_OVERFLOW)
  276. *
  277. ******************************************************************************/
  278. static acpi_status
  279. acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit)
  280. {
  281. acpi_status status;
  282. u64 product;
  283. /* Make room in the accumulated value for the incoming digit */
  284. status = acpi_ut_strtoul_multiply64(*accumulated_value, base, &product);
  285. if (ACPI_FAILURE(status)) {
  286. return (status);
  287. }
  288. /* Add in the new digit, and store the sum to the accumulated value */
  289. status =
  290. acpi_ut_strtoul_add64(product,
  291. acpi_ut_ascii_char_to_hex(ascii_digit),
  292. accumulated_value);
  293. return (status);
  294. }
  295. /*******************************************************************************
  296. *
  297. * FUNCTION: acpi_ut_strtoul_multiply64
  298. *
  299. * PARAMETERS: multiplicand - Current accumulated converted integer
  300. * base - Base/Radix
  301. * out_product - Where the product is returned
  302. *
  303. * RETURN: Status and 64-bit product
  304. *
  305. * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as
  306. * well as 32-bit overflow if necessary (if the current global
  307. * integer width is 32).
  308. *
  309. ******************************************************************************/
  310. static acpi_status
  311. acpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product)
  312. {
  313. u64 product;
  314. u64 quotient;
  315. /* Exit if either operand is zero */
  316. *out_product = 0;
  317. if (!multiplicand || !base) {
  318. return (AE_OK);
  319. }
  320. /*
  321. * Check for 64-bit overflow before the actual multiplication.
  322. *
  323. * Notes: 64-bit division is often not supported on 32-bit platforms
  324. * (it requires a library function), Therefore ACPICA has a local
  325. * 64-bit divide function. Also, Multiplier is currently only used
  326. * as the radix (8/10/16), to the 64/32 divide will always work.
  327. */
  328. acpi_ut_short_divide(ACPI_UINT64_MAX, base, &quotient, NULL);
  329. if (multiplicand > quotient) {
  330. return (AE_NUMERIC_OVERFLOW);
  331. }
  332. product = multiplicand * base;
  333. /* Check for 32-bit overflow if necessary */
  334. if ((acpi_gbl_integer_bit_width == 32) && (product > ACPI_UINT32_MAX)) {
  335. return (AE_NUMERIC_OVERFLOW);
  336. }
  337. *out_product = product;
  338. return (AE_OK);
  339. }
  340. /*******************************************************************************
  341. *
  342. * FUNCTION: acpi_ut_strtoul_add64
  343. *
  344. * PARAMETERS: addend1 - Current accumulated converted integer
  345. * digit - New hex value/char
  346. * out_sum - Where sum is returned (Accumulator)
  347. *
  348. * RETURN: Status and 64-bit sum
  349. *
  350. * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as
  351. * well as 32-bit overflow if necessary (if the current global
  352. * integer width is 32).
  353. *
  354. ******************************************************************************/
  355. static acpi_status acpi_ut_strtoul_add64(u64 addend1, u32 digit, u64 *out_sum)
  356. {
  357. u64 sum;
  358. /* Check for 64-bit overflow before the actual addition */
  359. if ((addend1 > 0) && (digit > (ACPI_UINT64_MAX - addend1))) {
  360. return (AE_NUMERIC_OVERFLOW);
  361. }
  362. sum = addend1 + digit;
  363. /* Check for 32-bit overflow if necessary */
  364. if ((acpi_gbl_integer_bit_width == 32) && (sum > ACPI_UINT32_MAX)) {
  365. return (AE_NUMERIC_OVERFLOW);
  366. }
  367. *out_sum = sum;
  368. return (AE_OK);
  369. }