cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

utstrsuppt.c (13200B)


      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
     12ACPI_MODULE_NAME("utstrsuppt")
     13
     14/* Local prototypes */
     15static acpi_status
     16acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit);
     17
     18static acpi_status
     19acpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product);
     20
     21static 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
     40acpi_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:
     50		 * 1) Runtime: terminate with no error, per the ACPI spec
     51		 * 2) Compiler: return an error
     52		 */
     53		if (!(ACPI_IS_OCTAL_DIGIT(*string))) {
     54#ifdef ACPI_ASL_COMPILER
     55			status = AE_BAD_OCTAL_CONSTANT;
     56#endif
     57			break;
     58		}
     59
     60		/* Convert and insert this octal digit into the accumulator */
     61
     62		status = acpi_ut_insert_digit(&accumulated_value, 8, *string);
     63		if (ACPI_FAILURE(status)) {
     64			status = AE_OCTAL_OVERFLOW;
     65			break;
     66		}
     67
     68		string++;
     69	}
     70
     71	/* Always return the value that has been accumulated */
     72
     73	*return_value_ptr = accumulated_value;
     74	return (status);
     75}
     76
     77/*******************************************************************************
     78 *
     79 * FUNCTION:    acpi_ut_convert_decimal_string
     80 *
     81 * PARAMETERS:  string                  - Null terminated input string
     82 *              return_value_ptr        - Where the converted value is returned
     83 *
     84 * RETURN:      Status and 64-bit converted integer
     85 *
     86 * DESCRIPTION: Performs a base 10 conversion of the input string to an
     87 *              integer value, either 32 or 64 bits.
     88 *
     89 * NOTE:        Maximum 64-bit unsigned decimal value is 18446744073709551615
     90 *              Maximum 32-bit unsigned decimal value is 4294967295
     91 *
     92 ******************************************************************************/
     93
     94acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr)
     95{
     96	u64 accumulated_value = 0;
     97	acpi_status status = AE_OK;
     98
     99	/* Convert each ASCII byte in the input string */
    100
    101	while (*string) {
    102		/*
    103		 * Character must be ASCII 0-9, otherwise:
    104		 * 1) Runtime: terminate with no error, per the ACPI spec
    105		 * 2) Compiler: return an error
    106		 */
    107		if (!isdigit((int)*string)) {
    108#ifdef ACPI_ASL_COMPILER
    109			status = AE_BAD_DECIMAL_CONSTANT;
    110#endif
    111			break;
    112		}
    113
    114		/* Convert and insert this decimal digit into the accumulator */
    115
    116		status = acpi_ut_insert_digit(&accumulated_value, 10, *string);
    117		if (ACPI_FAILURE(status)) {
    118			status = AE_DECIMAL_OVERFLOW;
    119			break;
    120		}
    121
    122		string++;
    123	}
    124
    125	/* Always return the value that has been accumulated */
    126
    127	*return_value_ptr = accumulated_value;
    128	return (status);
    129}
    130
    131/*******************************************************************************
    132 *
    133 * FUNCTION:    acpi_ut_convert_hex_string
    134 *
    135 * PARAMETERS:  string                  - Null terminated input string
    136 *              return_value_ptr        - Where the converted value is returned
    137 *
    138 * RETURN:      Status and 64-bit converted integer
    139 *
    140 * DESCRIPTION: Performs a base 16 conversion of the input string to an
    141 *              integer value, either 32 or 64 bits.
    142 *
    143 * NOTE:        Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF
    144 *              Maximum 32-bit unsigned hex value is 0xFFFFFFFF
    145 *
    146 ******************************************************************************/
    147
    148acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr)
    149{
    150	u64 accumulated_value = 0;
    151	acpi_status status = AE_OK;
    152
    153	/* Convert each ASCII byte in the input string */
    154
    155	while (*string) {
    156		/*
    157		 * Character must be ASCII A-F, a-f, or 0-9, otherwise:
    158		 * 1) Runtime: terminate with no error, per the ACPI spec
    159		 * 2) Compiler: return an error
    160		 */
    161		if (!isxdigit((int)*string)) {
    162#ifdef ACPI_ASL_COMPILER
    163			status = AE_BAD_HEX_CONSTANT;
    164#endif
    165			break;
    166		}
    167
    168		/* Convert and insert this hex digit into the accumulator */
    169
    170		status = acpi_ut_insert_digit(&accumulated_value, 16, *string);
    171		if (ACPI_FAILURE(status)) {
    172			status = AE_HEX_OVERFLOW;
    173			break;
    174		}
    175
    176		string++;
    177	}
    178
    179	/* Always return the value that has been accumulated */
    180
    181	*return_value_ptr = accumulated_value;
    182	return (status);
    183}
    184
    185/*******************************************************************************
    186 *
    187 * FUNCTION:    acpi_ut_remove_leading_zeros
    188 *
    189 * PARAMETERS:  string                  - Pointer to input ASCII string
    190 *
    191 * RETURN:      Next character after any leading zeros. This character may be
    192 *              used by the caller to detect end-of-string.
    193 *
    194 * DESCRIPTION: Remove any leading zeros in the input string. Return the
    195 *              next character after the final ASCII zero to enable the caller
    196 *              to check for the end of the string (NULL terminator).
    197 *
    198 ******************************************************************************/
    199
    200char acpi_ut_remove_leading_zeros(char **string)
    201{
    202
    203	while (**string == ACPI_ASCII_ZERO) {
    204		*string += 1;
    205	}
    206
    207	return (**string);
    208}
    209
    210/*******************************************************************************
    211 *
    212 * FUNCTION:    acpi_ut_remove_whitespace
    213 *
    214 * PARAMETERS:  string                  - Pointer to input ASCII string
    215 *
    216 * RETURN:      Next character after any whitespace. This character may be
    217 *              used by the caller to detect end-of-string.
    218 *
    219 * DESCRIPTION: Remove any leading whitespace in the input string. Return the
    220 *              next character after the final ASCII zero to enable the caller
    221 *              to check for the end of the string (NULL terminator).
    222 *
    223 ******************************************************************************/
    224
    225char acpi_ut_remove_whitespace(char **string)
    226{
    227
    228	while (isspace((u8)**string)) {
    229		*string += 1;
    230	}
    231
    232	return (**string);
    233}
    234
    235/*******************************************************************************
    236 *
    237 * FUNCTION:    acpi_ut_detect_hex_prefix
    238 *
    239 * PARAMETERS:  string                  - Pointer to input ASCII string
    240 *
    241 * RETURN:      TRUE if a "0x" prefix was found at the start of the string
    242 *
    243 * DESCRIPTION: Detect and remove a hex "0x" prefix
    244 *
    245 ******************************************************************************/
    246
    247u8 acpi_ut_detect_hex_prefix(char **string)
    248{
    249	char *initial_position = *string;
    250
    251	acpi_ut_remove_hex_prefix(string);
    252	if (*string != initial_position) {
    253		return (TRUE);	/* String is past leading 0x */
    254	}
    255
    256	return (FALSE);		/* Not a hex string */
    257}
    258
    259/*******************************************************************************
    260 *
    261 * FUNCTION:    acpi_ut_remove_hex_prefix
    262 *
    263 * PARAMETERS:  string                  - Pointer to input ASCII string
    264 *
    265 * RETURN:      none
    266 *
    267 * DESCRIPTION: Remove a hex "0x" prefix
    268 *
    269 ******************************************************************************/
    270
    271void acpi_ut_remove_hex_prefix(char **string)
    272{
    273	if ((**string == ACPI_ASCII_ZERO) &&
    274	    (tolower((int)*(*string + 1)) == 'x')) {
    275		*string += 2;	/* Go past the leading 0x */
    276	}
    277}
    278
    279/*******************************************************************************
    280 *
    281 * FUNCTION:    acpi_ut_detect_octal_prefix
    282 *
    283 * PARAMETERS:  string                  - Pointer to input ASCII string
    284 *
    285 * RETURN:      True if an octal "0" prefix was found at the start of the
    286 *              string
    287 *
    288 * DESCRIPTION: Detect and remove an octal prefix (zero)
    289 *
    290 ******************************************************************************/
    291
    292u8 acpi_ut_detect_octal_prefix(char **string)
    293{
    294
    295	if (**string == ACPI_ASCII_ZERO) {
    296		*string += 1;	/* Go past the leading 0 */
    297		return (TRUE);
    298	}
    299
    300	return (FALSE);		/* Not an octal string */
    301}
    302
    303/*******************************************************************************
    304 *
    305 * FUNCTION:    acpi_ut_insert_digit
    306 *
    307 * PARAMETERS:  accumulated_value       - Current value of the integer value
    308 *                                        accumulator. The new value is
    309 *                                        returned here.
    310 *              base                    - Radix, either 8/10/16
    311 *              ascii_digit             - ASCII single digit to be inserted
    312 *
    313 * RETURN:      Status and result of the convert/insert operation. The only
    314 *              possible returned exception code is numeric overflow of
    315 *              either the multiply or add conversion operations.
    316 *
    317 * DESCRIPTION: Generic conversion and insertion function for all bases:
    318 *
    319 *              1) Multiply the current accumulated/converted value by the
    320 *              base in order to make room for the new character.
    321 *
    322 *              2) Convert the new character to binary and add it to the
    323 *              current accumulated value.
    324 *
    325 *              Note: The only possible exception indicates an integer
    326 *              overflow (AE_NUMERIC_OVERFLOW)
    327 *
    328 ******************************************************************************/
    329
    330static acpi_status
    331acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit)
    332{
    333	acpi_status status;
    334	u64 product;
    335
    336	/* Make room in the accumulated value for the incoming digit */
    337
    338	status = acpi_ut_strtoul_multiply64(*accumulated_value, base, &product);
    339	if (ACPI_FAILURE(status)) {
    340		return (status);
    341	}
    342
    343	/* Add in the new digit, and store the sum to the accumulated value */
    344
    345	status =
    346	    acpi_ut_strtoul_add64(product,
    347				  acpi_ut_ascii_char_to_hex(ascii_digit),
    348				  accumulated_value);
    349
    350	return (status);
    351}
    352
    353/*******************************************************************************
    354 *
    355 * FUNCTION:    acpi_ut_strtoul_multiply64
    356 *
    357 * PARAMETERS:  multiplicand            - Current accumulated converted integer
    358 *              base                    - Base/Radix
    359 *              out_product             - Where the product is returned
    360 *
    361 * RETURN:      Status and 64-bit product
    362 *
    363 * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as
    364 *              well as 32-bit overflow if necessary (if the current global
    365 *              integer width is 32).
    366 *
    367 ******************************************************************************/
    368
    369static acpi_status
    370acpi_ut_strtoul_multiply64(u64 multiplicand, u32 base, u64 *out_product)
    371{
    372	u64 product;
    373	u64 quotient;
    374
    375	/* Exit if either operand is zero */
    376
    377	*out_product = 0;
    378	if (!multiplicand || !base) {
    379		return (AE_OK);
    380	}
    381
    382	/*
    383	 * Check for 64-bit overflow before the actual multiplication.
    384	 *
    385	 * Notes: 64-bit division is often not supported on 32-bit platforms
    386	 * (it requires a library function), Therefore ACPICA has a local
    387	 * 64-bit divide function. Also, Multiplier is currently only used
    388	 * as the radix (8/10/16), to the 64/32 divide will always work.
    389	 */
    390	acpi_ut_short_divide(ACPI_UINT64_MAX, base, &quotient, NULL);
    391	if (multiplicand > quotient) {
    392		return (AE_NUMERIC_OVERFLOW);
    393	}
    394
    395	product = multiplicand * base;
    396
    397	/* Check for 32-bit overflow if necessary */
    398
    399	if ((acpi_gbl_integer_bit_width == 32) && (product > ACPI_UINT32_MAX)) {
    400		return (AE_NUMERIC_OVERFLOW);
    401	}
    402
    403	*out_product = product;
    404	return (AE_OK);
    405}
    406
    407/*******************************************************************************
    408 *
    409 * FUNCTION:    acpi_ut_strtoul_add64
    410 *
    411 * PARAMETERS:  addend1                 - Current accumulated converted integer
    412 *              digit                   - New hex value/char
    413 *              out_sum                 - Where sum is returned (Accumulator)
    414 *
    415 * RETURN:      Status and 64-bit sum
    416 *
    417 * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as
    418 *              well as 32-bit overflow if necessary (if the current global
    419 *              integer width is 32).
    420 *
    421 ******************************************************************************/
    422
    423static acpi_status acpi_ut_strtoul_add64(u64 addend1, u32 digit, u64 *out_sum)
    424{
    425	u64 sum;
    426
    427	/* Check for 64-bit overflow before the actual addition */
    428
    429	if ((addend1 > 0) && (digit > (ACPI_UINT64_MAX - addend1))) {
    430		return (AE_NUMERIC_OVERFLOW);
    431	}
    432
    433	sum = addend1 + digit;
    434
    435	/* Check for 32-bit overflow if necessary */
    436
    437	if ((acpi_gbl_integer_bit_width == 32) && (sum > ACPI_UINT32_MAX)) {
    438		return (AE_NUMERIC_OVERFLOW);
    439	}
    440
    441	*out_sum = sum;
    442	return (AE_OK);
    443}