blob: f0275025b718d7c45ce10046e3cf86d75a6392df [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*******************************************************************************
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#include <acpi/acpi.h>
45#include <acpi/acnamesp.h>
46
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#define _COMPONENT ACPI_UTILITIES
Len Brown4be44fc2005-08-05 00:44:28 -040048ACPI_MODULE_NAME("utmisc")
Robert Moore44f6c012005-04-18 22:49:35 -040049
50/*******************************************************************************
51 *
Robert Mooref9f46012005-07-08 00:00:00 -040052 * FUNCTION: acpi_ut_allocate_owner_id
53 *
54 * PARAMETERS: owner_id - Where the new owner ID is returned
55 *
Robert Moore0c9938c2005-07-29 15:15:00 -070056 * 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.
Robert Mooref9f46012005-07-08 00:00:00 -040061 *
62 ******************************************************************************/
Len Brown4be44fc2005-08-05 00:44:28 -040063acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
Robert Mooref9f46012005-07-08 00:00:00 -040064{
Len Brown4be44fc2005-08-05 00:44:28 -040065 acpi_native_uint i;
66 acpi_status status;
Robert Mooref9f46012005-07-08 00:00:00 -040067
Len Brown4be44fc2005-08-05 00:44:28 -040068 ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
Robert Mooref9f46012005-07-08 00:00:00 -040069
Robert Moore0c9938c2005-07-29 15:15:00 -070070 /* Mutex for the global ID mask */
71
Len Brown4be44fc2005-08-05 00:44:28 -040072 status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
73 if (ACPI_FAILURE(status)) {
74 return_ACPI_STATUS(status);
Robert Mooref9f46012005-07-08 00:00:00 -040075 }
76
77 /* Find a free owner ID */
78
79 for (i = 0; i < 32; i++) {
80 if (!(acpi_gbl_owner_id_mask & (1 << i))) {
Bob Moorea18ecf42005-08-15 03:42:00 -080081 ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
82 "Current owner_id mask: %8.8X New ID: %2.2X\n",
83 acpi_gbl_owner_id_mask, (i + 1)));
84
Robert Mooref9f46012005-07-08 00:00:00 -040085 acpi_gbl_owner_id_mask |= (1 << i);
Robert Moore0c9938c2005-07-29 15:15:00 -070086 *owner_id = (acpi_owner_id) (i + 1);
Robert Mooref9f46012005-07-08 00:00:00 -040087 goto exit;
88 }
89 }
90
91 /*
92 * If we are here, all owner_ids have been allocated. This probably should
93 * not happen since the IDs are reused after deallocation. The IDs are
94 * allocated upon table load (one per table) and method execution, and
95 * they are released when a table is unloaded or a method completes
96 * execution.
97 */
Robert Moore0c9938c2005-07-29 15:15:00 -070098 *owner_id = 0;
Robert Mooref9f46012005-07-08 00:00:00 -040099 status = AE_OWNER_ID_LIMIT;
Len Brown4be44fc2005-08-05 00:44:28 -0400100 ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n"));
Robert Mooref9f46012005-07-08 00:00:00 -0400101
Len Brown4be44fc2005-08-05 00:44:28 -0400102 exit:
103 (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
104 return_ACPI_STATUS(status);
Robert Mooref9f46012005-07-08 00:00:00 -0400105}
106
Robert Mooref9f46012005-07-08 00:00:00 -0400107/*******************************************************************************
108 *
109 * FUNCTION: acpi_ut_release_owner_id
110 *
Robert Moore0c9938c2005-07-29 15:15:00 -0700111 * PARAMETERS: owner_id_ptr - Pointer to a previously allocated owner_iD
Robert Mooref9f46012005-07-08 00:00:00 -0400112 *
Robert Moore0c9938c2005-07-29 15:15:00 -0700113 * RETURN: None. No error is returned because we are either exiting a
114 * control method or unloading a table. Either way, we would
115 * ignore any error anyway.
116 *
117 * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 32
Robert Mooref9f46012005-07-08 00:00:00 -0400118 *
119 ******************************************************************************/
120
Len Brown4be44fc2005-08-05 00:44:28 -0400121void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
Robert Mooref9f46012005-07-08 00:00:00 -0400122{
Len Brown4be44fc2005-08-05 00:44:28 -0400123 acpi_owner_id owner_id = *owner_id_ptr;
124 acpi_status status;
Robert Mooref9f46012005-07-08 00:00:00 -0400125
Bob Moorea18ecf42005-08-15 03:42:00 -0800126 ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id);
Robert Mooref9f46012005-07-08 00:00:00 -0400127
Robert Moore0c9938c2005-07-29 15:15:00 -0700128 /* Always clear the input owner_id (zero is an invalid ID) */
129
130 *owner_id_ptr = 0;
131
132 /* Zero is not a valid owner_iD */
133
134 if ((owner_id == 0) || (owner_id > 32)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400135 ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id));
Robert Moore0c9938c2005-07-29 15:15:00 -0700136 return_VOID;
Robert Mooref9f46012005-07-08 00:00:00 -0400137 }
138
Robert Moore0c9938c2005-07-29 15:15:00 -0700139 /* Mutex for the global ID mask */
140
Len Brown4be44fc2005-08-05 00:44:28 -0400141 status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
142 if (ACPI_FAILURE(status)) {
Robert Moore0c9938c2005-07-29 15:15:00 -0700143 return_VOID;
144 }
145
Len Brown4be44fc2005-08-05 00:44:28 -0400146 owner_id--; /* Normalize to zero */
Robert Moore0c9938c2005-07-29 15:15:00 -0700147
148 /* Free the owner ID only if it is valid */
Robert Mooref9f46012005-07-08 00:00:00 -0400149
150 if (acpi_gbl_owner_id_mask & (1 << owner_id)) {
151 acpi_gbl_owner_id_mask ^= (1 << owner_id);
152 }
Robert Mooref9f46012005-07-08 00:00:00 -0400153
Len Brown4be44fc2005-08-05 00:44:28 -0400154 (void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
Robert Moore0c9938c2005-07-29 15:15:00 -0700155 return_VOID;
Robert Mooref9f46012005-07-08 00:00:00 -0400156}
157
Robert Mooref9f46012005-07-08 00:00:00 -0400158/*******************************************************************************
159 *
Robert Moore44f6c012005-04-18 22:49:35 -0400160 * FUNCTION: acpi_ut_strupr (strupr)
161 *
162 * PARAMETERS: src_string - The source string to convert
163 *
Robert Moore0c9938c2005-07-29 15:15:00 -0700164 * RETURN: None
Robert Moore44f6c012005-04-18 22:49:35 -0400165 *
166 * DESCRIPTION: Convert string to uppercase
167 *
168 * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
169 *
170 ******************************************************************************/
171
Len Brown4be44fc2005-08-05 00:44:28 -0400172void acpi_ut_strupr(char *src_string)
Robert Moore44f6c012005-04-18 22:49:35 -0400173{
Len Brown4be44fc2005-08-05 00:44:28 -0400174 char *string;
Robert Moore44f6c012005-04-18 22:49:35 -0400175
Len Brown4be44fc2005-08-05 00:44:28 -0400176 ACPI_FUNCTION_ENTRY();
Robert Moore44f6c012005-04-18 22:49:35 -0400177
Robert Moore73459f72005-06-24 00:00:00 -0400178 if (!src_string) {
Robert Moore0c9938c2005-07-29 15:15:00 -0700179 return;
Robert Moore73459f72005-06-24 00:00:00 -0400180 }
181
Robert Moore44f6c012005-04-18 22:49:35 -0400182 /* Walk entire string, uppercasing the letters */
183
184 for (string = src_string; *string; string++) {
Len Brown4be44fc2005-08-05 00:44:28 -0400185 *string = (char)ACPI_TOUPPER(*string);
Robert Moore44f6c012005-04-18 22:49:35 -0400186 }
187
Robert Moore0c9938c2005-07-29 15:15:00 -0700188 return;
Robert Moore44f6c012005-04-18 22:49:35 -0400189}
190
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191/*******************************************************************************
192 *
193 * FUNCTION: acpi_ut_print_string
194 *
195 * PARAMETERS: String - Null terminated ASCII string
Robert Moore44f6c012005-04-18 22:49:35 -0400196 * max_length - Maximum output length
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 *
198 * RETURN: None
199 *
200 * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
201 * sequences.
202 *
203 ******************************************************************************/
204
Len Brown4be44fc2005-08-05 00:44:28 -0400205void acpi_ut_print_string(char *string, u8 max_length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206{
Len Brown4be44fc2005-08-05 00:44:28 -0400207 u32 i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
209 if (!string) {
Len Brown4be44fc2005-08-05 00:44:28 -0400210 acpi_os_printf("<\"NULL STRING PTR\">");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 return;
212 }
213
Len Brown4be44fc2005-08-05 00:44:28 -0400214 acpi_os_printf("\"");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 for (i = 0; string[i] && (i < max_length); i++) {
216 /* Escape sequences */
217
218 switch (string[i]) {
219 case 0x07:
Len Brown4be44fc2005-08-05 00:44:28 -0400220 acpi_os_printf("\\a"); /* BELL */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 break;
222
223 case 0x08:
Len Brown4be44fc2005-08-05 00:44:28 -0400224 acpi_os_printf("\\b"); /* BACKSPACE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225 break;
226
227 case 0x0C:
Len Brown4be44fc2005-08-05 00:44:28 -0400228 acpi_os_printf("\\f"); /* FORMFEED */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 break;
230
231 case 0x0A:
Len Brown4be44fc2005-08-05 00:44:28 -0400232 acpi_os_printf("\\n"); /* LINEFEED */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 break;
234
235 case 0x0D:
Len Brown4be44fc2005-08-05 00:44:28 -0400236 acpi_os_printf("\\r"); /* CARRIAGE RETURN */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 break;
238
239 case 0x09:
Len Brown4be44fc2005-08-05 00:44:28 -0400240 acpi_os_printf("\\t"); /* HORIZONTAL TAB */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 break;
242
243 case 0x0B:
Len Brown4be44fc2005-08-05 00:44:28 -0400244 acpi_os_printf("\\v"); /* VERTICAL TAB */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 break;
246
Len Brown4be44fc2005-08-05 00:44:28 -0400247 case '\'': /* Single Quote */
248 case '\"': /* Double Quote */
249 case '\\': /* Backslash */
250 acpi_os_printf("\\%c", (int)string[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 break;
252
253 default:
254
255 /* Check for printable character or hex escape */
256
Len Brown4be44fc2005-08-05 00:44:28 -0400257 if (ACPI_IS_PRINT(string[i])) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 /* This is a normal character */
259
Len Brown4be44fc2005-08-05 00:44:28 -0400260 acpi_os_printf("%c", (int)string[i]);
261 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 /* All others will be Hex escapes */
263
Len Brown4be44fc2005-08-05 00:44:28 -0400264 acpi_os_printf("\\x%2.2X", (s32) string[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 }
266 break;
267 }
268 }
Len Brown4be44fc2005-08-05 00:44:28 -0400269 acpi_os_printf("\"");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
271 if (i == max_length && string[i]) {
Len Brown4be44fc2005-08-05 00:44:28 -0400272 acpi_os_printf("...");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 }
274}
275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276/*******************************************************************************
277 *
278 * FUNCTION: acpi_ut_dword_byte_swap
279 *
280 * PARAMETERS: Value - Value to be converted
281 *
Robert Moore44f6c012005-04-18 22:49:35 -0400282 * RETURN: u32 integer with bytes swapped
283 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
285 *
286 ******************************************************************************/
287
Len Brown4be44fc2005-08-05 00:44:28 -0400288u32 acpi_ut_dword_byte_swap(u32 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289{
290 union {
Len Brown4be44fc2005-08-05 00:44:28 -0400291 u32 value;
292 u8 bytes[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 } out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 union {
Len Brown4be44fc2005-08-05 00:44:28 -0400295 u32 value;
296 u8 bytes[4];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 } in;
298
Len Brown4be44fc2005-08-05 00:44:28 -0400299 ACPI_FUNCTION_ENTRY();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 in.value = value;
302
303 out.bytes[0] = in.bytes[3];
304 out.bytes[1] = in.bytes[2];
305 out.bytes[2] = in.bytes[1];
306 out.bytes[3] = in.bytes[0];
307
308 return (out.value);
309}
310
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311/*******************************************************************************
312 *
313 * FUNCTION: acpi_ut_set_integer_width
314 *
315 * PARAMETERS: Revision From DSDT header
316 *
317 * RETURN: None
318 *
319 * DESCRIPTION: Set the global integer bit width based upon the revision
320 * of the DSDT. For Revision 1 and 0, Integers are 32 bits.
321 * For Revision 2 and above, Integers are 64 bits. Yes, this
322 * makes a difference.
323 *
324 ******************************************************************************/
325
Len Brown4be44fc2005-08-05 00:44:28 -0400326void acpi_ut_set_integer_width(u8 revision)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327{
328
329 if (revision <= 1) {
330 acpi_gbl_integer_bit_width = 32;
331 acpi_gbl_integer_nybble_width = 8;
332 acpi_gbl_integer_byte_width = 4;
Len Brown4be44fc2005-08-05 00:44:28 -0400333 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 acpi_gbl_integer_bit_width = 64;
335 acpi_gbl_integer_nybble_width = 16;
336 acpi_gbl_integer_byte_width = 8;
337 }
338}
339
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340#ifdef ACPI_DEBUG_OUTPUT
341/*******************************************************************************
342 *
343 * FUNCTION: acpi_ut_display_init_pathname
344 *
Robert Moore44f6c012005-04-18 22:49:35 -0400345 * PARAMETERS: Type - Object type of the node
346 * obj_handle - Handle whose pathname will be displayed
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347 * Path - Additional path string to be appended.
348 * (NULL if no extra path)
349 *
350 * RETURN: acpi_status
351 *
352 * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
353 *
354 ******************************************************************************/
355
356void
Len Brown4be44fc2005-08-05 00:44:28 -0400357acpi_ut_display_init_pathname(u8 type,
358 struct acpi_namespace_node *obj_handle,
359 char *path)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360{
Len Brown4be44fc2005-08-05 00:44:28 -0400361 acpi_status status;
362 struct acpi_buffer buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Len Brown4be44fc2005-08-05 00:44:28 -0400364 ACPI_FUNCTION_ENTRY();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366 /* Only print the path if the appropriate debug level is enabled */
367
368 if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
369 return;
370 }
371
372 /* Get the full pathname to the node */
373
374 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
Len Brown4be44fc2005-08-05 00:44:28 -0400375 status = acpi_ns_handle_to_pathname(obj_handle, &buffer);
376 if (ACPI_FAILURE(status)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 return;
378 }
379
380 /* Print what we're doing */
381
382 switch (type) {
383 case ACPI_TYPE_METHOD:
Len Brown4be44fc2005-08-05 00:44:28 -0400384 acpi_os_printf("Executing ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 break;
386
387 default:
Len Brown4be44fc2005-08-05 00:44:28 -0400388 acpi_os_printf("Initializing ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 break;
390 }
391
392 /* Print the object type and pathname */
393
Len Brown4be44fc2005-08-05 00:44:28 -0400394 acpi_os_printf("%-12s %s",
395 acpi_ut_get_type_name(type), (char *)buffer.pointer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
397 /* Extra path is used to append names like _STA, _INI, etc. */
398
399 if (path) {
Len Brown4be44fc2005-08-05 00:44:28 -0400400 acpi_os_printf(".%s", path);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
Len Brown4be44fc2005-08-05 00:44:28 -0400402 acpi_os_printf("\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Len Brown4be44fc2005-08-05 00:44:28 -0400404 ACPI_MEM_FREE(buffer.pointer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405}
406#endif
407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408/*******************************************************************************
409 *
410 * FUNCTION: acpi_ut_valid_acpi_name
411 *
Robert Moore44f6c012005-04-18 22:49:35 -0400412 * PARAMETERS: Name - The name to be examined
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 *
Robert Moore44f6c012005-04-18 22:49:35 -0400414 * RETURN: TRUE if the name is valid, FALSE otherwise
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 *
416 * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
417 * 1) Upper case alpha
418 * 2) numeric
419 * 3) underscore
420 *
421 ******************************************************************************/
422
Len Brown4be44fc2005-08-05 00:44:28 -0400423u8 acpi_ut_valid_acpi_name(u32 name)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
Len Brown4be44fc2005-08-05 00:44:28 -0400425 char *name_ptr = (char *)&name;
426 char character;
427 acpi_native_uint i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
Len Brown4be44fc2005-08-05 00:44:28 -0400429 ACPI_FUNCTION_ENTRY();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
431 for (i = 0; i < ACPI_NAME_SIZE; i++) {
432 character = *name_ptr;
433 name_ptr++;
434
435 if (!((character == '_') ||
Len Brown4be44fc2005-08-05 00:44:28 -0400436 (character >= 'A' && character <= 'Z') ||
437 (character >= '0' && character <= '9'))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438 return (FALSE);
439 }
440 }
441
442 return (TRUE);
443}
444
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445/*******************************************************************************
446 *
447 * FUNCTION: acpi_ut_valid_acpi_character
448 *
449 * PARAMETERS: Character - The character to be examined
450 *
451 * RETURN: 1 if Character may appear in a name, else 0
452 *
453 * DESCRIPTION: Check for a printable character
454 *
455 ******************************************************************************/
456
Len Brown4be44fc2005-08-05 00:44:28 -0400457u8 acpi_ut_valid_acpi_character(char character)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458{
459
Len Brown4be44fc2005-08-05 00:44:28 -0400460 ACPI_FUNCTION_ENTRY();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Len Brown4be44fc2005-08-05 00:44:28 -0400462 return ((u8) ((character == '_') ||
463 (character >= 'A' && character <= 'Z') ||
464 (character >= '0' && character <= '9')));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465}
466
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467/*******************************************************************************
468 *
469 * FUNCTION: acpi_ut_strtoul64
470 *
471 * PARAMETERS: String - Null terminated string
472 * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE
473 * ret_integer - Where the converted integer is returned
474 *
475 * RETURN: Status and Converted value
476 *
477 * DESCRIPTION: Convert a string into an unsigned value.
478 * NOTE: Does not support Octal strings, not needed.
479 *
480 ******************************************************************************/
481
482acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400483acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
Len Brown4be44fc2005-08-05 00:44:28 -0400485 u32 this_digit = 0;
486 acpi_integer return_value = 0;
487 acpi_integer quotient;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
Len Brown4be44fc2005-08-05 00:44:28 -0400489 ACPI_FUNCTION_TRACE("ut_stroul64");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
491 if ((!string) || !(*string)) {
492 goto error_exit;
493 }
494
495 switch (base) {
496 case ACPI_ANY_BASE:
497 case 10:
498 case 16:
499 break;
500
501 default:
502 /* Invalid Base */
Len Brown4be44fc2005-08-05 00:44:28 -0400503 return_ACPI_STATUS(AE_BAD_PARAMETER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 }
505
506 /* Skip over any white space in the buffer */
507
Len Brown4be44fc2005-08-05 00:44:28 -0400508 while (ACPI_IS_SPACE(*string) || *string == '\t') {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 string++;
510 }
511
512 /*
513 * If the input parameter Base is zero, then we need to
514 * determine if it is decimal or hexadecimal:
515 */
516 if (base == 0) {
Len Brown4be44fc2005-08-05 00:44:28 -0400517 if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 base = 16;
519 string += 2;
Len Brown4be44fc2005-08-05 00:44:28 -0400520 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 base = 10;
522 }
523 }
524
525 /*
526 * For hexadecimal base, skip over the leading
527 * 0 or 0x, if they are present.
528 */
529 if ((base == 16) &&
Len Brown4be44fc2005-08-05 00:44:28 -0400530 (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 string += 2;
532 }
533
534 /* Any string left? */
535
536 if (!(*string)) {
537 goto error_exit;
538 }
539
540 /* Main loop: convert the string to a 64-bit integer */
541
542 while (*string) {
Len Brown4be44fc2005-08-05 00:44:28 -0400543 if (ACPI_IS_DIGIT(*string)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 /* Convert ASCII 0-9 to Decimal value */
545
Len Brown4be44fc2005-08-05 00:44:28 -0400546 this_digit = ((u8) * string) - '0';
547 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 if (base == 10) {
549 /* Digit is out of range */
550
551 goto error_exit;
552 }
553
Len Brown4be44fc2005-08-05 00:44:28 -0400554 this_digit = (u8) ACPI_TOUPPER(*string);
555 if (ACPI_IS_XDIGIT((char)this_digit)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 /* Convert ASCII Hex char to value */
557
558 this_digit = this_digit - 'A' + 10;
Len Brown4be44fc2005-08-05 00:44:28 -0400559 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 /*
561 * We allow non-hex chars, just stop now, same as end-of-string.
562 * See ACPI spec, string-to-integer conversion.
563 */
564 break;
565 }
566 }
567
568 /* Divide the digit into the correct position */
569
Len Brown4be44fc2005-08-05 00:44:28 -0400570 (void)
571 acpi_ut_short_divide((ACPI_INTEGER_MAX -
572 (acpi_integer) this_digit), base,
573 &quotient, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 if (return_value > quotient) {
575 goto error_exit;
576 }
577
578 return_value *= base;
579 return_value += this_digit;
580 string++;
581 }
582
583 /* All done, normal exit */
584
585 *ret_integer = return_value;
Len Brown4be44fc2005-08-05 00:44:28 -0400586 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Len Brown4be44fc2005-08-05 00:44:28 -0400588 error_exit:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 /* Base was set/validated above */
590
591 if (base == 10) {
Len Brown4be44fc2005-08-05 00:44:28 -0400592 return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT);
593 } else {
594 return_ACPI_STATUS(AE_BAD_HEX_CONSTANT);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 }
596}
597
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598/*******************************************************************************
599 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 * FUNCTION: acpi_ut_create_update_state_and_push
601 *
Robert Moore44f6c012005-04-18 22:49:35 -0400602 * PARAMETERS: Object - Object to be added to the new state
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 * Action - Increment/Decrement
604 * state_list - List the state will be added to
605 *
Robert Moore44f6c012005-04-18 22:49:35 -0400606 * RETURN: Status
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 *
608 * DESCRIPTION: Create a new state and push it
609 *
610 ******************************************************************************/
611
612acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400613acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
614 u16 action,
615 union acpi_generic_state **state_list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616{
Len Brown4be44fc2005-08-05 00:44:28 -0400617 union acpi_generic_state *state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
Len Brown4be44fc2005-08-05 00:44:28 -0400619 ACPI_FUNCTION_ENTRY();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621 /* Ignore null objects; these are expected */
622
623 if (!object) {
624 return (AE_OK);
625 }
626
Len Brown4be44fc2005-08-05 00:44:28 -0400627 state = acpi_ut_create_update_state(object, action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 if (!state) {
629 return (AE_NO_MEMORY);
630 }
631
Len Brown4be44fc2005-08-05 00:44:28 -0400632 acpi_ut_push_generic_state(state_list, state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 return (AE_OK);
634}
635
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636/*******************************************************************************
637 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 * FUNCTION: acpi_ut_walk_package_tree
639 *
Robert Moore44f6c012005-04-18 22:49:35 -0400640 * PARAMETERS: source_object - The package to walk
641 * target_object - Target object (if package is being copied)
642 * walk_callback - Called once for each package element
643 * Context - Passed to the callback function
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 *
645 * RETURN: Status
646 *
647 * DESCRIPTION: Walk through a package
648 *
649 ******************************************************************************/
650
651acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400652acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
653 void *target_object,
654 acpi_pkg_callback walk_callback, void *context)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
Len Brown4be44fc2005-08-05 00:44:28 -0400656 acpi_status status = AE_OK;
657 union acpi_generic_state *state_list = NULL;
658 union acpi_generic_state *state;
659 u32 this_index;
660 union acpi_operand_object *this_source_obj;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Len Brown4be44fc2005-08-05 00:44:28 -0400662 ACPI_FUNCTION_TRACE("ut_walk_package_tree");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
Len Brown4be44fc2005-08-05 00:44:28 -0400664 state = acpi_ut_create_pkg_state(source_object, target_object, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 if (!state) {
Len Brown4be44fc2005-08-05 00:44:28 -0400666 return_ACPI_STATUS(AE_NO_MEMORY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 }
668
669 while (state) {
670 /* Get one element of the package */
671
Len Brown4be44fc2005-08-05 00:44:28 -0400672 this_index = state->pkg.index;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 this_source_obj = (union acpi_operand_object *)
Len Brown4be44fc2005-08-05 00:44:28 -0400674 state->pkg.source_object->package.elements[this_index];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
676 /*
677 * Check for:
678 * 1) An uninitialized package element. It is completely
679 * legal to declare a package and leave it uninitialized
680 * 2) Not an internal object - can be a namespace node instead
681 * 3) Any type other than a package. Packages are handled in else
682 * case below.
683 */
684 if ((!this_source_obj) ||
Len Brown4be44fc2005-08-05 00:44:28 -0400685 (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=
686 ACPI_DESC_TYPE_OPERAND)
687 || (ACPI_GET_OBJECT_TYPE(this_source_obj) !=
688 ACPI_TYPE_PACKAGE)) {
689 status =
690 walk_callback(ACPI_COPY_TYPE_SIMPLE,
691 this_source_obj, state, context);
692 if (ACPI_FAILURE(status)) {
693 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 }
695
696 state->pkg.index++;
Len Brown4be44fc2005-08-05 00:44:28 -0400697 while (state->pkg.index >=
698 state->pkg.source_object->package.count) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 /*
700 * We've handled all of the objects at this level, This means
701 * that we have just completed a package. That package may
702 * have contained one or more packages itself.
703 *
704 * Delete this state and pop the previous state (package).
705 */
Len Brown4be44fc2005-08-05 00:44:28 -0400706 acpi_ut_delete_generic_state(state);
707 state = acpi_ut_pop_generic_state(&state_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 /* Finished when there are no more states */
710
711 if (!state) {
712 /*
713 * We have handled all of the objects in the top level
714 * package just add the length of the package objects
715 * and exit
716 */
Len Brown4be44fc2005-08-05 00:44:28 -0400717 return_ACPI_STATUS(AE_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 }
719
720 /*
721 * Go back up a level and move the index past the just
722 * completed package object.
723 */
724 state->pkg.index++;
725 }
Len Brown4be44fc2005-08-05 00:44:28 -0400726 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 /* This is a subobject of type package */
728
Len Brown4be44fc2005-08-05 00:44:28 -0400729 status =
730 walk_callback(ACPI_COPY_TYPE_PACKAGE,
731 this_source_obj, state, context);
732 if (ACPI_FAILURE(status)) {
733 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 }
735
736 /*
737 * Push the current state and create a new one
738 * The callback above returned a new target package object.
739 */
Len Brown4be44fc2005-08-05 00:44:28 -0400740 acpi_ut_push_generic_state(&state_list, state);
741 state = acpi_ut_create_pkg_state(this_source_obj,
742 state->pkg.
743 this_target_obj, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 if (!state) {
Len Brown4be44fc2005-08-05 00:44:28 -0400745 return_ACPI_STATUS(AE_NO_MEMORY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 }
747 }
748 }
749
750 /* We should never get here */
751
Len Brown4be44fc2005-08-05 00:44:28 -0400752 return_ACPI_STATUS(AE_AML_INTERNAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753}
754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755/*******************************************************************************
756 *
757 * FUNCTION: acpi_ut_generate_checksum
758 *
759 * PARAMETERS: Buffer - Buffer to be scanned
760 * Length - number of bytes to examine
761 *
Robert Moore44f6c012005-04-18 22:49:35 -0400762 * RETURN: The generated checksum
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 *
764 * DESCRIPTION: Generate a checksum on a raw buffer
765 *
766 ******************************************************************************/
767
Len Brown4be44fc2005-08-05 00:44:28 -0400768u8 acpi_ut_generate_checksum(u8 * buffer, u32 length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769{
Len Brown4be44fc2005-08-05 00:44:28 -0400770 u32 i;
771 signed char sum = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
773 for (i = 0; i < length; i++) {
Len Brown4be44fc2005-08-05 00:44:28 -0400774 sum = (signed char)(sum + buffer[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 }
776
777 return ((u8) (0 - sum));
778}
779
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780/*******************************************************************************
781 *
782 * FUNCTION: acpi_ut_get_resource_end_tag
783 *
784 * PARAMETERS: obj_desc - The resource template buffer object
785 *
786 * RETURN: Pointer to the end tag
787 *
788 * DESCRIPTION: Find the END_TAG resource descriptor in a resource template
789 *
790 ******************************************************************************/
791
Len Brown4be44fc2005-08-05 00:44:28 -0400792u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793{
Len Brown4be44fc2005-08-05 00:44:28 -0400794 u8 buffer_byte;
795 u8 *buffer;
796 u8 *end_buffer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
Len Brown4be44fc2005-08-05 00:44:28 -0400798 buffer = obj_desc->buffer.pointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 end_buffer = buffer + obj_desc->buffer.length;
800
801 while (buffer < end_buffer) {
802 buffer_byte = *buffer;
803 if (buffer_byte & ACPI_RDESC_TYPE_MASK) {
804 /* Large Descriptor - Length is next 2 bytes */
805
Len Brown4be44fc2005-08-05 00:44:28 -0400806 buffer += ((*(buffer + 1) | (*(buffer + 2) << 8)) + 3);
807 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 /* Small Descriptor. End Tag will be found here */
809
Len Brown4be44fc2005-08-05 00:44:28 -0400810 if ((buffer_byte & ACPI_RDESC_SMALL_MASK) ==
811 ACPI_RDESC_TYPE_END_TAG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 /* Found the end tag descriptor, all done. */
813
814 return (buffer);
815 }
816
817 /* Length is in the header */
818
819 buffer += ((buffer_byte & 0x07) + 1);
820 }
821 }
822
823 /* End tag not found */
824
825 return (NULL);
826}
827
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828/*******************************************************************************
829 *
830 * FUNCTION: acpi_ut_report_error
831 *
832 * PARAMETERS: module_name - Caller's module name (for error output)
833 * line_number - Caller's line number (for error output)
834 * component_id - Caller's component ID (for error output)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 *
836 * RETURN: None
837 *
838 * DESCRIPTION: Print error message
839 *
840 ******************************************************************************/
841
Len Brown4be44fc2005-08-05 00:44:28 -0400842void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843{
844
Len Brown4be44fc2005-08-05 00:44:28 -0400845 acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846}
847
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848/*******************************************************************************
849 *
850 * FUNCTION: acpi_ut_report_warning
851 *
852 * PARAMETERS: module_name - Caller's module name (for error output)
853 * line_number - Caller's line number (for error output)
854 * component_id - Caller's component ID (for error output)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 *
856 * RETURN: None
857 *
858 * DESCRIPTION: Print warning message
859 *
860 ******************************************************************************/
861
862void
Len Brown4be44fc2005-08-05 00:44:28 -0400863acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864{
865
Len Brown4be44fc2005-08-05 00:44:28 -0400866 acpi_os_printf("%8s-%04d: *** Warning: ", module_name, line_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867}
868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869/*******************************************************************************
870 *
871 * FUNCTION: acpi_ut_report_info
872 *
873 * PARAMETERS: module_name - Caller's module name (for error output)
874 * line_number - Caller's line number (for error output)
875 * component_id - Caller's component ID (for error output)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 *
877 * RETURN: None
878 *
879 * DESCRIPTION: Print information message
880 *
881 ******************************************************************************/
882
Len Brown4be44fc2005-08-05 00:44:28 -0400883void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884{
885
Len Brown4be44fc2005-08-05 00:44:28 -0400886 acpi_os_printf("%8s-%04d: *** Info: ", module_name, line_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887}