1 /******************************************************************************* 2 * 3 * Module Name: utstrsuppt - Support functions for string-to-integer conversion 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 47 #define _COMPONENT ACPI_UTILITIES 48 ACPI_MODULE_NAME("utstrsuppt") 49 50 /* Local prototypes */ 51 static acpi_status 52 acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit); 53 54 static acpi_status 55 acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product); 56 57 static acpi_status 58 acpi_ut_strtoul_add64(u64 addend1, u64 addend2, u64 *out_sum); 59 60 /******************************************************************************* 61 * 62 * FUNCTION: acpi_ut_convert_octal_string 63 * 64 * PARAMETERS: string - Null terminated input string 65 * return_value_ptr - Where the converted value is returned 66 * 67 * RETURN: Status and 64-bit converted integer 68 * 69 * DESCRIPTION: Performs a base 8 conversion of the input string to an 70 * integer value, either 32 or 64 bits. 71 * 72 * NOTE: Maximum 64-bit unsigned octal value is 01777777777777777777777 73 * Maximum 32-bit unsigned octal value is 037777777777 74 * 75 ******************************************************************************/ 76 77 acpi_status acpi_ut_convert_octal_string(char *string, u64 *return_value_ptr) 78 { 79 u64 accumulated_value = 0; 80 acpi_status status = AE_OK; 81 82 /* Convert each ASCII byte in the input string */ 83 84 while (*string) { 85 86 /* Character must be ASCII 0-7, otherwise terminate with no error */ 87 88 if (!(ACPI_IS_OCTAL_DIGIT(*string))) { 89 break; 90 } 91 92 /* Convert and insert this octal digit into the accumulator */ 93 94 status = acpi_ut_insert_digit(&accumulated_value, 8, *string); 95 if (ACPI_FAILURE(status)) { 96 status = AE_OCTAL_OVERFLOW; 97 break; 98 } 99 100 string++; 101 } 102 103 /* Always return the value that has been accumulated */ 104 105 *return_value_ptr = accumulated_value; 106 return (status); 107 } 108 109 /******************************************************************************* 110 * 111 * FUNCTION: acpi_ut_convert_decimal_string 112 * 113 * PARAMETERS: string - Null terminated input string 114 * return_value_ptr - Where the converted value is returned 115 * 116 * RETURN: Status and 64-bit converted integer 117 * 118 * DESCRIPTION: Performs a base 10 conversion of the input string to an 119 * integer value, either 32 or 64 bits. 120 * 121 * NOTE: Maximum 64-bit unsigned decimal value is 18446744073709551615 122 * Maximum 32-bit unsigned decimal value is 4294967295 123 * 124 ******************************************************************************/ 125 126 acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr) 127 { 128 u64 accumulated_value = 0; 129 acpi_status status = AE_OK; 130 131 /* Convert each ASCII byte in the input string */ 132 133 while (*string) { 134 135 /* Character must be ASCII 0-9, otherwise terminate with no error */ 136 137 if (!isdigit(*string)) { 138 break; 139 } 140 141 /* Convert and insert this decimal digit into the accumulator */ 142 143 status = acpi_ut_insert_digit(&accumulated_value, 10, *string); 144 if (ACPI_FAILURE(status)) { 145 status = AE_DECIMAL_OVERFLOW; 146 break; 147 } 148 149 string++; 150 } 151 152 /* Always return the value that has been accumulated */ 153 154 *return_value_ptr = accumulated_value; 155 return (status); 156 } 157 158 /******************************************************************************* 159 * 160 * FUNCTION: acpi_ut_convert_hex_string 161 * 162 * PARAMETERS: string - Null terminated input string 163 * return_value_ptr - Where the converted value is returned 164 * 165 * RETURN: Status and 64-bit converted integer 166 * 167 * DESCRIPTION: Performs a base 16 conversion of the input string to an 168 * integer value, either 32 or 64 bits. 169 * 170 * NOTE: Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF 171 * Maximum 32-bit unsigned hex value is 0xFFFFFFFF 172 * 173 ******************************************************************************/ 174 175 acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr) 176 { 177 u64 accumulated_value = 0; 178 acpi_status status = AE_OK; 179 180 /* Convert each ASCII byte in the input string */ 181 182 while (*string) { 183 184 /* Must be ASCII A-F, a-f, or 0-9, otherwise terminate with no error */ 185 186 if (!isxdigit(*string)) { 187 break; 188 } 189 190 /* Convert and insert this hex digit into the accumulator */ 191 192 status = acpi_ut_insert_digit(&accumulated_value, 16, *string); 193 if (ACPI_FAILURE(status)) { 194 status = AE_HEX_OVERFLOW; 195 break; 196 } 197 198 string++; 199 } 200 201 /* Always return the value that has been accumulated */ 202 203 *return_value_ptr = accumulated_value; 204 return (status); 205 } 206 207 /******************************************************************************* 208 * 209 * FUNCTION: acpi_ut_remove_leading_zeros 210 * 211 * PARAMETERS: string - Pointer to input ASCII string 212 * 213 * RETURN: Next character after any leading zeros. This character may be 214 * used by the caller to detect end-of-string. 215 * 216 * DESCRIPTION: Remove any leading zeros in the input string. Return the 217 * next character after the final ASCII zero to enable the caller 218 * to check for the end of the string (NULL terminator). 219 * 220 ******************************************************************************/ 221 222 char acpi_ut_remove_leading_zeros(char **string) 223 { 224 225 while (**string == ACPI_ASCII_ZERO) { 226 *string += 1; 227 } 228 229 return (**string); 230 } 231 232 /******************************************************************************* 233 * 234 * FUNCTION: acpi_ut_remove_whitespace 235 * 236 * PARAMETERS: string - Pointer to input ASCII string 237 * 238 * RETURN: Next character after any whitespace. This character may be 239 * used by the caller to detect end-of-string. 240 * 241 * DESCRIPTION: Remove any leading whitespace in the input string. Return the 242 * next character after the final ASCII zero to enable the caller 243 * to check for the end of the string (NULL terminator). 244 * 245 ******************************************************************************/ 246 247 char acpi_ut_remove_whitespace(char **string) 248 { 249 250 while (isspace((u8)**string)) { 251 *string += 1; 252 } 253 254 return (**string); 255 } 256 257 /******************************************************************************* 258 * 259 * FUNCTION: acpi_ut_detect_hex_prefix 260 * 261 * PARAMETERS: string - Pointer to input ASCII string 262 * 263 * RETURN: TRUE if a "0x" prefix was found at the start of the string 264 * 265 * DESCRIPTION: Detect and remove a hex "0x" prefix 266 * 267 ******************************************************************************/ 268 269 u8 acpi_ut_detect_hex_prefix(char **string) 270 { 271 272 if ((**string == ACPI_ASCII_ZERO) && 273 (tolower((int)*(*string + 1)) == 'x')) { 274 *string += 2; /* Go past the leading 0x */ 275 return (TRUE); 276 } 277 278 return (FALSE); /* Not a hex string */ 279 } 280 281 /******************************************************************************* 282 * 283 * FUNCTION: acpi_ut_detect_octal_prefix 284 * 285 * PARAMETERS: string - Pointer to input ASCII string 286 * 287 * RETURN: True if an octal "0" prefix was found at the start of the 288 * string 289 * 290 * DESCRIPTION: Detect and remove an octal prefix (zero) 291 * 292 ******************************************************************************/ 293 294 u8 acpi_ut_detect_octal_prefix(char **string) 295 { 296 297 if (**string == ACPI_ASCII_ZERO) { 298 *string += 1; /* Go past the leading 0 */ 299 return (TRUE); 300 } 301 302 return (FALSE); /* Not an octal string */ 303 } 304 305 /******************************************************************************* 306 * 307 * FUNCTION: acpi_ut_insert_digit 308 * 309 * PARAMETERS: accumulated_value - Current value of the integer value 310 * accumulator. The new value is 311 * returned here. 312 * base - Radix, either 8/10/16 313 * ascii_digit - ASCII single digit to be inserted 314 * 315 * RETURN: Status and result of the convert/insert operation. The only 316 * possible returned exception code is numeric overflow of 317 * either the multiply or add conversion operations. 318 * 319 * DESCRIPTION: Generic conversion and insertion function for all bases: 320 * 321 * 1) Multiply the current accumulated/converted value by the 322 * base in order to make room for the new character. 323 * 324 * 2) Convert the new character to binary and add it to the 325 * current accumulated value. 326 * 327 * Note: The only possible exception indicates an integer 328 * overflow (AE_NUMERIC_OVERFLOW) 329 * 330 ******************************************************************************/ 331 332 static acpi_status 333 acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit) 334 { 335 acpi_status status; 336 u64 product; 337 338 /* Make room in the accumulated value for the incoming digit */ 339 340 status = acpi_ut_strtoul_multiply64(*accumulated_value, base, &product); 341 if (ACPI_FAILURE(status)) { 342 return (status); 343 } 344 345 /* Add in the new digit, and store the sum to the accumulated value */ 346 347 status = 348 acpi_ut_strtoul_add64(product, 349 acpi_ut_ascii_char_to_hex(ascii_digit), 350 accumulated_value); 351 352 return (status); 353 } 354 355 /******************************************************************************* 356 * 357 * FUNCTION: acpi_ut_strtoul_multiply64 358 * 359 * PARAMETERS: multiplicand - Current accumulated converted integer 360 * multiplier - Base/Radix 361 * out_product - Where the product is returned 362 * 363 * RETURN: Status and 64-bit product 364 * 365 * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as 366 * well as 32-bit overflow if necessary (if the current global 367 * integer width is 32). 368 * 369 ******************************************************************************/ 370 371 static acpi_status 372 acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product) 373 { 374 u64 val; 375 376 /* Exit if either operand is zero */ 377 378 *out_product = 0; 379 if (!multiplicand || !multiplier) { 380 return (AE_OK); 381 } 382 383 /* Check for 64-bit overflow before the actual multiplication */ 384 385 acpi_ut_short_divide(ACPI_UINT64_MAX, (u32)multiplier, &val, NULL); 386 if (multiplicand > val) { 387 return (AE_NUMERIC_OVERFLOW); 388 } 389 390 val = multiplicand * multiplier; 391 392 /* Check for 32-bit overflow if necessary */ 393 394 if ((acpi_gbl_integer_bit_width == 32) && (val > ACPI_UINT32_MAX)) { 395 return (AE_NUMERIC_OVERFLOW); 396 } 397 398 *out_product = val; 399 return (AE_OK); 400 } 401 402 /******************************************************************************* 403 * 404 * FUNCTION: acpi_ut_strtoul_add64 405 * 406 * PARAMETERS: addend1 - Current accumulated converted integer 407 * addend2 - New hex value/char 408 * out_sum - Where sum is returned (Accumulator) 409 * 410 * RETURN: Status and 64-bit sum 411 * 412 * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as 413 * well as 32-bit overflow if necessary (if the current global 414 * integer width is 32). 415 * 416 ******************************************************************************/ 417 418 static acpi_status acpi_ut_strtoul_add64(u64 addend1, u64 addend2, u64 *out_sum) 419 { 420 u64 sum; 421 422 /* Check for 64-bit overflow before the actual addition */ 423 424 if ((addend1 > 0) && (addend2 > (ACPI_UINT64_MAX - addend1))) { 425 return (AE_NUMERIC_OVERFLOW); 426 } 427 428 sum = addend1 + addend2; 429 430 /* Check for 32-bit overflow if necessary */ 431 432 if ((acpi_gbl_integer_bit_width == 32) && (sum > ACPI_UINT32_MAX)) { 433 return (AE_NUMERIC_OVERFLOW); 434 } 435 436 *out_sum = sum; 437 return (AE_OK); 438 } 439