:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / namespace / nsnames.c
1 /*******************************************************************************
2  *
3  * Module Name: nsnames - Name manipulation and search
4  *              $Revision$
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 #include "amlcode.h"
29 #include "acinterp.h"
30 #include "acnamesp.h"
31
32
33 #define _COMPONENT          ACPI_NAMESPACE
34          MODULE_NAME         ("nsnames")
35
36
37 /*******************************************************************************
38  *
39  * FUNCTION:    Acpi_ns_get_table_pathname
40  *
41  * PARAMETERS:  Node        - Scope whose name is needed
42  *
43  * RETURN:      Pointer to storage containing the fully qualified name of
44  *              the scope, in Label format (all segments strung together
45  *              with no separators)
46  *
47  * DESCRIPTION: Used for debug printing in Acpi_ns_search_table().
48  *
49  ******************************************************************************/
50
51 NATIVE_CHAR *
52 acpi_ns_get_table_pathname (
53         ACPI_NAMESPACE_NODE     *node)
54 {
55         NATIVE_CHAR             *name_buffer;
56         u32                     size;
57         ACPI_NAME               name;
58         ACPI_NAMESPACE_NODE     *child_node;
59         ACPI_NAMESPACE_NODE     *parent_node;
60
61
62         if (!acpi_gbl_root_node || !node) {
63                 /*
64                  * If the name space has not been initialized,
65                  * this function should not have been called.
66                  */
67                 return (NULL);
68         }
69
70         child_node = node->child;
71
72
73         /* Calculate required buffer size based on depth below root */
74
75         size = 1;
76         parent_node = child_node;
77         while (parent_node) {
78                 parent_node = acpi_ns_get_parent_object (parent_node);
79                 if (parent_node) {
80                         size += ACPI_NAME_SIZE;
81                 }
82         }
83
84
85         /* Allocate a buffer to be returned to caller */
86
87         name_buffer = acpi_cm_callocate (size + 1);
88         if (!name_buffer) {
89                 REPORT_ERROR (("Ns_get_table_pathname: allocation failure\n"));
90                 return (NULL);
91         }
92
93
94         /* Store terminator byte, then build name backwards */
95
96         name_buffer[size] = '\0';
97         while ((size > ACPI_NAME_SIZE) &&
98                 acpi_ns_get_parent_object (child_node)) {
99                 size -= ACPI_NAME_SIZE;
100                 name = acpi_ns_find_parent_name (child_node);
101
102                 /* Put the name into the buffer */
103
104                 MOVE_UNALIGNED32_TO_32 ((name_buffer + size), &name);
105                 child_node = acpi_ns_get_parent_object (child_node);
106         }
107
108         name_buffer[--size] = AML_ROOT_PREFIX;
109
110
111         return (name_buffer);
112 }
113
114
115 /*******************************************************************************
116  *
117  * FUNCTION:    Acpi_ns_get_pathname_length
118  *
119  * PARAMETERS:  Node        - Namespace node
120  *
121  * RETURN:      Length of path, including prefix
122  *
123  * DESCRIPTION: Get the length of the pathname string for this node
124  *
125  ******************************************************************************/
126
127 u32
128 acpi_ns_get_pathname_length (
129         ACPI_NAMESPACE_NODE     *node)
130 {
131         u32                     size;
132         ACPI_NAMESPACE_NODE     *next_node;
133
134         /*
135          * Compute length of pathname as 5 * number of name segments.
136          * Go back up the parent tree to the root
137          */
138         for (size = 0, next_node = node;
139                   acpi_ns_get_parent_object (next_node);
140                   next_node = acpi_ns_get_parent_object (next_node)) {
141                 size += PATH_SEGMENT_LENGTH;
142         }
143
144         /* Special case for size still 0 - no parent for "special" nodes */
145
146         if (!size) {
147                 size = PATH_SEGMENT_LENGTH;
148         }
149
150         return (size + 1);
151 }
152
153
154 /*******************************************************************************
155  *
156  * FUNCTION:    Acpi_ns_handle_to_pathname
157  *
158  * PARAMETERS:  Target_handle           - Handle of named object whose name is
159  *                                        to be found
160  *              Buf_size                - Size of the buffer provided
161  *              User_buffer             - Where the pathname is returned
162  *
163  * RETURN:      Status, Buffer is filled with pathname if status is AE_OK
164  *
165  * DESCRIPTION: Build and return a full namespace pathname
166  *
167  * MUTEX:       Locks Namespace
168  *
169  ******************************************************************************/
170
171 ACPI_STATUS
172 acpi_ns_handle_to_pathname (
173         ACPI_HANDLE             target_handle,
174         u32                     *buf_size,
175         NATIVE_CHAR             *user_buffer)
176 {
177         ACPI_STATUS             status = AE_OK;
178         ACPI_NAMESPACE_NODE     *node;
179         u32                     path_length;
180         u32                     user_buf_size;
181         ACPI_NAME               name;
182         u32                     size;
183
184
185         if (!acpi_gbl_root_node || !target_handle) {
186                 /*
187                  * If the name space has not been initialized,
188                  * this function should not have been called.
189                  */
190
191                 return (AE_NO_NAMESPACE);
192         }
193
194         node = acpi_ns_convert_handle_to_entry (target_handle);
195         if (!node) {
196                 return (AE_BAD_PARAMETER);
197         }
198
199
200         /* Set return length to the required path length */
201
202         path_length = acpi_ns_get_pathname_length (node);
203         size = path_length - 1;
204
205         user_buf_size = *buf_size;
206         *buf_size = path_length;
207
208         /* Check if the user buffer is sufficiently large */
209
210         if (path_length > user_buf_size) {
211                 status = AE_BUFFER_OVERFLOW;
212                 goto exit;
213         }
214
215         /* Store null terminator */
216
217         user_buffer[size] = 0;
218         size -= ACPI_NAME_SIZE;
219
220         /* Put the original ACPI name at the end of the path */
221
222         MOVE_UNALIGNED32_TO_32 ((user_buffer + size),
223                          &node->name);
224
225         user_buffer[--size] = PATH_SEPARATOR;
226
227         /* Build name backwards, putting "." between segments */
228
229         while ((size > ACPI_NAME_SIZE) && node) {
230                 size -= ACPI_NAME_SIZE;
231                 name = acpi_ns_find_parent_name (node);
232                 MOVE_UNALIGNED32_TO_32 ((user_buffer + size), &name);
233
234                 user_buffer[--size] = PATH_SEPARATOR;
235                 node = acpi_ns_get_parent_object (node);
236         }
237
238         /*
239          * Overlay the "." preceding the first segment with
240          * the root name "\"
241          */
242
243         user_buffer[size] = '\\';
244
245 exit:
246         return (status);
247 }
248
249