1 /*******************************************************************************
3 * Module Name: nsnames - Name manipulation and search
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2017, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
50 #define _COMPONENT ACPI_NAMESPACE
51 ACPI_MODULE_NAME ("nsnames")
53 /* Local Prototypes */
56 AcpiNsNormalizePathname (
60 /*******************************************************************************
62 * FUNCTION: AcpiNsGetExternalPathname
64 * PARAMETERS: Node - Namespace node whose pathname is needed
66 * RETURN: Pointer to storage containing the fully qualified name of
67 * the node, In external format (name segments separated by path
70 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
71 * for error and debug statements.
73 ******************************************************************************/
76 AcpiNsGetExternalPathname (
77 ACPI_NAMESPACE_NODE
*Node
)
82 ACPI_FUNCTION_TRACE_PTR (NsGetExternalPathname
, Node
);
85 NameBuffer
= AcpiNsGetNormalizedPathname (Node
, FALSE
);
86 return_PTR (NameBuffer
);
90 /*******************************************************************************
92 * FUNCTION: AcpiNsGetPathnameLength
94 * PARAMETERS: Node - Namespace node
96 * RETURN: Length of path, including prefix
98 * DESCRIPTION: Get the length of the pathname string for this node
100 ******************************************************************************/
103 AcpiNsGetPathnameLength (
104 ACPI_NAMESPACE_NODE
*Node
)
109 /* Validate the Node */
111 if (ACPI_GET_DESCRIPTOR_TYPE (Node
) != ACPI_DESC_TYPE_NAMED
)
113 ACPI_ERROR ((AE_INFO
,
114 "Invalid/cached reference target node: %p, descriptor type %d",
115 Node
, ACPI_GET_DESCRIPTOR_TYPE (Node
)));
119 Size
= AcpiNsBuildNormalizedPath (Node
, NULL
, 0, FALSE
);
124 /*******************************************************************************
126 * FUNCTION: AcpiNsHandleToName
128 * PARAMETERS: TargetHandle - Handle of named object whose name is
130 * Buffer - Where the name is returned
132 * RETURN: Status, Buffer is filled with name if status is AE_OK
134 * DESCRIPTION: Build and return a full namespace name
136 ******************************************************************************/
140 ACPI_HANDLE TargetHandle
,
144 ACPI_NAMESPACE_NODE
*Node
;
145 const char *NodeName
;
148 ACPI_FUNCTION_TRACE_PTR (NsHandleToName
, TargetHandle
);
151 Node
= AcpiNsValidateHandle (TargetHandle
);
154 return_ACPI_STATUS (AE_BAD_PARAMETER
);
157 /* Validate/Allocate/Clear caller buffer */
159 Status
= AcpiUtInitializeBuffer (Buffer
, ACPI_PATH_SEGMENT_LENGTH
);
160 if (ACPI_FAILURE (Status
))
162 return_ACPI_STATUS (Status
);
165 /* Just copy the ACPI name from the Node and zero terminate it */
167 NodeName
= AcpiUtGetNodeName (Node
);
168 ACPI_MOVE_NAME (Buffer
->Pointer
, NodeName
);
169 ((char *) Buffer
->Pointer
) [ACPI_NAME_SIZE
] = 0;
171 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "%4.4s\n", (char *) Buffer
->Pointer
));
172 return_ACPI_STATUS (AE_OK
);
176 /*******************************************************************************
178 * FUNCTION: AcpiNsHandleToPathname
180 * PARAMETERS: TargetHandle - Handle of named object whose name is
182 * Buffer - Where the pathname is returned
183 * NoTrailing - Remove trailing '_' for each name
186 * RETURN: Status, Buffer is filled with pathname if status is AE_OK
188 * DESCRIPTION: Build and return a full namespace pathname
190 ******************************************************************************/
193 AcpiNsHandleToPathname (
194 ACPI_HANDLE TargetHandle
,
199 ACPI_NAMESPACE_NODE
*Node
;
200 ACPI_SIZE RequiredSize
;
203 ACPI_FUNCTION_TRACE_PTR (NsHandleToPathname
, TargetHandle
);
206 Node
= AcpiNsValidateHandle (TargetHandle
);
209 return_ACPI_STATUS (AE_BAD_PARAMETER
);
212 /* Determine size required for the caller buffer */
214 RequiredSize
= AcpiNsBuildNormalizedPath (Node
, NULL
, 0, NoTrailing
);
217 return_ACPI_STATUS (AE_BAD_PARAMETER
);
220 /* Validate/Allocate/Clear caller buffer */
222 Status
= AcpiUtInitializeBuffer (Buffer
, RequiredSize
);
223 if (ACPI_FAILURE (Status
))
225 return_ACPI_STATUS (Status
);
228 /* Build the path in the caller buffer */
230 (void) AcpiNsBuildNormalizedPath (Node
, Buffer
->Pointer
,
231 RequiredSize
, NoTrailing
);
233 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC
, "%s [%X]\n",
234 (char *) Buffer
->Pointer
, (UINT32
) RequiredSize
));
235 return_ACPI_STATUS (AE_OK
);
239 /*******************************************************************************
241 * FUNCTION: AcpiNsBuildNormalizedPath
243 * PARAMETERS: Node - Namespace node
244 * FullPath - Where the path name is returned
245 * PathSize - Size of returned path name buffer
246 * NoTrailing - Remove trailing '_' from each name segment
248 * RETURN: Return 1 if the AML path is empty, otherwise returning (length
249 * of pathname + 1) which means the 'FullPath' contains a trailing
252 * DESCRIPTION: Build and return a full namespace pathname.
253 * Note that if the size of 'FullPath' isn't large enough to
254 * contain the namespace node's path name, the actual required
255 * buffer length is returned, and it should be greater than
256 * 'PathSize'. So callers are able to check the returning value
257 * to determine the buffer size of 'FullPath'.
259 ******************************************************************************/
262 AcpiNsBuildNormalizedPath (
263 ACPI_NAMESPACE_NODE
*Node
,
268 UINT32 Length
= 0, i
;
269 char Name
[ACPI_NAME_SIZE
];
270 BOOLEAN DoNoTrailing
;
271 char c
, *Left
, *Right
;
272 ACPI_NAMESPACE_NODE
*NextNode
;
275 ACPI_FUNCTION_TRACE_PTR (NsBuildNormalizedPath
, Node
);
278 #define ACPI_PATH_PUT8(Path, Size, Byte, Length) \
280 if ((Length) < (Size)) \
282 (Path)[(Length)] = (Byte); \
288 * Make sure the PathSize is correct, so that we don't need to
289 * validate both FullPath and PathSize.
298 goto BuildTrailingNull
;
302 while (NextNode
&& NextNode
!= AcpiGbl_RootNode
)
304 if (NextNode
!= Node
)
306 ACPI_PATH_PUT8(FullPath
, PathSize
, AML_DUAL_NAME_PREFIX
, Length
);
309 ACPI_MOVE_32_TO_32 (Name
, &NextNode
->Name
);
310 DoNoTrailing
= NoTrailing
;
311 for (i
= 0; i
< 4; i
++)
314 if (DoNoTrailing
&& c
!= '_')
316 DoNoTrailing
= FALSE
;
320 ACPI_PATH_PUT8(FullPath
, PathSize
, c
, Length
);
324 NextNode
= NextNode
->Parent
;
327 ACPI_PATH_PUT8(FullPath
, PathSize
, AML_ROOT_PREFIX
, Length
);
329 /* Reverse the path string */
331 if (Length
<= PathSize
)
334 Right
= FullPath
+Length
- 1;
344 /* Append the trailing null */
347 ACPI_PATH_PUT8 (FullPath
, PathSize
, '\0', Length
);
349 #undef ACPI_PATH_PUT8
351 return_UINT32 (Length
);
355 /*******************************************************************************
357 * FUNCTION: AcpiNsGetNormalizedPathname
359 * PARAMETERS: Node - Namespace node whose pathname is needed
360 * NoTrailing - Remove trailing '_' from each name segment
362 * RETURN: Pointer to storage containing the fully qualified name of
363 * the node, In external format (name segments separated by path
366 * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually
367 * for error and debug statements. All trailing '_' will be
368 * removed from the full pathname if 'NoTrailing' is specified..
370 ******************************************************************************/
373 AcpiNsGetNormalizedPathname (
374 ACPI_NAMESPACE_NODE
*Node
,
381 ACPI_FUNCTION_TRACE_PTR (NsGetNormalizedPathname
, Node
);
384 /* Calculate required buffer size based on depth below root */
386 Size
= AcpiNsBuildNormalizedPath (Node
, NULL
, 0, NoTrailing
);
392 /* Allocate a buffer to be returned to caller */
394 NameBuffer
= ACPI_ALLOCATE_ZEROED (Size
);
397 ACPI_ERROR ((AE_INFO
,
398 "Could not allocate %u bytes", (UINT32
) Size
));
402 /* Build the path in the allocated buffer */
404 (void) AcpiNsBuildNormalizedPath (Node
, NameBuffer
, Size
, NoTrailing
);
406 return_PTR (NameBuffer
);
410 /*******************************************************************************
412 * FUNCTION: AcpiNsBuildPrefixedPathname
414 * PARAMETERS: PrefixScope - Scope/Path that prefixes the internal path
415 * InternalPath - Name or path of the namespace node
419 * DESCRIPTION: Construct a fully qualified pathname from a concatenation of:
420 * 1) Path associated with the PrefixScope namespace node
421 * 2) External path representation of the Internal path
423 ******************************************************************************/
426 AcpiNsBuildPrefixedPathname (
427 ACPI_GENERIC_STATE
*PrefixScope
,
428 const char *InternalPath
)
431 char *FullPath
= NULL
;
432 char *ExternalPath
= NULL
;
433 char *PrefixPath
= NULL
;
434 UINT32 PrefixPathLength
= 0;
437 /* If there is a prefix, get the pathname to it */
439 if (PrefixScope
&& PrefixScope
->Scope
.Node
)
441 PrefixPath
= AcpiNsGetNormalizedPathname (PrefixScope
->Scope
.Node
, TRUE
);
444 PrefixPathLength
= strlen (PrefixPath
);
448 Status
= AcpiNsExternalizeName (ACPI_UINT32_MAX
, InternalPath
,
449 NULL
, &ExternalPath
);
450 if (ACPI_FAILURE (Status
))
455 /* Merge the prefix path and the path. 2 is for one dot and trailing null */
457 FullPath
= ACPI_ALLOCATE_ZEROED (
458 PrefixPathLength
+ strlen (ExternalPath
) + 2);
464 /* Don't merge if the External path is already fully qualified */
467 (*ExternalPath
!= '\\') &&
468 (*ExternalPath
!= '^'))
470 strcat (FullPath
, PrefixPath
);
473 strcat (FullPath
, ".");
477 AcpiNsNormalizePathname (ExternalPath
);
478 strcat (FullPath
, ExternalPath
);
483 ACPI_FREE (PrefixPath
);
487 ACPI_FREE (ExternalPath
);
494 /*******************************************************************************
496 * FUNCTION: AcpiNsNormalizePathname
498 * PARAMETERS: OriginalPath - Path to be normalized, in External format
500 * RETURN: The original path is processed in-place
502 * DESCRIPTION: Remove trailing underscores from each element of a path.
504 * For example: \A___.B___.C___ becomes \A.B.C
506 ******************************************************************************/
509 AcpiNsNormalizePathname (
512 char *InputPath
= OriginalPath
;
518 /* Allocate a temp buffer in which to construct the new path */
520 NewPathBuffer
= ACPI_ALLOCATE_ZEROED (strlen (InputPath
) + 1);
521 NewPath
= NewPathBuffer
;
527 /* Special characters may appear at the beginning of the path */
529 if (*InputPath
== '\\')
531 *NewPath
= *InputPath
;
536 while (*InputPath
== '^')
538 *NewPath
= *InputPath
;
543 /* Remainder of the path */
547 /* Do one nameseg at a time */
549 for (i
= 0; (i
< ACPI_NAME_SIZE
) && *InputPath
; i
++)
551 if ((i
== 0) || (*InputPath
!= '_')) /* First char is allowed to be underscore */
553 *NewPath
= *InputPath
;
560 /* Dot means that there are more namesegs to come */
562 if (*InputPath
== '.')
564 *NewPath
= *InputPath
;
571 strcpy (OriginalPath
, NewPathBuffer
);
572 ACPI_FREE (NewPathBuffer
);