1 /******************************************************************************* 2 * 3 * Module Name: utstrsuppt - Support functions for string-to-integer conversion 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 315 if ((**String == ACPI_ASCII_ZERO) && 316 (tolower ((int) *(*String + 1)) == 'x')) 317 { 318 *String += 2; /* Go past the leading 0x */ 319 return (TRUE); 320 } 321 322 return (FALSE); /* Not a hex string */ 323 } 324 325 326 /******************************************************************************* 327 * 328 * FUNCTION: AcpiUtDetectOctalPrefix 329 * 330 * PARAMETERS: String - Pointer to input ASCII string 331 * 332 * RETURN: True if an octal "0" prefix was found at the start of the 333 * string 334 * 335 * DESCRIPTION: Detect and remove an octal prefix (zero) 336 * 337 ******************************************************************************/ 338 339 BOOLEAN 340 AcpiUtDetectOctalPrefix ( 341 char **String) 342 { 343 344 if (**String == ACPI_ASCII_ZERO) 345 { 346 *String += 1; /* Go past the leading 0 */ 347 return (TRUE); 348 } 349 350 return (FALSE); /* Not an octal string */ 351 } 352 353 354 /******************************************************************************* 355 * 356 * FUNCTION: AcpiUtInsertDigit 357 * 358 * PARAMETERS: AccumulatedValue - Current value of the integer value 359 * accumulator. The new value is 360 * returned here. 361 * Base - Radix, either 8/10/16 362 * AsciiDigit - ASCII single digit to be inserted 363 * 364 * RETURN: Status and result of the convert/insert operation. The only 365 * possible returned exception code is numeric overflow of 366 * either the multiply or add conversion operations. 367 * 368 * DESCRIPTION: Generic conversion and insertion function for all bases: 369 * 370 * 1) Multiply the current accumulated/converted value by the 371 * base in order to make room for the new character. 372 * 373 * 2) Convert the new character to binary and add it to the 374 * current accumulated value. 375 * 376 * Note: The only possible exception indicates an integer 377 * overflow (AE_NUMERIC_OVERFLOW) 378 * 379 ******************************************************************************/ 380 381 static ACPI_STATUS 382 AcpiUtInsertDigit ( 383 UINT64 *AccumulatedValue, 384 UINT32 Base, 385 int AsciiDigit) 386 { 387 ACPI_STATUS Status; 388 UINT64 Product; 389 390 391 /* Make room in the accumulated value for the incoming digit */ 392 393 Status = AcpiUtStrtoulMultiply64 (*AccumulatedValue, Base, &Product); 394 if (ACPI_FAILURE (Status)) 395 { 396 return (Status); 397 } 398 399 /* Add in the new digit, and store the sum to the accumulated value */ 400 401 Status = AcpiUtStrtoulAdd64 (Product, AcpiUtAsciiCharToHex (AsciiDigit), 402 AccumulatedValue); 403 404 return (Status); 405 } 406 407 408 /******************************************************************************* 409 * 410 * FUNCTION: AcpiUtStrtoulMultiply64 411 * 412 * PARAMETERS: Multiplicand - Current accumulated converted integer 413 * Base - Base/Radix 414 * OutProduct - Where the product is returned 415 * 416 * RETURN: Status and 64-bit product 417 * 418 * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as 419 * well as 32-bit overflow if necessary (if the current global 420 * integer width is 32). 421 * 422 ******************************************************************************/ 423 424 static ACPI_STATUS 425 AcpiUtStrtoulMultiply64 ( 426 UINT64 Multiplicand, 427 UINT32 Base, 428 UINT64 *OutProduct) 429 { 430 UINT64 Product; 431 UINT64 Quotient; 432 433 434 /* Exit if either operand is zero */ 435 436 *OutProduct = 0; 437 if (!Multiplicand || !Base) 438 { 439 return (AE_OK); 440 } 441 442 /* 443 * Check for 64-bit overflow before the actual multiplication. 444 * 445 * Notes: 64-bit division is often not supported on 32-bit platforms 446 * (it requires a library function), Therefore ACPICA has a local 447 * 64-bit divide function. Also, Multiplier is currently only used 448 * as the radix (8/10/16), to the 64/32 divide will always work. 449 */ 450 AcpiUtShortDivide (ACPI_UINT64_MAX, Base, &Quotient, NULL); 451 if (Multiplicand > Quotient) 452 { 453 return (AE_NUMERIC_OVERFLOW); 454 } 455 456 Product = Multiplicand * Base; 457 458 /* Check for 32-bit overflow if necessary */ 459 460 if ((AcpiGbl_IntegerBitWidth == 32) && (Product > ACPI_UINT32_MAX)) 461 { 462 return (AE_NUMERIC_OVERFLOW); 463 } 464 465 *OutProduct = Product; 466 return (AE_OK); 467 } 468 469 470 /******************************************************************************* 471 * 472 * FUNCTION: AcpiUtStrtoulAdd64 473 * 474 * PARAMETERS: Addend1 - Current accumulated converted integer 475 * Digit - New hex value/char 476 * OutSum - Where sum is returned (Accumulator) 477 * 478 * RETURN: Status and 64-bit sum 479 * 480 * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as 481 * well as 32-bit overflow if necessary (if the current global 482 * integer width is 32). 483 * 484 ******************************************************************************/ 485 486 static ACPI_STATUS 487 AcpiUtStrtoulAdd64 ( 488 UINT64 Addend1, 489 UINT32 Digit, 490 UINT64 *OutSum) 491 { 492 UINT64 Sum; 493 494 495 /* Check for 64-bit overflow before the actual addition */ 496 497 if ((Addend1 > 0) && (Digit > (ACPI_UINT64_MAX - Addend1))) 498 { 499 return (AE_NUMERIC_OVERFLOW); 500 } 501 502 Sum = Addend1 + Digit; 503 504 /* Check for 32-bit overflow if necessary */ 505 506 if ((AcpiGbl_IntegerBitWidth == 32) && (Sum > ACPI_UINT32_MAX)) 507 { 508 return (AE_NUMERIC_OVERFLOW); 509 } 510 511 *OutSum = Sum; 512 return (AE_OK); 513 } 514