root/drivers/acpi/acpica/utstrsuppt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ut_convert_decimal_string
  3. acpi_ut_convert_hex_string
  4. acpi_ut_remove_leading_zeros
  5. acpi_ut_remove_whitespace
  6. acpi_ut_detect_hex_prefix
  7. acpi_ut_remove_hex_prefix
  8. acpi_ut_detect_octal_prefix
  9. acpi_ut_insert_digit
  10. acpi_ut_strtoul_multiply64
  11. acpi_ut_strtoul_add64

   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 acpi_status acpi_ut_convert_octal_string(char *string, u64 *return_value_ptr)
  41 {
  42         u64 accumulated_value = 0;
  43         acpi_status status = AE_OK;
  44 
  45         /* Convert each ASCII byte in the input string */
  46 
  47         while (*string) {
  48 
  49                 /* Character must be ASCII 0-7, otherwise terminate with no error */
  50 
  51                 if (!(ACPI_IS_OCTAL_DIGIT(*string))) {
  52                         break;
  53                 }
  54 
  55                 /* Convert and insert this octal digit into the accumulator */
  56 
  57                 status = acpi_ut_insert_digit(&accumulated_value, 8, *string);
  58                 if (ACPI_FAILURE(status)) {
  59                         status = AE_OCTAL_OVERFLOW;
  60                         break;
  61                 }
  62 
  63                 string++;
  64         }
  65 
  66         /* Always return the value that has been accumulated */
  67 
  68         *return_value_ptr = accumulated_value;
  69         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 acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr)
  90 {
  91         u64 accumulated_value = 0;
  92         acpi_status status = AE_OK;
  93 
  94         /* Convert each ASCII byte in the input string */
  95 
  96         while (*string) {
  97 
  98                 /* Character must be ASCII 0-9, otherwise terminate with no error */
  99 
 100                 if (!isdigit(*string)) {
 101                         break;
 102                 }
 103 
 104                 /* Convert and insert this decimal digit into the accumulator */
 105 
 106                 status = acpi_ut_insert_digit(&accumulated_value, 10, *string);
 107                 if (ACPI_FAILURE(status)) {
 108                         status = AE_DECIMAL_OVERFLOW;
 109                         break;
 110                 }
 111 
 112                 string++;
 113         }
 114 
 115         /* Always return the value that has been accumulated */
 116 
 117         *return_value_ptr = accumulated_value;
 118         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 acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr)
 139 {
 140         u64 accumulated_value = 0;
 141         acpi_status status = AE_OK;
 142 
 143         /* Convert each ASCII byte in the input string */
 144 
 145         while (*string) {
 146 
 147                 /* Must be ASCII A-F, a-f, or 0-9, otherwise terminate with no error */
 148 
 149                 if (!isxdigit(*string)) {
 150                         break;
 151                 }
 152 
 153                 /* Convert and insert this hex digit into the accumulator */
 154 
 155                 status = acpi_ut_insert_digit(&accumulated_value, 16, *string);
 156                 if (ACPI_FAILURE(status)) {
 157                         status = AE_HEX_OVERFLOW;
 158                         break;
 159                 }
 160 
 161                 string++;
 162         }
 163 
 164         /* Always return the value that has been accumulated */
 165 
 166         *return_value_ptr = accumulated_value;
 167         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 char acpi_ut_remove_leading_zeros(char **string)
 186 {
 187 
 188         while (**string == ACPI_ASCII_ZERO) {
 189                 *string += 1;
 190         }
 191 
 192         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 char acpi_ut_remove_whitespace(char **string)
 211 {
 212 
 213         while (isspace((u8)**string)) {
 214                 *string += 1;
 215         }
 216 
 217         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 u8 acpi_ut_detect_hex_prefix(char **string)
 233 {
 234         char *initial_position = *string;
 235 
 236         acpi_ut_remove_hex_prefix(string);
 237         if (*string != initial_position) {
 238                 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 void acpi_ut_remove_hex_prefix(char **string)
 257 {
 258         if ((**string == ACPI_ASCII_ZERO) &&
 259             (tolower((int)*(*string + 1)) == 'x')) {
 260                 *string += 2;   /* Go past the leading 0x */
 261         }
 262 }
 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 u8 acpi_ut_detect_octal_prefix(char **string)
 278 {
 279 
 280         if (**string == ACPI_ASCII_ZERO) {
 281                 *string += 1;   /* Go past the leading 0 */
 282                 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 acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit)
 317 {
 318         acpi_status status;
 319         u64 product;
 320 
 321         /* Make room in the accumulated value for the incoming digit */
 322 
 323         status = acpi_ut_strtoul_multiply64(*accumulated_value, base, &product);
 324         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         status =
 331             acpi_ut_strtoul_add64(product,
 332                                   acpi_ut_ascii_char_to_hex(ascii_digit),
 333                                   accumulated_value);
 334 
 335         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 acpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product)
 356 {
 357         u64 product;
 358         u64 quotient;
 359 
 360         /* Exit if either operand is zero */
 361 
 362         *out_product = 0;
 363         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         acpi_ut_short_divide(ACPI_UINT64_MAX, base, &quotient, NULL);
 376         if (multiplicand > quotient) {
 377                 return (AE_NUMERIC_OVERFLOW);
 378         }
 379 
 380         product = multiplicand * base;
 381 
 382         /* Check for 32-bit overflow if necessary */
 383 
 384         if ((acpi_gbl_integer_bit_width == 32) && (product > ACPI_UINT32_MAX)) {
 385                 return (AE_NUMERIC_OVERFLOW);
 386         }
 387 
 388         *out_product = product;
 389         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 static acpi_status acpi_ut_strtoul_add64(u64 addend1, u32 digit, u64 *out_sum)
 409 {
 410         u64 sum;
 411 
 412         /* Check for 64-bit overflow before the actual addition */
 413 
 414         if ((addend1 > 0) && (digit > (ACPI_UINT64_MAX - addend1))) {
 415                 return (AE_NUMERIC_OVERFLOW);
 416         }
 417 
 418         sum = addend1 + digit;
 419 
 420         /* Check for 32-bit overflow if necessary */
 421 
 422         if ((acpi_gbl_integer_bit_width == 32) && (sum > ACPI_UINT32_MAX)) {
 423                 return (AE_NUMERIC_OVERFLOW);
 424         }
 425 
 426         *out_sum = sum;
 427         return (AE_OK);
 428 }

/* [<][>][^][v][top][bottom][index][help] */