1 /******************************************************************************* 2 * 3 * Module Name: utstrsuppt - Support functions for string-to-integer conversion 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2019, 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.h" 45 #include "accommon.h" 46 47 #define _COMPONENT ACPI_UTILITIES 48 ACPI_MODULE_NAME ("utstrsuppt") 49 50 51 /* Local prototypes */ 52 53 static ACPI_STATUS 54 AcpiUtInsertDigit ( 55 UINT64 *AccumulatedValue, 56 UINT32 Base, 57 int AsciiDigit); 58 59 static ACPI_STATUS 60 AcpiUtStrtoulMultiply64 ( 61 UINT64 Multiplicand, 62 UINT32 Base, 63 UINT64 *OutProduct); 64 65 static ACPI_STATUS 66 AcpiUtStrtoulAdd64 ( 67 UINT64 Addend1, 68 UINT32 Digit, 69 UINT64 *OutSum); 70 71 72 /******************************************************************************* 73 * 74 * FUNCTION: AcpiUtConvertOctalString 75 * 76 * PARAMETERS: String - Null terminated input string 77 * ReturnValuePtr - Where the converted value is returned 78 * 79 * RETURN: Status and 64-bit converted integer 80 * 81 * DESCRIPTION: Performs a base 8 conversion of the input string to an 82 * integer value, either 32 or 64 bits. 83 * 84 * NOTE: Maximum 64-bit unsigned octal value is 01777777777777777777777 85 * Maximum 32-bit unsigned octal value is 037777777777 86 * 87 ******************************************************************************/ 88 89 ACPI_STATUS 90 AcpiUtConvertOctalString ( 91 char *String, 92 UINT64 *ReturnValuePtr) 93 { 94 UINT64 AccumulatedValue = 0; 95 ACPI_STATUS Status = AE_OK; 96 97 98 /* Convert each ASCII byte in the input string */ 99 100 while (*String) 101 { 102 /* Character must be ASCII 0-7, otherwise terminate with no error */ 103 104 if (!(ACPI_IS_OCTAL_DIGIT (*String))) 105 { 106 break; 107 } 108 109 /* Convert and insert this octal digit into the accumulator */ 110 111 Status = AcpiUtInsertDigit (&AccumulatedValue, 8, *String); 112 if (ACPI_FAILURE (Status)) 113 { 114 Status = AE_OCTAL_OVERFLOW; 115 break; 116 } 117 118 String++; 119 } 120 121 /* Always return the value that has been accumulated */ 122 123 *ReturnValuePtr = AccumulatedValue; 124 return (Status); 125 } 126 127 128 /******************************************************************************* 129 * 130 * FUNCTION: AcpiUtConvertDecimalString 131 * 132 * PARAMETERS: String - Null terminated input string 133 * ReturnValuePtr - Where the converted value is returned 134 * 135 * RETURN: Status and 64-bit converted integer 136 * 137 * DESCRIPTION: Performs a base 10 conversion of the input string to an 138 * integer value, either 32 or 64 bits. 139 * 140 * NOTE: Maximum 64-bit unsigned decimal value is 18446744073709551615 141 * Maximum 32-bit unsigned decimal value is 4294967295 142 * 143 ******************************************************************************/ 144 145 ACPI_STATUS 146 AcpiUtConvertDecimalString ( 147 char *String, 148 UINT64 *ReturnValuePtr) 149 { 150 UINT64 AccumulatedValue = 0; 151 ACPI_STATUS Status = AE_OK; 152 153 154 /* Convert each ASCII byte in the input string */ 155 156 while (*String) 157 { 158 /* Character must be ASCII 0-9, otherwise terminate with no error */ 159 160 if (!isdigit (*String)) 161 { 162 break; 163 } 164 165 /* Convert and insert this decimal digit into the accumulator */ 166 167 Status = AcpiUtInsertDigit (&AccumulatedValue, 10, *String); 168 if (ACPI_FAILURE (Status)) 169 { 170 Status = AE_DECIMAL_OVERFLOW; 171 break; 172 } 173 174 String++; 175 } 176 177 /* Always return the value that has been accumulated */ 178 179 *ReturnValuePtr = AccumulatedValue; 180 return (Status); 181 } 182 183 184 /******************************************************************************* 185 * 186 * FUNCTION: AcpiUtConvertHexString 187 * 188 * PARAMETERS: String - Null terminated input string 189 * ReturnValuePtr - Where the converted value is returned 190 * 191 * RETURN: Status and 64-bit converted integer 192 * 193 * DESCRIPTION: Performs a base 16 conversion of the input string to an 194 * integer value, either 32 or 64 bits. 195 * 196 * NOTE: Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF 197 * Maximum 32-bit unsigned hex value is 0xFFFFFFFF 198 * 199 ******************************************************************************/ 200 201 ACPI_STATUS 202 AcpiUtConvertHexString ( 203 char *String, 204 UINT64 *ReturnValuePtr) 205 { 206 UINT64 AccumulatedValue = 0; 207 ACPI_STATUS Status = AE_OK; 208 209 210 /* Convert each ASCII byte in the input string */ 211 212 while (*String) 213 { 214 /* Must be ASCII A-F, a-f, or 0-9, otherwise terminate with no error */ 215 216 if (!isxdigit (*String)) 217 { 218 break; 219 } 220 221 /* Convert and insert this hex digit into the accumulator */ 222 223 Status = AcpiUtInsertDigit (&AccumulatedValue, 16, *String); 224 if (ACPI_FAILURE (Status)) 225 { 226 Status = AE_HEX_OVERFLOW; 227 break; 228 } 229 230 String++; 231 } 232 233 /* Always return the value that has been accumulated */ 234 235 *ReturnValuePtr = AccumulatedValue; 236 return (Status); 237 } 238 239 240 /******************************************************************************* 241 * 242 * FUNCTION: AcpiUtRemoveLeadingZeros 243 * 244 * PARAMETERS: String - Pointer to input ASCII string 245 * 246 * RETURN: Next character after any leading zeros. This character may be 247 * used by the caller to detect end-of-string. 248 * 249 * DESCRIPTION: Remove any leading zeros in the input string. Return the 250 * next character after the final ASCII zero to enable the caller 251 * to check for the end of the string (NULL terminator). 252 * 253 ******************************************************************************/ 254 255 char 256 AcpiUtRemoveLeadingZeros ( 257 char **String) 258 { 259 260 while (**String == ACPI_ASCII_ZERO) 261 { 262 *String += 1; 263 } 264 265 return (**String); 266 } 267 268 269 /******************************************************************************* 270 * 271 * FUNCTION: AcpiUtRemoveWhitespace 272 * 273 * PARAMETERS: String - Pointer to input ASCII string 274 * 275 * RETURN: Next character after any whitespace. This character may be 276 * used by the caller to detect end-of-string. 277 * 278 * DESCRIPTION: Remove any leading whitespace in the input string. Return the 279 * next character after the final ASCII zero to enable the caller 280 * to check for the end of the string (NULL terminator). 281 * 282 ******************************************************************************/ 283 284 char 285 AcpiUtRemoveWhitespace ( 286 char **String) 287 { 288 289 while (isspace ((UINT8) **String)) 290 { 291 *String += 1; 292 } 293 294 return (**String); 295 } 296 297 298 /******************************************************************************* 299 * 300 * FUNCTION: AcpiUtDetectHexPrefix 301 * 302 * PARAMETERS: String - Pointer to input ASCII string 303 * 304 * RETURN: TRUE if a "0x" prefix was found at the start of the string 305 * 306 * DESCRIPTION: Detect and remove a hex "0x" prefix 307 * 308 ******************************************************************************/ 309 310 BOOLEAN 311 AcpiUtDetectHexPrefix ( 312 char **String) 313 { 314 char *InitialPosition = *String; 315 316 AcpiUtRemoveHexPrefix (String); 317 if (*String != InitialPosition) 318 { 319 return (TRUE); /* String is past leading 0x */ 320 } 321 322 return (FALSE); /* Not a hex string */ 323 } 324 325 326 /******************************************************************************* 327 * 328 * FUNCTION: AcpiUtRemoveHexPrefix 329 * 330 * PARAMETERS: String - Pointer to input ASCII string 331 * 332 * RETURN: none 333 * 334 * DESCRIPTION: Remove a hex "0x" prefix 335 * 336 ******************************************************************************/ 337 338 void 339 AcpiUtRemoveHexPrefix ( 340 char **String) 341 { 342 if ((**String == ACPI_ASCII_ZERO) && 343 (tolower ((int) *(*String + 1)) == 'x')) 344 { 345 *String += 2; /* Go past the leading 0x */ 346 } 347 } 348 349 350 /******************************************************************************* 351 * 352 * FUNCTION: AcpiUtDetectOctalPrefix 353 * 354 * PARAMETERS: String - Pointer to input ASCII string 355 * 356 * RETURN: True if an octal "0" prefix was found at the start of the 357 * string 358 * 359 * DESCRIPTION: Detect and remove an octal prefix (zero) 360 * 361 ******************************************************************************/ 362 363 BOOLEAN 364 AcpiUtDetectOctalPrefix ( 365 char **String) 366 { 367 368 if (**String == ACPI_ASCII_ZERO) 369 { 370 *String += 1; /* Go past the leading 0 */ 371 return (TRUE); 372 } 373 374 return (FALSE); /* Not an octal string */ 375 } 376 377 378 /******************************************************************************* 379 * 380 * FUNCTION: AcpiUtInsertDigit 381 * 382 * PARAMETERS: AccumulatedValue - Current value of the integer value 383 * accumulator. The new value is 384 * returned here. 385 * Base - Radix, either 8/10/16 386 * AsciiDigit - ASCII single digit to be inserted 387 * 388 * RETURN: Status and result of the convert/insert operation. The only 389 * possible returned exception code is numeric overflow of 390 * either the multiply or add conversion operations. 391 * 392 * DESCRIPTION: Generic conversion and insertion function for all bases: 393 * 394 * 1) Multiply the current accumulated/converted value by the 395 * base in order to make room for the new character. 396 * 397 * 2) Convert the new character to binary and add it to the 398 * current accumulated value. 399 * 400 * Note: The only possible exception indicates an integer 401 * overflow (AE_NUMERIC_OVERFLOW) 402 * 403 ******************************************************************************/ 404 405 static ACPI_STATUS 406 AcpiUtInsertDigit ( 407 UINT64 *AccumulatedValue, 408 UINT32 Base, 409 int AsciiDigit) 410 { 411 ACPI_STATUS Status; 412 UINT64 Product; 413 414 415 /* Make room in the accumulated value for the incoming digit */ 416 417 Status = AcpiUtStrtoulMultiply64 (*AccumulatedValue, Base, &Product); 418 if (ACPI_FAILURE (Status)) 419 { 420 return (Status); 421 } 422 423 /* Add in the new digit, and store the sum to the accumulated value */ 424 425 Status = AcpiUtStrtoulAdd64 (Product, AcpiUtAsciiCharToHex (AsciiDigit), 426 AccumulatedValue); 427 428 return (Status); 429 } 430 431 432 /******************************************************************************* 433 * 434 * FUNCTION: AcpiUtStrtoulMultiply64 435 * 436 * PARAMETERS: Multiplicand - Current accumulated converted integer 437 * Base - Base/Radix 438 * OutProduct - Where the product is returned 439 * 440 * RETURN: Status and 64-bit product 441 * 442 * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as 443 * well as 32-bit overflow if necessary (if the current global 444 * integer width is 32). 445 * 446 ******************************************************************************/ 447 448 static ACPI_STATUS 449 AcpiUtStrtoulMultiply64 ( 450 UINT64 Multiplicand, 451 UINT32 Base, 452 UINT64 *OutProduct) 453 { 454 UINT64 Product; 455 UINT64 Quotient; 456 457 458 /* Exit if either operand is zero */ 459 460 *OutProduct = 0; 461 if (!Multiplicand || !Base) 462 { 463 return (AE_OK); 464 } 465 466 /* 467 * Check for 64-bit overflow before the actual multiplication. 468 * 469 * Notes: 64-bit division is often not supported on 32-bit platforms 470 * (it requires a library function), Therefore ACPICA has a local 471 * 64-bit divide function. Also, Multiplier is currently only used 472 * as the radix (8/10/16), to the 64/32 divide will always work. 473 */ 474 AcpiUtShortDivide (ACPI_UINT64_MAX, Base, &Quotient, NULL); 475 if (Multiplicand > Quotient) 476 { 477 return (AE_NUMERIC_OVERFLOW); 478 } 479 480 Product = Multiplicand * Base; 481 482 /* Check for 32-bit overflow if necessary */ 483 484 if ((AcpiGbl_IntegerBitWidth == 32) && (Product > ACPI_UINT32_MAX)) 485 { 486 return (AE_NUMERIC_OVERFLOW); 487 } 488 489 *OutProduct = Product; 490 return (AE_OK); 491 } 492 493 494 /******************************************************************************* 495 * 496 * FUNCTION: AcpiUtStrtoulAdd64 497 * 498 * PARAMETERS: Addend1 - Current accumulated converted integer 499 * Digit - New hex value/char 500 * OutSum - Where sum is returned (Accumulator) 501 * 502 * RETURN: Status and 64-bit sum 503 * 504 * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as 505 * well as 32-bit overflow if necessary (if the current global 506 * integer width is 32). 507 * 508 ******************************************************************************/ 509 510 static ACPI_STATUS 511 AcpiUtStrtoulAdd64 ( 512 UINT64 Addend1, 513 UINT32 Digit, 514 UINT64 *OutSum) 515 { 516 UINT64 Sum; 517 518 519 /* Check for 64-bit overflow before the actual addition */ 520 521 if ((Addend1 > 0) && (Digit > (ACPI_UINT64_MAX - Addend1))) 522 { 523 return (AE_NUMERIC_OVERFLOW); 524 } 525 526 Sum = Addend1 + Digit; 527 528 /* Check for 32-bit overflow if necessary */ 529 530 if ((AcpiGbl_IntegerBitWidth == 32) && (Sum > ACPI_UINT32_MAX)) 531 { 532 return (AE_NUMERIC_OVERFLOW); 533 } 534 535 *OutSum = Sum; 536 return (AE_OK); 537 } 538