xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/nsutils.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
5*4882a593Smuzhiyun  *                        parents and siblings and Scope manipulation
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 2000 - 2020, Intel Corp.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  *****************************************************************************/
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <acpi/acpi.h>
12*4882a593Smuzhiyun #include "accommon.h"
13*4882a593Smuzhiyun #include "acnamesp.h"
14*4882a593Smuzhiyun #include "amlcode.h"
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define _COMPONENT          ACPI_NAMESPACE
17*4882a593Smuzhiyun ACPI_MODULE_NAME("nsutils")
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /* Local prototypes */
20*4882a593Smuzhiyun #ifdef ACPI_OBSOLETE_FUNCTIONS
21*4882a593Smuzhiyun acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
22*4882a593Smuzhiyun #endif
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun /*******************************************************************************
25*4882a593Smuzhiyun  *
26*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_print_node_pathname
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  * PARAMETERS:  node            - Object
29*4882a593Smuzhiyun  *              message         - Prefix message
30*4882a593Smuzhiyun  *
31*4882a593Smuzhiyun  * DESCRIPTION: Print an object's full namespace pathname
32*4882a593Smuzhiyun  *              Manages allocation/freeing of a pathname buffer
33*4882a593Smuzhiyun  *
34*4882a593Smuzhiyun  ******************************************************************************/
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun void
acpi_ns_print_node_pathname(struct acpi_namespace_node * node,const char * message)37*4882a593Smuzhiyun acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
38*4882a593Smuzhiyun 			    const char *message)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun 	struct acpi_buffer buffer;
41*4882a593Smuzhiyun 	acpi_status status;
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	if (!node) {
44*4882a593Smuzhiyun 		acpi_os_printf("[NULL NAME]");
45*4882a593Smuzhiyun 		return;
46*4882a593Smuzhiyun 	}
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	/* Convert handle to full pathname and print it (with supplied message) */
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
53*4882a593Smuzhiyun 	if (ACPI_SUCCESS(status)) {
54*4882a593Smuzhiyun 		if (message) {
55*4882a593Smuzhiyun 			acpi_os_printf("%s ", message);
56*4882a593Smuzhiyun 		}
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 		acpi_os_printf("%s", (char *)buffer.pointer);
59*4882a593Smuzhiyun 		ACPI_FREE(buffer.pointer);
60*4882a593Smuzhiyun 	}
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /*******************************************************************************
64*4882a593Smuzhiyun  *
65*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_get_type
66*4882a593Smuzhiyun  *
67*4882a593Smuzhiyun  * PARAMETERS:  node        - Parent Node to be examined
68*4882a593Smuzhiyun  *
69*4882a593Smuzhiyun  * RETURN:      Type field from Node whose handle is passed
70*4882a593Smuzhiyun  *
71*4882a593Smuzhiyun  * DESCRIPTION: Return the type of a Namespace node
72*4882a593Smuzhiyun  *
73*4882a593Smuzhiyun  ******************************************************************************/
74*4882a593Smuzhiyun 
acpi_ns_get_type(struct acpi_namespace_node * node)75*4882a593Smuzhiyun acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ns_get_type);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	if (!node) {
80*4882a593Smuzhiyun 		ACPI_WARNING((AE_INFO, "Null Node parameter"));
81*4882a593Smuzhiyun 		return_UINT8(ACPI_TYPE_ANY);
82*4882a593Smuzhiyun 	}
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	return_UINT8(node->type);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun /*******************************************************************************
88*4882a593Smuzhiyun  *
89*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_local
90*4882a593Smuzhiyun  *
91*4882a593Smuzhiyun  * PARAMETERS:  type        - A namespace object type
92*4882a593Smuzhiyun  *
93*4882a593Smuzhiyun  * RETURN:      LOCAL if names must be found locally in objects of the
94*4882a593Smuzhiyun  *              passed type, 0 if enclosing scopes should be searched
95*4882a593Smuzhiyun  *
96*4882a593Smuzhiyun  * DESCRIPTION: Returns scope rule for the given object type.
97*4882a593Smuzhiyun  *
98*4882a593Smuzhiyun  ******************************************************************************/
99*4882a593Smuzhiyun 
acpi_ns_local(acpi_object_type type)100*4882a593Smuzhiyun u32 acpi_ns_local(acpi_object_type type)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ns_local);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	if (!acpi_ut_valid_object_type(type)) {
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 		/* Type code out of range  */
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
109*4882a593Smuzhiyun 		return_UINT32(ACPI_NS_NORMAL);
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun /*******************************************************************************
116*4882a593Smuzhiyun  *
117*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_get_internal_name_length
118*4882a593Smuzhiyun  *
119*4882a593Smuzhiyun  * PARAMETERS:  info            - Info struct initialized with the
120*4882a593Smuzhiyun  *                                external name pointer.
121*4882a593Smuzhiyun  *
122*4882a593Smuzhiyun  * RETURN:      None
123*4882a593Smuzhiyun  *
124*4882a593Smuzhiyun  * DESCRIPTION: Calculate the length of the internal (AML) namestring
125*4882a593Smuzhiyun  *              corresponding to the external (ASL) namestring.
126*4882a593Smuzhiyun  *
127*4882a593Smuzhiyun  ******************************************************************************/
128*4882a593Smuzhiyun 
acpi_ns_get_internal_name_length(struct acpi_namestring_info * info)129*4882a593Smuzhiyun void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	const char *next_external_char;
132*4882a593Smuzhiyun 	u32 i;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	ACPI_FUNCTION_ENTRY();
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	next_external_char = info->external_name;
137*4882a593Smuzhiyun 	info->num_carats = 0;
138*4882a593Smuzhiyun 	info->num_segments = 0;
139*4882a593Smuzhiyun 	info->fully_qualified = FALSE;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	/*
142*4882a593Smuzhiyun 	 * For the internal name, the required length is 4 bytes per segment,
143*4882a593Smuzhiyun 	 * plus 1 each for root_prefix, multi_name_prefix_op, segment count,
144*4882a593Smuzhiyun 	 * trailing null (which is not really needed, but no there's harm in
145*4882a593Smuzhiyun 	 * putting it there)
146*4882a593Smuzhiyun 	 *
147*4882a593Smuzhiyun 	 * strlen() + 1 covers the first name_seg, which has no path separator
148*4882a593Smuzhiyun 	 */
149*4882a593Smuzhiyun 	if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
150*4882a593Smuzhiyun 		info->fully_qualified = TRUE;
151*4882a593Smuzhiyun 		next_external_char++;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 		/* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 		while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
156*4882a593Smuzhiyun 			next_external_char++;
157*4882a593Smuzhiyun 		}
158*4882a593Smuzhiyun 	} else {
159*4882a593Smuzhiyun 		/* Handle Carat prefixes */
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 		while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
162*4882a593Smuzhiyun 			info->num_carats++;
163*4882a593Smuzhiyun 			next_external_char++;
164*4882a593Smuzhiyun 		}
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/*
168*4882a593Smuzhiyun 	 * Determine the number of ACPI name "segments" by counting the number of
169*4882a593Smuzhiyun 	 * path separators within the string. Start with one segment since the
170*4882a593Smuzhiyun 	 * segment count is [(# separators) + 1], and zero separators is ok.
171*4882a593Smuzhiyun 	 */
172*4882a593Smuzhiyun 	if (*next_external_char) {
173*4882a593Smuzhiyun 		info->num_segments = 1;
174*4882a593Smuzhiyun 		for (i = 0; next_external_char[i]; i++) {
175*4882a593Smuzhiyun 			if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
176*4882a593Smuzhiyun 				info->num_segments++;
177*4882a593Smuzhiyun 			}
178*4882a593Smuzhiyun 		}
179*4882a593Smuzhiyun 	}
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	info->length = (ACPI_NAMESEG_SIZE * info->num_segments) +
182*4882a593Smuzhiyun 	    4 + info->num_carats;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	info->next_external_char = next_external_char;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun /*******************************************************************************
188*4882a593Smuzhiyun  *
189*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_build_internal_name
190*4882a593Smuzhiyun  *
191*4882a593Smuzhiyun  * PARAMETERS:  info            - Info struct fully initialized
192*4882a593Smuzhiyun  *
193*4882a593Smuzhiyun  * RETURN:      Status
194*4882a593Smuzhiyun  *
195*4882a593Smuzhiyun  * DESCRIPTION: Construct the internal (AML) namestring
196*4882a593Smuzhiyun  *              corresponding to the external (ASL) namestring.
197*4882a593Smuzhiyun  *
198*4882a593Smuzhiyun  ******************************************************************************/
199*4882a593Smuzhiyun 
acpi_ns_build_internal_name(struct acpi_namestring_info * info)200*4882a593Smuzhiyun acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	u32 num_segments = info->num_segments;
203*4882a593Smuzhiyun 	char *internal_name = info->internal_name;
204*4882a593Smuzhiyun 	const char *external_name = info->next_external_char;
205*4882a593Smuzhiyun 	char *result = NULL;
206*4882a593Smuzhiyun 	u32 i;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ns_build_internal_name);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	/* Setup the correct prefixes, counts, and pointers */
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	if (info->fully_qualified) {
213*4882a593Smuzhiyun 		internal_name[0] = AML_ROOT_PREFIX;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 		if (num_segments <= 1) {
216*4882a593Smuzhiyun 			result = &internal_name[1];
217*4882a593Smuzhiyun 		} else if (num_segments == 2) {
218*4882a593Smuzhiyun 			internal_name[1] = AML_DUAL_NAME_PREFIX;
219*4882a593Smuzhiyun 			result = &internal_name[2];
220*4882a593Smuzhiyun 		} else {
221*4882a593Smuzhiyun 			internal_name[1] = AML_MULTI_NAME_PREFIX;
222*4882a593Smuzhiyun 			internal_name[2] = (char)num_segments;
223*4882a593Smuzhiyun 			result = &internal_name[3];
224*4882a593Smuzhiyun 		}
225*4882a593Smuzhiyun 	} else {
226*4882a593Smuzhiyun 		/*
227*4882a593Smuzhiyun 		 * Not fully qualified.
228*4882a593Smuzhiyun 		 * Handle Carats first, then append the name segments
229*4882a593Smuzhiyun 		 */
230*4882a593Smuzhiyun 		i = 0;
231*4882a593Smuzhiyun 		if (info->num_carats) {
232*4882a593Smuzhiyun 			for (i = 0; i < info->num_carats; i++) {
233*4882a593Smuzhiyun 				internal_name[i] = AML_PARENT_PREFIX;
234*4882a593Smuzhiyun 			}
235*4882a593Smuzhiyun 		}
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 		if (num_segments <= 1) {
238*4882a593Smuzhiyun 			result = &internal_name[i];
239*4882a593Smuzhiyun 		} else if (num_segments == 2) {
240*4882a593Smuzhiyun 			internal_name[i] = AML_DUAL_NAME_PREFIX;
241*4882a593Smuzhiyun 			result = &internal_name[(acpi_size)i + 1];
242*4882a593Smuzhiyun 		} else {
243*4882a593Smuzhiyun 			internal_name[i] = AML_MULTI_NAME_PREFIX;
244*4882a593Smuzhiyun 			internal_name[(acpi_size)i + 1] = (char)num_segments;
245*4882a593Smuzhiyun 			result = &internal_name[(acpi_size)i + 2];
246*4882a593Smuzhiyun 		}
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	/* Build the name (minus path separators) */
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	for (; num_segments; num_segments--) {
252*4882a593Smuzhiyun 		for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
253*4882a593Smuzhiyun 			if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
254*4882a593Smuzhiyun 			    (*external_name == 0)) {
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 				/* Pad the segment with underscore(s) if segment is short */
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 				result[i] = '_';
259*4882a593Smuzhiyun 			} else {
260*4882a593Smuzhiyun 				/* Convert the character to uppercase and save it */
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 				result[i] = (char)toupper((int)*external_name);
263*4882a593Smuzhiyun 				external_name++;
264*4882a593Smuzhiyun 			}
265*4882a593Smuzhiyun 		}
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 		/* Now we must have a path separator, or the pathname is bad */
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 		if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
270*4882a593Smuzhiyun 		    (*external_name != 0)) {
271*4882a593Smuzhiyun 			return_ACPI_STATUS(AE_BAD_PATHNAME);
272*4882a593Smuzhiyun 		}
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun 		/* Move on the next segment */
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 		external_name++;
277*4882a593Smuzhiyun 		result += ACPI_NAMESEG_SIZE;
278*4882a593Smuzhiyun 	}
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	/* Terminate the string */
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	*result = 0;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	if (info->fully_qualified) {
285*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
286*4882a593Smuzhiyun 				  "Returning [%p] (abs) \"\\%s\"\n",
287*4882a593Smuzhiyun 				  internal_name, internal_name));
288*4882a593Smuzhiyun 	} else {
289*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
290*4882a593Smuzhiyun 				  internal_name, internal_name));
291*4882a593Smuzhiyun 	}
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun /*******************************************************************************
297*4882a593Smuzhiyun  *
298*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_internalize_name
299*4882a593Smuzhiyun  *
300*4882a593Smuzhiyun  * PARAMETERS:  *external_name          - External representation of name
301*4882a593Smuzhiyun  *              **Converted name        - Where to return the resulting
302*4882a593Smuzhiyun  *                                        internal represention of the name
303*4882a593Smuzhiyun  *
304*4882a593Smuzhiyun  * RETURN:      Status
305*4882a593Smuzhiyun  *
306*4882a593Smuzhiyun  * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
307*4882a593Smuzhiyun  *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
308*4882a593Smuzhiyun  *
309*4882a593Smuzhiyun  *******************************************************************************/
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun acpi_status
acpi_ns_internalize_name(const char * external_name,char ** converted_name)312*4882a593Smuzhiyun acpi_ns_internalize_name(const char *external_name, char **converted_name)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun 	char *internal_name;
315*4882a593Smuzhiyun 	struct acpi_namestring_info info;
316*4882a593Smuzhiyun 	acpi_status status;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ns_internalize_name);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	if ((!external_name) || (*external_name == 0) || (!converted_name)) {
321*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_BAD_PARAMETER);
322*4882a593Smuzhiyun 	}
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	/* Get the length of the new internal name */
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	info.external_name = external_name;
327*4882a593Smuzhiyun 	acpi_ns_get_internal_name_length(&info);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	/* We need a segment to store the internal  name */
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	internal_name = ACPI_ALLOCATE_ZEROED(info.length);
332*4882a593Smuzhiyun 	if (!internal_name) {
333*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NO_MEMORY);
334*4882a593Smuzhiyun 	}
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	/* Build the name */
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	info.internal_name = internal_name;
339*4882a593Smuzhiyun 	status = acpi_ns_build_internal_name(&info);
340*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
341*4882a593Smuzhiyun 		ACPI_FREE(internal_name);
342*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
343*4882a593Smuzhiyun 	}
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	*converted_name = internal_name;
346*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun /*******************************************************************************
350*4882a593Smuzhiyun  *
351*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_externalize_name
352*4882a593Smuzhiyun  *
353*4882a593Smuzhiyun  * PARAMETERS:  internal_name_length - Length of the internal name below
354*4882a593Smuzhiyun  *              internal_name       - Internal representation of name
355*4882a593Smuzhiyun  *              converted_name_length - Where the length is returned
356*4882a593Smuzhiyun  *              converted_name      - Where the resulting external name
357*4882a593Smuzhiyun  *                                    is returned
358*4882a593Smuzhiyun  *
359*4882a593Smuzhiyun  * RETURN:      Status
360*4882a593Smuzhiyun  *
361*4882a593Smuzhiyun  * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
362*4882a593Smuzhiyun  *              to its external (printable) form (e.g. "\_PR_.CPU0")
363*4882a593Smuzhiyun  *
364*4882a593Smuzhiyun  ******************************************************************************/
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun acpi_status
acpi_ns_externalize_name(u32 internal_name_length,const char * internal_name,u32 * converted_name_length,char ** converted_name)367*4882a593Smuzhiyun acpi_ns_externalize_name(u32 internal_name_length,
368*4882a593Smuzhiyun 			 const char *internal_name,
369*4882a593Smuzhiyun 			 u32 * converted_name_length, char **converted_name)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun 	u32 names_index = 0;
372*4882a593Smuzhiyun 	u32 num_segments = 0;
373*4882a593Smuzhiyun 	u32 required_length;
374*4882a593Smuzhiyun 	u32 prefix_length = 0;
375*4882a593Smuzhiyun 	u32 i = 0;
376*4882a593Smuzhiyun 	u32 j = 0;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ns_externalize_name);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	if (!internal_name_length || !internal_name || !converted_name) {
381*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_BAD_PARAMETER);
382*4882a593Smuzhiyun 	}
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	/* Check for a prefix (one '\' | one or more '^') */
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	switch (internal_name[0]) {
387*4882a593Smuzhiyun 	case AML_ROOT_PREFIX:
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 		prefix_length = 1;
390*4882a593Smuzhiyun 		break;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	case AML_PARENT_PREFIX:
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 		for (i = 0; i < internal_name_length; i++) {
395*4882a593Smuzhiyun 			if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
396*4882a593Smuzhiyun 				prefix_length = i + 1;
397*4882a593Smuzhiyun 			} else {
398*4882a593Smuzhiyun 				break;
399*4882a593Smuzhiyun 			}
400*4882a593Smuzhiyun 		}
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 		if (i == internal_name_length) {
403*4882a593Smuzhiyun 			prefix_length = i;
404*4882a593Smuzhiyun 		}
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 		break;
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	default:
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 		break;
411*4882a593Smuzhiyun 	}
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	/*
414*4882a593Smuzhiyun 	 * Check for object names. Note that there could be 0-255 of these
415*4882a593Smuzhiyun 	 * 4-byte elements.
416*4882a593Smuzhiyun 	 */
417*4882a593Smuzhiyun 	if (prefix_length < internal_name_length) {
418*4882a593Smuzhiyun 		switch (internal_name[prefix_length]) {
419*4882a593Smuzhiyun 		case AML_MULTI_NAME_PREFIX:
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 			/* <count> 4-byte names */
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 			names_index = prefix_length + 2;
424*4882a593Smuzhiyun 			num_segments = (u8)
425*4882a593Smuzhiyun 			    internal_name[(acpi_size)prefix_length + 1];
426*4882a593Smuzhiyun 			break;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 		case AML_DUAL_NAME_PREFIX:
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 			/* Two 4-byte names */
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 			names_index = prefix_length + 1;
433*4882a593Smuzhiyun 			num_segments = 2;
434*4882a593Smuzhiyun 			break;
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 		case 0:
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 			/* null_name */
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 			names_index = 0;
441*4882a593Smuzhiyun 			num_segments = 0;
442*4882a593Smuzhiyun 			break;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 		default:
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 			/* one 4-byte name */
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 			names_index = prefix_length;
449*4882a593Smuzhiyun 			num_segments = 1;
450*4882a593Smuzhiyun 			break;
451*4882a593Smuzhiyun 		}
452*4882a593Smuzhiyun 	}
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	/*
455*4882a593Smuzhiyun 	 * Calculate the length of converted_name, which equals the length
456*4882a593Smuzhiyun 	 * of the prefix, length of all object names, length of any required
457*4882a593Smuzhiyun 	 * punctuation ('.') between object names, plus the NULL terminator.
458*4882a593Smuzhiyun 	 */
459*4882a593Smuzhiyun 	required_length = prefix_length + (4 * num_segments) +
460*4882a593Smuzhiyun 	    ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun 	/*
463*4882a593Smuzhiyun 	 * Check to see if we're still in bounds. If not, there's a problem
464*4882a593Smuzhiyun 	 * with internal_name (invalid format).
465*4882a593Smuzhiyun 	 */
466*4882a593Smuzhiyun 	if (required_length > internal_name_length) {
467*4882a593Smuzhiyun 		ACPI_ERROR((AE_INFO, "Invalid internal name"));
468*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_BAD_PATHNAME);
469*4882a593Smuzhiyun 	}
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	/* Build the converted_name */
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	*converted_name = ACPI_ALLOCATE_ZEROED(required_length);
474*4882a593Smuzhiyun 	if (!(*converted_name)) {
475*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_NO_MEMORY);
476*4882a593Smuzhiyun 	}
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	j = 0;
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	for (i = 0; i < prefix_length; i++) {
481*4882a593Smuzhiyun 		(*converted_name)[j++] = internal_name[i];
482*4882a593Smuzhiyun 	}
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	if (num_segments > 0) {
485*4882a593Smuzhiyun 		for (i = 0; i < num_segments; i++) {
486*4882a593Smuzhiyun 			if (i > 0) {
487*4882a593Smuzhiyun 				(*converted_name)[j++] = '.';
488*4882a593Smuzhiyun 			}
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 			/* Copy and validate the 4-char name segment */
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 			ACPI_COPY_NAMESEG(&(*converted_name)[j],
493*4882a593Smuzhiyun 					  &internal_name[names_index]);
494*4882a593Smuzhiyun 			acpi_ut_repair_name(&(*converted_name)[j]);
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 			j += ACPI_NAMESEG_SIZE;
497*4882a593Smuzhiyun 			names_index += ACPI_NAMESEG_SIZE;
498*4882a593Smuzhiyun 		}
499*4882a593Smuzhiyun 	}
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun 	if (converted_name_length) {
502*4882a593Smuzhiyun 		*converted_name_length = (u32) required_length;
503*4882a593Smuzhiyun 	}
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	return_ACPI_STATUS(AE_OK);
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun /*******************************************************************************
509*4882a593Smuzhiyun  *
510*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_validate_handle
511*4882a593Smuzhiyun  *
512*4882a593Smuzhiyun  * PARAMETERS:  handle          - Handle to be validated and typecast to a
513*4882a593Smuzhiyun  *                                namespace node.
514*4882a593Smuzhiyun  *
515*4882a593Smuzhiyun  * RETURN:      A pointer to a namespace node
516*4882a593Smuzhiyun  *
517*4882a593Smuzhiyun  * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
518*4882a593Smuzhiyun  *              cases for the root node.
519*4882a593Smuzhiyun  *
520*4882a593Smuzhiyun  * NOTE: Real integer handles would allow for more verification
521*4882a593Smuzhiyun  *       and keep all pointers within this subsystem - however this introduces
522*4882a593Smuzhiyun  *       more overhead and has not been necessary to this point. Drivers
523*4882a593Smuzhiyun  *       holding handles are typically notified before a node becomes invalid
524*4882a593Smuzhiyun  *       due to a table unload.
525*4882a593Smuzhiyun  *
526*4882a593Smuzhiyun  ******************************************************************************/
527*4882a593Smuzhiyun 
acpi_ns_validate_handle(acpi_handle handle)528*4882a593Smuzhiyun struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	ACPI_FUNCTION_ENTRY();
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	/* Parameter validation */
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
536*4882a593Smuzhiyun 		return (acpi_gbl_root_node);
537*4882a593Smuzhiyun 	}
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 	/* We can at least attempt to verify the handle */
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
542*4882a593Smuzhiyun 		return (NULL);
543*4882a593Smuzhiyun 	}
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun /*******************************************************************************
549*4882a593Smuzhiyun  *
550*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_terminate
551*4882a593Smuzhiyun  *
552*4882a593Smuzhiyun  * PARAMETERS:  none
553*4882a593Smuzhiyun  *
554*4882a593Smuzhiyun  * RETURN:      none
555*4882a593Smuzhiyun  *
556*4882a593Smuzhiyun  * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
557*4882a593Smuzhiyun  *
558*4882a593Smuzhiyun  ******************************************************************************/
559*4882a593Smuzhiyun 
acpi_ns_terminate(void)560*4882a593Smuzhiyun void acpi_ns_terminate(void)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun 	acpi_status status;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE(ns_terminate);
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun 	/*
567*4882a593Smuzhiyun 	 * Free the entire namespace -- all nodes and all objects
568*4882a593Smuzhiyun 	 * attached to the nodes
569*4882a593Smuzhiyun 	 */
570*4882a593Smuzhiyun 	acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	/* Delete any objects attached to the root node */
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
575*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
576*4882a593Smuzhiyun 		return_VOID;
577*4882a593Smuzhiyun 	}
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	acpi_ns_delete_node(acpi_gbl_root_node);
580*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
583*4882a593Smuzhiyun 	return_VOID;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun /*******************************************************************************
587*4882a593Smuzhiyun  *
588*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_opens_scope
589*4882a593Smuzhiyun  *
590*4882a593Smuzhiyun  * PARAMETERS:  type        - A valid namespace type
591*4882a593Smuzhiyun  *
592*4882a593Smuzhiyun  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
593*4882a593Smuzhiyun  *              to the ACPI specification, else 0
594*4882a593Smuzhiyun  *
595*4882a593Smuzhiyun  ******************************************************************************/
596*4882a593Smuzhiyun 
acpi_ns_opens_scope(acpi_object_type type)597*4882a593Smuzhiyun u32 acpi_ns_opens_scope(acpi_object_type type)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	ACPI_FUNCTION_ENTRY();
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun 	if (type > ACPI_TYPE_LOCAL_MAX) {
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 		/* type code out of range  */
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 		ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
606*4882a593Smuzhiyun 		return (ACPI_NS_NORMAL);
607*4882a593Smuzhiyun 	}
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
610*4882a593Smuzhiyun }
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun /*******************************************************************************
613*4882a593Smuzhiyun  *
614*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_get_node_unlocked
615*4882a593Smuzhiyun  *
616*4882a593Smuzhiyun  * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
617*4882a593Smuzhiyun  *                            \ (backslash) and ^ (carat) prefixes, and the
618*4882a593Smuzhiyun  *                            . (period) to separate segments are supported.
619*4882a593Smuzhiyun  *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
620*4882a593Smuzhiyun  *                            root of the name space. If Name is fully
621*4882a593Smuzhiyun  *                            qualified (first s8 is '\'), the passed value
622*4882a593Smuzhiyun  *                            of Scope will not be accessed.
623*4882a593Smuzhiyun  *              flags       - Used to indicate whether to perform upsearch or
624*4882a593Smuzhiyun  *                            not.
625*4882a593Smuzhiyun  *              return_node - Where the Node is returned
626*4882a593Smuzhiyun  *
627*4882a593Smuzhiyun  * DESCRIPTION: Look up a name relative to a given scope and return the
628*4882a593Smuzhiyun  *              corresponding Node. NOTE: Scope can be null.
629*4882a593Smuzhiyun  *
630*4882a593Smuzhiyun  * MUTEX:       Doesn't locks namespace
631*4882a593Smuzhiyun  *
632*4882a593Smuzhiyun  ******************************************************************************/
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun acpi_status
acpi_ns_get_node_unlocked(struct acpi_namespace_node * prefix_node,const char * pathname,u32 flags,struct acpi_namespace_node ** return_node)635*4882a593Smuzhiyun acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node,
636*4882a593Smuzhiyun 			  const char *pathname,
637*4882a593Smuzhiyun 			  u32 flags, struct acpi_namespace_node **return_node)
638*4882a593Smuzhiyun {
639*4882a593Smuzhiyun 	union acpi_generic_state scope_info;
640*4882a593Smuzhiyun 	acpi_status status;
641*4882a593Smuzhiyun 	char *internal_path;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked,
644*4882a593Smuzhiyun 				ACPI_CAST_PTR(char, pathname));
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	/* Simplest case is a null pathname */
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	if (!pathname) {
649*4882a593Smuzhiyun 		*return_node = prefix_node;
650*4882a593Smuzhiyun 		if (!prefix_node) {
651*4882a593Smuzhiyun 			*return_node = acpi_gbl_root_node;
652*4882a593Smuzhiyun 		}
653*4882a593Smuzhiyun 
654*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_OK);
655*4882a593Smuzhiyun 	}
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	/* Quick check for a reference to the root */
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) {
660*4882a593Smuzhiyun 		*return_node = acpi_gbl_root_node;
661*4882a593Smuzhiyun 		return_ACPI_STATUS(AE_OK);
662*4882a593Smuzhiyun 	}
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun 	/* Convert path to internal representation */
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	status = acpi_ns_internalize_name(pathname, &internal_path);
667*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
668*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
669*4882a593Smuzhiyun 	}
670*4882a593Smuzhiyun 
671*4882a593Smuzhiyun 	/* Setup lookup scope (search starting point) */
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 	scope_info.scope.node = prefix_node;
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	/* Lookup the name in the namespace */
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
678*4882a593Smuzhiyun 				ACPI_IMODE_EXECUTE,
679*4882a593Smuzhiyun 				(flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
680*4882a593Smuzhiyun 				return_node);
681*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
682*4882a593Smuzhiyun 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
683*4882a593Smuzhiyun 				  pathname, acpi_format_exception(status)));
684*4882a593Smuzhiyun 	}
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	ACPI_FREE(internal_path);
687*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
688*4882a593Smuzhiyun }
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun /*******************************************************************************
691*4882a593Smuzhiyun  *
692*4882a593Smuzhiyun  * FUNCTION:    acpi_ns_get_node
693*4882a593Smuzhiyun  *
694*4882a593Smuzhiyun  * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
695*4882a593Smuzhiyun  *                            \ (backslash) and ^ (carat) prefixes, and the
696*4882a593Smuzhiyun  *                            . (period) to separate segments are supported.
697*4882a593Smuzhiyun  *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
698*4882a593Smuzhiyun  *                            root of the name space. If Name is fully
699*4882a593Smuzhiyun  *                            qualified (first s8 is '\'), the passed value
700*4882a593Smuzhiyun  *                            of Scope will not be accessed.
701*4882a593Smuzhiyun  *              flags       - Used to indicate whether to perform upsearch or
702*4882a593Smuzhiyun  *                            not.
703*4882a593Smuzhiyun  *              return_node - Where the Node is returned
704*4882a593Smuzhiyun  *
705*4882a593Smuzhiyun  * DESCRIPTION: Look up a name relative to a given scope and return the
706*4882a593Smuzhiyun  *              corresponding Node. NOTE: Scope can be null.
707*4882a593Smuzhiyun  *
708*4882a593Smuzhiyun  * MUTEX:       Locks namespace
709*4882a593Smuzhiyun  *
710*4882a593Smuzhiyun  ******************************************************************************/
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun acpi_status
acpi_ns_get_node(struct acpi_namespace_node * prefix_node,const char * pathname,u32 flags,struct acpi_namespace_node ** return_node)713*4882a593Smuzhiyun acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
714*4882a593Smuzhiyun 		 const char *pathname,
715*4882a593Smuzhiyun 		 u32 flags, struct acpi_namespace_node **return_node)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun 	acpi_status status;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun 	ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
722*4882a593Smuzhiyun 	if (ACPI_FAILURE(status)) {
723*4882a593Smuzhiyun 		return_ACPI_STATUS(status);
724*4882a593Smuzhiyun 	}
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun 	status = acpi_ns_get_node_unlocked(prefix_node, pathname,
727*4882a593Smuzhiyun 					   flags, return_node);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
730*4882a593Smuzhiyun 	return_ACPI_STATUS(status);
731*4882a593Smuzhiyun }
732