- Send the SCM reply packet with the final status after completing the requested...
[reactos.git] / reactos / drivers / bus / acpi / namespace / nsnames.c
1 /*******************************************************************************
2 *
3 * Module Name: nsnames - Name manipulation and search
4 * $Revision: 1.1 $
5 *
6 ******************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 R. Byron Moore
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26
27 #include <acpi.h>
28
29 #define _COMPONENT ACPI_NAMESPACE
30 MODULE_NAME ("nsnames")
31
32
33 /*******************************************************************************
34 *
35 * FUNCTION: Acpi_ns_get_table_pathname
36 *
37 * PARAMETERS: Node - Scope whose name is needed
38 *
39 * RETURN: Pointer to storage containing the fully qualified name of
40 * the scope, in Label format (all segments strung together
41 * with no separators)
42 *
43 * DESCRIPTION: Used for debug printing in Acpi_ns_search_table().
44 *
45 ******************************************************************************/
46
47 NATIVE_CHAR *
48 acpi_ns_get_table_pathname (
49 ACPI_NAMESPACE_NODE *node)
50 {
51 NATIVE_CHAR *name_buffer;
52 u32 size;
53 ACPI_NAME name;
54 ACPI_NAMESPACE_NODE *child_node;
55 ACPI_NAMESPACE_NODE *parent_node;
56
57
58 if (!acpi_gbl_root_node || !node) {
59 /*
60 * If the name space has not been initialized,
61 * this function should not have been called.
62 */
63 return (NULL);
64 }
65
66 child_node = node->child;
67
68
69 /* Calculate required buffer size based on depth below root */
70
71 size = 1;
72 parent_node = child_node;
73 while (parent_node) {
74 parent_node = acpi_ns_get_parent_object (parent_node);
75 if (parent_node) {
76 size += ACPI_NAME_SIZE;
77 }
78 }
79
80
81 /* Allocate a buffer to be returned to caller */
82
83 name_buffer = acpi_cm_callocate (size + 1);
84 if (!name_buffer) {
85 REPORT_ERROR (("Ns_get_table_pathname: allocation failure\n"));
86 return (NULL);
87 }
88
89
90 /* Store terminator byte, then build name backwards */
91
92 name_buffer[size] = '\0';
93 while ((size > ACPI_NAME_SIZE) &&
94 acpi_ns_get_parent_object (child_node)) {
95 size -= ACPI_NAME_SIZE;
96 name = acpi_ns_find_parent_name (child_node);
97
98 /* Put the name into the buffer */
99
100 MOVE_UNALIGNED32_TO_32 ((name_buffer + size), &name);
101 child_node = acpi_ns_get_parent_object (child_node);
102 }
103
104 name_buffer[--size] = AML_ROOT_PREFIX;
105
106
107 return (name_buffer);
108 }
109
110
111 /*******************************************************************************
112 *
113 * FUNCTION: Acpi_ns_get_pathname_length
114 *
115 * PARAMETERS: Node - Namespace node
116 *
117 * RETURN: Length of path, including prefix
118 *
119 * DESCRIPTION: Get the length of the pathname string for this node
120 *
121 ******************************************************************************/
122
123 u32
124 acpi_ns_get_pathname_length (
125 ACPI_NAMESPACE_NODE *node)
126 {
127 u32 size;
128 ACPI_NAMESPACE_NODE *next_node;
129
130 /*
131 * Compute length of pathname as 5 * number of name segments.
132 * Go back up the parent tree to the root
133 */
134 for (size = 0, next_node = node;
135 acpi_ns_get_parent_object (next_node);
136 next_node = acpi_ns_get_parent_object (next_node)) {
137 size += PATH_SEGMENT_LENGTH;
138 }
139
140 /* Special case for size still 0 - no parent for "special" nodes */
141
142 if (!size) {
143 size = PATH_SEGMENT_LENGTH;
144 }
145
146 return (size + 1);
147 }
148
149
150 /*******************************************************************************
151 *
152 * FUNCTION: Acpi_ns_handle_to_pathname
153 *
154 * PARAMETERS: Target_handle - Handle of named object whose name is
155 * to be found
156 * Buf_size - Size of the buffer provided
157 * User_buffer - Where the pathname is returned
158 *
159 * RETURN: Status, Buffer is filled with pathname if status is AE_OK
160 *
161 * DESCRIPTION: Build and return a full namespace pathname
162 *
163 * MUTEX: Locks Namespace
164 *
165 ******************************************************************************/
166
167 ACPI_STATUS
168 acpi_ns_handle_to_pathname (
169 ACPI_HANDLE target_handle,
170 u32 *buf_size,
171 NATIVE_CHAR *user_buffer)
172 {
173 ACPI_STATUS status = AE_OK;
174 ACPI_NAMESPACE_NODE *node;
175 u32 path_length;
176 u32 user_buf_size;
177 ACPI_NAME name;
178 u32 size;
179
180
181 if (!acpi_gbl_root_node || !target_handle) {
182 /*
183 * If the name space has not been initialized,
184 * this function should not have been called.
185 */
186
187 return (AE_NO_NAMESPACE);
188 }
189
190 node = acpi_ns_convert_handle_to_entry (target_handle);
191 if (!node) {
192 return (AE_BAD_PARAMETER);
193 }
194
195
196 /* Set return length to the required path length */
197
198 path_length = acpi_ns_get_pathname_length (node);
199 size = path_length - 1;
200
201 user_buf_size = *buf_size;
202 *buf_size = path_length;
203
204 /* Check if the user buffer is sufficiently large */
205
206 if (path_length > user_buf_size) {
207 status = AE_BUFFER_OVERFLOW;
208 goto exit;
209 }
210
211 /* Store null terminator */
212
213 user_buffer[size] = 0;
214 size -= ACPI_NAME_SIZE;
215
216 /* Put the original ACPI name at the end of the path */
217
218 MOVE_UNALIGNED32_TO_32 ((user_buffer + size),
219 &node->name);
220
221 user_buffer[--size] = PATH_SEPARATOR;
222
223 /* Build name backwards, putting "." between segments */
224
225 while ((size > ACPI_NAME_SIZE) && node) {
226 size -= ACPI_NAME_SIZE;
227 name = acpi_ns_find_parent_name (node);
228 MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &name);
229
230 user_buffer[--size] = PATH_SEPARATOR;
231 node = acpi_ns_get_parent_object (node);
232 }
233
234 /*
235 * Overlay the "." preceding the first segment with
236 * the root name "\"
237 */
238
239 user_buffer[size] = '\\';
240
241 exit:
242 return (status);
243 }
244
245