162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/******************************************************************************* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: utstrsuppt - Support functions for string-to-integer conversion 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci ******************************************************************************/ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <acpi/acpi.h> 962306a36Sopenharmony_ci#include "accommon.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#define _COMPONENT ACPI_UTILITIES 1262306a36Sopenharmony_ciACPI_MODULE_NAME("utstrsuppt") 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* Local prototypes */ 1562306a36Sopenharmony_cistatic acpi_status 1662306a36Sopenharmony_ciacpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit); 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic acpi_status 1962306a36Sopenharmony_ciacpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic acpi_status acpi_ut_strtoul_add64(u64 addend1, u32 digit, u64 *out_sum); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/******************************************************************************* 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * FUNCTION: acpi_ut_convert_octal_string 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * PARAMETERS: string - Null terminated input string 2862306a36Sopenharmony_ci * return_value_ptr - Where the converted value is returned 2962306a36Sopenharmony_ci * 3062306a36Sopenharmony_ci * RETURN: Status and 64-bit converted integer 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * DESCRIPTION: Performs a base 8 conversion of the input string to an 3362306a36Sopenharmony_ci * integer value, either 32 or 64 bits. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * NOTE: Maximum 64-bit unsigned octal value is 01777777777777777777777 3662306a36Sopenharmony_ci * Maximum 32-bit unsigned octal value is 037777777777 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci ******************************************************************************/ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciacpi_status acpi_ut_convert_octal_string(char *string, u64 *return_value_ptr) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci u64 accumulated_value = 0; 4362306a36Sopenharmony_ci acpi_status status = AE_OK; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci /* Convert each ASCII byte in the input string */ 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci while (*string) { 4862306a36Sopenharmony_ci /* 4962306a36Sopenharmony_ci * Character must be ASCII 0-7, otherwise: 5062306a36Sopenharmony_ci * 1) Runtime: terminate with no error, per the ACPI spec 5162306a36Sopenharmony_ci * 2) Compiler: return an error 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci if (!(ACPI_IS_OCTAL_DIGIT(*string))) { 5462306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 5562306a36Sopenharmony_ci status = AE_BAD_OCTAL_CONSTANT; 5662306a36Sopenharmony_ci#endif 5762306a36Sopenharmony_ci break; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci /* Convert and insert this octal digit into the accumulator */ 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci status = acpi_ut_insert_digit(&accumulated_value, 8, *string); 6362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 6462306a36Sopenharmony_ci status = AE_OCTAL_OVERFLOW; 6562306a36Sopenharmony_ci break; 6662306a36Sopenharmony_ci } 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci string++; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci /* Always return the value that has been accumulated */ 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci *return_value_ptr = accumulated_value; 7462306a36Sopenharmony_ci return (status); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/******************************************************************************* 7862306a36Sopenharmony_ci * 7962306a36Sopenharmony_ci * FUNCTION: acpi_ut_convert_decimal_string 8062306a36Sopenharmony_ci * 8162306a36Sopenharmony_ci * PARAMETERS: string - Null terminated input string 8262306a36Sopenharmony_ci * return_value_ptr - Where the converted value is returned 8362306a36Sopenharmony_ci * 8462306a36Sopenharmony_ci * RETURN: Status and 64-bit converted integer 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * DESCRIPTION: Performs a base 10 conversion of the input string to an 8762306a36Sopenharmony_ci * integer value, either 32 or 64 bits. 8862306a36Sopenharmony_ci * 8962306a36Sopenharmony_ci * NOTE: Maximum 64-bit unsigned decimal value is 18446744073709551615 9062306a36Sopenharmony_ci * Maximum 32-bit unsigned decimal value is 4294967295 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci ******************************************************************************/ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciacpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr) 9562306a36Sopenharmony_ci{ 9662306a36Sopenharmony_ci u64 accumulated_value = 0; 9762306a36Sopenharmony_ci acpi_status status = AE_OK; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* Convert each ASCII byte in the input string */ 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci while (*string) { 10262306a36Sopenharmony_ci /* 10362306a36Sopenharmony_ci * Character must be ASCII 0-9, otherwise: 10462306a36Sopenharmony_ci * 1) Runtime: terminate with no error, per the ACPI spec 10562306a36Sopenharmony_ci * 2) Compiler: return an error 10662306a36Sopenharmony_ci */ 10762306a36Sopenharmony_ci if (!isdigit((int)*string)) { 10862306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 10962306a36Sopenharmony_ci status = AE_BAD_DECIMAL_CONSTANT; 11062306a36Sopenharmony_ci#endif 11162306a36Sopenharmony_ci break; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* Convert and insert this decimal digit into the accumulator */ 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci status = acpi_ut_insert_digit(&accumulated_value, 10, *string); 11762306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 11862306a36Sopenharmony_ci status = AE_DECIMAL_OVERFLOW; 11962306a36Sopenharmony_ci break; 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci string++; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci /* Always return the value that has been accumulated */ 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci *return_value_ptr = accumulated_value; 12862306a36Sopenharmony_ci return (status); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/******************************************************************************* 13262306a36Sopenharmony_ci * 13362306a36Sopenharmony_ci * FUNCTION: acpi_ut_convert_hex_string 13462306a36Sopenharmony_ci * 13562306a36Sopenharmony_ci * PARAMETERS: string - Null terminated input string 13662306a36Sopenharmony_ci * return_value_ptr - Where the converted value is returned 13762306a36Sopenharmony_ci * 13862306a36Sopenharmony_ci * RETURN: Status and 64-bit converted integer 13962306a36Sopenharmony_ci * 14062306a36Sopenharmony_ci * DESCRIPTION: Performs a base 16 conversion of the input string to an 14162306a36Sopenharmony_ci * integer value, either 32 or 64 bits. 14262306a36Sopenharmony_ci * 14362306a36Sopenharmony_ci * NOTE: Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF 14462306a36Sopenharmony_ci * Maximum 32-bit unsigned hex value is 0xFFFFFFFF 14562306a36Sopenharmony_ci * 14662306a36Sopenharmony_ci ******************************************************************************/ 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ciacpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr) 14962306a36Sopenharmony_ci{ 15062306a36Sopenharmony_ci u64 accumulated_value = 0; 15162306a36Sopenharmony_ci acpi_status status = AE_OK; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci /* Convert each ASCII byte in the input string */ 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci while (*string) { 15662306a36Sopenharmony_ci /* 15762306a36Sopenharmony_ci * Character must be ASCII A-F, a-f, or 0-9, otherwise: 15862306a36Sopenharmony_ci * 1) Runtime: terminate with no error, per the ACPI spec 15962306a36Sopenharmony_ci * 2) Compiler: return an error 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci if (!isxdigit((int)*string)) { 16262306a36Sopenharmony_ci#ifdef ACPI_ASL_COMPILER 16362306a36Sopenharmony_ci status = AE_BAD_HEX_CONSTANT; 16462306a36Sopenharmony_ci#endif 16562306a36Sopenharmony_ci break; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* Convert and insert this hex digit into the accumulator */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci status = acpi_ut_insert_digit(&accumulated_value, 16, *string); 17162306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 17262306a36Sopenharmony_ci status = AE_HEX_OVERFLOW; 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci string++; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* Always return the value that has been accumulated */ 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci *return_value_ptr = accumulated_value; 18262306a36Sopenharmony_ci return (status); 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/******************************************************************************* 18662306a36Sopenharmony_ci * 18762306a36Sopenharmony_ci * FUNCTION: acpi_ut_remove_leading_zeros 18862306a36Sopenharmony_ci * 18962306a36Sopenharmony_ci * PARAMETERS: string - Pointer to input ASCII string 19062306a36Sopenharmony_ci * 19162306a36Sopenharmony_ci * RETURN: Next character after any leading zeros. This character may be 19262306a36Sopenharmony_ci * used by the caller to detect end-of-string. 19362306a36Sopenharmony_ci * 19462306a36Sopenharmony_ci * DESCRIPTION: Remove any leading zeros in the input string. Return the 19562306a36Sopenharmony_ci * next character after the final ASCII zero to enable the caller 19662306a36Sopenharmony_ci * to check for the end of the string (NULL terminator). 19762306a36Sopenharmony_ci * 19862306a36Sopenharmony_ci ******************************************************************************/ 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cichar acpi_ut_remove_leading_zeros(char **string) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci while (**string == ACPI_ASCII_ZERO) { 20462306a36Sopenharmony_ci *string += 1; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci return (**string); 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci/******************************************************************************* 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * FUNCTION: acpi_ut_remove_whitespace 21362306a36Sopenharmony_ci * 21462306a36Sopenharmony_ci * PARAMETERS: string - Pointer to input ASCII string 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * RETURN: Next character after any whitespace. This character may be 21762306a36Sopenharmony_ci * used by the caller to detect end-of-string. 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * DESCRIPTION: Remove any leading whitespace in the input string. Return the 22062306a36Sopenharmony_ci * next character after the final ASCII zero to enable the caller 22162306a36Sopenharmony_ci * to check for the end of the string (NULL terminator). 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci ******************************************************************************/ 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cichar acpi_ut_remove_whitespace(char **string) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci while (isspace((u8)**string)) { 22962306a36Sopenharmony_ci *string += 1; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci return (**string); 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci/******************************************************************************* 23662306a36Sopenharmony_ci * 23762306a36Sopenharmony_ci * FUNCTION: acpi_ut_detect_hex_prefix 23862306a36Sopenharmony_ci * 23962306a36Sopenharmony_ci * PARAMETERS: string - Pointer to input ASCII string 24062306a36Sopenharmony_ci * 24162306a36Sopenharmony_ci * RETURN: TRUE if a "0x" prefix was found at the start of the string 24262306a36Sopenharmony_ci * 24362306a36Sopenharmony_ci * DESCRIPTION: Detect and remove a hex "0x" prefix 24462306a36Sopenharmony_ci * 24562306a36Sopenharmony_ci ******************************************************************************/ 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ciu8 acpi_ut_detect_hex_prefix(char **string) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci char *initial_position = *string; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci acpi_ut_remove_hex_prefix(string); 25262306a36Sopenharmony_ci if (*string != initial_position) { 25362306a36Sopenharmony_ci return (TRUE); /* String is past leading 0x */ 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci return (FALSE); /* Not a hex string */ 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci/******************************************************************************* 26062306a36Sopenharmony_ci * 26162306a36Sopenharmony_ci * FUNCTION: acpi_ut_remove_hex_prefix 26262306a36Sopenharmony_ci * 26362306a36Sopenharmony_ci * PARAMETERS: string - Pointer to input ASCII string 26462306a36Sopenharmony_ci * 26562306a36Sopenharmony_ci * RETURN: none 26662306a36Sopenharmony_ci * 26762306a36Sopenharmony_ci * DESCRIPTION: Remove a hex "0x" prefix 26862306a36Sopenharmony_ci * 26962306a36Sopenharmony_ci ******************************************************************************/ 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_civoid acpi_ut_remove_hex_prefix(char **string) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci if ((**string == ACPI_ASCII_ZERO) && 27462306a36Sopenharmony_ci (tolower((int)*(*string + 1)) == 'x')) { 27562306a36Sopenharmony_ci *string += 2; /* Go past the leading 0x */ 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci/******************************************************************************* 28062306a36Sopenharmony_ci * 28162306a36Sopenharmony_ci * FUNCTION: acpi_ut_detect_octal_prefix 28262306a36Sopenharmony_ci * 28362306a36Sopenharmony_ci * PARAMETERS: string - Pointer to input ASCII string 28462306a36Sopenharmony_ci * 28562306a36Sopenharmony_ci * RETURN: True if an octal "0" prefix was found at the start of the 28662306a36Sopenharmony_ci * string 28762306a36Sopenharmony_ci * 28862306a36Sopenharmony_ci * DESCRIPTION: Detect and remove an octal prefix (zero) 28962306a36Sopenharmony_ci * 29062306a36Sopenharmony_ci ******************************************************************************/ 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ciu8 acpi_ut_detect_octal_prefix(char **string) 29362306a36Sopenharmony_ci{ 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (**string == ACPI_ASCII_ZERO) { 29662306a36Sopenharmony_ci *string += 1; /* Go past the leading 0 */ 29762306a36Sopenharmony_ci return (TRUE); 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci return (FALSE); /* Not an octal string */ 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/******************************************************************************* 30462306a36Sopenharmony_ci * 30562306a36Sopenharmony_ci * FUNCTION: acpi_ut_insert_digit 30662306a36Sopenharmony_ci * 30762306a36Sopenharmony_ci * PARAMETERS: accumulated_value - Current value of the integer value 30862306a36Sopenharmony_ci * accumulator. The new value is 30962306a36Sopenharmony_ci * returned here. 31062306a36Sopenharmony_ci * base - Radix, either 8/10/16 31162306a36Sopenharmony_ci * ascii_digit - ASCII single digit to be inserted 31262306a36Sopenharmony_ci * 31362306a36Sopenharmony_ci * RETURN: Status and result of the convert/insert operation. The only 31462306a36Sopenharmony_ci * possible returned exception code is numeric overflow of 31562306a36Sopenharmony_ci * either the multiply or add conversion operations. 31662306a36Sopenharmony_ci * 31762306a36Sopenharmony_ci * DESCRIPTION: Generic conversion and insertion function for all bases: 31862306a36Sopenharmony_ci * 31962306a36Sopenharmony_ci * 1) Multiply the current accumulated/converted value by the 32062306a36Sopenharmony_ci * base in order to make room for the new character. 32162306a36Sopenharmony_ci * 32262306a36Sopenharmony_ci * 2) Convert the new character to binary and add it to the 32362306a36Sopenharmony_ci * current accumulated value. 32462306a36Sopenharmony_ci * 32562306a36Sopenharmony_ci * Note: The only possible exception indicates an integer 32662306a36Sopenharmony_ci * overflow (AE_NUMERIC_OVERFLOW) 32762306a36Sopenharmony_ci * 32862306a36Sopenharmony_ci ******************************************************************************/ 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic acpi_status 33162306a36Sopenharmony_ciacpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci acpi_status status; 33462306a36Sopenharmony_ci u64 product; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* Make room in the accumulated value for the incoming digit */ 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci status = acpi_ut_strtoul_multiply64(*accumulated_value, base, &product); 33962306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 34062306a36Sopenharmony_ci return (status); 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci /* Add in the new digit, and store the sum to the accumulated value */ 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci status = 34662306a36Sopenharmony_ci acpi_ut_strtoul_add64(product, 34762306a36Sopenharmony_ci acpi_ut_ascii_char_to_hex(ascii_digit), 34862306a36Sopenharmony_ci accumulated_value); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci return (status); 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/******************************************************************************* 35462306a36Sopenharmony_ci * 35562306a36Sopenharmony_ci * FUNCTION: acpi_ut_strtoul_multiply64 35662306a36Sopenharmony_ci * 35762306a36Sopenharmony_ci * PARAMETERS: multiplicand - Current accumulated converted integer 35862306a36Sopenharmony_ci * base - Base/Radix 35962306a36Sopenharmony_ci * out_product - Where the product is returned 36062306a36Sopenharmony_ci * 36162306a36Sopenharmony_ci * RETURN: Status and 64-bit product 36262306a36Sopenharmony_ci * 36362306a36Sopenharmony_ci * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as 36462306a36Sopenharmony_ci * well as 32-bit overflow if necessary (if the current global 36562306a36Sopenharmony_ci * integer width is 32). 36662306a36Sopenharmony_ci * 36762306a36Sopenharmony_ci ******************************************************************************/ 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic acpi_status 37062306a36Sopenharmony_ciacpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci u64 product; 37362306a36Sopenharmony_ci u64 quotient; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* Exit if either operand is zero */ 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci *out_product = 0; 37862306a36Sopenharmony_ci if (!multiplicand || !base) { 37962306a36Sopenharmony_ci return (AE_OK); 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci /* 38362306a36Sopenharmony_ci * Check for 64-bit overflow before the actual multiplication. 38462306a36Sopenharmony_ci * 38562306a36Sopenharmony_ci * Notes: 64-bit division is often not supported on 32-bit platforms 38662306a36Sopenharmony_ci * (it requires a library function), Therefore ACPICA has a local 38762306a36Sopenharmony_ci * 64-bit divide function. Also, Multiplier is currently only used 38862306a36Sopenharmony_ci * as the radix (8/10/16), to the 64/32 divide will always work. 38962306a36Sopenharmony_ci */ 39062306a36Sopenharmony_ci acpi_ut_short_divide(ACPI_UINT64_MAX, base, "ient, NULL); 39162306a36Sopenharmony_ci if (multiplicand > quotient) { 39262306a36Sopenharmony_ci return (AE_NUMERIC_OVERFLOW); 39362306a36Sopenharmony_ci } 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci product = multiplicand * base; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci /* Check for 32-bit overflow if necessary */ 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci if ((acpi_gbl_integer_bit_width == 32) && (product > ACPI_UINT32_MAX)) { 40062306a36Sopenharmony_ci return (AE_NUMERIC_OVERFLOW); 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci *out_product = product; 40462306a36Sopenharmony_ci return (AE_OK); 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci/******************************************************************************* 40862306a36Sopenharmony_ci * 40962306a36Sopenharmony_ci * FUNCTION: acpi_ut_strtoul_add64 41062306a36Sopenharmony_ci * 41162306a36Sopenharmony_ci * PARAMETERS: addend1 - Current accumulated converted integer 41262306a36Sopenharmony_ci * digit - New hex value/char 41362306a36Sopenharmony_ci * out_sum - Where sum is returned (Accumulator) 41462306a36Sopenharmony_ci * 41562306a36Sopenharmony_ci * RETURN: Status and 64-bit sum 41662306a36Sopenharmony_ci * 41762306a36Sopenharmony_ci * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as 41862306a36Sopenharmony_ci * well as 32-bit overflow if necessary (if the current global 41962306a36Sopenharmony_ci * integer width is 32). 42062306a36Sopenharmony_ci * 42162306a36Sopenharmony_ci ******************************************************************************/ 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic acpi_status acpi_ut_strtoul_add64(u64 addend1, u32 digit, u64 *out_sum) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci u64 sum; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* Check for 64-bit overflow before the actual addition */ 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci if ((addend1 > 0) && (digit > (ACPI_UINT64_MAX - addend1))) { 43062306a36Sopenharmony_ci return (AE_NUMERIC_OVERFLOW); 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci sum = addend1 + digit; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci /* Check for 32-bit overflow if necessary */ 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if ((acpi_gbl_integer_bit_width == 32) && (sum > ACPI_UINT32_MAX)) { 43862306a36Sopenharmony_ci return (AE_NUMERIC_OVERFLOW); 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci *out_sum = sum; 44262306a36Sopenharmony_ci return (AE_OK); 44362306a36Sopenharmony_ci} 444