nsutils.c 20.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8
/******************************************************************************
 *
 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
 *                        parents and siblings and Scope manipulation
 *
 *****************************************************************************/

/*
9
 * Copyright (C) 2000 - 2012, Intel Corp.
L
Linus Torvalds 已提交
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
 * 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>
L
Len Brown 已提交
46 47 48 49
#include "accommon.h"
#include "acnamesp.h"
#include "amlcode.h"
#include "actables.h"
L
Linus Torvalds 已提交
50 51

#define _COMPONENT          ACPI_NAMESPACE
L
Len Brown 已提交
52
ACPI_MODULE_NAME("nsutils")
L
Linus Torvalds 已提交
53

R
Robert Moore 已提交
54
/* Local prototypes */
L
Len Brown 已提交
55
static u8 acpi_ns_valid_path_separator(char sep);
R
Robert Moore 已提交
56 57

#ifdef ACPI_OBSOLETE_FUNCTIONS
L
Len Brown 已提交
58
acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
R
Robert Moore 已提交
59 60
#endif

L
Linus Torvalds 已提交
61 62 63 64
/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_print_node_pathname
 *
R
Robert Moore 已提交
65 66
 * PARAMETERS:  Node            - Object
 *              Message         - Prefix message
L
Linus Torvalds 已提交
67 68 69 70 71 72 73
 *
 * DESCRIPTION: Print an object's full namespace pathname
 *              Manages allocation/freeing of a pathname buffer
 *
 ******************************************************************************/

void
74 75
acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
			    const char *message)
L
Linus Torvalds 已提交
76
{
L
Len Brown 已提交
77 78
	struct acpi_buffer buffer;
	acpi_status status;
L
Linus Torvalds 已提交
79 80

	if (!node) {
L
Len Brown 已提交
81
		acpi_os_printf("[NULL NAME]");
L
Linus Torvalds 已提交
82 83 84 85 86 87 88
		return;
	}

	/* Convert handle to full pathname and print it (with supplied message) */

	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;

L
Len Brown 已提交
89 90
	status = acpi_ns_handle_to_pathname(node, &buffer);
	if (ACPI_SUCCESS(status)) {
R
Robert Moore 已提交
91
		if (message) {
L
Len Brown 已提交
92
			acpi_os_printf("%s ", message);
L
Linus Torvalds 已提交
93 94
		}

L
Len Brown 已提交
95
		acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node);
B
Bob Moore 已提交
96
		ACPI_FREE(buffer.pointer);
L
Linus Torvalds 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
	}
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_valid_root_prefix
 *
 * PARAMETERS:  Prefix          - Character to be checked
 *
 * RETURN:      TRUE if a valid prefix
 *
 * DESCRIPTION: Check if a character is a valid ACPI Root prefix
 *
 ******************************************************************************/

L
Len Brown 已提交
112
u8 acpi_ns_valid_root_prefix(char prefix)
L
Linus Torvalds 已提交
113 114 115 116 117 118 119 120 121
{

	return ((u8) (prefix == '\\'));
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_valid_path_separator
 *
R
Robert Moore 已提交
122
 * PARAMETERS:  Sep         - Character to be checked
L
Linus Torvalds 已提交
123 124 125 126 127 128 129
 *
 * RETURN:      TRUE if a valid path separator
 *
 * DESCRIPTION: Check if a character is a valid ACPI path separator
 *
 ******************************************************************************/

L
Len Brown 已提交
130
static u8 acpi_ns_valid_path_separator(char sep)
L
Linus Torvalds 已提交
131 132 133 134 135 136 137 138 139
{

	return ((u8) (sep == '.'));
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_type
 *
R
Robert Moore 已提交
140
 * PARAMETERS:  Node        - Parent Node to be examined
L
Linus Torvalds 已提交
141 142 143
 *
 * RETURN:      Type field from Node whose handle is passed
 *
R
Robert Moore 已提交
144 145
 * DESCRIPTION: Return the type of a Namespace node
 *
L
Linus Torvalds 已提交
146 147
 ******************************************************************************/

L
Len Brown 已提交
148
acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
L
Linus Torvalds 已提交
149
{
B
Bob Moore 已提交
150
	ACPI_FUNCTION_TRACE(ns_get_type);
L
Linus Torvalds 已提交
151 152

	if (!node) {
B
Bob Moore 已提交
153
		ACPI_WARNING((AE_INFO, "Null Node parameter"));
B
Bob Moore 已提交
154
		return_UINT32(ACPI_TYPE_ANY);
L
Linus Torvalds 已提交
155 156
	}

B
Bob Moore 已提交
157
	return_UINT32((acpi_object_type) node->type);
L
Linus Torvalds 已提交
158 159 160 161 162 163
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_local
 *
R
Robert Moore 已提交
164
 * PARAMETERS:  Type        - A namespace object type
L
Linus Torvalds 已提交
165 166 167 168
 *
 * RETURN:      LOCAL if names must be found locally in objects of the
 *              passed type, 0 if enclosing scopes should be searched
 *
R
Robert Moore 已提交
169 170
 * DESCRIPTION: Returns scope rule for the given object type.
 *
L
Linus Torvalds 已提交
171 172
 ******************************************************************************/

L
Len Brown 已提交
173
u32 acpi_ns_local(acpi_object_type type)
L
Linus Torvalds 已提交
174
{
B
Bob Moore 已提交
175
	ACPI_FUNCTION_TRACE(ns_local);
L
Linus Torvalds 已提交
176

L
Len Brown 已提交
177
	if (!acpi_ut_valid_object_type(type)) {
B
Bob Moore 已提交
178

L
Linus Torvalds 已提交
179 180
		/* Type code out of range  */

181
		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
B
Bob Moore 已提交
182
		return_UINT32(ACPI_NS_NORMAL);
L
Linus Torvalds 已提交
183 184
	}

B
Bob Moore 已提交
185
	return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
L
Linus Torvalds 已提交
186 187 188 189 190 191 192 193 194
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_internal_name_length
 *
 * PARAMETERS:  Info            - Info struct initialized with the
 *                                external name pointer.
 *
R
Robert Moore 已提交
195
 * RETURN:      None
L
Linus Torvalds 已提交
196 197 198 199 200 201
 *
 * DESCRIPTION: Calculate the length of the internal (AML) namestring
 *              corresponding to the external (ASL) namestring.
 *
 ******************************************************************************/

L
Len Brown 已提交
202
void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
L
Linus Torvalds 已提交
203
{
204
	const char *next_external_char;
L
Len Brown 已提交
205
	u32 i;
L
Linus Torvalds 已提交
206

L
Len Brown 已提交
207
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
208 209 210 211 212 213 214 215 216 217 218 219 220

	next_external_char = info->external_name;
	info->num_carats = 0;
	info->num_segments = 0;
	info->fully_qualified = FALSE;

	/*
	 * For the internal name, the required length is 4 bytes per segment, plus
	 * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null
	 * (which is not really needed, but no there's harm in putting it there)
	 *
	 * strlen() + 1 covers the first name_seg, which has no path separator
	 */
221
	if (acpi_ns_valid_root_prefix(*next_external_char)) {
L
Linus Torvalds 已提交
222 223
		info->fully_qualified = TRUE;
		next_external_char++;
224 225 226 227 228 229

		/* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */

		while (acpi_ns_valid_root_prefix(*next_external_char)) {
			next_external_char++;
		}
L
Len Brown 已提交
230
	} else {
231 232
		/* Handle Carat prefixes */

L
Linus Torvalds 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246
		while (*next_external_char == '^') {
			info->num_carats++;
			next_external_char++;
		}
	}

	/*
	 * Determine the number of ACPI name "segments" by counting the number of
	 * path separators within the string. Start with one segment since the
	 * segment count is [(# separators) + 1], and zero separators is ok.
	 */
	if (*next_external_char) {
		info->num_segments = 1;
		for (i = 0; next_external_char[i]; i++) {
L
Len Brown 已提交
247
			if (acpi_ns_valid_path_separator(next_external_char[i])) {
L
Linus Torvalds 已提交
248 249 250 251 252 253
				info->num_segments++;
			}
		}
	}

	info->length = (ACPI_NAME_SIZE * info->num_segments) +
L
Len Brown 已提交
254
	    4 + info->num_carats;
L
Linus Torvalds 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271

	info->next_external_char = next_external_char;
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_build_internal_name
 *
 * PARAMETERS:  Info            - Info struct fully initialized
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Construct the internal (AML) namestring
 *              corresponding to the external (ASL) namestring.
 *
 ******************************************************************************/

L
Len Brown 已提交
272
acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
L
Linus Torvalds 已提交
273
{
L
Len Brown 已提交
274 275
	u32 num_segments = info->num_segments;
	char *internal_name = info->internal_name;
276
	const char *external_name = info->next_external_char;
L
Len Brown 已提交
277
	char *result = NULL;
278
	u32 i;
L
Linus Torvalds 已提交
279

B
Bob Moore 已提交
280
	ACPI_FUNCTION_TRACE(ns_build_internal_name);
L
Linus Torvalds 已提交
281 282 283 284 285 286 287 288

	/* Setup the correct prefixes, counts, and pointers */

	if (info->fully_qualified) {
		internal_name[0] = '\\';

		if (num_segments <= 1) {
			result = &internal_name[1];
L
Len Brown 已提交
289
		} else if (num_segments == 2) {
L
Linus Torvalds 已提交
290 291
			internal_name[1] = AML_DUAL_NAME_PREFIX;
			result = &internal_name[2];
L
Len Brown 已提交
292
		} else {
L
Linus Torvalds 已提交
293
			internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
L
Len Brown 已提交
294
			internal_name[2] = (char)num_segments;
L
Linus Torvalds 已提交
295 296
			result = &internal_name[3];
		}
L
Len Brown 已提交
297
	} else {
L
Linus Torvalds 已提交
298 299 300 301 302 303 304 305 306 307 308 309 310
		/*
		 * Not fully qualified.
		 * Handle Carats first, then append the name segments
		 */
		i = 0;
		if (info->num_carats) {
			for (i = 0; i < info->num_carats; i++) {
				internal_name[i] = '^';
			}
		}

		if (num_segments <= 1) {
			result = &internal_name[i];
L
Len Brown 已提交
311
		} else if (num_segments == 2) {
L
Linus Torvalds 已提交
312
			internal_name[i] = AML_DUAL_NAME_PREFIX;
313
			result = &internal_name[(acpi_size) i + 1];
L
Len Brown 已提交
314
		} else {
L
Linus Torvalds 已提交
315
			internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
316 317
			internal_name[(acpi_size) i + 1] = (char)num_segments;
			result = &internal_name[(acpi_size) i + 2];
L
Linus Torvalds 已提交
318 319 320 321 322 323 324
		}
	}

	/* Build the name (minus path separators) */

	for (; num_segments; num_segments--) {
		for (i = 0; i < ACPI_NAME_SIZE; i++) {
L
Len Brown 已提交
325 326
			if (acpi_ns_valid_path_separator(*external_name) ||
			    (*external_name == 0)) {
B
Bob Moore 已提交
327

L
Linus Torvalds 已提交
328 329 330
				/* Pad the segment with underscore(s) if segment is short */

				result[i] = '_';
L
Len Brown 已提交
331
			} else {
L
Linus Torvalds 已提交
332 333
				/* Convert the character to uppercase and save it */

L
Len Brown 已提交
334 335
				result[i] =
				    (char)ACPI_TOUPPER((int)*external_name);
L
Linus Torvalds 已提交
336 337 338 339 340 341
				external_name++;
			}
		}

		/* Now we must have a path separator, or the pathname is bad */

L
Len Brown 已提交
342 343
		if (!acpi_ns_valid_path_separator(*external_name) &&
		    (*external_name != 0)) {
344
			return_ACPI_STATUS(AE_BAD_PATHNAME);
L
Linus Torvalds 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357
		}

		/* Move on the next segment */

		external_name++;
		result += ACPI_NAME_SIZE;
	}

	/* Terminate the string */

	*result = 0;

	if (info->fully_qualified) {
L
Len Brown 已提交
358 359 360 361 362 363
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
				  "Returning [%p] (abs) \"\\%s\"\n",
				  internal_name, internal_name));
	} else {
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
				  internal_name, internal_name));
L
Linus Torvalds 已提交
364 365
	}

L
Len Brown 已提交
366
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_internalize_name
 *
 * PARAMETERS:  *external_name          - External representation of name
 *              **Converted Name        - Where to return the resulting
 *                                        internal represention of the name
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
 *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
 *
 *******************************************************************************/

384 385
acpi_status
acpi_ns_internalize_name(const char *external_name, char **converted_name)
L
Linus Torvalds 已提交
386
{
L
Len Brown 已提交
387 388 389
	char *internal_name;
	struct acpi_namestring_info info;
	acpi_status status;
L
Linus Torvalds 已提交
390

B
Bob Moore 已提交
391
	ACPI_FUNCTION_TRACE(ns_internalize_name);
L
Linus Torvalds 已提交
392

L
Len Brown 已提交
393 394
	if ((!external_name) || (*external_name == 0) || (!converted_name)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
395 396 397 398 399
	}

	/* Get the length of the new internal name */

	info.external_name = external_name;
L
Len Brown 已提交
400
	acpi_ns_get_internal_name_length(&info);
L
Linus Torvalds 已提交
401 402 403

	/* We need a segment to store the internal  name */

B
Bob Moore 已提交
404
	internal_name = ACPI_ALLOCATE_ZEROED(info.length);
L
Linus Torvalds 已提交
405
	if (!internal_name) {
L
Len Brown 已提交
406
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
407 408 409 410 411
	}

	/* Build the name */

	info.internal_name = internal_name;
L
Len Brown 已提交
412 413
	status = acpi_ns_build_internal_name(&info);
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
414
		ACPI_FREE(internal_name);
L
Len Brown 已提交
415
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
416 417 418
	}

	*converted_name = internal_name;
L
Len Brown 已提交
419
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
420 421 422 423 424 425
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_externalize_name
 *
R
Robert Moore 已提交
426 427 428 429 430
 * PARAMETERS:  internal_name_length - Lenth of the internal name below
 *              internal_name       - Internal representation of name
 *              converted_name_length - Where the length is returned
 *              converted_name      - Where the resulting external name
 *                                    is returned
L
Linus Torvalds 已提交
431 432 433 434
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
R
Robert Moore 已提交
435
 *              to its external (printable) form (e.g. "\_PR_.CPU0")
L
Linus Torvalds 已提交
436 437 438 439
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
440
acpi_ns_externalize_name(u32 internal_name_length,
441
			 const char *internal_name,
L
Len Brown 已提交
442
			 u32 * converted_name_length, char **converted_name)
L
Linus Torvalds 已提交
443
{
444 445 446 447 448 449
	u32 names_index = 0;
	u32 num_segments = 0;
	u32 required_length;
	u32 prefix_length = 0;
	u32 i = 0;
	u32 j = 0;
L
Linus Torvalds 已提交
450

B
Bob Moore 已提交
451
	ACPI_FUNCTION_TRACE(ns_externalize_name);
L
Linus Torvalds 已提交
452

L
Len Brown 已提交
453 454
	if (!internal_name_length || !internal_name || !converted_name) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
455 456
	}

457 458
	/* Check for a prefix (one '\' | one or more '^') */

L
Linus Torvalds 已提交
459 460 461 462 463 464 465 466 467
	switch (internal_name[0]) {
	case '\\':
		prefix_length = 1;
		break;

	case '^':
		for (i = 0; i < internal_name_length; i++) {
			if (internal_name[i] == '^') {
				prefix_length = i + 1;
L
Len Brown 已提交
468
			} else {
L
Linus Torvalds 已提交
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483
				break;
			}
		}

		if (i == internal_name_length) {
			prefix_length = i;
		}

		break;

	default:
		break;
	}

	/*
484
	 * Check for object names. Note that there could be 0-255 of these
L
Linus Torvalds 已提交
485 486 487 488 489 490 491 492 493
	 * 4-byte elements.
	 */
	if (prefix_length < internal_name_length) {
		switch (internal_name[prefix_length]) {
		case AML_MULTI_NAME_PREFIX_OP:

			/* <count> 4-byte names */

			names_index = prefix_length + 2;
494 495
			num_segments = (u8)
			    internal_name[(acpi_size) prefix_length + 1];
L
Linus Torvalds 已提交
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
			break;

		case AML_DUAL_NAME_PREFIX:

			/* Two 4-byte names */

			names_index = prefix_length + 1;
			num_segments = 2;
			break;

		case 0:

			/* null_name */

			names_index = 0;
			num_segments = 0;
			break;

		default:

			/* one 4-byte name */

			names_index = prefix_length;
			num_segments = 1;
			break;
		}
	}

	/*
	 * Calculate the length of converted_name, which equals the length
	 * of the prefix, length of all object names, length of any required
	 * punctuation ('.') between object names, plus the NULL terminator.
	 */
	required_length = prefix_length + (4 * num_segments) +
L
Len Brown 已提交
530
	    ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
L
Linus Torvalds 已提交
531 532 533 534 535 536

	/*
	 * Check to see if we're still in bounds.  If not, there's a problem
	 * with internal_name (invalid format).
	 */
	if (required_length > internal_name_length) {
B
Bob Moore 已提交
537
		ACPI_ERROR((AE_INFO, "Invalid internal name"));
L
Len Brown 已提交
538
		return_ACPI_STATUS(AE_BAD_PATHNAME);
L
Linus Torvalds 已提交
539 540
	}

541 542
	/* Build the converted_name */

B
Bob Moore 已提交
543
	*converted_name = ACPI_ALLOCATE_ZEROED(required_length);
L
Linus Torvalds 已提交
544
	if (!(*converted_name)) {
L
Len Brown 已提交
545
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
	}

	j = 0;

	for (i = 0; i < prefix_length; i++) {
		(*converted_name)[j++] = internal_name[i];
	}

	if (num_segments > 0) {
		for (i = 0; i < num_segments; i++) {
			if (i > 0) {
				(*converted_name)[j++] = '.';
			}

			(*converted_name)[j++] = internal_name[names_index++];
			(*converted_name)[j++] = internal_name[names_index++];
			(*converted_name)[j++] = internal_name[names_index++];
			(*converted_name)[j++] = internal_name[names_index++];
		}
	}

	if (converted_name_length) {
		*converted_name_length = (u32) required_length;
	}

L
Len Brown 已提交
571
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
572 573 574 575
}

/*******************************************************************************
 *
576
 * FUNCTION:    acpi_ns_validate_handle
L
Linus Torvalds 已提交
577
 *
578 579
 * PARAMETERS:  Handle          - Handle to be validated and typecast to a
 *                                namespace node.
L
Linus Torvalds 已提交
580
 *
581
 * RETURN:      A pointer to a namespace node
L
Linus Torvalds 已提交
582
 *
583 584
 * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
 *              cases for the root node.
L
Linus Torvalds 已提交
585
 *
586
 * NOTE: Real integer handles would allow for more verification
R
Robert Moore 已提交
587
 *       and keep all pointers within this subsystem - however this introduces
588 589 590
 *       more overhead and has not been necessary to this point. Drivers
 *       holding handles are typically notified before a node becomes invalid
 *       due to a table unload.
591
 *
L
Linus Torvalds 已提交
592 593
 ******************************************************************************/

594
struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
L
Linus Torvalds 已提交
595 596
{

L
Len Brown 已提交
597
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
598

599 600
	/* Parameter validation */

B
Bob Moore 已提交
601
	if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
L
Linus Torvalds 已提交
602 603 604 605 606
		return (acpi_gbl_root_node);
	}

	/* We can at least attempt to verify the handle */

L
Len Brown 已提交
607
	if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
L
Linus Torvalds 已提交
608 609 610
		return (NULL);
	}

B
Bob Moore 已提交
611
	return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
L
Linus Torvalds 已提交
612 613 614 615 616 617 618 619 620 621
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_terminate
 *
 * PARAMETERS:  none
 *
 * RETURN:      none
 *
R
Robert Moore 已提交
622
 * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
L
Linus Torvalds 已提交
623 624 625
 *
 ******************************************************************************/

L
Len Brown 已提交
626
void acpi_ns_terminate(void)
L
Linus Torvalds 已提交
627
{
L
Len Brown 已提交
628
	union acpi_operand_object *obj_desc;
L
Linus Torvalds 已提交
629

B
Bob Moore 已提交
630
	ACPI_FUNCTION_TRACE(ns_terminate);
L
Linus Torvalds 已提交
631 632 633 634 635 636

	/*
	 * 1) Free the entire namespace -- all nodes and objects
	 *
	 * Delete all object descriptors attached to namepsace nodes
	 */
L
Len Brown 已提交
637
	acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
L
Linus Torvalds 已提交
638 639 640

	/* Detach any objects attached to the root */

L
Len Brown 已提交
641
	obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
L
Linus Torvalds 已提交
642
	if (obj_desc) {
L
Len Brown 已提交
643
		acpi_ns_detach_object(acpi_gbl_root_node);
L
Linus Torvalds 已提交
644 645
	}

L
Len Brown 已提交
646
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
L
Linus Torvalds 已提交
647 648 649 650 651 652 653 654 655 656 657 658 659 660
	return_VOID;
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_opens_scope
 *
 * PARAMETERS:  Type        - A valid namespace type
 *
 * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
 *              to the ACPI specification, else 0
 *
 ******************************************************************************/

L
Len Brown 已提交
661
u32 acpi_ns_opens_scope(acpi_object_type type)
L
Linus Torvalds 已提交
662
{
B
Bob Moore 已提交
663
	ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type));
L
Linus Torvalds 已提交
664

L
Len Brown 已提交
665
	if (!acpi_ut_valid_object_type(type)) {
B
Bob Moore 已提交
666

L
Linus Torvalds 已提交
667 668
		/* type code out of range  */

669
		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
B
Bob Moore 已提交
670
		return_UINT32(ACPI_NS_NORMAL);
L
Linus Torvalds 已提交
671 672
	}

B
Bob Moore 已提交
673
	return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
L
Linus Torvalds 已提交
674 675 676 677
}

/*******************************************************************************
 *
B
Bob Moore 已提交
678
 * FUNCTION:    acpi_ns_get_node
L
Linus Torvalds 已提交
679 680 681 682
 *
 * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
 *                            \ (backslash) and ^ (carat) prefixes, and the
 *                            . (period) to separate segments are supported.
B
Bob Moore 已提交
683
 *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
L
Linus Torvalds 已提交
684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
 *                            root of the name space.  If Name is fully
 *                            qualified (first s8 is '\'), the passed value
 *                            of Scope will not be accessed.
 *              Flags       - Used to indicate whether to perform upsearch or
 *                            not.
 *              return_node - Where the Node is returned
 *
 * DESCRIPTION: Look up a name relative to a given scope and return the
 *              corresponding Node.  NOTE: Scope can be null.
 *
 * MUTEX:       Locks namespace
 *
 ******************************************************************************/

acpi_status
B
Bob Moore 已提交
699
acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
700
		 const char *pathname,
B
Bob Moore 已提交
701
		 u32 flags, struct acpi_namespace_node **return_node)
L
Linus Torvalds 已提交
702
{
L
Len Brown 已提交
703 704
	union acpi_generic_state scope_info;
	acpi_status status;
B
Bob Moore 已提交
705
	char *internal_path;
L
Linus Torvalds 已提交
706

707
	ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
L
Linus Torvalds 已提交
708

B
Bob Moore 已提交
709 710 711 712 713 714 715
	if (!pathname) {
		*return_node = prefix_node;
		if (!prefix_node) {
			*return_node = acpi_gbl_root_node;
		}
		return_ACPI_STATUS(AE_OK);
	}
B
Bob Moore 已提交
716

B
Bob Moore 已提交
717
	/* Convert path to internal representation */
L
Linus Torvalds 已提交
718

B
Bob Moore 已提交
719 720 721
	status = acpi_ns_internalize_name(pathname, &internal_path);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
722 723 724 725
	}

	/* Must lock namespace during lookup */

L
Len Brown 已提交
726 727
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
728 729 730 731 732
		goto cleanup;
	}

	/* Setup lookup scope (search starting point) */

B
Bob Moore 已提交
733
	scope_info.scope.node = prefix_node;
L
Linus Torvalds 已提交
734 735 736

	/* Lookup the name in the namespace */

B
Bob Moore 已提交
737 738 739 740
	status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
				ACPI_IMODE_EXECUTE,
				(flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
				return_node);
L
Len Brown 已提交
741
	if (ACPI_FAILURE(status)) {
742
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
B
Bob Moore 已提交
743
				  pathname, acpi_format_exception(status)));
L
Linus Torvalds 已提交
744 745
	}

L
Len Brown 已提交
746
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
L
Linus Torvalds 已提交
747

L
Len Brown 已提交
748
      cleanup:
B
Bob Moore 已提交
749
	ACPI_FREE(internal_path);
L
Len Brown 已提交
750
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
751
}