Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /******************************************************************************* |
2 | * | |
3 | * Module Name: utmisc - common utility procedures | |
4 | * | |
5 | ******************************************************************************/ | |
6 | ||
7 | /* | |
8 | * Copyright (C) 2000 - 2005, R. Byron Moore | |
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 | ||
1da177e4 LT |
44 | #include <acpi/acpi.h> |
45 | #include <acpi/acnamesp.h> | |
46 | ||
1da177e4 | 47 | #define _COMPONENT ACPI_UTILITIES |
4be44fcd | 48 | ACPI_MODULE_NAME("utmisc") |
44f6c012 | 49 | |
f9f4601f RM |
50 | /******************************************************************************* |
51 | * | |
52 | * FUNCTION: acpi_ut_allocate_owner_id | |
53 | * | |
54 | * PARAMETERS: owner_id - Where the new owner ID is returned | |
55 | * | |
0c9938cc RM |
56 | * RETURN: Status |
57 | * | |
58 | * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to | |
59 | * track objects created by the table or method, to be deleted | |
60 | * when the method exits or the table is unloaded. | |
f9f4601f RM |
61 | * |
62 | ******************************************************************************/ | |
4be44fcd | 63 | acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) |
f9f4601f | 64 | { |
4be44fcd LB |
65 | acpi_native_uint i; |
66 | acpi_status status; | |
f9f4601f | 67 | |
4be44fcd | 68 | ACPI_FUNCTION_TRACE("ut_allocate_owner_id"); |
f9f4601f | 69 | |
aff8c277 RM |
70 | /* Guard against multiple allocations of ID to the same location */ |
71 | ||
72 | if (*owner_id) { | |
73 | ACPI_REPORT_ERROR(("Owner ID [%2.2X] already exists\n", | |
74 | *owner_id)); | |
75 | return_ACPI_STATUS(AE_ALREADY_EXISTS); | |
76 | } | |
77 | ||
0c9938cc RM |
78 | /* Mutex for the global ID mask */ |
79 | ||
4be44fcd LB |
80 | status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); |
81 | if (ACPI_FAILURE(status)) { | |
82 | return_ACPI_STATUS(status); | |
f9f4601f RM |
83 | } |
84 | ||
85 | /* Find a free owner ID */ | |
86 | ||
87 | for (i = 0; i < 32; i++) { | |
88 | if (!(acpi_gbl_owner_id_mask & (1 << i))) { | |
a18ecf41 BM |
89 | ACPI_DEBUG_PRINT((ACPI_DB_VALUES, |
90 | "Current owner_id mask: %8.8X New ID: %2.2X\n", | |
aff8c277 RM |
91 | acpi_gbl_owner_id_mask, |
92 | (unsigned int)(i + 1))); | |
a18ecf41 | 93 | |
f9f4601f | 94 | acpi_gbl_owner_id_mask |= (1 << i); |
0c9938cc | 95 | *owner_id = (acpi_owner_id) (i + 1); |
f9f4601f RM |
96 | goto exit; |
97 | } | |
98 | } | |
99 | ||
100 | /* | |
101 | * If we are here, all owner_ids have been allocated. This probably should | |
102 | * not happen since the IDs are reused after deallocation. The IDs are | |
103 | * allocated upon table load (one per table) and method execution, and | |
104 | * they are released when a table is unloaded or a method completes | |
105 | * execution. | |
106 | */ | |
0c9938cc | 107 | *owner_id = 0; |
f9f4601f | 108 | status = AE_OWNER_ID_LIMIT; |
4be44fcd | 109 | ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n")); |
f9f4601f | 110 | |
4be44fcd LB |
111 | exit: |
112 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); | |
113 | return_ACPI_STATUS(status); | |
f9f4601f RM |
114 | } |
115 | ||
f9f4601f RM |
116 | /******************************************************************************* |
117 | * | |
118 | * FUNCTION: acpi_ut_release_owner_id | |
119 | * | |
0c9938cc | 120 | * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD |
f9f4601f | 121 | * |
0c9938cc RM |
122 | * RETURN: None. No error is returned because we are either exiting a |
123 | * control method or unloading a table. Either way, we would | |
124 | * ignore any error anyway. | |
125 | * | |
126 | * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32 | |
f9f4601f RM |
127 | * |
128 | ******************************************************************************/ | |
129 | ||
4be44fcd | 130 | void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr) |
f9f4601f | 131 | { |
4be44fcd LB |
132 | acpi_owner_id owner_id = *owner_id_ptr; |
133 | acpi_status status; | |
f9f4601f | 134 | |
a18ecf41 | 135 | ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id); |
f9f4601f | 136 | |
0c9938cc RM |
137 | /* Always clear the input owner_id (zero is an invalid ID) */ |
138 | ||
139 | *owner_id_ptr = 0; | |
140 | ||
141 | /* Zero is not a valid owner_iD */ | |
142 | ||
143 | if ((owner_id == 0) || (owner_id > 32)) { | |
4be44fcd | 144 | ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id)); |
0c9938cc RM |
145 | return_VOID; |
146 | } | |
147 | ||
148 | /* Mutex for the global ID mask */ | |
149 | ||
4be44fcd LB |
150 | status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES); |
151 | if (ACPI_FAILURE(status)) { | |
0c9938cc | 152 | return_VOID; |
f9f4601f RM |
153 | } |
154 | ||
aff8c277 RM |
155 | /* Normalize the ID to zero */ |
156 | ||
157 | owner_id--; | |
0c9938cc RM |
158 | |
159 | /* Free the owner ID only if it is valid */ | |
f9f4601f RM |
160 | |
161 | if (acpi_gbl_owner_id_mask & (1 << owner_id)) { | |
162 | acpi_gbl_owner_id_mask ^= (1 << owner_id); | |
163 | } | |
f9f4601f | 164 | |
4be44fcd | 165 | (void)acpi_ut_release_mutex(ACPI_MTX_CACHES); |
0c9938cc | 166 | return_VOID; |
f9f4601f RM |
167 | } |
168 | ||
44f6c012 RM |
169 | /******************************************************************************* |
170 | * | |
171 | * FUNCTION: acpi_ut_strupr (strupr) | |
172 | * | |
173 | * PARAMETERS: src_string - The source string to convert | |
174 | * | |
0c9938cc | 175 | * RETURN: None |
44f6c012 RM |
176 | * |
177 | * DESCRIPTION: Convert string to uppercase | |
178 | * | |
179 | * NOTE: This is not a POSIX function, so it appears here, not in utclib.c | |
180 | * | |
181 | ******************************************************************************/ | |
182 | ||
4be44fcd | 183 | void acpi_ut_strupr(char *src_string) |
44f6c012 | 184 | { |
4be44fcd | 185 | char *string; |
44f6c012 | 186 | |
4be44fcd | 187 | ACPI_FUNCTION_ENTRY(); |
44f6c012 | 188 | |
73459f73 | 189 | if (!src_string) { |
0c9938cc | 190 | return; |
73459f73 RM |
191 | } |
192 | ||
44f6c012 RM |
193 | /* Walk entire string, uppercasing the letters */ |
194 | ||
195 | for (string = src_string; *string; string++) { | |
4be44fcd | 196 | *string = (char)ACPI_TOUPPER(*string); |
44f6c012 RM |
197 | } |
198 | ||
0c9938cc | 199 | return; |
44f6c012 RM |
200 | } |
201 | ||
1da177e4 LT |
202 | /******************************************************************************* |
203 | * | |
204 | * FUNCTION: acpi_ut_print_string | |
205 | * | |
206 | * PARAMETERS: String - Null terminated ASCII string | |
44f6c012 | 207 | * max_length - Maximum output length |
1da177e4 LT |
208 | * |
209 | * RETURN: None | |
210 | * | |
211 | * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape | |
212 | * sequences. | |
213 | * | |
214 | ******************************************************************************/ | |
215 | ||
4be44fcd | 216 | void acpi_ut_print_string(char *string, u8 max_length) |
1da177e4 | 217 | { |
4be44fcd | 218 | u32 i; |
1da177e4 LT |
219 | |
220 | if (!string) { | |
4be44fcd | 221 | acpi_os_printf("<\"NULL STRING PTR\">"); |
1da177e4 LT |
222 | return; |
223 | } | |
224 | ||
4be44fcd | 225 | acpi_os_printf("\""); |
1da177e4 LT |
226 | for (i = 0; string[i] && (i < max_length); i++) { |
227 | /* Escape sequences */ | |
228 | ||
229 | switch (string[i]) { | |
230 | case 0x07: | |
4be44fcd | 231 | acpi_os_printf("\\a"); /* BELL */ |
1da177e4 LT |
232 | break; |
233 | ||
234 | case 0x08: | |
4be44fcd | 235 | acpi_os_printf("\\b"); /* BACKSPACE */ |
1da177e4 LT |
236 | break; |
237 | ||
238 | case 0x0C: | |
4be44fcd | 239 | acpi_os_printf("\\f"); /* FORMFEED */ |
1da177e4 LT |
240 | break; |
241 | ||
242 | case 0x0A: | |
4be44fcd | 243 | acpi_os_printf("\\n"); /* LINEFEED */ |
1da177e4 LT |
244 | break; |
245 | ||
246 | case 0x0D: | |
4be44fcd | 247 | acpi_os_printf("\\r"); /* CARRIAGE RETURN */ |
1da177e4 LT |
248 | break; |
249 | ||
250 | case 0x09: | |
4be44fcd | 251 | acpi_os_printf("\\t"); /* HORIZONTAL TAB */ |
1da177e4 LT |
252 | break; |
253 | ||
254 | case 0x0B: | |
4be44fcd | 255 | acpi_os_printf("\\v"); /* VERTICAL TAB */ |
1da177e4 LT |
256 | break; |
257 | ||
4be44fcd LB |
258 | case '\'': /* Single Quote */ |
259 | case '\"': /* Double Quote */ | |
260 | case '\\': /* Backslash */ | |
261 | acpi_os_printf("\\%c", (int)string[i]); | |
1da177e4 LT |
262 | break; |
263 | ||
264 | default: | |
265 | ||
266 | /* Check for printable character or hex escape */ | |
267 | ||
4be44fcd | 268 | if (ACPI_IS_PRINT(string[i])) { |
1da177e4 LT |
269 | /* This is a normal character */ |
270 | ||
4be44fcd LB |
271 | acpi_os_printf("%c", (int)string[i]); |
272 | } else { | |
1da177e4 LT |
273 | /* All others will be Hex escapes */ |
274 | ||
4be44fcd | 275 | acpi_os_printf("\\x%2.2X", (s32) string[i]); |
1da177e4 LT |
276 | } |
277 | break; | |
278 | } | |
279 | } | |
4be44fcd | 280 | acpi_os_printf("\""); |
1da177e4 LT |
281 | |
282 | if (i == max_length && string[i]) { | |
4be44fcd | 283 | acpi_os_printf("..."); |
1da177e4 LT |
284 | } |
285 | } | |
286 | ||
1da177e4 LT |
287 | /******************************************************************************* |
288 | * | |
289 | * FUNCTION: acpi_ut_dword_byte_swap | |
290 | * | |
291 | * PARAMETERS: Value - Value to be converted | |
292 | * | |
44f6c012 RM |
293 | * RETURN: u32 integer with bytes swapped |
294 | * | |
1da177e4 LT |
295 | * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) |
296 | * | |
297 | ******************************************************************************/ | |
298 | ||
4be44fcd | 299 | u32 acpi_ut_dword_byte_swap(u32 value) |
1da177e4 LT |
300 | { |
301 | union { | |
4be44fcd LB |
302 | u32 value; |
303 | u8 bytes[4]; | |
1da177e4 | 304 | } out; |
1da177e4 | 305 | union { |
4be44fcd LB |
306 | u32 value; |
307 | u8 bytes[4]; | |
1da177e4 LT |
308 | } in; |
309 | ||
4be44fcd | 310 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
311 | |
312 | in.value = value; | |
313 | ||
314 | out.bytes[0] = in.bytes[3]; | |
315 | out.bytes[1] = in.bytes[2]; | |
316 | out.bytes[2] = in.bytes[1]; | |
317 | out.bytes[3] = in.bytes[0]; | |
318 | ||
319 | return (out.value); | |
320 | } | |
321 | ||
1da177e4 LT |
322 | /******************************************************************************* |
323 | * | |
324 | * FUNCTION: acpi_ut_set_integer_width | |
325 | * | |
326 | * PARAMETERS: Revision From DSDT header | |
327 | * | |
328 | * RETURN: None | |
329 | * | |
330 | * DESCRIPTION: Set the global integer bit width based upon the revision | |
331 | * of the DSDT. For Revision 1 and 0, Integers are 32 bits. | |
332 | * For Revision 2 and above, Integers are 64 bits. Yes, this | |
333 | * makes a difference. | |
334 | * | |
335 | ******************************************************************************/ | |
336 | ||
4be44fcd | 337 | void acpi_ut_set_integer_width(u8 revision) |
1da177e4 LT |
338 | { |
339 | ||
340 | if (revision <= 1) { | |
341 | acpi_gbl_integer_bit_width = 32; | |
342 | acpi_gbl_integer_nybble_width = 8; | |
343 | acpi_gbl_integer_byte_width = 4; | |
4be44fcd | 344 | } else { |
1da177e4 LT |
345 | acpi_gbl_integer_bit_width = 64; |
346 | acpi_gbl_integer_nybble_width = 16; | |
347 | acpi_gbl_integer_byte_width = 8; | |
348 | } | |
349 | } | |
350 | ||
1da177e4 LT |
351 | #ifdef ACPI_DEBUG_OUTPUT |
352 | /******************************************************************************* | |
353 | * | |
354 | * FUNCTION: acpi_ut_display_init_pathname | |
355 | * | |
44f6c012 RM |
356 | * PARAMETERS: Type - Object type of the node |
357 | * obj_handle - Handle whose pathname will be displayed | |
1da177e4 LT |
358 | * Path - Additional path string to be appended. |
359 | * (NULL if no extra path) | |
360 | * | |
361 | * RETURN: acpi_status | |
362 | * | |
363 | * DESCRIPTION: Display full pathname of an object, DEBUG ONLY | |
364 | * | |
365 | ******************************************************************************/ | |
366 | ||
367 | void | |
4be44fcd LB |
368 | acpi_ut_display_init_pathname(u8 type, |
369 | struct acpi_namespace_node *obj_handle, | |
370 | char *path) | |
1da177e4 | 371 | { |
4be44fcd LB |
372 | acpi_status status; |
373 | struct acpi_buffer buffer; | |
1da177e4 | 374 | |
4be44fcd | 375 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
376 | |
377 | /* Only print the path if the appropriate debug level is enabled */ | |
378 | ||
379 | if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { | |
380 | return; | |
381 | } | |
382 | ||
383 | /* Get the full pathname to the node */ | |
384 | ||
385 | buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | |
4be44fcd LB |
386 | status = acpi_ns_handle_to_pathname(obj_handle, &buffer); |
387 | if (ACPI_FAILURE(status)) { | |
1da177e4 LT |
388 | return; |
389 | } | |
390 | ||
391 | /* Print what we're doing */ | |
392 | ||
393 | switch (type) { | |
394 | case ACPI_TYPE_METHOD: | |
4be44fcd | 395 | acpi_os_printf("Executing "); |
1da177e4 LT |
396 | break; |
397 | ||
398 | default: | |
4be44fcd | 399 | acpi_os_printf("Initializing "); |
1da177e4 LT |
400 | break; |
401 | } | |
402 | ||
403 | /* Print the object type and pathname */ | |
404 | ||
4be44fcd LB |
405 | acpi_os_printf("%-12s %s", |
406 | acpi_ut_get_type_name(type), (char *)buffer.pointer); | |
1da177e4 LT |
407 | |
408 | /* Extra path is used to append names like _STA, _INI, etc. */ | |
409 | ||
410 | if (path) { | |
4be44fcd | 411 | acpi_os_printf(".%s", path); |
1da177e4 | 412 | } |
4be44fcd | 413 | acpi_os_printf("\n"); |
1da177e4 | 414 | |
4be44fcd | 415 | ACPI_MEM_FREE(buffer.pointer); |
1da177e4 LT |
416 | } |
417 | #endif | |
418 | ||
1da177e4 LT |
419 | /******************************************************************************* |
420 | * | |
421 | * FUNCTION: acpi_ut_valid_acpi_name | |
422 | * | |
44f6c012 | 423 | * PARAMETERS: Name - The name to be examined |
1da177e4 | 424 | * |
44f6c012 | 425 | * RETURN: TRUE if the name is valid, FALSE otherwise |
1da177e4 LT |
426 | * |
427 | * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: | |
428 | * 1) Upper case alpha | |
429 | * 2) numeric | |
430 | * 3) underscore | |
431 | * | |
432 | ******************************************************************************/ | |
433 | ||
4be44fcd | 434 | u8 acpi_ut_valid_acpi_name(u32 name) |
1da177e4 | 435 | { |
4be44fcd LB |
436 | char *name_ptr = (char *)&name; |
437 | char character; | |
438 | acpi_native_uint i; | |
1da177e4 | 439 | |
4be44fcd | 440 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
441 | |
442 | for (i = 0; i < ACPI_NAME_SIZE; i++) { | |
443 | character = *name_ptr; | |
444 | name_ptr++; | |
445 | ||
446 | if (!((character == '_') || | |
4be44fcd LB |
447 | (character >= 'A' && character <= 'Z') || |
448 | (character >= '0' && character <= '9'))) { | |
1da177e4 LT |
449 | return (FALSE); |
450 | } | |
451 | } | |
452 | ||
453 | return (TRUE); | |
454 | } | |
455 | ||
1da177e4 LT |
456 | /******************************************************************************* |
457 | * | |
458 | * FUNCTION: acpi_ut_valid_acpi_character | |
459 | * | |
460 | * PARAMETERS: Character - The character to be examined | |
461 | * | |
462 | * RETURN: 1 if Character may appear in a name, else 0 | |
463 | * | |
464 | * DESCRIPTION: Check for a printable character | |
465 | * | |
466 | ******************************************************************************/ | |
467 | ||
4be44fcd | 468 | u8 acpi_ut_valid_acpi_character(char character) |
1da177e4 LT |
469 | { |
470 | ||
4be44fcd | 471 | ACPI_FUNCTION_ENTRY(); |
1da177e4 | 472 | |
4be44fcd LB |
473 | return ((u8) ((character == '_') || |
474 | (character >= 'A' && character <= 'Z') || | |
475 | (character >= '0' && character <= '9'))); | |
1da177e4 LT |
476 | } |
477 | ||
1da177e4 LT |
478 | /******************************************************************************* |
479 | * | |
480 | * FUNCTION: acpi_ut_strtoul64 | |
481 | * | |
482 | * PARAMETERS: String - Null terminated string | |
483 | * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE | |
484 | * ret_integer - Where the converted integer is returned | |
485 | * | |
486 | * RETURN: Status and Converted value | |
487 | * | |
488 | * DESCRIPTION: Convert a string into an unsigned value. | |
489 | * NOTE: Does not support Octal strings, not needed. | |
490 | * | |
491 | ******************************************************************************/ | |
492 | ||
493 | acpi_status | |
4be44fcd | 494 | acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer) |
1da177e4 | 495 | { |
4be44fcd LB |
496 | u32 this_digit = 0; |
497 | acpi_integer return_value = 0; | |
498 | acpi_integer quotient; | |
1da177e4 | 499 | |
4be44fcd | 500 | ACPI_FUNCTION_TRACE("ut_stroul64"); |
1da177e4 LT |
501 | |
502 | if ((!string) || !(*string)) { | |
503 | goto error_exit; | |
504 | } | |
505 | ||
506 | switch (base) { | |
507 | case ACPI_ANY_BASE: | |
508 | case 10: | |
509 | case 16: | |
510 | break; | |
511 | ||
512 | default: | |
513 | /* Invalid Base */ | |
4be44fcd | 514 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
1da177e4 LT |
515 | } |
516 | ||
517 | /* Skip over any white space in the buffer */ | |
518 | ||
4be44fcd | 519 | while (ACPI_IS_SPACE(*string) || *string == '\t') { |
1da177e4 LT |
520 | string++; |
521 | } | |
522 | ||
523 | /* | |
524 | * If the input parameter Base is zero, then we need to | |
525 | * determine if it is decimal or hexadecimal: | |
526 | */ | |
527 | if (base == 0) { | |
4be44fcd | 528 | if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { |
1da177e4 LT |
529 | base = 16; |
530 | string += 2; | |
4be44fcd | 531 | } else { |
1da177e4 LT |
532 | base = 10; |
533 | } | |
534 | } | |
535 | ||
536 | /* | |
537 | * For hexadecimal base, skip over the leading | |
538 | * 0 or 0x, if they are present. | |
539 | */ | |
540 | if ((base == 16) && | |
4be44fcd | 541 | (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { |
1da177e4 LT |
542 | string += 2; |
543 | } | |
544 | ||
545 | /* Any string left? */ | |
546 | ||
547 | if (!(*string)) { | |
548 | goto error_exit; | |
549 | } | |
550 | ||
551 | /* Main loop: convert the string to a 64-bit integer */ | |
552 | ||
553 | while (*string) { | |
4be44fcd | 554 | if (ACPI_IS_DIGIT(*string)) { |
1da177e4 LT |
555 | /* Convert ASCII 0-9 to Decimal value */ |
556 | ||
4be44fcd LB |
557 | this_digit = ((u8) * string) - '0'; |
558 | } else { | |
1da177e4 LT |
559 | if (base == 10) { |
560 | /* Digit is out of range */ | |
561 | ||
562 | goto error_exit; | |
563 | } | |
564 | ||
4be44fcd LB |
565 | this_digit = (u8) ACPI_TOUPPER(*string); |
566 | if (ACPI_IS_XDIGIT((char)this_digit)) { | |
1da177e4 LT |
567 | /* Convert ASCII Hex char to value */ |
568 | ||
569 | this_digit = this_digit - 'A' + 10; | |
4be44fcd | 570 | } else { |
1da177e4 LT |
571 | /* |
572 | * We allow non-hex chars, just stop now, same as end-of-string. | |
573 | * See ACPI spec, string-to-integer conversion. | |
574 | */ | |
575 | break; | |
576 | } | |
577 | } | |
578 | ||
579 | /* Divide the digit into the correct position */ | |
580 | ||
4be44fcd LB |
581 | (void) |
582 | acpi_ut_short_divide((ACPI_INTEGER_MAX - | |
583 | (acpi_integer) this_digit), base, | |
584 | "ient, NULL); | |
1da177e4 LT |
585 | if (return_value > quotient) { |
586 | goto error_exit; | |
587 | } | |
588 | ||
589 | return_value *= base; | |
590 | return_value += this_digit; | |
591 | string++; | |
592 | } | |
593 | ||
594 | /* All done, normal exit */ | |
595 | ||
596 | *ret_integer = return_value; | |
4be44fcd | 597 | return_ACPI_STATUS(AE_OK); |
1da177e4 | 598 | |
4be44fcd | 599 | error_exit: |
1da177e4 LT |
600 | /* Base was set/validated above */ |
601 | ||
602 | if (base == 10) { | |
4be44fcd LB |
603 | return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT); |
604 | } else { | |
605 | return_ACPI_STATUS(AE_BAD_HEX_CONSTANT); | |
1da177e4 LT |
606 | } |
607 | } | |
608 | ||
1da177e4 LT |
609 | /******************************************************************************* |
610 | * | |
611 | * FUNCTION: acpi_ut_create_update_state_and_push | |
612 | * | |
44f6c012 | 613 | * PARAMETERS: Object - Object to be added to the new state |
1da177e4 LT |
614 | * Action - Increment/Decrement |
615 | * state_list - List the state will be added to | |
616 | * | |
44f6c012 | 617 | * RETURN: Status |
1da177e4 LT |
618 | * |
619 | * DESCRIPTION: Create a new state and push it | |
620 | * | |
621 | ******************************************************************************/ | |
622 | ||
623 | acpi_status | |
4be44fcd LB |
624 | acpi_ut_create_update_state_and_push(union acpi_operand_object *object, |
625 | u16 action, | |
626 | union acpi_generic_state **state_list) | |
1da177e4 | 627 | { |
4be44fcd | 628 | union acpi_generic_state *state; |
1da177e4 | 629 | |
4be44fcd | 630 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
631 | |
632 | /* Ignore null objects; these are expected */ | |
633 | ||
634 | if (!object) { | |
635 | return (AE_OK); | |
636 | } | |
637 | ||
4be44fcd | 638 | state = acpi_ut_create_update_state(object, action); |
1da177e4 LT |
639 | if (!state) { |
640 | return (AE_NO_MEMORY); | |
641 | } | |
642 | ||
4be44fcd | 643 | acpi_ut_push_generic_state(state_list, state); |
1da177e4 LT |
644 | return (AE_OK); |
645 | } | |
646 | ||
1da177e4 LT |
647 | /******************************************************************************* |
648 | * | |
649 | * FUNCTION: acpi_ut_walk_package_tree | |
650 | * | |
44f6c012 RM |
651 | * PARAMETERS: source_object - The package to walk |
652 | * target_object - Target object (if package is being copied) | |
653 | * walk_callback - Called once for each package element | |
654 | * Context - Passed to the callback function | |
1da177e4 LT |
655 | * |
656 | * RETURN: Status | |
657 | * | |
658 | * DESCRIPTION: Walk through a package | |
659 | * | |
660 | ******************************************************************************/ | |
661 | ||
662 | acpi_status | |
4be44fcd LB |
663 | acpi_ut_walk_package_tree(union acpi_operand_object * source_object, |
664 | void *target_object, | |
665 | acpi_pkg_callback walk_callback, void *context) | |
1da177e4 | 666 | { |
4be44fcd LB |
667 | acpi_status status = AE_OK; |
668 | union acpi_generic_state *state_list = NULL; | |
669 | union acpi_generic_state *state; | |
670 | u32 this_index; | |
671 | union acpi_operand_object *this_source_obj; | |
1da177e4 | 672 | |
4be44fcd | 673 | ACPI_FUNCTION_TRACE("ut_walk_package_tree"); |
1da177e4 | 674 | |
4be44fcd | 675 | state = acpi_ut_create_pkg_state(source_object, target_object, 0); |
1da177e4 | 676 | if (!state) { |
4be44fcd | 677 | return_ACPI_STATUS(AE_NO_MEMORY); |
1da177e4 LT |
678 | } |
679 | ||
680 | while (state) { | |
681 | /* Get one element of the package */ | |
682 | ||
4be44fcd | 683 | this_index = state->pkg.index; |
1da177e4 | 684 | this_source_obj = (union acpi_operand_object *) |
4be44fcd | 685 | state->pkg.source_object->package.elements[this_index]; |
1da177e4 LT |
686 | |
687 | /* | |
688 | * Check for: | |
689 | * 1) An uninitialized package element. It is completely | |
690 | * legal to declare a package and leave it uninitialized | |
691 | * 2) Not an internal object - can be a namespace node instead | |
692 | * 3) Any type other than a package. Packages are handled in else | |
693 | * case below. | |
694 | */ | |
695 | if ((!this_source_obj) || | |
4be44fcd LB |
696 | (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) != |
697 | ACPI_DESC_TYPE_OPERAND) | |
698 | || (ACPI_GET_OBJECT_TYPE(this_source_obj) != | |
699 | ACPI_TYPE_PACKAGE)) { | |
700 | status = | |
701 | walk_callback(ACPI_COPY_TYPE_SIMPLE, | |
702 | this_source_obj, state, context); | |
703 | if (ACPI_FAILURE(status)) { | |
704 | return_ACPI_STATUS(status); | |
1da177e4 LT |
705 | } |
706 | ||
707 | state->pkg.index++; | |
4be44fcd LB |
708 | while (state->pkg.index >= |
709 | state->pkg.source_object->package.count) { | |
1da177e4 LT |
710 | /* |
711 | * We've handled all of the objects at this level, This means | |
712 | * that we have just completed a package. That package may | |
713 | * have contained one or more packages itself. | |
714 | * | |
715 | * Delete this state and pop the previous state (package). | |
716 | */ | |
4be44fcd LB |
717 | acpi_ut_delete_generic_state(state); |
718 | state = acpi_ut_pop_generic_state(&state_list); | |
1da177e4 LT |
719 | |
720 | /* Finished when there are no more states */ | |
721 | ||
722 | if (!state) { | |
723 | /* | |
724 | * We have handled all of the objects in the top level | |
725 | * package just add the length of the package objects | |
726 | * and exit | |
727 | */ | |
4be44fcd | 728 | return_ACPI_STATUS(AE_OK); |
1da177e4 LT |
729 | } |
730 | ||
731 | /* | |
732 | * Go back up a level and move the index past the just | |
733 | * completed package object. | |
734 | */ | |
735 | state->pkg.index++; | |
736 | } | |
4be44fcd | 737 | } else { |
1da177e4 LT |
738 | /* This is a subobject of type package */ |
739 | ||
4be44fcd LB |
740 | status = |
741 | walk_callback(ACPI_COPY_TYPE_PACKAGE, | |
742 | this_source_obj, state, context); | |
743 | if (ACPI_FAILURE(status)) { | |
744 | return_ACPI_STATUS(status); | |
1da177e4 LT |
745 | } |
746 | ||
747 | /* | |
748 | * Push the current state and create a new one | |
749 | * The callback above returned a new target package object. | |
750 | */ | |
4be44fcd LB |
751 | acpi_ut_push_generic_state(&state_list, state); |
752 | state = acpi_ut_create_pkg_state(this_source_obj, | |
753 | state->pkg. | |
754 | this_target_obj, 0); | |
1da177e4 | 755 | if (!state) { |
4be44fcd | 756 | return_ACPI_STATUS(AE_NO_MEMORY); |
1da177e4 LT |
757 | } |
758 | } | |
759 | } | |
760 | ||
761 | /* We should never get here */ | |
762 | ||
4be44fcd | 763 | return_ACPI_STATUS(AE_AML_INTERNAL); |
1da177e4 LT |
764 | } |
765 | ||
1da177e4 LT |
766 | /******************************************************************************* |
767 | * | |
768 | * FUNCTION: acpi_ut_generate_checksum | |
769 | * | |
770 | * PARAMETERS: Buffer - Buffer to be scanned | |
771 | * Length - number of bytes to examine | |
772 | * | |
44f6c012 | 773 | * RETURN: The generated checksum |
1da177e4 LT |
774 | * |
775 | * DESCRIPTION: Generate a checksum on a raw buffer | |
776 | * | |
777 | ******************************************************************************/ | |
778 | ||
4be44fcd | 779 | u8 acpi_ut_generate_checksum(u8 * buffer, u32 length) |
1da177e4 | 780 | { |
4be44fcd LB |
781 | u32 i; |
782 | signed char sum = 0; | |
1da177e4 LT |
783 | |
784 | for (i = 0; i < length; i++) { | |
4be44fcd | 785 | sum = (signed char)(sum + buffer[i]); |
1da177e4 LT |
786 | } |
787 | ||
788 | return ((u8) (0 - sum)); | |
789 | } | |
790 | ||
1da177e4 LT |
791 | /******************************************************************************* |
792 | * | |
793 | * FUNCTION: acpi_ut_report_error | |
794 | * | |
795 | * PARAMETERS: module_name - Caller's module name (for error output) | |
796 | * line_number - Caller's line number (for error output) | |
797 | * component_id - Caller's component ID (for error output) | |
1da177e4 LT |
798 | * |
799 | * RETURN: None | |
800 | * | |
801 | * DESCRIPTION: Print error message | |
802 | * | |
803 | ******************************************************************************/ | |
804 | ||
4be44fcd | 805 | void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id) |
1da177e4 LT |
806 | { |
807 | ||
4be44fcd | 808 | acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number); |
1da177e4 LT |
809 | } |
810 | ||
1da177e4 LT |
811 | /******************************************************************************* |
812 | * | |
813 | * FUNCTION: acpi_ut_report_warning | |
814 | * | |
815 | * PARAMETERS: module_name - Caller's module name (for error output) | |
816 | * line_number - Caller's line number (for error output) | |
817 | * component_id - Caller's component ID (for error output) | |
1da177e4 LT |
818 | * |
819 | * RETURN: None | |
820 | * | |
821 | * DESCRIPTION: Print warning message | |
822 | * | |
823 | ******************************************************************************/ | |
824 | ||
825 | void | |
4be44fcd | 826 | acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id) |
1da177e4 LT |
827 | { |
828 | ||
4be44fcd | 829 | acpi_os_printf("%8s-%04d: *** Warning: ", module_name, line_number); |
1da177e4 LT |
830 | } |
831 | ||
1da177e4 LT |
832 | /******************************************************************************* |
833 | * | |
834 | * FUNCTION: acpi_ut_report_info | |
835 | * | |
836 | * PARAMETERS: module_name - Caller's module name (for error output) | |
837 | * line_number - Caller's line number (for error output) | |
838 | * component_id - Caller's component ID (for error output) | |
1da177e4 LT |
839 | * |
840 | * RETURN: None | |
841 | * | |
842 | * DESCRIPTION: Print information message | |
843 | * | |
844 | ******************************************************************************/ | |
845 | ||
4be44fcd | 846 | void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id) |
1da177e4 LT |
847 | { |
848 | ||
4be44fcd | 849 | acpi_os_printf("%8s-%04d: *** Info: ", module_name, line_number); |
1da177e4 | 850 | } |