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