nsutils.c 19.8 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 - 2013, 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"));
115
		return_UINT8(ACPI_TYPE_ANY);
L
Linus Torvalds 已提交
116 117
	}

118
	return_UINT8(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));
143
		return_UINT32(ACPI_NS_NORMAL);
L
Linus Torvalds 已提交
144 145
	}

146
	return_UINT32(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:
422

L
Linus Torvalds 已提交
423 424 425
		prefix_length = 1;
		break;

426
	case AML_PARENT_PREFIX:
427

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

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

		break;

	default:
443

L
Linus Torvalds 已提交
444 445 446 447
		break;
	}

	/*
448
	 * Check for object names. Note that there could be 0-255 of these
L
Linus Torvalds 已提交
449 450 451 452 453 454 455 456 457
	 * 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;
458 459
			num_segments = (u8)
			    internal_name[(acpi_size) prefix_length + 1];
L
Linus Torvalds 已提交
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 491 492 493
			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 已提交
494
	    ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
L
Linus Torvalds 已提交
495 496

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

505 506
	/* Build the converted_name */

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

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

524 525 526 527 528
			/* 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]);
529 530 531

			j += ACPI_NAME_SIZE;
			names_index += ACPI_NAME_SIZE;
L
Linus Torvalds 已提交
532 533 534 535 536 537 538
		}
	}

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

L
Len Brown 已提交
539
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
540 541 542 543
}

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

562
struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
L
Linus Torvalds 已提交
563 564
{

L
Len Brown 已提交
565
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
566

567 568
	/* Parameter validation */

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

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

L
Len Brown 已提交
575
	if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
L
Linus Torvalds 已提交
576 577 578
		return (NULL);
	}

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

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

L
Len Brown 已提交
594
void acpi_ns_terminate(void)
L
Linus Torvalds 已提交
595
{
596
	acpi_status status;
L
Linus Torvalds 已提交
597

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

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

606
	/* Delete any objects attached to the root node */
L
Linus Torvalds 已提交
607

608 609 610
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_VOID;
L
Linus Torvalds 已提交
611 612
	}

613 614 615
	acpi_ns_delete_node(acpi_gbl_root_node);
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);

L
Len Brown 已提交
616
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
L
Linus Torvalds 已提交
617 618 619 620 621 622 623
	return_VOID;
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_opens_scope
 *
624
 * PARAMETERS:  type        - A valid namespace type
L
Linus Torvalds 已提交
625 626 627 628 629 630
 *
 * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
 *              to the ACPI specification, else 0
 *
 ******************************************************************************/

L
Len Brown 已提交
631
u32 acpi_ns_opens_scope(acpi_object_type type)
L
Linus Torvalds 已提交
632
{
633
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
634

635
	if (type > ACPI_TYPE_LOCAL_MAX) {
B
Bob Moore 已提交
636

L
Linus Torvalds 已提交
637 638
		/* type code out of range  */

639
		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
640
		return (ACPI_NS_NORMAL);
L
Linus Torvalds 已提交
641 642
	}

643
	return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
L
Linus Torvalds 已提交
644 645 646 647
}

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

acpi_status
B
Bob Moore 已提交
669
acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
670
		 const char *pathname,
B
Bob Moore 已提交
671
		 u32 flags, struct acpi_namespace_node **return_node)
L
Linus Torvalds 已提交
672
{
L
Len Brown 已提交
673 674
	union acpi_generic_state scope_info;
	acpi_status status;
B
Bob Moore 已提交
675
	char *internal_path;
L
Linus Torvalds 已提交
676

677
	ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
L
Linus Torvalds 已提交
678

679 680
	/* Simplest case is a null pathname */

B
Bob Moore 已提交
681 682 683 684 685 686 687
	if (!pathname) {
		*return_node = prefix_node;
		if (!prefix_node) {
			*return_node = acpi_gbl_root_node;
		}
		return_ACPI_STATUS(AE_OK);
	}
B
Bob Moore 已提交
688

689 690 691 692 693 694 695
	/* Quick check for a reference to the root */

	if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) {
		*return_node = acpi_gbl_root_node;
		return_ACPI_STATUS(AE_OK);
	}

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

B
Bob Moore 已提交
698 699 700
	status = acpi_ns_internalize_name(pathname, &internal_path);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
701 702 703 704
	}

	/* Must lock namespace during lookup */

L
Len Brown 已提交
705 706
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
707 708 709 710 711
		goto cleanup;
	}

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

B
Bob Moore 已提交
712
	scope_info.scope.node = prefix_node;
L
Linus Torvalds 已提交
713 714 715

	/* Lookup the name in the namespace */

B
Bob Moore 已提交
716 717 718 719
	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 已提交
720
	if (ACPI_FAILURE(status)) {
721
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
B
Bob Moore 已提交
722
				  pathname, acpi_format_exception(status)));
L
Linus Torvalds 已提交
723 724
	}

L
Len Brown 已提交
725
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
L
Linus Torvalds 已提交
726

727
cleanup:
B
Bob Moore 已提交
728
	ACPI_FREE(internal_path);
L
Len Brown 已提交
729
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
730
}