Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /******************************************************************************* |
2 | * | |
3 | * Module Name: nsnames - Name manipulation and search | |
4 | * | |
5 | ******************************************************************************/ | |
6 | ||
7 | /* | |
82a80941 | 8 | * Copyright (C) 2000 - 2015, Intel Corp. |
1da177e4 LT |
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 | ||
1da177e4 | 44 | #include <acpi/acpi.h> |
e2f7a777 LB |
45 | #include "accommon.h" |
46 | #include "amlcode.h" | |
47 | #include "acnamesp.h" | |
1da177e4 | 48 | |
1da177e4 | 49 | #define _COMPONENT ACPI_NAMESPACE |
4be44fcd | 50 | ACPI_MODULE_NAME("nsnames") |
1da177e4 | 51 | |
1da177e4 LT |
52 | /******************************************************************************* |
53 | * | |
54 | * FUNCTION: acpi_ns_build_external_path | |
55 | * | |
ba494bee BM |
56 | * PARAMETERS: node - NS node whose pathname is needed |
57 | * size - Size of the pathname | |
1da177e4 LT |
58 | * *name_buffer - Where to return the pathname |
59 | * | |
3c7db22a BM |
60 | * RETURN: Status |
61 | * Places the pathname into the name_buffer, in external format | |
1da177e4 LT |
62 | * (name segments separated by path separators) |
63 | * | |
64 | * DESCRIPTION: Generate a full pathaname | |
65 | * | |
66 | ******************************************************************************/ | |
3c7db22a | 67 | acpi_status |
4be44fcd LB |
68 | acpi_ns_build_external_path(struct acpi_namespace_node *node, |
69 | acpi_size size, char *name_buffer) | |
1da177e4 | 70 | { |
4be44fcd LB |
71 | acpi_size index; |
72 | struct acpi_namespace_node *parent_node; | |
1da177e4 | 73 | |
4a90c7e8 | 74 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
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; | |
3c7db22a | 82 | return (AE_OK); |
1da177e4 LT |
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 | ||
4be44fcd | 95 | ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name); |
c45b5c09 | 96 | parent_node = parent_node->parent; |
1da177e4 LT |
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) { | |
b8e4d893 | 109 | ACPI_ERROR((AE_INFO, |
f6a22b0b | 110 | "Could not construct external pathname; index=%u, size=%u, Path=%s", |
b8e4d893 | 111 | (u32) index, (u32) size, &name_buffer[size])); |
3c7db22a BM |
112 | |
113 | return (AE_BAD_PARAMETER); | |
1da177e4 LT |
114 | } |
115 | ||
3c7db22a | 116 | return (AE_OK); |
1da177e4 LT |
117 | } |
118 | ||
1da177e4 LT |
119 | /******************************************************************************* |
120 | * | |
121 | * FUNCTION: acpi_ns_get_external_pathname | |
122 | * | |
ba494bee | 123 | * PARAMETERS: node - Namespace node whose pathname is needed |
1da177e4 LT |
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 | * | |
75c8044f LZ |
129 | * DESCRIPTION: Used to obtain the full pathname to a namespace node, usually |
130 | * for error and debug statements. | |
1da177e4 LT |
131 | * |
132 | ******************************************************************************/ | |
133 | ||
4be44fcd | 134 | char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) |
1da177e4 | 135 | { |
3c7db22a | 136 | acpi_status status; |
4be44fcd LB |
137 | char *name_buffer; |
138 | acpi_size size; | |
1da177e4 | 139 | |
b229cf92 | 140 | ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node); |
1da177e4 LT |
141 | |
142 | /* Calculate required buffer size based on depth below root */ | |
143 | ||
4be44fcd | 144 | size = acpi_ns_get_pathname_length(node); |
f88133d7 | 145 | if (!size) { |
393a75d6 | 146 | return_PTR(NULL); |
f88133d7 | 147 | } |
1da177e4 LT |
148 | |
149 | /* Allocate a buffer to be returned to caller */ | |
150 | ||
8313524a | 151 | name_buffer = ACPI_ALLOCATE_ZEROED(size); |
1da177e4 | 152 | if (!name_buffer) { |
b21245a8 | 153 | ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size)); |
4be44fcd | 154 | return_PTR(NULL); |
1da177e4 LT |
155 | } |
156 | ||
157 | /* Build the path in the allocated buffer */ | |
158 | ||
3c7db22a BM |
159 | status = acpi_ns_build_external_path(node, size, name_buffer); |
160 | if (ACPI_FAILURE(status)) { | |
393a75d6 BM |
161 | ACPI_FREE(name_buffer); |
162 | return_PTR(NULL); | |
3c7db22a BM |
163 | } |
164 | ||
4be44fcd | 165 | return_PTR(name_buffer); |
1da177e4 | 166 | } |
1da177e4 | 167 | |
1da177e4 LT |
168 | /******************************************************************************* |
169 | * | |
170 | * FUNCTION: acpi_ns_get_pathname_length | |
171 | * | |
ba494bee | 172 | * PARAMETERS: node - Namespace node |
1da177e4 LT |
173 | * |
174 | * RETURN: Length of path, including prefix | |
175 | * | |
176 | * DESCRIPTION: Get the length of the pathname string for this node | |
177 | * | |
178 | ******************************************************************************/ | |
179 | ||
4be44fcd | 180 | acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) |
1da177e4 | 181 | { |
4be44fcd LB |
182 | acpi_size size; |
183 | struct acpi_namespace_node *next_node; | |
1da177e4 | 184 | |
4be44fcd | 185 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
186 | |
187 | /* | |
188 | * Compute length of pathname as 5 * number of name segments. | |
189 | * Go back up the parent tree to the root | |
190 | */ | |
191 | size = 0; | |
192 | next_node = node; | |
193 | ||
194 | while (next_node && (next_node != acpi_gbl_root_node)) { | |
d8841647 BM |
195 | if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { |
196 | ACPI_ERROR((AE_INFO, | |
3c7db22a | 197 | "Invalid Namespace Node (%p) while traversing namespace", |
d8841647 | 198 | next_node)); |
68aafc35 | 199 | return (0); |
d8841647 | 200 | } |
1da177e4 | 201 | size += ACPI_PATH_SEGMENT_LENGTH; |
c45b5c09 | 202 | next_node = next_node->parent; |
1da177e4 LT |
203 | } |
204 | ||
205 | if (!size) { | |
4be44fcd | 206 | size = 1; /* Root node case */ |
1da177e4 LT |
207 | } |
208 | ||
4be44fcd | 209 | return (size + 1); /* +1 for null string terminator */ |
1da177e4 LT |
210 | } |
211 | ||
1da177e4 LT |
212 | /******************************************************************************* |
213 | * | |
214 | * FUNCTION: acpi_ns_handle_to_pathname | |
215 | * | |
216 | * PARAMETERS: target_handle - Handle of named object whose name is | |
217 | * to be found | |
ba494bee | 218 | * buffer - Where the pathname is returned |
1da177e4 LT |
219 | * |
220 | * RETURN: Status, Buffer is filled with pathname if status is AE_OK | |
221 | * | |
222 | * DESCRIPTION: Build and return a full namespace pathname | |
223 | * | |
224 | ******************************************************************************/ | |
225 | ||
226 | acpi_status | |
4be44fcd LB |
227 | acpi_ns_handle_to_pathname(acpi_handle target_handle, |
228 | struct acpi_buffer * buffer) | |
1da177e4 | 229 | { |
4be44fcd LB |
230 | acpi_status status; |
231 | struct acpi_namespace_node *node; | |
232 | acpi_size required_size; | |
1da177e4 | 233 | |
b229cf92 | 234 | ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); |
1da177e4 | 235 | |
f24b664d | 236 | node = acpi_ns_validate_handle(target_handle); |
1da177e4 | 237 | if (!node) { |
4be44fcd | 238 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
1da177e4 LT |
239 | } |
240 | ||
241 | /* Determine size required for the caller buffer */ | |
242 | ||
4be44fcd | 243 | required_size = acpi_ns_get_pathname_length(node); |
f88133d7 | 244 | if (!required_size) { |
3c7db22a | 245 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
f88133d7 | 246 | } |
1da177e4 LT |
247 | |
248 | /* Validate/Allocate/Clear caller buffer */ | |
249 | ||
4be44fcd LB |
250 | status = acpi_ut_initialize_buffer(buffer, required_size); |
251 | if (ACPI_FAILURE(status)) { | |
252 | return_ACPI_STATUS(status); | |
1da177e4 LT |
253 | } |
254 | ||
255 | /* Build the path in the caller buffer */ | |
256 | ||
3c7db22a BM |
257 | status = |
258 | acpi_ns_build_external_path(node, required_size, buffer->pointer); | |
259 | if (ACPI_FAILURE(status)) { | |
260 | return_ACPI_STATUS(status); | |
261 | } | |
1da177e4 | 262 | |
50eca3eb | 263 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n", |
4be44fcd LB |
264 | (char *)buffer->pointer, (u32) required_size)); |
265 | return_ACPI_STATUS(AE_OK); | |
1da177e4 | 266 | } |