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, &quotient, 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