utmisc.c 22.7 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
/*******************************************************************************
 *
 * Module Name: utmisc - common utility procedures
 *
 ******************************************************************************/

/*
 * Copyright (C) 2000 - 2005, R. Byron Moore
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
#include <acpi/acnamesp.h>

#define _COMPONENT          ACPI_UTILITIES
L
Len Brown 已提交
48
ACPI_MODULE_NAME("utmisc")
R
Robert Moore 已提交
49

50 51 52 53 54 55
/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_allocate_owner_id
 *
 * PARAMETERS:  owner_id        - Where the new owner ID is returned
 *
56 57 58 59 60
 * RETURN:      Status
 *
 * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to
 *              track objects created by the table or method, to be deleted
 *              when the method exits or the table is unloaded.
61 62
 *
 ******************************************************************************/
L
Len Brown 已提交
63
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
64
{
L
Len Brown 已提交
65 66
	acpi_native_uint i;
	acpi_status status;
67

L
Len Brown 已提交
68
	ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
69

70 71
	/* Mutex for the global ID mask */

L
Len Brown 已提交
72 73 74
	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
75 76 77 78 79 80 81
	}

	/* Find a free owner ID */

	for (i = 0; i < 32; i++) {
		if (!(acpi_gbl_owner_id_mask & (1 << i))) {
			acpi_gbl_owner_id_mask |= (1 << i);
82
			*owner_id = (acpi_owner_id) (i + 1);
83 84 85 86 87 88 89 90 91 92 93
			goto exit;
		}
	}

	/*
	 * If we are here, all owner_ids have been allocated. This probably should
	 * not happen since the IDs are reused after deallocation. The IDs are
	 * allocated upon table load (one per table) and method execution, and
	 * they are released when a table is unloaded or a method completes
	 * execution.
	 */
94
	*owner_id = 0;
95
	status = AE_OWNER_ID_LIMIT;
L
Len Brown 已提交
96
	ACPI_REPORT_ERROR(("Could not allocate new owner_id (32 max), AE_OWNER_ID_LIMIT\n"));
97

L
Len Brown 已提交
98 99 100
      exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
	return_ACPI_STATUS(status);
101 102 103 104 105 106
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_release_owner_id
 *
107
 * PARAMETERS:  owner_id_ptr        - Pointer to a previously allocated owner_iD
108
 *
109 110 111 112 113
 * RETURN:      None. No error is returned because we are either exiting a
 *              control method or unloading a table. Either way, we would
 *              ignore any error anyway.
 *
 * DESCRIPTION: Release a table or method owner ID.  Valid IDs are 1 - 32
114 115 116
 *
 ******************************************************************************/

L
Len Brown 已提交
117
void acpi_ut_release_owner_id(acpi_owner_id * owner_id_ptr)
118
{
L
Len Brown 已提交
119 120
	acpi_owner_id owner_id = *owner_id_ptr;
	acpi_status status;
121

L
Len Brown 已提交
122
	ACPI_FUNCTION_TRACE("ut_release_owner_id");
123

124 125 126 127 128 129 130
	/* Always clear the input owner_id (zero is an invalid ID) */

	*owner_id_ptr = 0;

	/* Zero is not a valid owner_iD */

	if ((owner_id == 0) || (owner_id > 32)) {
L
Len Brown 已提交
131
		ACPI_REPORT_ERROR(("Invalid owner_id: %2.2X\n", owner_id));
132 133 134 135 136
		return_VOID;
	}

	/* Mutex for the global ID mask */

L
Len Brown 已提交
137 138
	status = acpi_ut_acquire_mutex(ACPI_MTX_CACHES);
	if (ACPI_FAILURE(status)) {
139
		return_VOID;
140 141
	}

L
Len Brown 已提交
142
	owner_id--;		/* Normalize to zero */
143 144

	/* Free the owner ID only if it is valid */
145 146 147 148 149

	if (acpi_gbl_owner_id_mask & (1 << owner_id)) {
		acpi_gbl_owner_id_mask ^= (1 << owner_id);
	}

L
Len Brown 已提交
150
	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
151
	return_VOID;
152 153
}

R
Robert Moore 已提交
154 155 156 157 158 159
/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_strupr (strupr)
 *
 * PARAMETERS:  src_string      - The source string to convert
 *
160
 * RETURN:      None
R
Robert Moore 已提交
161 162 163 164 165 166 167
 *
 * DESCRIPTION: Convert string to uppercase
 *
 * NOTE: This is not a POSIX function, so it appears here, not in utclib.c
 *
 ******************************************************************************/

L
Len Brown 已提交
168
void acpi_ut_strupr(char *src_string)
R
Robert Moore 已提交
169
{
L
Len Brown 已提交
170
	char *string;
R
Robert Moore 已提交
171

L
Len Brown 已提交
172
	ACPI_FUNCTION_ENTRY();
R
Robert Moore 已提交
173

174
	if (!src_string) {
175
		return;
176 177
	}

R
Robert Moore 已提交
178 179 180
	/* Walk entire string, uppercasing the letters */

	for (string = src_string; *string; string++) {
L
Len Brown 已提交
181
		*string = (char)ACPI_TOUPPER(*string);
R
Robert Moore 已提交
182 183
	}

184
	return;
R
Robert Moore 已提交
185 186
}

L
Linus Torvalds 已提交
187 188 189 190 191
/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_print_string
 *
 * PARAMETERS:  String          - Null terminated ASCII string
R
Robert Moore 已提交
192
 *              max_length      - Maximum output length
L
Linus Torvalds 已提交
193 194 195 196 197 198 199 200
 *
 * RETURN:      None
 *
 * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape
 *              sequences.
 *
 ******************************************************************************/

L
Len Brown 已提交
201
void acpi_ut_print_string(char *string, u8 max_length)
L
Linus Torvalds 已提交
202
{
L
Len Brown 已提交
203
	u32 i;
L
Linus Torvalds 已提交
204 205

	if (!string) {
L
Len Brown 已提交
206
		acpi_os_printf("<\"NULL STRING PTR\">");
L
Linus Torvalds 已提交
207 208 209
		return;
	}

L
Len Brown 已提交
210
	acpi_os_printf("\"");
L
Linus Torvalds 已提交
211 212 213 214 215
	for (i = 0; string[i] && (i < max_length); i++) {
		/* Escape sequences */

		switch (string[i]) {
		case 0x07:
L
Len Brown 已提交
216
			acpi_os_printf("\\a");	/* BELL */
L
Linus Torvalds 已提交
217 218 219
			break;

		case 0x08:
L
Len Brown 已提交
220
			acpi_os_printf("\\b");	/* BACKSPACE */
L
Linus Torvalds 已提交
221 222 223
			break;

		case 0x0C:
L
Len Brown 已提交
224
			acpi_os_printf("\\f");	/* FORMFEED */
L
Linus Torvalds 已提交
225 226 227
			break;

		case 0x0A:
L
Len Brown 已提交
228
			acpi_os_printf("\\n");	/* LINEFEED */
L
Linus Torvalds 已提交
229 230 231
			break;

		case 0x0D:
L
Len Brown 已提交
232
			acpi_os_printf("\\r");	/* CARRIAGE RETURN */
L
Linus Torvalds 已提交
233 234 235
			break;

		case 0x09:
L
Len Brown 已提交
236
			acpi_os_printf("\\t");	/* HORIZONTAL TAB */
L
Linus Torvalds 已提交
237 238 239
			break;

		case 0x0B:
L
Len Brown 已提交
240
			acpi_os_printf("\\v");	/* VERTICAL TAB */
L
Linus Torvalds 已提交
241 242
			break;

L
Len Brown 已提交
243 244 245 246
		case '\'':	/* Single Quote */
		case '\"':	/* Double Quote */
		case '\\':	/* Backslash */
			acpi_os_printf("\\%c", (int)string[i]);
L
Linus Torvalds 已提交
247 248 249 250 251 252
			break;

		default:

			/* Check for printable character or hex escape */

L
Len Brown 已提交
253
			if (ACPI_IS_PRINT(string[i])) {
L
Linus Torvalds 已提交
254 255
				/* This is a normal character */

L
Len Brown 已提交
256 257
				acpi_os_printf("%c", (int)string[i]);
			} else {
L
Linus Torvalds 已提交
258 259
				/* All others will be Hex escapes */

L
Len Brown 已提交
260
				acpi_os_printf("\\x%2.2X", (s32) string[i]);
L
Linus Torvalds 已提交
261 262 263 264
			}
			break;
		}
	}
L
Len Brown 已提交
265
	acpi_os_printf("\"");
L
Linus Torvalds 已提交
266 267

	if (i == max_length && string[i]) {
L
Len Brown 已提交
268
		acpi_os_printf("...");
L
Linus Torvalds 已提交
269 270 271 272 273 274 275 276 277
	}
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_dword_byte_swap
 *
 * PARAMETERS:  Value           - Value to be converted
 *
R
Robert Moore 已提交
278 279
 * RETURN:      u32 integer with bytes swapped
 *
L
Linus Torvalds 已提交
280 281 282 283
 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)
 *
 ******************************************************************************/

L
Len Brown 已提交
284
u32 acpi_ut_dword_byte_swap(u32 value)
L
Linus Torvalds 已提交
285 286
{
	union {
L
Len Brown 已提交
287 288
		u32 value;
		u8 bytes[4];
L
Linus Torvalds 已提交
289 290
	} out;
	union {
L
Len Brown 已提交
291 292
		u32 value;
		u8 bytes[4];
L
Linus Torvalds 已提交
293 294
	} in;

L
Len Brown 已提交
295
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321

	in.value = value;

	out.bytes[0] = in.bytes[3];
	out.bytes[1] = in.bytes[2];
	out.bytes[2] = in.bytes[1];
	out.bytes[3] = in.bytes[0];

	return (out.value);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_set_integer_width
 *
 * PARAMETERS:  Revision            From DSDT header
 *
 * RETURN:      None
 *
 * DESCRIPTION: Set the global integer bit width based upon the revision
 *              of the DSDT.  For Revision 1 and 0, Integers are 32 bits.
 *              For Revision 2 and above, Integers are 64 bits.  Yes, this
 *              makes a difference.
 *
 ******************************************************************************/

L
Len Brown 已提交
322
void acpi_ut_set_integer_width(u8 revision)
L
Linus Torvalds 已提交
323 324 325 326 327 328
{

	if (revision <= 1) {
		acpi_gbl_integer_bit_width = 32;
		acpi_gbl_integer_nybble_width = 8;
		acpi_gbl_integer_byte_width = 4;
L
Len Brown 已提交
329
	} else {
L
Linus Torvalds 已提交
330 331 332 333 334 335 336 337 338 339 340
		acpi_gbl_integer_bit_width = 64;
		acpi_gbl_integer_nybble_width = 16;
		acpi_gbl_integer_byte_width = 8;
	}
}

#ifdef ACPI_DEBUG_OUTPUT
/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_display_init_pathname
 *
R
Robert Moore 已提交
341 342
 * PARAMETERS:  Type                - Object type of the node
 *              obj_handle          - Handle whose pathname will be displayed
L
Linus Torvalds 已提交
343 344 345 346 347 348 349 350 351 352
 *              Path                - Additional path string to be appended.
 *                                      (NULL if no extra path)
 *
 * RETURN:      acpi_status
 *
 * DESCRIPTION: Display full pathname of an object, DEBUG ONLY
 *
 ******************************************************************************/

void
L
Len Brown 已提交
353 354 355
acpi_ut_display_init_pathname(u8 type,
			      struct acpi_namespace_node *obj_handle,
			      char *path)
L
Linus Torvalds 已提交
356
{
L
Len Brown 已提交
357 358
	acpi_status status;
	struct acpi_buffer buffer;
L
Linus Torvalds 已提交
359

L
Len Brown 已提交
360
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
361 362 363 364 365 366 367 368 369 370

	/* Only print the path if the appropriate debug level is enabled */

	if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
		return;
	}

	/* Get the full pathname to the node */

	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
L
Len Brown 已提交
371 372
	status = acpi_ns_handle_to_pathname(obj_handle, &buffer);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
373 374 375 376 377 378 379
		return;
	}

	/* Print what we're doing */

	switch (type) {
	case ACPI_TYPE_METHOD:
L
Len Brown 已提交
380
		acpi_os_printf("Executing  ");
L
Linus Torvalds 已提交
381 382 383
		break;

	default:
L
Len Brown 已提交
384
		acpi_os_printf("Initializing ");
L
Linus Torvalds 已提交
385 386 387 388 389
		break;
	}

	/* Print the object type and pathname */

L
Len Brown 已提交
390 391
	acpi_os_printf("%-12s %s",
		       acpi_ut_get_type_name(type), (char *)buffer.pointer);
L
Linus Torvalds 已提交
392 393 394 395

	/* Extra path is used to append names like _STA, _INI, etc. */

	if (path) {
L
Len Brown 已提交
396
		acpi_os_printf(".%s", path);
L
Linus Torvalds 已提交
397
	}
L
Len Brown 已提交
398
	acpi_os_printf("\n");
L
Linus Torvalds 已提交
399

L
Len Brown 已提交
400
	ACPI_MEM_FREE(buffer.pointer);
L
Linus Torvalds 已提交
401 402 403 404 405 406 407
}
#endif

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_valid_acpi_name
 *
R
Robert Moore 已提交
408
 * PARAMETERS:  Name            - The name to be examined
L
Linus Torvalds 已提交
409
 *
R
Robert Moore 已提交
410
 * RETURN:      TRUE if the name is valid, FALSE otherwise
L
Linus Torvalds 已提交
411 412 413 414 415 416 417 418
 *
 * DESCRIPTION: Check for a valid ACPI name.  Each character must be one of:
 *              1) Upper case alpha
 *              2) numeric
 *              3) underscore
 *
 ******************************************************************************/

L
Len Brown 已提交
419
u8 acpi_ut_valid_acpi_name(u32 name)
L
Linus Torvalds 已提交
420
{
L
Len Brown 已提交
421 422 423
	char *name_ptr = (char *)&name;
	char character;
	acpi_native_uint i;
L
Linus Torvalds 已提交
424

L
Len Brown 已提交
425
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
426 427 428 429 430 431

	for (i = 0; i < ACPI_NAME_SIZE; i++) {
		character = *name_ptr;
		name_ptr++;

		if (!((character == '_') ||
L
Len Brown 已提交
432 433
		      (character >= 'A' && character <= 'Z') ||
		      (character >= '0' && character <= '9'))) {
L
Linus Torvalds 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
			return (FALSE);
		}
	}

	return (TRUE);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_valid_acpi_character
 *
 * PARAMETERS:  Character           - The character to be examined
 *
 * RETURN:      1 if Character may appear in a name, else 0
 *
 * DESCRIPTION: Check for a printable character
 *
 ******************************************************************************/

L
Len Brown 已提交
453
u8 acpi_ut_valid_acpi_character(char character)
L
Linus Torvalds 已提交
454 455
{

L
Len Brown 已提交
456
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
457

L
Len Brown 已提交
458 459 460
	return ((u8) ((character == '_') ||
		      (character >= 'A' && character <= 'Z') ||
		      (character >= '0' && character <= '9')));
L
Linus Torvalds 已提交
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_strtoul64
 *
 * PARAMETERS:  String          - Null terminated string
 *              Base            - Radix of the string: 10, 16, or ACPI_ANY_BASE
 *              ret_integer     - Where the converted integer is returned
 *
 * RETURN:      Status and Converted value
 *
 * DESCRIPTION: Convert a string into an unsigned value.
 *              NOTE: Does not support Octal strings, not needed.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
479
acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
L
Linus Torvalds 已提交
480
{
L
Len Brown 已提交
481 482 483
	u32 this_digit = 0;
	acpi_integer return_value = 0;
	acpi_integer quotient;
L
Linus Torvalds 已提交
484

L
Len Brown 已提交
485
	ACPI_FUNCTION_TRACE("ut_stroul64");
L
Linus Torvalds 已提交
486 487 488 489 490 491 492 493 494 495 496 497 498

	if ((!string) || !(*string)) {
		goto error_exit;
	}

	switch (base) {
	case ACPI_ANY_BASE:
	case 10:
	case 16:
		break;

	default:
		/* Invalid Base */
L
Len Brown 已提交
499
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
500 501 502 503
	}

	/* Skip over any white space in the buffer */

L
Len Brown 已提交
504
	while (ACPI_IS_SPACE(*string) || *string == '\t') {
L
Linus Torvalds 已提交
505 506 507 508 509 510 511 512
		string++;
	}

	/*
	 * If the input parameter Base is zero, then we need to
	 * determine if it is decimal or hexadecimal:
	 */
	if (base == 0) {
L
Len Brown 已提交
513
		if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
L
Linus Torvalds 已提交
514 515
			base = 16;
			string += 2;
L
Len Brown 已提交
516
		} else {
L
Linus Torvalds 已提交
517 518 519 520 521 522 523 524 525
			base = 10;
		}
	}

	/*
	 * For hexadecimal base, skip over the leading
	 * 0 or 0x, if they are present.
	 */
	if ((base == 16) &&
L
Len Brown 已提交
526
	    (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
L
Linus Torvalds 已提交
527 528 529 530 531 532 533 534 535 536 537 538
		string += 2;
	}

	/* Any string left? */

	if (!(*string)) {
		goto error_exit;
	}

	/* Main loop: convert the string to a 64-bit integer */

	while (*string) {
L
Len Brown 已提交
539
		if (ACPI_IS_DIGIT(*string)) {
L
Linus Torvalds 已提交
540 541
			/* Convert ASCII 0-9 to Decimal value */

L
Len Brown 已提交
542 543
			this_digit = ((u8) * string) - '0';
		} else {
L
Linus Torvalds 已提交
544 545 546 547 548 549
			if (base == 10) {
				/* Digit is out of range */

				goto error_exit;
			}

L
Len Brown 已提交
550 551
			this_digit = (u8) ACPI_TOUPPER(*string);
			if (ACPI_IS_XDIGIT((char)this_digit)) {
L
Linus Torvalds 已提交
552 553 554
				/* Convert ASCII Hex char to value */

				this_digit = this_digit - 'A' + 10;
L
Len Brown 已提交
555
			} else {
L
Linus Torvalds 已提交
556 557 558 559 560 561 562 563 564 565
				/*
				 * We allow non-hex chars, just stop now, same as end-of-string.
				 * See ACPI spec, string-to-integer conversion.
				 */
				break;
			}
		}

		/* Divide the digit into the correct position */

L
Len Brown 已提交
566 567 568 569
		(void)
		    acpi_ut_short_divide((ACPI_INTEGER_MAX -
					  (acpi_integer) this_digit), base,
					 &quotient, NULL);
L
Linus Torvalds 已提交
570 571 572 573 574 575 576 577 578 579 580 581
		if (return_value > quotient) {
			goto error_exit;
		}

		return_value *= base;
		return_value += this_digit;
		string++;
	}

	/* All done, normal exit */

	*ret_integer = return_value;
L
Len Brown 已提交
582
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
583

L
Len Brown 已提交
584
      error_exit:
L
Linus Torvalds 已提交
585 586 587
	/* Base was set/validated above */

	if (base == 10) {
L
Len Brown 已提交
588 589 590
		return_ACPI_STATUS(AE_BAD_DECIMAL_CONSTANT);
	} else {
		return_ACPI_STATUS(AE_BAD_HEX_CONSTANT);
L
Linus Torvalds 已提交
591 592 593 594 595 596 597
	}
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_create_update_state_and_push
 *
R
Robert Moore 已提交
598
 * PARAMETERS:  Object          - Object to be added to the new state
L
Linus Torvalds 已提交
599 600 601
 *              Action          - Increment/Decrement
 *              state_list      - List the state will be added to
 *
R
Robert Moore 已提交
602
 * RETURN:      Status
L
Linus Torvalds 已提交
603 604 605 606 607 608
 *
 * DESCRIPTION: Create a new state and push it
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
609 610 611
acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
				     u16 action,
				     union acpi_generic_state **state_list)
L
Linus Torvalds 已提交
612
{
L
Len Brown 已提交
613
	union acpi_generic_state *state;
L
Linus Torvalds 已提交
614

L
Len Brown 已提交
615
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
616 617 618 619 620 621 622

	/* Ignore null objects; these are expected */

	if (!object) {
		return (AE_OK);
	}

L
Len Brown 已提交
623
	state = acpi_ut_create_update_state(object, action);
L
Linus Torvalds 已提交
624 625 626 627
	if (!state) {
		return (AE_NO_MEMORY);
	}

L
Len Brown 已提交
628
	acpi_ut_push_generic_state(state_list, state);
L
Linus Torvalds 已提交
629 630 631 632 633 634 635
	return (AE_OK);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_walk_package_tree
 *
R
Robert Moore 已提交
636 637 638 639
 * PARAMETERS:  source_object       - The package to walk
 *              target_object       - Target object (if package is being copied)
 *              walk_callback       - Called once for each package element
 *              Context             - Passed to the callback function
L
Linus Torvalds 已提交
640 641 642 643 644 645 646 647
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Walk through a package
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
648 649 650
acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
			  void *target_object,
			  acpi_pkg_callback walk_callback, void *context)
L
Linus Torvalds 已提交
651
{
L
Len Brown 已提交
652 653 654 655 656
	acpi_status status = AE_OK;
	union acpi_generic_state *state_list = NULL;
	union acpi_generic_state *state;
	u32 this_index;
	union acpi_operand_object *this_source_obj;
L
Linus Torvalds 已提交
657

L
Len Brown 已提交
658
	ACPI_FUNCTION_TRACE("ut_walk_package_tree");
L
Linus Torvalds 已提交
659

L
Len Brown 已提交
660
	state = acpi_ut_create_pkg_state(source_object, target_object, 0);
L
Linus Torvalds 已提交
661
	if (!state) {
L
Len Brown 已提交
662
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
663 664 665 666 667
	}

	while (state) {
		/* Get one element of the package */

L
Len Brown 已提交
668
		this_index = state->pkg.index;
L
Linus Torvalds 已提交
669
		this_source_obj = (union acpi_operand_object *)
L
Len Brown 已提交
670
		    state->pkg.source_object->package.elements[this_index];
L
Linus Torvalds 已提交
671 672 673 674 675 676 677 678 679 680

		/*
		 * Check for:
		 * 1) An uninitialized package element.  It is completely
		 *    legal to declare a package and leave it uninitialized
		 * 2) Not an internal object - can be a namespace node instead
		 * 3) Any type other than a package.  Packages are handled in else
		 *    case below.
		 */
		if ((!this_source_obj) ||
L
Len Brown 已提交
681 682 683 684 685 686 687 688 689
		    (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=
		     ACPI_DESC_TYPE_OPERAND)
		    || (ACPI_GET_OBJECT_TYPE(this_source_obj) !=
			ACPI_TYPE_PACKAGE)) {
			status =
			    walk_callback(ACPI_COPY_TYPE_SIMPLE,
					  this_source_obj, state, context);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
690 691 692
			}

			state->pkg.index++;
L
Len Brown 已提交
693 694
			while (state->pkg.index >=
			       state->pkg.source_object->package.count) {
L
Linus Torvalds 已提交
695 696 697 698 699 700 701
				/*
				 * We've handled all of the objects at this level,  This means
				 * that we have just completed a package.  That package may
				 * have contained one or more packages itself.
				 *
				 * Delete this state and pop the previous state (package).
				 */
L
Len Brown 已提交
702 703
				acpi_ut_delete_generic_state(state);
				state = acpi_ut_pop_generic_state(&state_list);
L
Linus Torvalds 已提交
704 705 706 707 708 709 710 711 712

				/* Finished when there are no more states */

				if (!state) {
					/*
					 * We have handled all of the objects in the top level
					 * package just add the length of the package objects
					 * and exit
					 */
L
Len Brown 已提交
713
					return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
714 715 716 717 718 719 720 721
				}

				/*
				 * Go back up a level and move the index past the just
				 * completed package object.
				 */
				state->pkg.index++;
			}
L
Len Brown 已提交
722
		} else {
L
Linus Torvalds 已提交
723 724
			/* This is a subobject of type package */

L
Len Brown 已提交
725 726 727 728 729
			status =
			    walk_callback(ACPI_COPY_TYPE_PACKAGE,
					  this_source_obj, state, context);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
730 731 732 733 734 735
			}

			/*
			 * Push the current state and create a new one
			 * The callback above returned a new target package object.
			 */
L
Len Brown 已提交
736 737 738 739
			acpi_ut_push_generic_state(&state_list, state);
			state = acpi_ut_create_pkg_state(this_source_obj,
							 state->pkg.
							 this_target_obj, 0);
L
Linus Torvalds 已提交
740
			if (!state) {
L
Len Brown 已提交
741
				return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
742 743 744 745 746 747
			}
		}
	}

	/* We should never get here */

L
Len Brown 已提交
748
	return_ACPI_STATUS(AE_AML_INTERNAL);
L
Linus Torvalds 已提交
749 750 751 752 753 754 755 756 757
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_generate_checksum
 *
 * PARAMETERS:  Buffer          - Buffer to be scanned
 *              Length          - number of bytes to examine
 *
R
Robert Moore 已提交
758
 * RETURN:      The generated checksum
L
Linus Torvalds 已提交
759 760 761 762 763
 *
 * DESCRIPTION: Generate a checksum on a raw buffer
 *
 ******************************************************************************/

L
Len Brown 已提交
764
u8 acpi_ut_generate_checksum(u8 * buffer, u32 length)
L
Linus Torvalds 已提交
765
{
L
Len Brown 已提交
766 767
	u32 i;
	signed char sum = 0;
L
Linus Torvalds 已提交
768 769

	for (i = 0; i < length; i++) {
L
Len Brown 已提交
770
		sum = (signed char)(sum + buffer[i]);
L
Linus Torvalds 已提交
771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787
	}

	return ((u8) (0 - sum));
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_get_resource_end_tag
 *
 * PARAMETERS:  obj_desc        - The resource template buffer object
 *
 * RETURN:      Pointer to the end tag
 *
 * DESCRIPTION: Find the END_TAG resource descriptor in a resource template
 *
 ******************************************************************************/

L
Len Brown 已提交
788
u8 *acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc)
L
Linus Torvalds 已提交
789
{
L
Len Brown 已提交
790 791 792
	u8 buffer_byte;
	u8 *buffer;
	u8 *end_buffer;
L
Linus Torvalds 已提交
793

L
Len Brown 已提交
794
	buffer = obj_desc->buffer.pointer;
L
Linus Torvalds 已提交
795 796 797 798 799 800 801
	end_buffer = buffer + obj_desc->buffer.length;

	while (buffer < end_buffer) {
		buffer_byte = *buffer;
		if (buffer_byte & ACPI_RDESC_TYPE_MASK) {
			/* Large Descriptor - Length is next 2 bytes */

L
Len Brown 已提交
802 803
			buffer += ((*(buffer + 1) | (*(buffer + 2) << 8)) + 3);
		} else {
L
Linus Torvalds 已提交
804 805
			/* Small Descriptor.  End Tag will be found here */

L
Len Brown 已提交
806 807
			if ((buffer_byte & ACPI_RDESC_SMALL_MASK) ==
			    ACPI_RDESC_TYPE_END_TAG) {
L
Linus Torvalds 已提交
808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837
				/* Found the end tag descriptor, all done. */

				return (buffer);
			}

			/* Length is in the header */

			buffer += ((buffer_byte & 0x07) + 1);
		}
	}

	/* End tag not found */

	return (NULL);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_report_error
 *
 * PARAMETERS:  module_name         - Caller's module name (for error output)
 *              line_number         - Caller's line number (for error output)
 *              component_id        - Caller's component ID (for error output)
 *
 * RETURN:      None
 *
 * DESCRIPTION: Print error message
 *
 ******************************************************************************/

L
Len Brown 已提交
838
void acpi_ut_report_error(char *module_name, u32 line_number, u32 component_id)
L
Linus Torvalds 已提交
839 840
{

L
Len Brown 已提交
841
	acpi_os_printf("%8s-%04d: *** Error: ", module_name, line_number);
L
Linus Torvalds 已提交
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_report_warning
 *
 * PARAMETERS:  module_name         - Caller's module name (for error output)
 *              line_number         - Caller's line number (for error output)
 *              component_id        - Caller's component ID (for error output)
 *
 * RETURN:      None
 *
 * DESCRIPTION: Print warning message
 *
 ******************************************************************************/

void
L
Len Brown 已提交
859
acpi_ut_report_warning(char *module_name, u32 line_number, u32 component_id)
L
Linus Torvalds 已提交
860 861
{

L
Len Brown 已提交
862
	acpi_os_printf("%8s-%04d: *** Warning: ", module_name, line_number);
L
Linus Torvalds 已提交
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_report_info
 *
 * PARAMETERS:  module_name         - Caller's module name (for error output)
 *              line_number         - Caller's line number (for error output)
 *              component_id        - Caller's component ID (for error output)
 *
 * RETURN:      None
 *
 * DESCRIPTION: Print information message
 *
 ******************************************************************************/

L
Len Brown 已提交
879
void acpi_ut_report_info(char *module_name, u32 line_number, u32 component_id)
L
Linus Torvalds 已提交
880 881
{

L
Len Brown 已提交
882
	acpi_os_printf("%8s-%04d: *** Info: ", module_name, line_number);
L
Linus Torvalds 已提交
883
}