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