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