Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Apr 14-17, 2025
Register
Loading...
Note: File does not exist in v3.1.
  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 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
 89acpi_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
138acpi_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
185char 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
210char 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
232u8 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
256void 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
277u8 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
315static acpi_status
316acpi_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
354static acpi_status
355acpi_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
408static 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}