nsutils.c 19.4 KB
Newer Older
E
Erik Schmauss 已提交
1
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
L
Linus Torvalds 已提交
2 3 4 5 6
/******************************************************************************
 *
 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
 *                        parents and siblings and Scope manipulation
 *
7
 * Copyright (C) 2000 - 2019, Intel Corp.
L
Linus Torvalds 已提交
8
 *
E
Erik Schmauss 已提交
9
 *****************************************************************************/
L
Linus Torvalds 已提交
10 11

#include <acpi/acpi.h>
L
Len Brown 已提交
12 13 14
#include "accommon.h"
#include "acnamesp.h"
#include "amlcode.h"
L
Linus Torvalds 已提交
15 16

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

R
Robert Moore 已提交
19 20
/* Local prototypes */
#ifdef ACPI_OBSOLETE_FUNCTIONS
L
Len Brown 已提交
21
acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
R
Robert Moore 已提交
22 23
#endif

L
Linus Torvalds 已提交
24 25 26 27
/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_print_node_pathname
 *
28 29
 * PARAMETERS:  node            - Object
 *              message         - Prefix message
L
Linus Torvalds 已提交
30 31 32 33 34 35 36
 *
 * DESCRIPTION: Print an object's full namespace pathname
 *              Manages allocation/freeing of a pathname buffer
 *
 ******************************************************************************/

void
37 38
acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
			    const char *message)
L
Linus Torvalds 已提交
39
{
L
Len Brown 已提交
40 41
	struct acpi_buffer buffer;
	acpi_status status;
L
Linus Torvalds 已提交
42 43

	if (!node) {
L
Len Brown 已提交
44
		acpi_os_printf("[NULL NAME]");
L
Linus Torvalds 已提交
45 46 47 48 49 50 51
		return;
	}

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

	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;

52
	status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
L
Len Brown 已提交
53
	if (ACPI_SUCCESS(status)) {
R
Robert Moore 已提交
54
		if (message) {
L
Len Brown 已提交
55
			acpi_os_printf("%s ", message);
L
Linus Torvalds 已提交
56 57
		}

58
		acpi_os_printf("%s", (char *)buffer.pointer);
B
Bob Moore 已提交
59
		ACPI_FREE(buffer.pointer);
L
Linus Torvalds 已提交
60 61 62 63 64 65 66
	}
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_type
 *
67
 * PARAMETERS:  node        - Parent Node to be examined
L
Linus Torvalds 已提交
68 69 70
 *
 * RETURN:      Type field from Node whose handle is passed
 *
R
Robert Moore 已提交
71 72
 * DESCRIPTION: Return the type of a Namespace node
 *
L
Linus Torvalds 已提交
73 74
 ******************************************************************************/

L
Len Brown 已提交
75
acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
L
Linus Torvalds 已提交
76
{
B
Bob Moore 已提交
77
	ACPI_FUNCTION_TRACE(ns_get_type);
L
Linus Torvalds 已提交
78 79

	if (!node) {
B
Bob Moore 已提交
80
		ACPI_WARNING((AE_INFO, "Null Node parameter"));
81
		return_UINT8(ACPI_TYPE_ANY);
L
Linus Torvalds 已提交
82 83
	}

84
	return_UINT8(node->type);
L
Linus Torvalds 已提交
85 86 87 88 89 90
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_local
 *
91
 * PARAMETERS:  type        - A namespace object type
L
Linus Torvalds 已提交
92 93 94 95
 *
 * RETURN:      LOCAL if names must be found locally in objects of the
 *              passed type, 0 if enclosing scopes should be searched
 *
R
Robert Moore 已提交
96 97
 * DESCRIPTION: Returns scope rule for the given object type.
 *
L
Linus Torvalds 已提交
98 99
 ******************************************************************************/

L
Len Brown 已提交
100
u32 acpi_ns_local(acpi_object_type type)
L
Linus Torvalds 已提交
101
{
B
Bob Moore 已提交
102
	ACPI_FUNCTION_TRACE(ns_local);
L
Linus Torvalds 已提交
103

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

L
Linus Torvalds 已提交
106 107
		/* Type code out of range  */

108
		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
109
		return_UINT32(ACPI_NS_NORMAL);
L
Linus Torvalds 已提交
110 111
	}

112
	return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
L
Linus Torvalds 已提交
113 114 115 116 117 118
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_internal_name_length
 *
119
 * PARAMETERS:  info            - Info struct initialized with the
L
Linus Torvalds 已提交
120 121
 *                                external name pointer.
 *
R
Robert Moore 已提交
122
 * RETURN:      None
L
Linus Torvalds 已提交
123 124 125 126 127 128
 *
 * DESCRIPTION: Calculate the length of the internal (AML) namestring
 *              corresponding to the external (ASL) namestring.
 *
 ******************************************************************************/

L
Len Brown 已提交
129
void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
L
Linus Torvalds 已提交
130
{
131
	const char *next_external_char;
L
Len Brown 已提交
132
	u32 i;
L
Linus Torvalds 已提交
133

L
Len Brown 已提交
134
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
135 136 137 138 139 140 141

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

	/*
142 143 144 145
	 * 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)
L
Linus Torvalds 已提交
146 147 148
	 *
	 * strlen() + 1 covers the first name_seg, which has no path separator
	 */
149
	if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
L
Linus Torvalds 已提交
150 151
		info->fully_qualified = TRUE;
		next_external_char++;
152 153 154

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

155
		while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
156 157
			next_external_char++;
		}
L
Len Brown 已提交
158
	} else {
159 160
		/* Handle Carat prefixes */

161
		while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
L
Linus Torvalds 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174
			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++) {
175
			if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
L
Linus Torvalds 已提交
176 177 178 179 180
				info->num_segments++;
			}
		}
	}

181
	info->length = (ACPI_NAMESEG_SIZE * info->num_segments) +
L
Len Brown 已提交
182
	    4 + info->num_carats;
L
Linus Torvalds 已提交
183 184 185 186 187 188 189 190

	info->next_external_char = next_external_char;
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_build_internal_name
 *
191
 * PARAMETERS:  info            - Info struct fully initialized
L
Linus Torvalds 已提交
192 193 194 195 196 197 198 199
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Construct the internal (AML) namestring
 *              corresponding to the external (ASL) namestring.
 *
 ******************************************************************************/

L
Len Brown 已提交
200
acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
L
Linus Torvalds 已提交
201
{
L
Len Brown 已提交
202 203
	u32 num_segments = info->num_segments;
	char *internal_name = info->internal_name;
204
	const char *external_name = info->next_external_char;
L
Len Brown 已提交
205
	char *result = NULL;
206
	u32 i;
L
Linus Torvalds 已提交
207

B
Bob Moore 已提交
208
	ACPI_FUNCTION_TRACE(ns_build_internal_name);
L
Linus Torvalds 已提交
209 210 211 212

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

	if (info->fully_qualified) {
213
		internal_name[0] = AML_ROOT_PREFIX;
L
Linus Torvalds 已提交
214 215 216

		if (num_segments <= 1) {
			result = &internal_name[1];
L
Len Brown 已提交
217
		} else if (num_segments == 2) {
L
Linus Torvalds 已提交
218 219
			internal_name[1] = AML_DUAL_NAME_PREFIX;
			result = &internal_name[2];
L
Len Brown 已提交
220
		} else {
221
			internal_name[1] = AML_MULTI_NAME_PREFIX;
L
Len Brown 已提交
222
			internal_name[2] = (char)num_segments;
L
Linus Torvalds 已提交
223 224
			result = &internal_name[3];
		}
L
Len Brown 已提交
225
	} else {
L
Linus Torvalds 已提交
226 227 228 229 230 231 232
		/*
		 * 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++) {
233
				internal_name[i] = AML_PARENT_PREFIX;
L
Linus Torvalds 已提交
234 235 236 237 238
			}
		}

		if (num_segments <= 1) {
			result = &internal_name[i];
L
Len Brown 已提交
239
		} else if (num_segments == 2) {
L
Linus Torvalds 已提交
240
			internal_name[i] = AML_DUAL_NAME_PREFIX;
241
			result = &internal_name[(acpi_size)i + 1];
L
Len Brown 已提交
242
		} else {
243
			internal_name[i] = AML_MULTI_NAME_PREFIX;
244 245
			internal_name[(acpi_size)i + 1] = (char)num_segments;
			result = &internal_name[(acpi_size)i + 2];
L
Linus Torvalds 已提交
246 247 248 249 250 251
		}
	}

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

	for (; num_segments; num_segments--) {
252
		for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
253
			if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
L
Len Brown 已提交
254
			    (*external_name == 0)) {
B
Bob Moore 已提交
255

L
Linus Torvalds 已提交
256 257 258
				/* Pad the segment with underscore(s) if segment is short */

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

262
				result[i] = (char)toupper((int)*external_name);
L
Linus Torvalds 已提交
263 264 265 266 267 268
				external_name++;
			}
		}

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

269
		if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
L
Len Brown 已提交
270
		    (*external_name != 0)) {
271
			return_ACPI_STATUS(AE_BAD_PATHNAME);
L
Linus Torvalds 已提交
272 273 274 275 276
		}

		/* Move on the next segment */

		external_name++;
277
		result += ACPI_NAMESEG_SIZE;
L
Linus Torvalds 已提交
278 279 280 281 282 283 284
	}

	/* Terminate the string */

	*result = 0;

	if (info->fully_qualified) {
L
Len Brown 已提交
285 286 287 288 289 290
		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 已提交
291 292
	}

L
Len Brown 已提交
293
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
294 295 296 297 298 299 300
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_internalize_name
 *
 * PARAMETERS:  *external_name          - External representation of name
301
 *              **Converted name        - Where to return the resulting
L
Linus Torvalds 已提交
302 303 304 305 306 307 308 309 310
 *                                        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)
 *
 *******************************************************************************/

311 312
acpi_status
acpi_ns_internalize_name(const char *external_name, char **converted_name)
L
Linus Torvalds 已提交
313
{
L
Len Brown 已提交
314 315 316
	char *internal_name;
	struct acpi_namestring_info info;
	acpi_status status;
L
Linus Torvalds 已提交
317

B
Bob Moore 已提交
318
	ACPI_FUNCTION_TRACE(ns_internalize_name);
L
Linus Torvalds 已提交
319

L
Len Brown 已提交
320 321
	if ((!external_name) || (*external_name == 0) || (!converted_name)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
322 323 324 325 326
	}

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

	info.external_name = external_name;
L
Len Brown 已提交
327
	acpi_ns_get_internal_name_length(&info);
L
Linus Torvalds 已提交
328 329 330

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

B
Bob Moore 已提交
331
	internal_name = ACPI_ALLOCATE_ZEROED(info.length);
L
Linus Torvalds 已提交
332
	if (!internal_name) {
L
Len Brown 已提交
333
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
334 335 336 337 338
	}

	/* Build the name */

	info.internal_name = internal_name;
L
Len Brown 已提交
339 340
	status = acpi_ns_build_internal_name(&info);
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
341
		ACPI_FREE(internal_name);
L
Len Brown 已提交
342
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
343 344 345
	}

	*converted_name = internal_name;
L
Len Brown 已提交
346
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
347 348 349 350 351 352
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_externalize_name
 *
353
 * PARAMETERS:  internal_name_length - Length of the internal name below
R
Robert Moore 已提交
354 355 356 357
 *              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 已提交
358 359 360 361
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
R
Robert Moore 已提交
362
 *              to its external (printable) form (e.g. "\_PR_.CPU0")
L
Linus Torvalds 已提交
363 364 365 366
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
367
acpi_ns_externalize_name(u32 internal_name_length,
368
			 const char *internal_name,
L
Len Brown 已提交
369
			 u32 * converted_name_length, char **converted_name)
L
Linus Torvalds 已提交
370
{
371 372 373 374 375 376
	u32 names_index = 0;
	u32 num_segments = 0;
	u32 required_length;
	u32 prefix_length = 0;
	u32 i = 0;
	u32 j = 0;
L
Linus Torvalds 已提交
377

B
Bob Moore 已提交
378
	ACPI_FUNCTION_TRACE(ns_externalize_name);
L
Linus Torvalds 已提交
379

L
Len Brown 已提交
380 381
	if (!internal_name_length || !internal_name || !converted_name) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
382 383
	}

384 385
	/* Check for a prefix (one '\' | one or more '^') */

L
Linus Torvalds 已提交
386
	switch (internal_name[0]) {
387
	case AML_ROOT_PREFIX:
388

L
Linus Torvalds 已提交
389 390 391
		prefix_length = 1;
		break;

392
	case AML_PARENT_PREFIX:
393

L
Linus Torvalds 已提交
394
		for (i = 0; i < internal_name_length; i++) {
395
			if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
L
Linus Torvalds 已提交
396
				prefix_length = i + 1;
L
Len Brown 已提交
397
			} else {
L
Linus Torvalds 已提交
398 399 400 401 402 403 404 405 406 407 408
				break;
			}
		}

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

		break;

	default:
409

L
Linus Torvalds 已提交
410 411 412 413
		break;
	}

	/*
414
	 * Check for object names. Note that there could be 0-255 of these
L
Linus Torvalds 已提交
415 416 417 418
	 * 4-byte elements.
	 */
	if (prefix_length < internal_name_length) {
		switch (internal_name[prefix_length]) {
419
		case AML_MULTI_NAME_PREFIX:
L
Linus Torvalds 已提交
420 421 422 423

			/* <count> 4-byte names */

			names_index = prefix_length + 2;
424
			num_segments = (u8)
425
			    internal_name[(acpi_size)prefix_length + 1];
L
Linus Torvalds 已提交
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
			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 已提交
460
	    ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
L
Linus Torvalds 已提交
461 462

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

471 472
	/* Build the converted_name */

B
Bob Moore 已提交
473
	*converted_name = ACPI_ALLOCATE_ZEROED(required_length);
L
Linus Torvalds 已提交
474
	if (!(*converted_name)) {
L
Len Brown 已提交
475
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489
	}

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

490 491
			/* Copy and validate the 4-char name segment */

492 493
			ACPI_COPY_NAMESEG(&(*converted_name)[j],
					  &internal_name[names_index]);
494
			acpi_ut_repair_name(&(*converted_name)[j]);
495

496 497
			j += ACPI_NAMESEG_SIZE;
			names_index += ACPI_NAMESEG_SIZE;
L
Linus Torvalds 已提交
498 499 500 501 502 503 504
		}
	}

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

L
Len Brown 已提交
505
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
506 507 508 509
}

/*******************************************************************************
 *
510
 * FUNCTION:    acpi_ns_validate_handle
L
Linus Torvalds 已提交
511
 *
512
 * PARAMETERS:  handle          - Handle to be validated and typecast to a
513
 *                                namespace node.
L
Linus Torvalds 已提交
514
 *
515
 * RETURN:      A pointer to a namespace node
L
Linus Torvalds 已提交
516
 *
517 518
 * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
 *              cases for the root node.
L
Linus Torvalds 已提交
519
 *
520
 * NOTE: Real integer handles would allow for more verification
R
Robert Moore 已提交
521
 *       and keep all pointers within this subsystem - however this introduces
522 523 524
 *       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.
525
 *
L
Linus Torvalds 已提交
526 527
 ******************************************************************************/

528
struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
L
Linus Torvalds 已提交
529 530
{

L
Len Brown 已提交
531
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
532

533 534
	/* Parameter validation */

B
Bob Moore 已提交
535
	if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
L
Linus Torvalds 已提交
536 537 538 539 540
		return (acpi_gbl_root_node);
	}

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

L
Len Brown 已提交
541
	if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
L
Linus Torvalds 已提交
542 543 544
		return (NULL);
	}

B
Bob Moore 已提交
545
	return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
L
Linus Torvalds 已提交
546 547 548 549 550 551 552 553 554 555
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_terminate
 *
 * PARAMETERS:  none
 *
 * RETURN:      none
 *
R
Robert Moore 已提交
556
 * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
L
Linus Torvalds 已提交
557 558 559
 *
 ******************************************************************************/

L
Len Brown 已提交
560
void acpi_ns_terminate(void)
L
Linus Torvalds 已提交
561
{
562
	acpi_status status;
L
Linus Torvalds 已提交
563

B
Bob Moore 已提交
564
	ACPI_FUNCTION_TRACE(ns_terminate);
L
Linus Torvalds 已提交
565 566

	/*
567 568
	 * Free the entire namespace -- all nodes and all objects
	 * attached to the nodes
L
Linus Torvalds 已提交
569
	 */
L
Len Brown 已提交
570
	acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
L
Linus Torvalds 已提交
571

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

574 575 576
	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_VOID;
L
Linus Torvalds 已提交
577 578
	}

579 580 581
	acpi_ns_delete_node(acpi_gbl_root_node);
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);

L
Len Brown 已提交
582
	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
L
Linus Torvalds 已提交
583 584 585 586 587 588 589
	return_VOID;
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_opens_scope
 *
590
 * PARAMETERS:  type        - A valid namespace type
L
Linus Torvalds 已提交
591 592 593 594 595 596
 *
 * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
 *              to the ACPI specification, else 0
 *
 ******************************************************************************/

L
Len Brown 已提交
597
u32 acpi_ns_opens_scope(acpi_object_type type)
L
Linus Torvalds 已提交
598
{
599
	ACPI_FUNCTION_ENTRY();
L
Linus Torvalds 已提交
600

601
	if (type > ACPI_TYPE_LOCAL_MAX) {
B
Bob Moore 已提交
602

L
Linus Torvalds 已提交
603 604
		/* type code out of range  */

605
		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
606
		return (ACPI_NS_NORMAL);
L
Linus Torvalds 已提交
607 608
	}

609
	return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
L
Linus Torvalds 已提交
610 611 612 613
}

/*******************************************************************************
 *
614
 * FUNCTION:    acpi_ns_get_node_unlocked
L
Linus Torvalds 已提交
615
 *
616
 * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
L
Linus Torvalds 已提交
617 618
 *                            \ (backslash) and ^ (carat) prefixes, and the
 *                            . (period) to separate segments are supported.
B
Bob Moore 已提交
619
 *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
620
 *                            root of the name space. If Name is fully
L
Linus Torvalds 已提交
621 622
 *                            qualified (first s8 is '\'), the passed value
 *                            of Scope will not be accessed.
623
 *              flags       - Used to indicate whether to perform upsearch or
L
Linus Torvalds 已提交
624 625 626 627
 *                            not.
 *              return_node - Where the Node is returned
 *
 * DESCRIPTION: Look up a name relative to a given scope and return the
628
 *              corresponding Node. NOTE: Scope can be null.
L
Linus Torvalds 已提交
629
 *
630
 * MUTEX:       Doesn't locks namespace
L
Linus Torvalds 已提交
631 632 633 634
 *
 ******************************************************************************/

acpi_status
635 636 637
acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node,
			  const char *pathname,
			  u32 flags, struct acpi_namespace_node **return_node)
L
Linus Torvalds 已提交
638
{
L
Len Brown 已提交
639 640
	union acpi_generic_state scope_info;
	acpi_status status;
B
Bob Moore 已提交
641
	char *internal_path;
L
Linus Torvalds 已提交
642

643 644
	ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked,
				ACPI_CAST_PTR(char, pathname));
L
Linus Torvalds 已提交
645

646 647
	/* Simplest case is a null pathname */

B
Bob Moore 已提交
648 649 650 651 652
	if (!pathname) {
		*return_node = prefix_node;
		if (!prefix_node) {
			*return_node = acpi_gbl_root_node;
		}
653

B
Bob Moore 已提交
654 655
		return_ACPI_STATUS(AE_OK);
	}
B
Bob Moore 已提交
656

657 658 659 660 661 662 663
	/* 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 已提交
664
	/* Convert path to internal representation */
L
Linus Torvalds 已提交
665

B
Bob Moore 已提交
666 667 668
	status = acpi_ns_internalize_name(pathname, &internal_path);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
669 670 671 672
	}

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

B
Bob Moore 已提交
673
	scope_info.scope.node = prefix_node;
L
Linus Torvalds 已提交
674 675 676

	/* Lookup the name in the namespace */

B
Bob Moore 已提交
677 678 679 680
	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 已提交
681
	if (ACPI_FAILURE(status)) {
682
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
B
Bob Moore 已提交
683
				  pathname, acpi_format_exception(status)));
L
Linus Torvalds 已提交
684 685
	}

B
Bob Moore 已提交
686
	ACPI_FREE(internal_path);
L
Len Brown 已提交
687
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
688
}
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731

/*******************************************************************************
 *
 * FUNCTION:    acpi_ns_get_node
 *
 * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
 *                            \ (backslash) and ^ (carat) prefixes, and the
 *                            . (period) to separate segments are supported.
 *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
 *                            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
acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
		 const char *pathname,
		 u32 flags, struct acpi_namespace_node **return_node)
{
	acpi_status status;

	ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	status = acpi_ns_get_node_unlocked(prefix_node, pathname,
					   flags, return_node);

	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return_ACPI_STATUS(status);
}