nsutils.c 19.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
#include "accommon.h"
#include "acnamesp.h"
#include "amlcode.h"
L
Linus Torvalds 已提交
49 50

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

R
Robert Moore 已提交
53 54
/* Local prototypes */
#ifdef ACPI_OBSOLETE_FUNCTIONS
L
Len Brown 已提交
55
acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
R
Robert Moore 已提交
56 57
#endif

L
Linus Torvalds 已提交
58 59 60 61
/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_print_node_pathname
 *
62 63
 * PARAMETERS:  node            - Object
 *              message         - Prefix message
L
Linus Torvalds 已提交
64 65 66 67 68 69 70
 *
 * DESCRIPTION: Print an object's full namespace pathname
 *              Manages allocation/freeing of a pathname buffer
 *
 ******************************************************************************/

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

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

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

	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;

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

L
Len Brown 已提交
92
		acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node);
B
Bob Moore 已提交
93
		ACPI_FREE(buffer.pointer);
L
Linus Torvalds 已提交
94 95 96 97 98 99 100
	}
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_type
 *
101
 * PARAMETERS:  node        - Parent Node to be examined
L
Linus Torvalds 已提交
102 103 104
 *
 * RETURN:      Type field from Node whose handle is passed
 *
R
Robert Moore 已提交
105 106
 * DESCRIPTION: Return the type of a Namespace node
 *
L
Linus Torvalds 已提交
107 108
 ******************************************************************************/

L
Len Brown 已提交
109
acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
L
Linus Torvalds 已提交
110
{
B
Bob Moore 已提交
111
	ACPI_FUNCTION_TRACE(ns_get_type);
L
Linus Torvalds 已提交
112 113

	if (!node) {
B
Bob Moore 已提交
114
		ACPI_WARNING((AE_INFO, "Null Node parameter"));
B
Bob Moore 已提交
115
		return_UINT32(ACPI_TYPE_ANY);
L
Linus Torvalds 已提交
116 117
	}

B
Bob Moore 已提交
118
	return_UINT32((acpi_object_type) node->type);
L
Linus Torvalds 已提交
119 120 121 122 123 124
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_local
 *
125
 * PARAMETERS:  type        - A namespace object type
L
Linus Torvalds 已提交
126 127 128 129
 *
 * RETURN:      LOCAL if names must be found locally in objects of the
 *              passed type, 0 if enclosing scopes should be searched
 *
R
Robert Moore 已提交
130 131
 * DESCRIPTION: Returns scope rule for the given object type.
 *
L
Linus Torvalds 已提交
132 133
 ******************************************************************************/

L
Len Brown 已提交
134
u32 acpi_ns_local(acpi_object_type type)
L
Linus Torvalds 已提交
135
{
B
Bob Moore 已提交
136
	ACPI_FUNCTION_TRACE(ns_local);
L
Linus Torvalds 已提交
137

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

L
Linus Torvalds 已提交
140 141
		/* Type code out of range  */

142
		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
B
Bob Moore 已提交
143
		return_UINT32(ACPI_NS_NORMAL);
L
Linus Torvalds 已提交
144 145
	}

B
Bob Moore 已提交
146
	return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
L
Linus Torvalds 已提交
147 148 149 150 151 152
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_internal_name_length
 *
153
 * PARAMETERS:  info            - Info struct initialized with the
L
Linus Torvalds 已提交
154 155
 *                                external name pointer.
 *
R
Robert Moore 已提交
156
 * RETURN:      None
L
Linus Torvalds 已提交
157 158 159 160 161 162
 *
 * DESCRIPTION: Calculate the length of the internal (AML) namestring
 *              corresponding to the external (ASL) namestring.
 *
 ******************************************************************************/

L
Len Brown 已提交
163
void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
L
Linus Torvalds 已提交
164
{
165
	const char *next_external_char;
L
Len Brown 已提交
166
	u32 i;
L
Linus Torvalds 已提交
167

L
Len Brown 已提交
168
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
169 170 171 172 173 174 175 176 177 178 179 180 181

	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
	 */
182
	if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
L
Linus Torvalds 已提交
183 184
		info->fully_qualified = TRUE;
		next_external_char++;
185 186 187

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

188
		while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
189 190
			next_external_char++;
		}
L
Len Brown 已提交
191
	} else {
192 193
		/* Handle Carat prefixes */

194
		while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
L
Linus Torvalds 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207
			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++) {
208
			if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
L
Linus Torvalds 已提交
209 210 211 212 213 214
				info->num_segments++;
			}
		}
	}

	info->length = (ACPI_NAME_SIZE * info->num_segments) +
L
Len Brown 已提交
215
	    4 + info->num_carats;
L
Linus Torvalds 已提交
216 217 218 219 220 221 222 223

	info->next_external_char = next_external_char;
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_build_internal_name
 *
224
 * PARAMETERS:  info            - Info struct fully initialized
L
Linus Torvalds 已提交
225 226 227 228 229 230 231 232
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Construct the internal (AML) namestring
 *              corresponding to the external (ASL) namestring.
 *
 ******************************************************************************/

L
Len Brown 已提交
233
acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
L
Linus Torvalds 已提交
234
{
L
Len Brown 已提交
235 236
	u32 num_segments = info->num_segments;
	char *internal_name = info->internal_name;
237
	const char *external_name = info->next_external_char;
L
Len Brown 已提交
238
	char *result = NULL;
239
	u32 i;
L
Linus Torvalds 已提交
240

B
Bob Moore 已提交
241
	ACPI_FUNCTION_TRACE(ns_build_internal_name);
L
Linus Torvalds 已提交
242 243 244 245

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

	if (info->fully_qualified) {
246
		internal_name[0] = AML_ROOT_PREFIX;
L
Linus Torvalds 已提交
247 248 249

		if (num_segments <= 1) {
			result = &internal_name[1];
L
Len Brown 已提交
250
		} else if (num_segments == 2) {
L
Linus Torvalds 已提交
251 252
			internal_name[1] = AML_DUAL_NAME_PREFIX;
			result = &internal_name[2];
L
Len Brown 已提交
253
		} else {
L
Linus Torvalds 已提交
254
			internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
L
Len Brown 已提交
255
			internal_name[2] = (char)num_segments;
L
Linus Torvalds 已提交
256 257
			result = &internal_name[3];
		}
L
Len Brown 已提交
258
	} else {
L
Linus Torvalds 已提交
259 260 261 262 263 264 265
		/*
		 * 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++) {
266
				internal_name[i] = AML_PARENT_PREFIX;
L
Linus Torvalds 已提交
267 268 269 270 271
			}
		}

		if (num_segments <= 1) {
			result = &internal_name[i];
L
Len Brown 已提交
272
		} else if (num_segments == 2) {
L
Linus Torvalds 已提交
273
			internal_name[i] = AML_DUAL_NAME_PREFIX;
274
			result = &internal_name[(acpi_size) i + 1];
L
Len Brown 已提交
275
		} else {
L
Linus Torvalds 已提交
276
			internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
277 278
			internal_name[(acpi_size) i + 1] = (char)num_segments;
			result = &internal_name[(acpi_size) i + 2];
L
Linus Torvalds 已提交
279 280 281 282 283 284 285
		}
	}

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

	for (; num_segments; num_segments--) {
		for (i = 0; i < ACPI_NAME_SIZE; i++) {
286
			if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
L
Len Brown 已提交
287
			    (*external_name == 0)) {
B
Bob Moore 已提交
288

L
Linus Torvalds 已提交
289 290 291
				/* Pad the segment with underscore(s) if segment is short */

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

L
Len Brown 已提交
295 296
				result[i] =
				    (char)ACPI_TOUPPER((int)*external_name);
L
Linus Torvalds 已提交
297 298 299 300 301 302
				external_name++;
			}
		}

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

303
		if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
L
Len Brown 已提交
304
		    (*external_name != 0)) {
305
			return_ACPI_STATUS(AE_BAD_PATHNAME);
L
Linus Torvalds 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318
		}

		/* Move on the next segment */

		external_name++;
		result += ACPI_NAME_SIZE;
	}

	/* Terminate the string */

	*result = 0;

	if (info->fully_qualified) {
L
Len Brown 已提交
319 320 321 322 323 324
		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 已提交
325 326
	}

L
Len Brown 已提交
327
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
328 329 330 331 332 333 334
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_internalize_name
 *
 * PARAMETERS:  *external_name          - External representation of name
335
 *              **Converted name        - Where to return the resulting
L
Linus Torvalds 已提交
336 337 338 339 340 341 342 343 344
 *                                        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)
 *
 *******************************************************************************/

345 346
acpi_status
acpi_ns_internalize_name(const char *external_name, char **converted_name)
L
Linus Torvalds 已提交
347
{
L
Len Brown 已提交
348 349 350
	char *internal_name;
	struct acpi_namestring_info info;
	acpi_status status;
L
Linus Torvalds 已提交
351

B
Bob Moore 已提交
352
	ACPI_FUNCTION_TRACE(ns_internalize_name);
L
Linus Torvalds 已提交
353

L
Len Brown 已提交
354 355
	if ((!external_name) || (*external_name == 0) || (!converted_name)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
356 357 358 359 360
	}

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

	info.external_name = external_name;
L
Len Brown 已提交
361
	acpi_ns_get_internal_name_length(&info);
L
Linus Torvalds 已提交
362 363 364

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

B
Bob Moore 已提交
365
	internal_name = ACPI_ALLOCATE_ZEROED(info.length);
L
Linus Torvalds 已提交
366
	if (!internal_name) {
L
Len Brown 已提交
367
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
368 369 370 371 372
	}

	/* Build the name */

	info.internal_name = internal_name;
L
Len Brown 已提交
373 374
	status = acpi_ns_build_internal_name(&info);
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
375
		ACPI_FREE(internal_name);
L
Len Brown 已提交
376
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
377 378 379
	}

	*converted_name = internal_name;
L
Len Brown 已提交
380
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
381 382 383 384 385 386
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_externalize_name
 *
R
Robert Moore 已提交
387 388 389 390 391
 * 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 已提交
392 393 394 395
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
R
Robert Moore 已提交
396
 *              to its external (printable) form (e.g. "\_PR_.CPU0")
L
Linus Torvalds 已提交
397 398 399 400
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
401
acpi_ns_externalize_name(u32 internal_name_length,
402
			 const char *internal_name,
L
Len Brown 已提交
403
			 u32 * converted_name_length, char **converted_name)
L
Linus Torvalds 已提交
404
{
405 406 407 408 409 410
	u32 names_index = 0;
	u32 num_segments = 0;
	u32 required_length;
	u32 prefix_length = 0;
	u32 i = 0;
	u32 j = 0;
L
Linus Torvalds 已提交
411

B
Bob Moore 已提交
412
	ACPI_FUNCTION_TRACE(ns_externalize_name);
L
Linus Torvalds 已提交
413

L
Len Brown 已提交
414 415
	if (!internal_name_length || !internal_name || !converted_name) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
416 417
	}

418 419
	/* Check for a prefix (one '\' | one or more '^') */

L
Linus Torvalds 已提交
420
	switch (internal_name[0]) {
421
	case AML_ROOT_PREFIX:
L
Linus Torvalds 已提交
422 423 424
		prefix_length = 1;
		break;

425
	case AML_PARENT_PREFIX:
L
Linus Torvalds 已提交
426
		for (i = 0; i < internal_name_length; i++) {
427
			if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
L
Linus Torvalds 已提交
428
				prefix_length = i + 1;
L
Len Brown 已提交
429
			} else {
L
Linus Torvalds 已提交
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
				break;
			}
		}

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

		break;

	default:
		break;
	}

	/*
445
	 * Check for object names. Note that there could be 0-255 of these
L
Linus Torvalds 已提交
446 447 448 449 450 451 452 453 454
	 * 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;
455 456
			num_segments = (u8)
			    internal_name[(acpi_size) prefix_length + 1];
L
Linus Torvalds 已提交
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
			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 已提交
491
	    ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
L
Linus Torvalds 已提交
492 493

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

502 503
	/* Build the converted_name */

B
Bob Moore 已提交
504
	*converted_name = ACPI_ALLOCATE_ZEROED(required_length);
L
Linus Torvalds 已提交
505
	if (!(*converted_name)) {
L
Len Brown 已提交
506
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
507 508 509 510 511 512 513 514 515 516 517 518 519 520
	}

	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++] = '.';
			}

521 522 523 524 525
			/* Copy and validate the 4-char name segment */

			ACPI_MOVE_NAME(&(*converted_name)[j],
				       &internal_name[names_index]);
			acpi_ut_repair_name(&(*converted_name)[j]);
526 527 528

			j += ACPI_NAME_SIZE;
			names_index += ACPI_NAME_SIZE;
L
Linus Torvalds 已提交
529 530 531 532 533 534 535
		}
	}

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

L
Len Brown 已提交
536
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
537 538 539 540
}

/*******************************************************************************
 *
541
 * FUNCTION:    acpi_ns_validate_handle
L
Linus Torvalds 已提交
542
 *
543
 * PARAMETERS:  handle          - Handle to be validated and typecast to a
544
 *                                namespace node.
L
Linus Torvalds 已提交
545
 *
546
 * RETURN:      A pointer to a namespace node
L
Linus Torvalds 已提交
547
 *
548 549
 * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
 *              cases for the root node.
L
Linus Torvalds 已提交
550
 *
551
 * NOTE: Real integer handles would allow for more verification
R
Robert Moore 已提交
552
 *       and keep all pointers within this subsystem - however this introduces
553 554 555
 *       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.
556
 *
L
Linus Torvalds 已提交
557 558
 ******************************************************************************/

559
struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
L
Linus Torvalds 已提交
560 561
{

L
Len Brown 已提交
562
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
563

564 565
	/* Parameter validation */

B
Bob Moore 已提交
566
	if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
L
Linus Torvalds 已提交
567 568 569 570 571
		return (acpi_gbl_root_node);
	}

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

L
Len Brown 已提交
572
	if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
L
Linus Torvalds 已提交
573 574 575
		return (NULL);
	}

B
Bob Moore 已提交
576
	return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
L
Linus Torvalds 已提交
577 578 579 580 581 582 583 584 585 586
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_terminate
 *
 * PARAMETERS:  none
 *
 * RETURN:      none
 *
R
Robert Moore 已提交
587
 * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
L
Linus Torvalds 已提交
588 589 590
 *
 ******************************************************************************/

L
Len Brown 已提交
591
void acpi_ns_terminate(void)
L
Linus Torvalds 已提交
592
{
L
Len Brown 已提交
593
	union acpi_operand_object *obj_desc;
L
Linus Torvalds 已提交
594

B
Bob Moore 已提交
595
	ACPI_FUNCTION_TRACE(ns_terminate);
L
Linus Torvalds 已提交
596 597 598 599 600 601

	/*
	 * 1) Free the entire namespace -- all nodes and objects
	 *
	 * Delete all object descriptors attached to namepsace nodes
	 */
L
Len Brown 已提交
602
	acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
L
Linus Torvalds 已提交
603 604 605

	/* Detach any objects attached to the root */

L
Len Brown 已提交
606
	obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
L
Linus Torvalds 已提交
607
	if (obj_desc) {
L
Len Brown 已提交
608
		acpi_ns_detach_object(acpi_gbl_root_node);
L
Linus Torvalds 已提交
609 610
	}

L
Len Brown 已提交
611
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
L
Linus Torvalds 已提交
612 613 614 615 616 617 618
	return_VOID;
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_opens_scope
 *
619
 * PARAMETERS:  type        - A valid namespace type
L
Linus Torvalds 已提交
620 621 622 623 624 625
 *
 * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
 *              to the ACPI specification, else 0
 *
 ******************************************************************************/

L
Len Brown 已提交
626
u32 acpi_ns_opens_scope(acpi_object_type type)
L
Linus Torvalds 已提交
627
{
628
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
629

630
	if (type > ACPI_TYPE_LOCAL_MAX) {
B
Bob Moore 已提交
631

L
Linus Torvalds 已提交
632 633
		/* type code out of range  */

634
		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
635
		return (ACPI_NS_NORMAL);
L
Linus Torvalds 已提交
636 637
	}

638
	return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
L
Linus Torvalds 已提交
639 640 641 642
}

/*******************************************************************************
 *
B
Bob Moore 已提交
643
 * FUNCTION:    acpi_ns_get_node
L
Linus Torvalds 已提交
644
 *
645
 * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
L
Linus Torvalds 已提交
646 647
 *                            \ (backslash) and ^ (carat) prefixes, and the
 *                            . (period) to separate segments are supported.
B
Bob Moore 已提交
648
 *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
649
 *                            root of the name space. If Name is fully
L
Linus Torvalds 已提交
650 651
 *                            qualified (first s8 is '\'), the passed value
 *                            of Scope will not be accessed.
652
 *              flags       - Used to indicate whether to perform upsearch or
L
Linus Torvalds 已提交
653 654 655 656
 *                            not.
 *              return_node - Where the Node is returned
 *
 * DESCRIPTION: Look up a name relative to a given scope and return the
657
 *              corresponding Node. NOTE: Scope can be null.
L
Linus Torvalds 已提交
658 659 660 661 662 663
 *
 * MUTEX:       Locks namespace
 *
 ******************************************************************************/

acpi_status
B
Bob Moore 已提交
664
acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
665
		 const char *pathname,
B
Bob Moore 已提交
666
		 u32 flags, struct acpi_namespace_node **return_node)
L
Linus Torvalds 已提交
667
{
L
Len Brown 已提交
668 669
	union acpi_generic_state scope_info;
	acpi_status status;
B
Bob Moore 已提交
670
	char *internal_path;
L
Linus Torvalds 已提交
671

672
	ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
L
Linus Torvalds 已提交
673

B
Bob Moore 已提交
674 675 676 677 678 679 680
	if (!pathname) {
		*return_node = prefix_node;
		if (!prefix_node) {
			*return_node = acpi_gbl_root_node;
		}
		return_ACPI_STATUS(AE_OK);
	}
B
Bob Moore 已提交
681

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

B
Bob Moore 已提交
684 685 686
	status = acpi_ns_internalize_name(pathname, &internal_path);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
687 688 689 690
	}

	/* Must lock namespace during lookup */

L
Len Brown 已提交
691 692
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
693 694 695 696 697
		goto cleanup;
	}

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

B
Bob Moore 已提交
698
	scope_info.scope.node = prefix_node;
L
Linus Torvalds 已提交
699 700 701

	/* Lookup the name in the namespace */

B
Bob Moore 已提交
702 703 704 705
	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 已提交
706
	if (ACPI_FAILURE(status)) {
707
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
B
Bob Moore 已提交
708
				  pathname, acpi_format_exception(status)));
L
Linus Torvalds 已提交
709 710
	}

L
Len Brown 已提交
711
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
L
Linus Torvalds 已提交
712

L
Len Brown 已提交
713
      cleanup:
B
Bob Moore 已提交
714
	ACPI_FREE(internal_path);
L
Len Brown 已提交
715
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
716
}