1 | /******************************************************************************* |
2 | * |
3 | * Module Name: utstrtoul64 - string to 64-bit integer support |
4 | * |
5 | ******************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, Intel Corp. |
9 | * All rights reserved. |
10 | * |
11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions |
13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions, and the following disclaimer, |
16 | * without modification. |
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
18 | * substantially similar to the "NO WARRANTY" disclaimer below |
19 | * ("Disclaimer") and any redistribution must be conditioned upon |
20 | * including a substantially similar Disclaimer requirement for further |
21 | * binary redistribution. |
22 | * 3. Neither the names of the above-listed copyright holders nor the names |
23 | * of any contributors may be used to endorse or promote products derived |
24 | * from this software without specific prior written permission. |
25 | * |
26 | * Alternatively, this software may be distributed under the terms of the |
27 | * GNU General Public License ("GPL") version 2 as published by the Free |
28 | * Software Foundation. |
29 | * |
30 | * NO WARRANTY |
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
41 | * POSSIBILITY OF SUCH DAMAGES. |
42 | */ |
43 | |
44 | #include "acpi.h" |
45 | #include "accommon.h" |
46 | |
47 | |
48 | /******************************************************************************* |
49 | * |
50 | * The functions in this module satisfy the need for 64-bit string-to-integer |
51 | * conversions on both 32-bit and 64-bit platforms. |
52 | * |
53 | ******************************************************************************/ |
54 | |
55 | #define _COMPONENT ACPI_UTILITIES |
56 | ACPI_MODULE_NAME ("utstrtoul64" ) |
57 | |
58 | /* Local prototypes */ |
59 | |
60 | static UINT64 |
61 | AcpiUtStrtoulBase10 ( |
62 | char *String, |
63 | UINT32 Flags); |
64 | |
65 | static UINT64 |
66 | AcpiUtStrtoulBase16 ( |
67 | char *String, |
68 | UINT32 Flags); |
69 | |
70 | |
71 | /******************************************************************************* |
72 | * |
73 | * String conversion rules as written in the ACPI specification. The error |
74 | * conditions and behavior are different depending on the type of conversion. |
75 | * |
76 | * |
77 | * Implicit data type conversion: string-to-integer |
78 | * -------------------------------------------------- |
79 | * |
80 | * Base is always 16. This is the ACPI_STRTOUL_BASE16 case. |
81 | * |
82 | * Example: |
83 | * Add ("BA98", Arg0, Local0) |
84 | * |
85 | * The integer is initialized to the value zero. |
86 | * The ASCII string is interpreted as a hexadecimal constant. |
87 | * |
88 | * 1) A "0x" prefix is not allowed. However, ACPICA allows this for |
89 | * compatibility with previous ACPICA. (NO ERROR) |
90 | * |
91 | * 2) Terminates when the size of an integer is reached (32 or 64 bits). |
92 | * (NO ERROR) |
93 | * |
94 | * 3) The first non-hex character terminates the conversion without error. |
95 | * (NO ERROR) |
96 | * |
97 | * 4) Conversion of a null (zero-length) string to an integer is not |
98 | * allowed. However, ACPICA allows this for compatibility with previous |
99 | * ACPICA. This conversion returns the value 0. (NO ERROR) |
100 | * |
101 | * |
102 | * Explicit data type conversion: ToInteger() with string operand |
103 | * --------------------------------------------------------------- |
104 | * |
105 | * Base is either 10 (default) or 16 (with 0x prefix) |
106 | * |
107 | * Examples: |
108 | * ToInteger ("1000") |
109 | * ToInteger ("0xABCD") |
110 | * |
111 | * 1) Can be (must be) either a decimal or hexadecimal numeric string. |
112 | * A hex value must be prefixed by "0x" or it is interpreted as a decimal. |
113 | * |
114 | * 2) The value must not exceed the maximum of an integer value. ACPI spec |
115 | * states the behavior is "unpredictable", so ACPICA matches the behavior |
116 | * of the implicit conversion case.(NO ERROR) |
117 | * |
118 | * 3) Behavior on the first non-hex character is not specified by the ACPI |
119 | * spec, so ACPICA matches the behavior of the implicit conversion case |
120 | * and terminates. (NO ERROR) |
121 | * |
122 | * 4) A null (zero-length) string is illegal. |
123 | * However, ACPICA allows this for compatibility with previous ACPICA. |
124 | * This conversion returns the value 0. (NO ERROR) |
125 | * |
126 | ******************************************************************************/ |
127 | |
128 | |
129 | /******************************************************************************* |
130 | * |
131 | * FUNCTION: AcpiUtStrtoul64 |
132 | * |
133 | * PARAMETERS: String - Null terminated input string |
134 | * Flags - Conversion info, see below |
135 | * ReturnValue - Where the converted integer is |
136 | * returned |
137 | * |
138 | * RETURN: Status and Converted value |
139 | * |
140 | * DESCRIPTION: Convert a string into an unsigned value. Performs either a |
141 | * 32-bit or 64-bit conversion, depending on the input integer |
142 | * size in Flags (often the current mode of the interpreter). |
143 | * |
144 | * Values for Flags: |
145 | * ACPI_STRTOUL_32BIT - Max integer value is 32 bits |
146 | * ACPI_STRTOUL_64BIT - Max integer value is 64 bits |
147 | * ACPI_STRTOUL_BASE16 - Input string is hexadecimal. Default |
148 | * is 10/16 based on string prefix (0x). |
149 | * |
150 | * NOTES: |
151 | * Negative numbers are not supported, as they are not supported by ACPI. |
152 | * |
153 | * Supports only base 16 or base 10 strings/values. Does not |
154 | * support Octal strings, as these are not supported by ACPI. |
155 | * |
156 | * Current users of this support: |
157 | * |
158 | * Interpreter - Implicit and explicit conversions, GPE method names |
159 | * Debugger - Command line input string conversion |
160 | * iASL - Main parser, conversion of constants to integers |
161 | * iASL - Data Table Compiler parser (constant math expressions) |
162 | * iASL - Preprocessor (constant math expressions) |
163 | * AcpiDump - Input table addresses |
164 | * AcpiExec - Testing of the AcpiUtStrtoul64 function |
165 | * |
166 | * Note concerning callers: |
167 | * AcpiGbl_IntegerByteWidth can be used to set the 32/64 limit. If used, |
168 | * this global should be set to the proper width. For the core ACPICA code, |
169 | * this width depends on the DSDT version. For iASL, the default byte |
170 | * width is always 8 for the parser, but error checking is performed later |
171 | * to flag cases where a 64-bit constant is defined in a 32-bit DSDT/SSDT. |
172 | * |
173 | ******************************************************************************/ |
174 | |
175 | ACPI_STATUS |
176 | AcpiUtStrtoul64 ( |
177 | char *String, |
178 | UINT32 Flags, |
179 | UINT64 *ReturnValue) |
180 | { |
181 | ACPI_STATUS Status = AE_OK; |
182 | UINT32 Base; |
183 | |
184 | |
185 | ACPI_FUNCTION_TRACE_STR (UtStrtoul64, String); |
186 | |
187 | |
188 | /* Parameter validation */ |
189 | |
190 | if (!String || !ReturnValue) |
191 | { |
192 | return_ACPI_STATUS (AE_BAD_PARAMETER); |
193 | } |
194 | |
195 | *ReturnValue = 0; |
196 | |
197 | /* Check for zero-length string, returns 0 */ |
198 | |
199 | if (*String == 0) |
200 | { |
201 | return_ACPI_STATUS (AE_OK); |
202 | } |
203 | |
204 | /* Skip over any white space at start of string */ |
205 | |
206 | while (isspace ((int) *String)) |
207 | { |
208 | String++; |
209 | } |
210 | |
211 | /* End of string? return 0 */ |
212 | |
213 | if (*String == 0) |
214 | { |
215 | return_ACPI_STATUS (AE_OK); |
216 | } |
217 | |
218 | /* |
219 | * 1) The "0x" prefix indicates base 16. Per the ACPI specification, |
220 | * the "0x" prefix is only allowed for implicit (non-strict) conversions. |
221 | * However, we always allow it for compatibility with older ACPICA. |
222 | */ |
223 | if ((*String == ACPI_ASCII_ZERO) && |
224 | (tolower ((int) *(String + 1)) == 'x')) |
225 | { |
226 | String += 2; /* Go past the 0x */ |
227 | if (*String == 0) |
228 | { |
229 | return_ACPI_STATUS (AE_OK); /* Return value 0 */ |
230 | } |
231 | |
232 | Base = 16; |
233 | } |
234 | |
235 | /* 2) Force to base 16 (implicit conversion case) */ |
236 | |
237 | else if (Flags & ACPI_STRTOUL_BASE16) |
238 | { |
239 | Base = 16; |
240 | } |
241 | |
242 | /* 3) Default fallback is to Base 10 */ |
243 | |
244 | else |
245 | { |
246 | Base = 10; |
247 | } |
248 | |
249 | /* Skip all leading zeros */ |
250 | |
251 | while (*String == ACPI_ASCII_ZERO) |
252 | { |
253 | String++; |
254 | if (*String == 0) |
255 | { |
256 | return_ACPI_STATUS (AE_OK); /* Return value 0 */ |
257 | } |
258 | } |
259 | |
260 | /* Perform the base 16 or 10 conversion */ |
261 | |
262 | if (Base == 16) |
263 | { |
264 | *ReturnValue = AcpiUtStrtoulBase16 (String, Flags); |
265 | } |
266 | else |
267 | { |
268 | *ReturnValue = AcpiUtStrtoulBase10 (String, Flags); |
269 | } |
270 | |
271 | return_ACPI_STATUS (Status); |
272 | } |
273 | |
274 | |
275 | /******************************************************************************* |
276 | * |
277 | * FUNCTION: AcpiUtStrtoulBase10 |
278 | * |
279 | * PARAMETERS: String - Null terminated input string |
280 | * Flags - Conversion info |
281 | * |
282 | * RETURN: 64-bit converted integer |
283 | * |
284 | * DESCRIPTION: Performs a base 10 conversion of the input string to an |
285 | * integer value, either 32 or 64 bits. |
286 | * Note: String must be valid and non-null. |
287 | * |
288 | ******************************************************************************/ |
289 | |
290 | static UINT64 |
291 | AcpiUtStrtoulBase10 ( |
292 | char *String, |
293 | UINT32 Flags) |
294 | { |
295 | int AsciiDigit; |
296 | UINT64 NextValue; |
297 | UINT64 ReturnValue = 0; |
298 | |
299 | |
300 | /* Main loop: convert each ASCII byte in the input string */ |
301 | |
302 | while (*String) |
303 | { |
304 | AsciiDigit = *String; |
305 | if (!isdigit (AsciiDigit)) |
306 | { |
307 | /* Not ASCII 0-9, terminate */ |
308 | |
309 | goto Exit; |
310 | } |
311 | |
312 | /* Convert and insert (add) the decimal digit */ |
313 | |
314 | NextValue = |
315 | (ReturnValue * 10) + (AsciiDigit - ACPI_ASCII_ZERO); |
316 | |
317 | /* Check for overflow (32 or 64 bit) - return current converted value */ |
318 | |
319 | if (((Flags & ACPI_STRTOUL_32BIT) && (NextValue > ACPI_UINT32_MAX)) || |
320 | (NextValue < ReturnValue)) /* 64-bit overflow case */ |
321 | { |
322 | goto Exit; |
323 | } |
324 | |
325 | ReturnValue = NextValue; |
326 | String++; |
327 | } |
328 | |
329 | Exit: |
330 | return (ReturnValue); |
331 | } |
332 | |
333 | |
334 | /******************************************************************************* |
335 | * |
336 | * FUNCTION: AcpiUtStrtoulBase16 |
337 | * |
338 | * PARAMETERS: String - Null terminated input string |
339 | * Flags - conversion info |
340 | * |
341 | * RETURN: 64-bit converted integer |
342 | * |
343 | * DESCRIPTION: Performs a base 16 conversion of the input string to an |
344 | * integer value, either 32 or 64 bits. |
345 | * Note: String must be valid and non-null. |
346 | * |
347 | ******************************************************************************/ |
348 | |
349 | static UINT64 |
350 | AcpiUtStrtoulBase16 ( |
351 | char *String, |
352 | UINT32 Flags) |
353 | { |
354 | int AsciiDigit; |
355 | UINT32 ValidDigits = 1; |
356 | UINT64 ReturnValue = 0; |
357 | |
358 | |
359 | /* Main loop: convert each ASCII byte in the input string */ |
360 | |
361 | while (*String) |
362 | { |
363 | /* Check for overflow (32 or 64 bit) - return current converted value */ |
364 | |
365 | if ((ValidDigits > 16) || |
366 | ((ValidDigits > 8) && (Flags & ACPI_STRTOUL_32BIT))) |
367 | { |
368 | goto Exit; |
369 | } |
370 | |
371 | AsciiDigit = *String; |
372 | if (!isxdigit (AsciiDigit)) |
373 | { |
374 | /* Not Hex ASCII A-F, a-f, or 0-9, terminate */ |
375 | |
376 | goto Exit; |
377 | } |
378 | |
379 | /* Convert and insert the hex digit */ |
380 | |
381 | ReturnValue = |
382 | (ReturnValue << 4) | AcpiUtAsciiCharToHex (AsciiDigit); |
383 | |
384 | String++; |
385 | ValidDigits++; |
386 | } |
387 | |
388 | Exit: |
389 | return (ReturnValue); |
390 | } |
391 | |