195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
595b482a8SLen Brown * parents and siblings and Scope manipulation
695b482a8SLen Brown *
7*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
895b482a8SLen Brown *
995857638SErik Schmauss *****************************************************************************/
1095b482a8SLen Brown
1195b482a8SLen Brown #include <acpi/acpi.h>
12e2f7a777SLen Brown #include "accommon.h"
13e2f7a777SLen Brown #include "acnamesp.h"
14e2f7a777SLen Brown #include "amlcode.h"
1595b482a8SLen Brown
1695b482a8SLen Brown #define _COMPONENT ACPI_NAMESPACE
1795b482a8SLen Brown ACPI_MODULE_NAME("nsutils")
1895b482a8SLen Brown
1995b482a8SLen Brown /* Local prototypes */
2095b482a8SLen Brown #ifdef ACPI_OBSOLETE_FUNCTIONS
2195b482a8SLen Brown acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
2295b482a8SLen Brown #endif
2395b482a8SLen Brown
2495b482a8SLen Brown /*******************************************************************************
2595b482a8SLen Brown *
2695b482a8SLen Brown * FUNCTION: acpi_ns_print_node_pathname
2795b482a8SLen Brown *
28ba494beeSBob Moore * PARAMETERS: node - Object
29ba494beeSBob Moore * message - Prefix message
3095b482a8SLen Brown *
3195b482a8SLen Brown * DESCRIPTION: Print an object's full namespace pathname
3295b482a8SLen Brown * Manages allocation/freeing of a pathname buffer
3395b482a8SLen Brown *
3495b482a8SLen Brown ******************************************************************************/
3595b482a8SLen Brown
3695b482a8SLen Brown void
acpi_ns_print_node_pathname(struct acpi_namespace_node * node,const char * message)3795b482a8SLen Brown acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
3895b482a8SLen Brown const char *message)
3995b482a8SLen Brown {
4095b482a8SLen Brown struct acpi_buffer buffer;
4195b482a8SLen Brown acpi_status status;
4295b482a8SLen Brown
4395b482a8SLen Brown if (!node) {
4495b482a8SLen Brown acpi_os_printf("[NULL NAME]");
4595b482a8SLen Brown return;
4695b482a8SLen Brown }
4795b482a8SLen Brown
4895b482a8SLen Brown /* Convert handle to full pathname and print it (with supplied message) */
4995b482a8SLen Brown
5095b482a8SLen Brown buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
5195b482a8SLen Brown
522e5321cbSLv Zheng status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
5395b482a8SLen Brown if (ACPI_SUCCESS(status)) {
5495b482a8SLen Brown if (message) {
5595b482a8SLen Brown acpi_os_printf("%s ", message);
5695b482a8SLen Brown }
5795b482a8SLen Brown
581537f303SBob Moore acpi_os_printf("%s", (char *)buffer.pointer);
5995b482a8SLen Brown ACPI_FREE(buffer.pointer);
6095b482a8SLen Brown }
6195b482a8SLen Brown }
6295b482a8SLen Brown
6395b482a8SLen Brown /*******************************************************************************
6495b482a8SLen Brown *
6595b482a8SLen Brown * FUNCTION: acpi_ns_get_type
6695b482a8SLen Brown *
67ba494beeSBob Moore * PARAMETERS: node - Parent Node to be examined
6895b482a8SLen Brown *
6995b482a8SLen Brown * RETURN: Type field from Node whose handle is passed
7095b482a8SLen Brown *
7195b482a8SLen Brown * DESCRIPTION: Return the type of a Namespace node
7295b482a8SLen Brown *
7395b482a8SLen Brown ******************************************************************************/
7495b482a8SLen Brown
acpi_ns_get_type(struct acpi_namespace_node * node)7595b482a8SLen Brown acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
7695b482a8SLen Brown {
7795b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_get_type);
7895b482a8SLen Brown
7995b482a8SLen Brown if (!node) {
8095b482a8SLen Brown ACPI_WARNING((AE_INFO, "Null Node parameter"));
81fd1af712SBob Moore return_UINT8(ACPI_TYPE_ANY);
8295b482a8SLen Brown }
8395b482a8SLen Brown
84fd1af712SBob Moore return_UINT8(node->type);
8595b482a8SLen Brown }
8695b482a8SLen Brown
8795b482a8SLen Brown /*******************************************************************************
8895b482a8SLen Brown *
8995b482a8SLen Brown * FUNCTION: acpi_ns_local
9095b482a8SLen Brown *
91ba494beeSBob Moore * PARAMETERS: type - A namespace object type
9295b482a8SLen Brown *
9395b482a8SLen Brown * RETURN: LOCAL if names must be found locally in objects of the
9495b482a8SLen Brown * passed type, 0 if enclosing scopes should be searched
9595b482a8SLen Brown *
9695b482a8SLen Brown * DESCRIPTION: Returns scope rule for the given object type.
9795b482a8SLen Brown *
9895b482a8SLen Brown ******************************************************************************/
9995b482a8SLen Brown
acpi_ns_local(acpi_object_type type)10095b482a8SLen Brown u32 acpi_ns_local(acpi_object_type type)
10195b482a8SLen Brown {
10295b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_local);
10395b482a8SLen Brown
10495b482a8SLen Brown if (!acpi_ut_valid_object_type(type)) {
10595b482a8SLen Brown
10695b482a8SLen Brown /* Type code out of range */
10795b482a8SLen Brown
108f6a22b0bSBob Moore ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
109fd1af712SBob Moore return_UINT32(ACPI_NS_NORMAL);
11095b482a8SLen Brown }
11195b482a8SLen Brown
112fd1af712SBob Moore return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
11395b482a8SLen Brown }
11495b482a8SLen Brown
11595b482a8SLen Brown /*******************************************************************************
11695b482a8SLen Brown *
11795b482a8SLen Brown * FUNCTION: acpi_ns_get_internal_name_length
11895b482a8SLen Brown *
119ba494beeSBob Moore * PARAMETERS: info - Info struct initialized with the
12095b482a8SLen Brown * external name pointer.
12195b482a8SLen Brown *
12295b482a8SLen Brown * RETURN: None
12395b482a8SLen Brown *
12495b482a8SLen Brown * DESCRIPTION: Calculate the length of the internal (AML) namestring
12595b482a8SLen Brown * corresponding to the external (ASL) namestring.
12695b482a8SLen Brown *
12795b482a8SLen Brown ******************************************************************************/
12895b482a8SLen Brown
acpi_ns_get_internal_name_length(struct acpi_namestring_info * info)12995b482a8SLen Brown void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
13095b482a8SLen Brown {
13195b482a8SLen Brown const char *next_external_char;
13295b482a8SLen Brown u32 i;
13395b482a8SLen Brown
13495b482a8SLen Brown ACPI_FUNCTION_ENTRY();
13595b482a8SLen Brown
13695b482a8SLen Brown next_external_char = info->external_name;
13795b482a8SLen Brown info->num_carats = 0;
13895b482a8SLen Brown info->num_segments = 0;
13995b482a8SLen Brown info->fully_qualified = FALSE;
14095b482a8SLen Brown
14195b482a8SLen Brown /*
1421fad8738SBob Moore * For the internal name, the required length is 4 bytes per segment,
1431fad8738SBob Moore * plus 1 each for root_prefix, multi_name_prefix_op, segment count,
1441fad8738SBob Moore * trailing null (which is not really needed, but no there's harm in
1451fad8738SBob Moore * putting it there)
14695b482a8SLen Brown *
14795b482a8SLen Brown * strlen() + 1 covers the first name_seg, which has no path separator
14895b482a8SLen Brown */
14904a81dceSBob Moore if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
15095b482a8SLen Brown info->fully_qualified = TRUE;
15195b482a8SLen Brown next_external_char++;
15295b482a8SLen Brown
15395b482a8SLen Brown /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */
15495b482a8SLen Brown
15504a81dceSBob Moore while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
15695b482a8SLen Brown next_external_char++;
15795b482a8SLen Brown }
15895b482a8SLen Brown } else {
159d4913dc6SBob Moore /* Handle Carat prefixes */
160d4913dc6SBob Moore
16104a81dceSBob Moore while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
16295b482a8SLen Brown info->num_carats++;
16395b482a8SLen Brown next_external_char++;
16495b482a8SLen Brown }
16595b482a8SLen Brown }
16695b482a8SLen Brown
16795b482a8SLen Brown /*
16895b482a8SLen Brown * Determine the number of ACPI name "segments" by counting the number of
16995b482a8SLen Brown * path separators within the string. Start with one segment since the
17095b482a8SLen Brown * segment count is [(# separators) + 1], and zero separators is ok.
17195b482a8SLen Brown */
17295b482a8SLen Brown if (*next_external_char) {
17395b482a8SLen Brown info->num_segments = 1;
17495b482a8SLen Brown for (i = 0; next_external_char[i]; i++) {
17504a81dceSBob Moore if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
17695b482a8SLen Brown info->num_segments++;
17795b482a8SLen Brown }
17895b482a8SLen Brown }
17995b482a8SLen Brown }
18095b482a8SLen Brown
18132786755SBob Moore info->length = (ACPI_NAMESEG_SIZE * info->num_segments) +
18295b482a8SLen Brown 4 + info->num_carats;
18395b482a8SLen Brown
18495b482a8SLen Brown info->next_external_char = next_external_char;
18595b482a8SLen Brown }
18695b482a8SLen Brown
18795b482a8SLen Brown /*******************************************************************************
18895b482a8SLen Brown *
18995b482a8SLen Brown * FUNCTION: acpi_ns_build_internal_name
19095b482a8SLen Brown *
191ba494beeSBob Moore * PARAMETERS: info - Info struct fully initialized
19295b482a8SLen Brown *
19395b482a8SLen Brown * RETURN: Status
19495b482a8SLen Brown *
19595b482a8SLen Brown * DESCRIPTION: Construct the internal (AML) namestring
19695b482a8SLen Brown * corresponding to the external (ASL) namestring.
19795b482a8SLen Brown *
19895b482a8SLen Brown ******************************************************************************/
19995b482a8SLen Brown
acpi_ns_build_internal_name(struct acpi_namestring_info * info)20095b482a8SLen Brown acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
20195b482a8SLen Brown {
20295b482a8SLen Brown u32 num_segments = info->num_segments;
20395b482a8SLen Brown char *internal_name = info->internal_name;
20495b482a8SLen Brown const char *external_name = info->next_external_char;
20595b482a8SLen Brown char *result = NULL;
20695b482a8SLen Brown u32 i;
20795b482a8SLen Brown
20895b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_build_internal_name);
20995b482a8SLen Brown
21095b482a8SLen Brown /* Setup the correct prefixes, counts, and pointers */
21195b482a8SLen Brown
21295b482a8SLen Brown if (info->fully_qualified) {
21304a81dceSBob Moore internal_name[0] = AML_ROOT_PREFIX;
21495b482a8SLen Brown
21595b482a8SLen Brown if (num_segments <= 1) {
21695b482a8SLen Brown result = &internal_name[1];
21795b482a8SLen Brown } else if (num_segments == 2) {
21895b482a8SLen Brown internal_name[1] = AML_DUAL_NAME_PREFIX;
21995b482a8SLen Brown result = &internal_name[2];
22095b482a8SLen Brown } else {
2219ff5a21aSBob Moore internal_name[1] = AML_MULTI_NAME_PREFIX;
22295b482a8SLen Brown internal_name[2] = (char)num_segments;
22395b482a8SLen Brown result = &internal_name[3];
22495b482a8SLen Brown }
22595b482a8SLen Brown } else {
22695b482a8SLen Brown /*
22795b482a8SLen Brown * Not fully qualified.
22895b482a8SLen Brown * Handle Carats first, then append the name segments
22995b482a8SLen Brown */
23095b482a8SLen Brown i = 0;
23195b482a8SLen Brown if (info->num_carats) {
23295b482a8SLen Brown for (i = 0; i < info->num_carats; i++) {
23304a81dceSBob Moore internal_name[i] = AML_PARENT_PREFIX;
23495b482a8SLen Brown }
23595b482a8SLen Brown }
23695b482a8SLen Brown
23795b482a8SLen Brown if (num_segments <= 1) {
23895b482a8SLen Brown result = &internal_name[i];
23995b482a8SLen Brown } else if (num_segments == 2) {
24095b482a8SLen Brown internal_name[i] = AML_DUAL_NAME_PREFIX;
24195b482a8SLen Brown result = &internal_name[(acpi_size)i + 1];
24295b482a8SLen Brown } else {
2439ff5a21aSBob Moore internal_name[i] = AML_MULTI_NAME_PREFIX;
24495b482a8SLen Brown internal_name[(acpi_size)i + 1] = (char)num_segments;
24595b482a8SLen Brown result = &internal_name[(acpi_size)i + 2];
24695b482a8SLen Brown }
24795b482a8SLen Brown }
24895b482a8SLen Brown
24995b482a8SLen Brown /* Build the name (minus path separators) */
25095b482a8SLen Brown
25195b482a8SLen Brown for (; num_segments; num_segments--) {
25232786755SBob Moore for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
25304a81dceSBob Moore if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
25495b482a8SLen Brown (*external_name == 0)) {
25595b482a8SLen Brown
25695b482a8SLen Brown /* Pad the segment with underscore(s) if segment is short */
25795b482a8SLen Brown
25895b482a8SLen Brown result[i] = '_';
25995b482a8SLen Brown } else {
26095b482a8SLen Brown /* Convert the character to uppercase and save it */
26195b482a8SLen Brown
2624fa4616eSBob Moore result[i] = (char)toupper((int)*external_name);
26395b482a8SLen Brown external_name++;
26495b482a8SLen Brown }
26595b482a8SLen Brown }
26695b482a8SLen Brown
26795b482a8SLen Brown /* Now we must have a path separator, or the pathname is bad */
26895b482a8SLen Brown
26904a81dceSBob Moore if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
27095b482a8SLen Brown (*external_name != 0)) {
271a1acd22fSBob Moore return_ACPI_STATUS(AE_BAD_PATHNAME);
27295b482a8SLen Brown }
27395b482a8SLen Brown
27495b482a8SLen Brown /* Move on the next segment */
27595b482a8SLen Brown
27695b482a8SLen Brown external_name++;
27732786755SBob Moore result += ACPI_NAMESEG_SIZE;
27895b482a8SLen Brown }
27995b482a8SLen Brown
28095b482a8SLen Brown /* Terminate the string */
28195b482a8SLen Brown
28295b482a8SLen Brown *result = 0;
28395b482a8SLen Brown
28495b482a8SLen Brown if (info->fully_qualified) {
28595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
28695b482a8SLen Brown "Returning [%p] (abs) \"\\%s\"\n",
28795b482a8SLen Brown internal_name, internal_name));
28895b482a8SLen Brown } else {
28995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
29095b482a8SLen Brown internal_name, internal_name));
29195b482a8SLen Brown }
29295b482a8SLen Brown
29395b482a8SLen Brown return_ACPI_STATUS(AE_OK);
29495b482a8SLen Brown }
29595b482a8SLen Brown
29695b482a8SLen Brown /*******************************************************************************
29795b482a8SLen Brown *
29895b482a8SLen Brown * FUNCTION: acpi_ns_internalize_name
29995b482a8SLen Brown *
30095b482a8SLen Brown * PARAMETERS: *external_name - External representation of name
301ba494beeSBob Moore * **Converted name - Where to return the resulting
30295b482a8SLen Brown * internal represention of the name
30395b482a8SLen Brown *
30495b482a8SLen Brown * RETURN: Status
30595b482a8SLen Brown *
30695b482a8SLen Brown * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
30795b482a8SLen Brown * to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
30895b482a8SLen Brown *
30995b482a8SLen Brown *******************************************************************************/
31095b482a8SLen Brown
31195b482a8SLen Brown acpi_status
acpi_ns_internalize_name(const char * external_name,char ** converted_name)31295b482a8SLen Brown acpi_ns_internalize_name(const char *external_name, char **converted_name)
31395b482a8SLen Brown {
31495b482a8SLen Brown char *internal_name;
31595b482a8SLen Brown struct acpi_namestring_info info;
31695b482a8SLen Brown acpi_status status;
31795b482a8SLen Brown
31895b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_internalize_name);
31995b482a8SLen Brown
32095b482a8SLen Brown if ((!external_name) || (*external_name == 0) || (!converted_name)) {
32195b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER);
32295b482a8SLen Brown }
32395b482a8SLen Brown
32495b482a8SLen Brown /* Get the length of the new internal name */
32595b482a8SLen Brown
32695b482a8SLen Brown info.external_name = external_name;
32795b482a8SLen Brown acpi_ns_get_internal_name_length(&info);
32895b482a8SLen Brown
32995b482a8SLen Brown /* We need a segment to store the internal name */
33095b482a8SLen Brown
33195b482a8SLen Brown internal_name = ACPI_ALLOCATE_ZEROED(info.length);
33295b482a8SLen Brown if (!internal_name) {
33395b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
33495b482a8SLen Brown }
33595b482a8SLen Brown
33695b482a8SLen Brown /* Build the name */
33795b482a8SLen Brown
33895b482a8SLen Brown info.internal_name = internal_name;
33995b482a8SLen Brown status = acpi_ns_build_internal_name(&info);
34095b482a8SLen Brown if (ACPI_FAILURE(status)) {
34195b482a8SLen Brown ACPI_FREE(internal_name);
34295b482a8SLen Brown return_ACPI_STATUS(status);
34395b482a8SLen Brown }
34495b482a8SLen Brown
34595b482a8SLen Brown *converted_name = internal_name;
34695b482a8SLen Brown return_ACPI_STATUS(AE_OK);
34795b482a8SLen Brown }
34895b482a8SLen Brown
34995b482a8SLen Brown /*******************************************************************************
35095b482a8SLen Brown *
35195b482a8SLen Brown * FUNCTION: acpi_ns_externalize_name
35295b482a8SLen Brown *
353c163f90cSErik Schmauss * PARAMETERS: internal_name_length - Length of the internal name below
35495b482a8SLen Brown * internal_name - Internal representation of name
35595b482a8SLen Brown * converted_name_length - Where the length is returned
35695b482a8SLen Brown * converted_name - Where the resulting external name
35795b482a8SLen Brown * is returned
35895b482a8SLen Brown *
35995b482a8SLen Brown * RETURN: Status
36095b482a8SLen Brown *
36195b482a8SLen Brown * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
36295b482a8SLen Brown * to its external (printable) form (e.g. "\_PR_.CPU0")
36395b482a8SLen Brown *
36495b482a8SLen Brown ******************************************************************************/
36595b482a8SLen Brown
36695b482a8SLen Brown acpi_status
acpi_ns_externalize_name(u32 internal_name_length,const char * internal_name,u32 * converted_name_length,char ** converted_name)36795b482a8SLen Brown acpi_ns_externalize_name(u32 internal_name_length,
36895b482a8SLen Brown const char *internal_name,
36995b482a8SLen Brown u32 * converted_name_length, char **converted_name)
37095b482a8SLen Brown {
37195b482a8SLen Brown u32 names_index = 0;
37295b482a8SLen Brown u32 num_segments = 0;
37395b482a8SLen Brown u32 required_length;
37495b482a8SLen Brown u32 prefix_length = 0;
37595b482a8SLen Brown u32 i = 0;
37695b482a8SLen Brown u32 j = 0;
37795b482a8SLen Brown
37895b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_externalize_name);
37995b482a8SLen Brown
38095b482a8SLen Brown if (!internal_name_length || !internal_name || !converted_name) {
38195b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER);
38295b482a8SLen Brown }
38395b482a8SLen Brown
384d4913dc6SBob Moore /* Check for a prefix (one '\' | one or more '^') */
385d4913dc6SBob Moore
38695b482a8SLen Brown switch (internal_name[0]) {
38704a81dceSBob Moore case AML_ROOT_PREFIX:
3881d1ea1b7SChao Guan
38995b482a8SLen Brown prefix_length = 1;
39095b482a8SLen Brown break;
39195b482a8SLen Brown
39204a81dceSBob Moore case AML_PARENT_PREFIX:
3931d1ea1b7SChao Guan
39495b482a8SLen Brown for (i = 0; i < internal_name_length; i++) {
39504a81dceSBob Moore if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
39695b482a8SLen Brown prefix_length = i + 1;
39795b482a8SLen Brown } else {
39895b482a8SLen Brown break;
39995b482a8SLen Brown }
40095b482a8SLen Brown }
40195b482a8SLen Brown
40295b482a8SLen Brown if (i == internal_name_length) {
40395b482a8SLen Brown prefix_length = i;
40495b482a8SLen Brown }
40595b482a8SLen Brown
40695b482a8SLen Brown break;
40795b482a8SLen Brown
40895b482a8SLen Brown default:
4091d1ea1b7SChao Guan
41095b482a8SLen Brown break;
41195b482a8SLen Brown }
41295b482a8SLen Brown
41395b482a8SLen Brown /*
41495b482a8SLen Brown * Check for object names. Note that there could be 0-255 of these
41595b482a8SLen Brown * 4-byte elements.
41695b482a8SLen Brown */
41795b482a8SLen Brown if (prefix_length < internal_name_length) {
41895b482a8SLen Brown switch (internal_name[prefix_length]) {
4199ff5a21aSBob Moore case AML_MULTI_NAME_PREFIX:
42095b482a8SLen Brown
42195b482a8SLen Brown /* <count> 4-byte names */
42295b482a8SLen Brown
42395b482a8SLen Brown names_index = prefix_length + 2;
42495b482a8SLen Brown num_segments = (u8)
42595b482a8SLen Brown internal_name[(acpi_size)prefix_length + 1];
42695b482a8SLen Brown break;
42795b482a8SLen Brown
42895b482a8SLen Brown case AML_DUAL_NAME_PREFIX:
42995b482a8SLen Brown
43095b482a8SLen Brown /* Two 4-byte names */
43195b482a8SLen Brown
43295b482a8SLen Brown names_index = prefix_length + 1;
43395b482a8SLen Brown num_segments = 2;
43495b482a8SLen Brown break;
43595b482a8SLen Brown
43695b482a8SLen Brown case 0:
43795b482a8SLen Brown
43895b482a8SLen Brown /* null_name */
43995b482a8SLen Brown
44095b482a8SLen Brown names_index = 0;
44195b482a8SLen Brown num_segments = 0;
44295b482a8SLen Brown break;
44395b482a8SLen Brown
44495b482a8SLen Brown default:
44595b482a8SLen Brown
44695b482a8SLen Brown /* one 4-byte name */
44795b482a8SLen Brown
44895b482a8SLen Brown names_index = prefix_length;
44995b482a8SLen Brown num_segments = 1;
45095b482a8SLen Brown break;
45195b482a8SLen Brown }
45295b482a8SLen Brown }
45395b482a8SLen Brown
45495b482a8SLen Brown /*
45595b482a8SLen Brown * Calculate the length of converted_name, which equals the length
45695b482a8SLen Brown * of the prefix, length of all object names, length of any required
45795b482a8SLen Brown * punctuation ('.') between object names, plus the NULL terminator.
45895b482a8SLen Brown */
45995b482a8SLen Brown required_length = prefix_length + (4 * num_segments) +
46095b482a8SLen Brown ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
46195b482a8SLen Brown
46295b482a8SLen Brown /*
46395b482a8SLen Brown * Check to see if we're still in bounds. If not, there's a problem
46495b482a8SLen Brown * with internal_name (invalid format).
46595b482a8SLen Brown */
46695b482a8SLen Brown if (required_length > internal_name_length) {
46795b482a8SLen Brown ACPI_ERROR((AE_INFO, "Invalid internal name"));
46895b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PATHNAME);
46995b482a8SLen Brown }
47095b482a8SLen Brown
471d4913dc6SBob Moore /* Build the converted_name */
472d4913dc6SBob Moore
47395b482a8SLen Brown *converted_name = ACPI_ALLOCATE_ZEROED(required_length);
47495b482a8SLen Brown if (!(*converted_name)) {
47595b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
47695b482a8SLen Brown }
47795b482a8SLen Brown
47895b482a8SLen Brown j = 0;
47995b482a8SLen Brown
48095b482a8SLen Brown for (i = 0; i < prefix_length; i++) {
48195b482a8SLen Brown (*converted_name)[j++] = internal_name[i];
48295b482a8SLen Brown }
48395b482a8SLen Brown
48495b482a8SLen Brown if (num_segments > 0) {
48595b482a8SLen Brown for (i = 0; i < num_segments; i++) {
48695b482a8SLen Brown if (i > 0) {
48795b482a8SLen Brown (*converted_name)[j++] = '.';
48895b482a8SLen Brown }
48995b482a8SLen Brown
49047abd13cSBob Moore /* Copy and validate the 4-char name segment */
49147abd13cSBob Moore
492a3ce7a8eSBob Moore ACPI_COPY_NAMESEG(&(*converted_name)[j],
49347abd13cSBob Moore &internal_name[names_index]);
49447abd13cSBob Moore acpi_ut_repair_name(&(*converted_name)[j]);
49500eb3255SBob Moore
49632786755SBob Moore j += ACPI_NAMESEG_SIZE;
49732786755SBob Moore names_index += ACPI_NAMESEG_SIZE;
49895b482a8SLen Brown }
49995b482a8SLen Brown }
50095b482a8SLen Brown
50195b482a8SLen Brown if (converted_name_length) {
50295b482a8SLen Brown *converted_name_length = (u32) required_length;
50395b482a8SLen Brown }
50495b482a8SLen Brown
50595b482a8SLen Brown return_ACPI_STATUS(AE_OK);
50695b482a8SLen Brown }
50795b482a8SLen Brown
50895b482a8SLen Brown /*******************************************************************************
50995b482a8SLen Brown *
510f24b664dSBob Moore * FUNCTION: acpi_ns_validate_handle
51195b482a8SLen Brown *
512ba494beeSBob Moore * PARAMETERS: handle - Handle to be validated and typecast to a
513f24b664dSBob Moore * namespace node.
51495b482a8SLen Brown *
515f24b664dSBob Moore * RETURN: A pointer to a namespace node
51695b482a8SLen Brown *
517f24b664dSBob Moore * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
518f24b664dSBob Moore * cases for the root node.
51995b482a8SLen Brown *
520f24b664dSBob Moore * NOTE: Real integer handles would allow for more verification
52195b482a8SLen Brown * and keep all pointers within this subsystem - however this introduces
522f24b664dSBob Moore * more overhead and has not been necessary to this point. Drivers
523f24b664dSBob Moore * holding handles are typically notified before a node becomes invalid
524f24b664dSBob Moore * due to a table unload.
525d4913dc6SBob Moore *
52695b482a8SLen Brown ******************************************************************************/
52795b482a8SLen Brown
acpi_ns_validate_handle(acpi_handle handle)528f24b664dSBob Moore struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
52995b482a8SLen Brown {
53095b482a8SLen Brown
53195b482a8SLen Brown ACPI_FUNCTION_ENTRY();
53295b482a8SLen Brown
533d4913dc6SBob Moore /* Parameter validation */
534d4913dc6SBob Moore
53595b482a8SLen Brown if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
53695b482a8SLen Brown return (acpi_gbl_root_node);
53795b482a8SLen Brown }
53895b482a8SLen Brown
53995b482a8SLen Brown /* We can at least attempt to verify the handle */
54095b482a8SLen Brown
54195b482a8SLen Brown if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
54295b482a8SLen Brown return (NULL);
54395b482a8SLen Brown }
54495b482a8SLen Brown
54595b482a8SLen Brown return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
54695b482a8SLen Brown }
54795b482a8SLen Brown
54895b482a8SLen Brown /*******************************************************************************
54995b482a8SLen Brown *
55095b482a8SLen Brown * FUNCTION: acpi_ns_terminate
55195b482a8SLen Brown *
55295b482a8SLen Brown * PARAMETERS: none
55395b482a8SLen Brown *
55495b482a8SLen Brown * RETURN: none
55595b482a8SLen Brown *
55695b482a8SLen Brown * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
55795b482a8SLen Brown *
55895b482a8SLen Brown ******************************************************************************/
55995b482a8SLen Brown
acpi_ns_terminate(void)56095b482a8SLen Brown void acpi_ns_terminate(void)
56195b482a8SLen Brown {
5623f69fe15SBob Moore acpi_status status;
56325823e78SBob Moore
5643b2d6911SSeunghun Han ACPI_FUNCTION_TRACE(ns_terminate);
5653b2d6911SSeunghun Han
56695b482a8SLen Brown /*
5673f69fe15SBob Moore * Free the entire namespace -- all nodes and all objects
5683f69fe15SBob Moore * attached to the nodes
56995b482a8SLen Brown */
57095b482a8SLen Brown acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
57195b482a8SLen Brown
5723f69fe15SBob Moore /* Delete any objects attached to the root node */
57395b482a8SLen Brown
5743f69fe15SBob Moore status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
5753f69fe15SBob Moore if (ACPI_FAILURE(status)) {
5763f69fe15SBob Moore return_VOID;
57795b482a8SLen Brown }
57895b482a8SLen Brown
5793f69fe15SBob Moore acpi_ns_delete_node(acpi_gbl_root_node);
5803f69fe15SBob Moore (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
5813f69fe15SBob Moore
58295b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
58395b482a8SLen Brown return_VOID;
58495b482a8SLen Brown }
58595b482a8SLen Brown
58695b482a8SLen Brown /*******************************************************************************
58795b482a8SLen Brown *
58895b482a8SLen Brown * FUNCTION: acpi_ns_opens_scope
58995b482a8SLen Brown *
590ba494beeSBob Moore * PARAMETERS: type - A valid namespace type
59195b482a8SLen Brown *
59295b482a8SLen Brown * RETURN: NEWSCOPE if the passed type "opens a name scope" according
59395b482a8SLen Brown * to the ACPI specification, else 0
59495b482a8SLen Brown *
59595b482a8SLen Brown ******************************************************************************/
59695b482a8SLen Brown
acpi_ns_opens_scope(acpi_object_type type)59795b482a8SLen Brown u32 acpi_ns_opens_scope(acpi_object_type type)
59895b482a8SLen Brown {
5990e770b32SBob Moore ACPI_FUNCTION_ENTRY();
60095b482a8SLen Brown
6010e770b32SBob Moore if (type > ACPI_TYPE_LOCAL_MAX) {
60295b482a8SLen Brown
60395b482a8SLen Brown /* type code out of range */
60495b482a8SLen Brown
605f6a22b0bSBob Moore ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
6060e770b32SBob Moore return (ACPI_NS_NORMAL);
60795b482a8SLen Brown }
60895b482a8SLen Brown
6090e770b32SBob Moore return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
61095b482a8SLen Brown }
61195b482a8SLen Brown
61295b482a8SLen Brown /*******************************************************************************
61395b482a8SLen Brown *
614c2d981aaSLv Zheng * FUNCTION: acpi_ns_get_node_unlocked
61595b482a8SLen Brown *
616ba494beeSBob Moore * PARAMETERS: *pathname - Name to be found, in external (ASL) format. The
61795b482a8SLen Brown * \ (backslash) and ^ (carat) prefixes, and the
61895b482a8SLen Brown * . (period) to separate segments are supported.
61995b482a8SLen Brown * prefix_node - Root of subtree to be searched, or NS_ALL for the
62095b482a8SLen Brown * root of the name space. If Name is fully
62195b482a8SLen Brown * qualified (first s8 is '\'), the passed value
62295b482a8SLen Brown * of Scope will not be accessed.
623ba494beeSBob Moore * flags - Used to indicate whether to perform upsearch or
62495b482a8SLen Brown * not.
62595b482a8SLen Brown * return_node - Where the Node is returned
62695b482a8SLen Brown *
62795b482a8SLen Brown * DESCRIPTION: Look up a name relative to a given scope and return the
62895b482a8SLen Brown * corresponding Node. NOTE: Scope can be null.
62995b482a8SLen Brown *
630c2d981aaSLv Zheng * MUTEX: Doesn't locks namespace
63195b482a8SLen Brown *
63295b482a8SLen Brown ******************************************************************************/
63395b482a8SLen Brown
63495b482a8SLen Brown acpi_status
acpi_ns_get_node_unlocked(struct acpi_namespace_node * prefix_node,const char * pathname,u32 flags,struct acpi_namespace_node ** return_node)635c2d981aaSLv Zheng acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node,
63695b482a8SLen Brown const char *pathname,
63795b482a8SLen Brown u32 flags, struct acpi_namespace_node **return_node)
63895b482a8SLen Brown {
63995b482a8SLen Brown union acpi_generic_state scope_info;
64095b482a8SLen Brown acpi_status status;
64195b482a8SLen Brown char *internal_path;
64295b482a8SLen Brown
643c2d981aaSLv Zheng ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked,
644c2d981aaSLv Zheng ACPI_CAST_PTR(char, pathname));
64595b482a8SLen Brown
646f8c9bfe4SBob Moore /* Simplest case is a null pathname */
647f8c9bfe4SBob Moore
64895b482a8SLen Brown if (!pathname) {
64995b482a8SLen Brown *return_node = prefix_node;
65095b482a8SLen Brown if (!prefix_node) {
65195b482a8SLen Brown *return_node = acpi_gbl_root_node;
65295b482a8SLen Brown }
6531fad8738SBob Moore
65495b482a8SLen Brown return_ACPI_STATUS(AE_OK);
65595b482a8SLen Brown }
65695b482a8SLen Brown
657f8c9bfe4SBob Moore /* Quick check for a reference to the root */
658f8c9bfe4SBob Moore
659f8c9bfe4SBob Moore if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) {
660f8c9bfe4SBob Moore *return_node = acpi_gbl_root_node;
661f8c9bfe4SBob Moore return_ACPI_STATUS(AE_OK);
662f8c9bfe4SBob Moore }
663f8c9bfe4SBob Moore
66495b482a8SLen Brown /* Convert path to internal representation */
66595b482a8SLen Brown
66695b482a8SLen Brown status = acpi_ns_internalize_name(pathname, &internal_path);
66795b482a8SLen Brown if (ACPI_FAILURE(status)) {
66895b482a8SLen Brown return_ACPI_STATUS(status);
66995b482a8SLen Brown }
67095b482a8SLen Brown
67195b482a8SLen Brown /* Setup lookup scope (search starting point) */
67295b482a8SLen Brown
67395b482a8SLen Brown scope_info.scope.node = prefix_node;
67495b482a8SLen Brown
67595b482a8SLen Brown /* Lookup the name in the namespace */
67695b482a8SLen Brown
67795b482a8SLen Brown status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
67895b482a8SLen Brown ACPI_IMODE_EXECUTE,
67995b482a8SLen Brown (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
68095b482a8SLen Brown return_node);
68195b482a8SLen Brown if (ACPI_FAILURE(status)) {
6827bcc06e8SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
68395b482a8SLen Brown pathname, acpi_format_exception(status)));
68495b482a8SLen Brown }
68595b482a8SLen Brown
68695b482a8SLen Brown ACPI_FREE(internal_path);
68795b482a8SLen Brown return_ACPI_STATUS(status);
68895b482a8SLen Brown }
689c2d981aaSLv Zheng
690c2d981aaSLv Zheng /*******************************************************************************
691c2d981aaSLv Zheng *
692c2d981aaSLv Zheng * FUNCTION: acpi_ns_get_node
693c2d981aaSLv Zheng *
694c2d981aaSLv Zheng * PARAMETERS: *pathname - Name to be found, in external (ASL) format. The
695c2d981aaSLv Zheng * \ (backslash) and ^ (carat) prefixes, and the
696c2d981aaSLv Zheng * . (period) to separate segments are supported.
697c2d981aaSLv Zheng * prefix_node - Root of subtree to be searched, or NS_ALL for the
698c2d981aaSLv Zheng * root of the name space. If Name is fully
699c2d981aaSLv Zheng * qualified (first s8 is '\'), the passed value
700c2d981aaSLv Zheng * of Scope will not be accessed.
701c2d981aaSLv Zheng * flags - Used to indicate whether to perform upsearch or
702c2d981aaSLv Zheng * not.
703c2d981aaSLv Zheng * return_node - Where the Node is returned
704c2d981aaSLv Zheng *
705c2d981aaSLv Zheng * DESCRIPTION: Look up a name relative to a given scope and return the
706c2d981aaSLv Zheng * corresponding Node. NOTE: Scope can be null.
707c2d981aaSLv Zheng *
708c2d981aaSLv Zheng * MUTEX: Locks namespace
709c2d981aaSLv Zheng *
710c2d981aaSLv Zheng ******************************************************************************/
711c2d981aaSLv Zheng
712c2d981aaSLv Zheng acpi_status
acpi_ns_get_node(struct acpi_namespace_node * prefix_node,const char * pathname,u32 flags,struct acpi_namespace_node ** return_node)713c2d981aaSLv Zheng acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
714c2d981aaSLv Zheng const char *pathname,
715c2d981aaSLv Zheng u32 flags, struct acpi_namespace_node **return_node)
716c2d981aaSLv Zheng {
717c2d981aaSLv Zheng acpi_status status;
718c2d981aaSLv Zheng
719c2d981aaSLv Zheng ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
720c2d981aaSLv Zheng
721c2d981aaSLv Zheng status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
722c2d981aaSLv Zheng if (ACPI_FAILURE(status)) {
723c2d981aaSLv Zheng return_ACPI_STATUS(status);
724c2d981aaSLv Zheng }
725c2d981aaSLv Zheng
726c2d981aaSLv Zheng status = acpi_ns_get_node_unlocked(prefix_node, pathname,
727c2d981aaSLv Zheng flags, return_node);
728c2d981aaSLv Zheng
729c2d981aaSLv Zheng (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
730c2d981aaSLv Zheng return_ACPI_STATUS(status);
731c2d981aaSLv Zheng }
732