1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: nsnames - Name manipulation and search
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun ******************************************************************************/
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun #include "amlcode.h"
11*4882a593Smuzhiyun #include "acnamesp.h"
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #define _COMPONENT ACPI_NAMESPACE
14*4882a593Smuzhiyun ACPI_MODULE_NAME("nsnames")
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun /*******************************************************************************
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * FUNCTION: acpi_ns_get_external_pathname
19*4882a593Smuzhiyun *
20*4882a593Smuzhiyun * PARAMETERS: node - Namespace node whose pathname is needed
21*4882a593Smuzhiyun *
22*4882a593Smuzhiyun * RETURN: Pointer to storage containing the fully qualified name of
23*4882a593Smuzhiyun * the node, In external format (name segments separated by path
24*4882a593Smuzhiyun * separators.)
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
27*4882a593Smuzhiyun * for error and debug statements.
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun ******************************************************************************/
acpi_ns_get_external_pathname(struct acpi_namespace_node * node)30*4882a593Smuzhiyun char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun char *name_buffer;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun name_buffer = acpi_ns_get_normalized_pathname(node, FALSE);
37*4882a593Smuzhiyun return_PTR(name_buffer);
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /*******************************************************************************
41*4882a593Smuzhiyun *
42*4882a593Smuzhiyun * FUNCTION: acpi_ns_get_pathname_length
43*4882a593Smuzhiyun *
44*4882a593Smuzhiyun * PARAMETERS: node - Namespace node
45*4882a593Smuzhiyun *
46*4882a593Smuzhiyun * RETURN: Length of path, including prefix
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun * DESCRIPTION: Get the length of the pathname string for this node
49*4882a593Smuzhiyun *
50*4882a593Smuzhiyun ******************************************************************************/
51*4882a593Smuzhiyun
acpi_ns_get_pathname_length(struct acpi_namespace_node * node)52*4882a593Smuzhiyun acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun acpi_size size;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* Validate the Node */
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
59*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
60*4882a593Smuzhiyun "Invalid/cached reference target node: %p, descriptor type %d",
61*4882a593Smuzhiyun node, ACPI_GET_DESCRIPTOR_TYPE(node)));
62*4882a593Smuzhiyun return (0);
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
66*4882a593Smuzhiyun return (size);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /*******************************************************************************
70*4882a593Smuzhiyun *
71*4882a593Smuzhiyun * FUNCTION: acpi_ns_handle_to_name
72*4882a593Smuzhiyun *
73*4882a593Smuzhiyun * PARAMETERS: target_handle - Handle of named object whose name is
74*4882a593Smuzhiyun * to be found
75*4882a593Smuzhiyun * buffer - Where the name is returned
76*4882a593Smuzhiyun *
77*4882a593Smuzhiyun * RETURN: Status, Buffer is filled with name if status is AE_OK
78*4882a593Smuzhiyun *
79*4882a593Smuzhiyun * DESCRIPTION: Build and return a full namespace name
80*4882a593Smuzhiyun *
81*4882a593Smuzhiyun ******************************************************************************/
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun acpi_status
acpi_ns_handle_to_name(acpi_handle target_handle,struct acpi_buffer * buffer)84*4882a593Smuzhiyun acpi_ns_handle_to_name(acpi_handle target_handle, struct acpi_buffer *buffer)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun acpi_status status;
87*4882a593Smuzhiyun struct acpi_namespace_node *node;
88*4882a593Smuzhiyun const char *node_name;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ns_handle_to_name, target_handle);
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun node = acpi_ns_validate_handle(target_handle);
93*4882a593Smuzhiyun if (!node) {
94*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* Validate/Allocate/Clear caller buffer */
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH);
100*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
101*4882a593Smuzhiyun return_ACPI_STATUS(status);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /* Just copy the ACPI name from the Node and zero terminate it */
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun node_name = acpi_ut_get_node_name(node);
107*4882a593Smuzhiyun ACPI_COPY_NAMESEG(buffer->pointer, node_name);
108*4882a593Smuzhiyun ((char *)buffer->pointer)[ACPI_NAMESEG_SIZE] = 0;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%4.4s\n", (char *)buffer->pointer));
111*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun /*******************************************************************************
115*4882a593Smuzhiyun *
116*4882a593Smuzhiyun * FUNCTION: acpi_ns_handle_to_pathname
117*4882a593Smuzhiyun *
118*4882a593Smuzhiyun * PARAMETERS: target_handle - Handle of named object whose name is
119*4882a593Smuzhiyun * to be found
120*4882a593Smuzhiyun * buffer - Where the pathname is returned
121*4882a593Smuzhiyun * no_trailing - Remove trailing '_' for each name
122*4882a593Smuzhiyun * segment
123*4882a593Smuzhiyun *
124*4882a593Smuzhiyun * RETURN: Status, Buffer is filled with pathname if status is AE_OK
125*4882a593Smuzhiyun *
126*4882a593Smuzhiyun * DESCRIPTION: Build and return a full namespace pathname
127*4882a593Smuzhiyun *
128*4882a593Smuzhiyun ******************************************************************************/
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun acpi_status
acpi_ns_handle_to_pathname(acpi_handle target_handle,struct acpi_buffer * buffer,u8 no_trailing)131*4882a593Smuzhiyun acpi_ns_handle_to_pathname(acpi_handle target_handle,
132*4882a593Smuzhiyun struct acpi_buffer *buffer, u8 no_trailing)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun acpi_status status;
135*4882a593Smuzhiyun struct acpi_namespace_node *node;
136*4882a593Smuzhiyun acpi_size required_size;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun node = acpi_ns_validate_handle(target_handle);
141*4882a593Smuzhiyun if (!node) {
142*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /* Determine size required for the caller buffer */
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun required_size =
148*4882a593Smuzhiyun acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
149*4882a593Smuzhiyun if (!required_size) {
150*4882a593Smuzhiyun return_ACPI_STATUS(AE_BAD_PARAMETER);
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* Validate/Allocate/Clear caller buffer */
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun status = acpi_ut_initialize_buffer(buffer, required_size);
156*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
157*4882a593Smuzhiyun return_ACPI_STATUS(status);
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* Build the path in the caller buffer */
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun (void)acpi_ns_build_normalized_path(node, buffer->pointer,
163*4882a593Smuzhiyun (u32)required_size, no_trailing);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n",
166*4882a593Smuzhiyun (char *)buffer->pointer, (u32) required_size));
167*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /*******************************************************************************
171*4882a593Smuzhiyun *
172*4882a593Smuzhiyun * FUNCTION: acpi_ns_build_normalized_path
173*4882a593Smuzhiyun *
174*4882a593Smuzhiyun * PARAMETERS: node - Namespace node
175*4882a593Smuzhiyun * full_path - Where the path name is returned
176*4882a593Smuzhiyun * path_size - Size of returned path name buffer
177*4882a593Smuzhiyun * no_trailing - Remove trailing '_' from each name segment
178*4882a593Smuzhiyun *
179*4882a593Smuzhiyun * RETURN: Return 1 if the AML path is empty, otherwise returning (length
180*4882a593Smuzhiyun * of pathname + 1) which means the 'FullPath' contains a trailing
181*4882a593Smuzhiyun * null.
182*4882a593Smuzhiyun *
183*4882a593Smuzhiyun * DESCRIPTION: Build and return a full namespace pathname.
184*4882a593Smuzhiyun * Note that if the size of 'FullPath' isn't large enough to
185*4882a593Smuzhiyun * contain the namespace node's path name, the actual required
186*4882a593Smuzhiyun * buffer length is returned, and it should be greater than
187*4882a593Smuzhiyun * 'PathSize'. So callers are able to check the returning value
188*4882a593Smuzhiyun * to determine the buffer size of 'FullPath'.
189*4882a593Smuzhiyun *
190*4882a593Smuzhiyun ******************************************************************************/
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun u32
acpi_ns_build_normalized_path(struct acpi_namespace_node * node,char * full_path,u32 path_size,u8 no_trailing)193*4882a593Smuzhiyun acpi_ns_build_normalized_path(struct acpi_namespace_node *node,
194*4882a593Smuzhiyun char *full_path, u32 path_size, u8 no_trailing)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun u32 length = 0, i;
197*4882a593Smuzhiyun char name[ACPI_NAMESEG_SIZE];
198*4882a593Smuzhiyun u8 do_no_trailing;
199*4882a593Smuzhiyun char c, *left, *right;
200*4882a593Smuzhiyun struct acpi_namespace_node *next_node;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ns_build_normalized_path, node);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun #define ACPI_PATH_PUT8(path, size, byte, length) \
205*4882a593Smuzhiyun do { \
206*4882a593Smuzhiyun if ((length) < (size)) \
207*4882a593Smuzhiyun { \
208*4882a593Smuzhiyun (path)[(length)] = (byte); \
209*4882a593Smuzhiyun } \
210*4882a593Smuzhiyun (length)++; \
211*4882a593Smuzhiyun } while (0)
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun /*
214*4882a593Smuzhiyun * Make sure the path_size is correct, so that we don't need to
215*4882a593Smuzhiyun * validate both full_path and path_size.
216*4882a593Smuzhiyun */
217*4882a593Smuzhiyun if (!full_path) {
218*4882a593Smuzhiyun path_size = 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun if (!node) {
222*4882a593Smuzhiyun goto build_trailing_null;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun next_node = node;
226*4882a593Smuzhiyun while (next_node && next_node != acpi_gbl_root_node) {
227*4882a593Smuzhiyun if (next_node != node) {
228*4882a593Smuzhiyun ACPI_PATH_PUT8(full_path, path_size,
229*4882a593Smuzhiyun AML_DUAL_NAME_PREFIX, length);
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun ACPI_MOVE_32_TO_32(name, &next_node->name);
233*4882a593Smuzhiyun do_no_trailing = no_trailing;
234*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
235*4882a593Smuzhiyun c = name[4 - i - 1];
236*4882a593Smuzhiyun if (do_no_trailing && c != '_') {
237*4882a593Smuzhiyun do_no_trailing = FALSE;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun if (!do_no_trailing) {
240*4882a593Smuzhiyun ACPI_PATH_PUT8(full_path, path_size, c, length);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun next_node = next_node->parent;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun ACPI_PATH_PUT8(full_path, path_size, AML_ROOT_PREFIX, length);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /* Reverse the path string */
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun if (length <= path_size) {
252*4882a593Smuzhiyun left = full_path;
253*4882a593Smuzhiyun right = full_path + length - 1;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun while (left < right) {
256*4882a593Smuzhiyun c = *left;
257*4882a593Smuzhiyun *left++ = *right;
258*4882a593Smuzhiyun *right-- = c;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* Append the trailing null */
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun build_trailing_null:
265*4882a593Smuzhiyun ACPI_PATH_PUT8(full_path, path_size, '\0', length);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun #undef ACPI_PATH_PUT8
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun return_UINT32(length);
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /*******************************************************************************
273*4882a593Smuzhiyun *
274*4882a593Smuzhiyun * FUNCTION: acpi_ns_get_normalized_pathname
275*4882a593Smuzhiyun *
276*4882a593Smuzhiyun * PARAMETERS: node - Namespace node whose pathname is needed
277*4882a593Smuzhiyun * no_trailing - Remove trailing '_' from each name segment
278*4882a593Smuzhiyun *
279*4882a593Smuzhiyun * RETURN: Pointer to storage containing the fully qualified name of
280*4882a593Smuzhiyun * the node, In external format (name segments separated by path
281*4882a593Smuzhiyun * separators.)
282*4882a593Smuzhiyun *
283*4882a593Smuzhiyun * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
284*4882a593Smuzhiyun * for error and debug statements. All trailing '_' will be
285*4882a593Smuzhiyun * removed from the full pathname if 'NoTrailing' is specified..
286*4882a593Smuzhiyun *
287*4882a593Smuzhiyun ******************************************************************************/
288*4882a593Smuzhiyun
acpi_ns_get_normalized_pathname(struct acpi_namespace_node * node,u8 no_trailing)289*4882a593Smuzhiyun char *acpi_ns_get_normalized_pathname(struct acpi_namespace_node *node,
290*4882a593Smuzhiyun u8 no_trailing)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun char *name_buffer;
293*4882a593Smuzhiyun acpi_size size;
294*4882a593Smuzhiyun
295*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_PTR(ns_get_normalized_pathname, node);
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun /* Calculate required buffer size based on depth below root */
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun size = acpi_ns_build_normalized_path(node, NULL, 0, no_trailing);
300*4882a593Smuzhiyun if (!size) {
301*4882a593Smuzhiyun return_PTR(NULL);
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /* Allocate a buffer to be returned to caller */
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun name_buffer = ACPI_ALLOCATE_ZEROED(size);
307*4882a593Smuzhiyun if (!name_buffer) {
308*4882a593Smuzhiyun ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size));
309*4882a593Smuzhiyun return_PTR(NULL);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /* Build the path in the allocated buffer */
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun (void)acpi_ns_build_normalized_path(node, name_buffer, (u32)size,
315*4882a593Smuzhiyun no_trailing);
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES, "%s: Path \"%s\"\n",
318*4882a593Smuzhiyun ACPI_GET_FUNCTION_NAME, name_buffer));
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun return_PTR(name_buffer);
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun /*******************************************************************************
324*4882a593Smuzhiyun *
325*4882a593Smuzhiyun * FUNCTION: acpi_ns_build_prefixed_pathname
326*4882a593Smuzhiyun *
327*4882a593Smuzhiyun * PARAMETERS: prefix_scope - Scope/Path that prefixes the internal path
328*4882a593Smuzhiyun * internal_path - Name or path of the namespace node
329*4882a593Smuzhiyun *
330*4882a593Smuzhiyun * RETURN: None
331*4882a593Smuzhiyun *
332*4882a593Smuzhiyun * DESCRIPTION: Construct a fully qualified pathname from a concatenation of:
333*4882a593Smuzhiyun * 1) Path associated with the prefix_scope namespace node
334*4882a593Smuzhiyun * 2) External path representation of the Internal path
335*4882a593Smuzhiyun *
336*4882a593Smuzhiyun ******************************************************************************/
337*4882a593Smuzhiyun
acpi_ns_build_prefixed_pathname(union acpi_generic_state * prefix_scope,const char * internal_path)338*4882a593Smuzhiyun char *acpi_ns_build_prefixed_pathname(union acpi_generic_state *prefix_scope,
339*4882a593Smuzhiyun const char *internal_path)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun acpi_status status;
342*4882a593Smuzhiyun char *full_path = NULL;
343*4882a593Smuzhiyun char *external_path = NULL;
344*4882a593Smuzhiyun char *prefix_path = NULL;
345*4882a593Smuzhiyun acpi_size prefix_path_length = 0;
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun /* If there is a prefix, get the pathname to it */
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun if (prefix_scope && prefix_scope->scope.node) {
350*4882a593Smuzhiyun prefix_path =
351*4882a593Smuzhiyun acpi_ns_get_normalized_pathname(prefix_scope->scope.node,
352*4882a593Smuzhiyun TRUE);
353*4882a593Smuzhiyun if (prefix_path) {
354*4882a593Smuzhiyun prefix_path_length = strlen(prefix_path);
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun status = acpi_ns_externalize_name(ACPI_UINT32_MAX, internal_path,
359*4882a593Smuzhiyun NULL, &external_path);
360*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
361*4882a593Smuzhiyun goto cleanup;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Merge the prefix path and the path. 2 is for one dot and trailing null */
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun full_path =
367*4882a593Smuzhiyun ACPI_ALLOCATE_ZEROED(prefix_path_length + strlen(external_path) +
368*4882a593Smuzhiyun 2);
369*4882a593Smuzhiyun if (!full_path) {
370*4882a593Smuzhiyun goto cleanup;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun /* Don't merge if the External path is already fully qualified */
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun if (prefix_path && (*external_path != '\\') && (*external_path != '^')) {
376*4882a593Smuzhiyun strcat(full_path, prefix_path);
377*4882a593Smuzhiyun if (prefix_path[1]) {
378*4882a593Smuzhiyun strcat(full_path, ".");
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun acpi_ns_normalize_pathname(external_path);
383*4882a593Smuzhiyun strcat(full_path, external_path);
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun cleanup:
386*4882a593Smuzhiyun if (prefix_path) {
387*4882a593Smuzhiyun ACPI_FREE(prefix_path);
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun if (external_path) {
390*4882a593Smuzhiyun ACPI_FREE(external_path);
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun return (full_path);
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /*******************************************************************************
397*4882a593Smuzhiyun *
398*4882a593Smuzhiyun * FUNCTION: acpi_ns_normalize_pathname
399*4882a593Smuzhiyun *
400*4882a593Smuzhiyun * PARAMETERS: original_path - Path to be normalized, in External format
401*4882a593Smuzhiyun *
402*4882a593Smuzhiyun * RETURN: The original path is processed in-place
403*4882a593Smuzhiyun *
404*4882a593Smuzhiyun * DESCRIPTION: Remove trailing underscores from each element of a path.
405*4882a593Smuzhiyun *
406*4882a593Smuzhiyun * For example: \A___.B___.C___ becomes \A.B.C
407*4882a593Smuzhiyun *
408*4882a593Smuzhiyun ******************************************************************************/
409*4882a593Smuzhiyun
acpi_ns_normalize_pathname(char * original_path)410*4882a593Smuzhiyun void acpi_ns_normalize_pathname(char *original_path)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun char *input_path = original_path;
413*4882a593Smuzhiyun char *new_path_buffer;
414*4882a593Smuzhiyun char *new_path;
415*4882a593Smuzhiyun u32 i;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /* Allocate a temp buffer in which to construct the new path */
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun new_path_buffer = ACPI_ALLOCATE_ZEROED(strlen(input_path) + 1);
420*4882a593Smuzhiyun new_path = new_path_buffer;
421*4882a593Smuzhiyun if (!new_path_buffer) {
422*4882a593Smuzhiyun return;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun /* Special characters may appear at the beginning of the path */
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun if (*input_path == '\\') {
428*4882a593Smuzhiyun *new_path = *input_path;
429*4882a593Smuzhiyun new_path++;
430*4882a593Smuzhiyun input_path++;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
433*4882a593Smuzhiyun while (*input_path == '^') {
434*4882a593Smuzhiyun *new_path = *input_path;
435*4882a593Smuzhiyun new_path++;
436*4882a593Smuzhiyun input_path++;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun /* Remainder of the path */
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun while (*input_path) {
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun /* Do one nameseg at a time */
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun for (i = 0; (i < ACPI_NAMESEG_SIZE) && *input_path; i++) {
446*4882a593Smuzhiyun if ((i == 0) || (*input_path != '_')) { /* First char is allowed to be underscore */
447*4882a593Smuzhiyun *new_path = *input_path;
448*4882a593Smuzhiyun new_path++;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun input_path++;
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun
454*4882a593Smuzhiyun /* Dot means that there are more namesegs to come */
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun if (*input_path == '.') {
457*4882a593Smuzhiyun *new_path = *input_path;
458*4882a593Smuzhiyun new_path++;
459*4882a593Smuzhiyun input_path++;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun *new_path = 0;
464*4882a593Smuzhiyun strcpy(original_path, new_path_buffer);
465*4882a593Smuzhiyun ACPI_FREE(new_path_buffer);
466*4882a593Smuzhiyun }
467