Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /******************************************************************************* |
2 | * | |
3 | * Module Name: nsnames - Name manipulation and search | |
4 | * | |
5 | ******************************************************************************/ | |
6 | ||
7 | /* | |
a8357b0c | 8 | * Copyright (C) 2000 - 2010, 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 | * | |
56 | * PARAMETERS: Node - NS node whose pathname is needed | |
57 | * Size - Size of the pathname | |
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 LB |
95 | ACPI_MOVE_32_TO_32((name_buffer + index), &parent_node->name); |
96 | parent_node = acpi_ns_get_parent_node(parent_node); | |
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 | * | |
44f6c012 | 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 | * | |
129 | * DESCRIPTION: Used for debug printing in acpi_ns_search_table(). | |
130 | * | |
131 | ******************************************************************************/ | |
132 | ||
4be44fcd | 133 | char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) |
1da177e4 | 134 | { |
3c7db22a | 135 | acpi_status status; |
4be44fcd LB |
136 | char *name_buffer; |
137 | acpi_size size; | |
1da177e4 | 138 | |
b229cf92 | 139 | ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node); |
1da177e4 LT |
140 | |
141 | /* Calculate required buffer size based on depth below root */ | |
142 | ||
4be44fcd | 143 | size = acpi_ns_get_pathname_length(node); |
f88133d7 | 144 | if (!size) { |
393a75d6 | 145 | return_PTR(NULL); |
f88133d7 | 146 | } |
1da177e4 LT |
147 | |
148 | /* Allocate a buffer to be returned to caller */ | |
149 | ||
8313524a | 150 | name_buffer = ACPI_ALLOCATE_ZEROED(size); |
1da177e4 | 151 | if (!name_buffer) { |
b21245a8 | 152 | ACPI_ERROR((AE_INFO, "Could not allocate %u bytes", (u32)size)); |
4be44fcd | 153 | return_PTR(NULL); |
1da177e4 LT |
154 | } |
155 | ||
156 | /* Build the path in the allocated buffer */ | |
157 | ||
3c7db22a BM |
158 | status = acpi_ns_build_external_path(node, size, name_buffer); |
159 | if (ACPI_FAILURE(status)) { | |
393a75d6 BM |
160 | ACPI_FREE(name_buffer); |
161 | return_PTR(NULL); | |
3c7db22a BM |
162 | } |
163 | ||
4be44fcd | 164 | return_PTR(name_buffer); |
1da177e4 | 165 | } |
1da177e4 | 166 | |
1da177e4 LT |
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 | ||
4be44fcd | 179 | acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) |
1da177e4 | 180 | { |
4be44fcd LB |
181 | acpi_size size; |
182 | struct acpi_namespace_node *next_node; | |
1da177e4 | 183 | |
4be44fcd | 184 | ACPI_FUNCTION_ENTRY(); |
1da177e4 LT |
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)) { | |
d8841647 BM |
194 | if (ACPI_GET_DESCRIPTOR_TYPE(next_node) != ACPI_DESC_TYPE_NAMED) { |
195 | ACPI_ERROR((AE_INFO, | |
3c7db22a | 196 | "Invalid Namespace Node (%p) while traversing namespace", |
d8841647 BM |
197 | next_node)); |
198 | return 0; | |
199 | } | |
1da177e4 | 200 | size += ACPI_PATH_SEGMENT_LENGTH; |
4be44fcd | 201 | next_node = acpi_ns_get_parent_node(next_node); |
1da177e4 LT |
202 | } |
203 | ||
204 | if (!size) { | |
4be44fcd | 205 | size = 1; /* Root node case */ |
1da177e4 LT |
206 | } |
207 | ||
4be44fcd | 208 | return (size + 1); /* +1 for null string terminator */ |
1da177e4 LT |
209 | } |
210 | ||
1da177e4 LT |
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 | ||
225 | acpi_status | |
4be44fcd LB |
226 | acpi_ns_handle_to_pathname(acpi_handle target_handle, |
227 | struct acpi_buffer * buffer) | |
1da177e4 | 228 | { |
4be44fcd LB |
229 | acpi_status status; |
230 | struct acpi_namespace_node *node; | |
231 | acpi_size required_size; | |
1da177e4 | 232 | |
b229cf92 | 233 | ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); |
1da177e4 | 234 | |
f24b664d | 235 | node = acpi_ns_validate_handle(target_handle); |
1da177e4 | 236 | if (!node) { |
4be44fcd | 237 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
1da177e4 LT |
238 | } |
239 | ||
240 | /* Determine size required for the caller buffer */ | |
241 | ||
4be44fcd | 242 | required_size = acpi_ns_get_pathname_length(node); |
f88133d7 | 243 | if (!required_size) { |
3c7db22a | 244 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
f88133d7 | 245 | } |
1da177e4 LT |
246 | |
247 | /* Validate/Allocate/Clear caller buffer */ | |
248 | ||
4be44fcd LB |
249 | status = acpi_ut_initialize_buffer(buffer, required_size); |
250 | if (ACPI_FAILURE(status)) { | |
251 | return_ACPI_STATUS(status); | |
1da177e4 LT |
252 | } |
253 | ||
254 | /* Build the path in the caller buffer */ | |
255 | ||
3c7db22a BM |
256 | status = |
257 | acpi_ns_build_external_path(node, required_size, buffer->pointer); | |
258 | if (ACPI_FAILURE(status)) { | |
259 | return_ACPI_STATUS(status); | |
260 | } | |
1da177e4 | 261 | |
50eca3eb | 262 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%X]\n", |
4be44fcd LB |
263 | (char *)buffer->pointer, (u32) required_size)); |
264 | return_ACPI_STATUS(AE_OK); | |
1da177e4 | 265 | } |