Linux Audio

Check our new training course

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