ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / acpi / executer / exnames.c
1
2 /******************************************************************************
3  *
4  * Module Name: exnames - interpreter/scanner name load/execute
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2004, R. Byron Moore
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44
45
46 #include <acpi/acpi.h>
47 #include <acpi/acinterp.h>
48 #include <acpi/amlcode.h>
49
50 #define _COMPONENT          ACPI_EXECUTER
51          ACPI_MODULE_NAME    ("exnames")
52
53
54 /* AML Package Length encodings */
55
56 #define ACPI_AML_PACKAGE_TYPE1   0x40
57 #define ACPI_AML_PACKAGE_TYPE2   0x4000
58 #define ACPI_AML_PACKAGE_TYPE3   0x400000
59 #define ACPI_AML_PACKAGE_TYPE4   0x40000000
60
61
62 /*******************************************************************************
63  *
64  * FUNCTION:    acpi_ex_allocate_name_string
65  *
66  * PARAMETERS:  prefix_count        - Count of parent levels. Special cases:
67  *                                    (-1) = root,  0 = none
68  *              num_name_segs       - count of 4-character name segments
69  *
70  * RETURN:      A pointer to the allocated string segment.  This segment must
71  *              be deleted by the caller.
72  *
73  * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
74  *              string is long enough, and set up prefix if any.
75  *
76  ******************************************************************************/
77
78 char *
79 acpi_ex_allocate_name_string (
80         u32                             prefix_count,
81         u32                             num_name_segs)
82 {
83         char                            *temp_ptr;
84         char                            *name_string;
85         u32                              size_needed;
86
87         ACPI_FUNCTION_TRACE ("ex_allocate_name_string");
88
89
90         /*
91          * Allow room for all \ and ^ prefixes, all segments, and a multi_name_prefix.
92          * Also, one byte for the null terminator.
93          * This may actually be somewhat longer than needed.
94          */
95         if (prefix_count == ACPI_UINT32_MAX) {
96                 /* Special case for root */
97
98                 size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
99         }
100         else {
101                 size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
102         }
103
104         /*
105          * Allocate a buffer for the name.
106          * This buffer must be deleted by the caller!
107          */
108         name_string = ACPI_MEM_ALLOCATE (size_needed);
109         if (!name_string) {
110                 ACPI_REPORT_ERROR (("ex_allocate_name_string: Could not allocate size %d\n", size_needed));
111                 return_PTR (NULL);
112         }
113
114         temp_ptr = name_string;
115
116         /* Set up Root or Parent prefixes if needed */
117
118         if (prefix_count == ACPI_UINT32_MAX) {
119                 *temp_ptr++ = AML_ROOT_PREFIX;
120         }
121         else {
122                 while (prefix_count--) {
123                         *temp_ptr++ = AML_PARENT_PREFIX;
124                 }
125         }
126
127
128         /* Set up Dual or Multi prefixes if needed */
129
130         if (num_name_segs > 2) {
131                 /* Set up multi prefixes   */
132
133                 *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
134                 *temp_ptr++ = (char) num_name_segs;
135         }
136         else if (2 == num_name_segs) {
137                 /* Set up dual prefixes */
138
139                 *temp_ptr++ = AML_DUAL_NAME_PREFIX;
140         }
141
142         /*
143          * Terminate string following prefixes. acpi_ex_name_segment() will
144          * append the segment(s)
145          */
146         *temp_ptr = 0;
147
148         return_PTR (name_string);
149 }
150
151 /*******************************************************************************
152  *
153  * FUNCTION:    acpi_ex_name_segment
154  *
155  * PARAMETERS:  interpreter_mode    - Current running mode (load1/Load2/Exec)
156  *
157  * RETURN:      Status
158  *
159  * DESCRIPTION: Execute a name segment (4 bytes)
160  *
161  ******************************************************************************/
162
163 acpi_status
164 acpi_ex_name_segment (
165         u8                              **in_aml_address,
166         char                            *name_string)
167 {
168         char                            *aml_address = (void *) *in_aml_address;
169         acpi_status                     status = AE_OK;
170         u32                             index;
171         char                            char_buf[5];
172
173
174         ACPI_FUNCTION_TRACE ("ex_name_segment");
175
176
177         /*
178          * If first character is a digit, then we know that we aren't looking at a
179          * valid name segment
180          */
181         char_buf[0] = *aml_address;
182
183         if ('0' <= char_buf[0] && char_buf[0] <= '9') {
184                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0]));
185                 return_ACPI_STATUS (AE_CTRL_PENDING);
186         }
187
188         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
189
190         for (index = 0;
191                 (index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address));
192                 index++) {
193                 char_buf[index] = *aml_address++;
194                 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index]));
195         }
196
197
198         /* Valid name segment  */
199
200         if (index == 4) {
201                 /* Found 4 valid characters */
202
203                 char_buf[4] = '\0';
204
205                 if (name_string) {
206                         ACPI_STRCAT (name_string, char_buf);
207                         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
208                                 "Appended to - %s \n", name_string));
209                 }
210                 else {
211                         ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
212                                 "No Name string - %s \n", char_buf));
213                 }
214         }
215         else if (index == 0) {
216                 /*
217                  * First character was not a valid name character,
218                  * so we are looking at something other than a name.
219                  */
220                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
221                         "Leading character is not alpha: %02Xh (not a name)\n",
222                         char_buf[0]));
223                 status = AE_CTRL_PENDING;
224         }
225         else {
226                 /* Segment started with one or more valid characters, but fewer than 4 */
227
228                 status = AE_AML_BAD_NAME;
229                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad character %02x in name, at %p\n",
230                         *aml_address, aml_address));
231         }
232
233         *in_aml_address = (u8 *) aml_address;
234         return_ACPI_STATUS (status);
235 }
236
237
238 /*******************************************************************************
239  *
240  * FUNCTION:    acpi_ex_get_name_string
241  *
242  * PARAMETERS:  data_type           - Data type to be associated with this name
243  *
244  * RETURN:      Status
245  *
246  * DESCRIPTION: Get a name, including any prefixes.
247  *
248  ******************************************************************************/
249
250 acpi_status
251 acpi_ex_get_name_string (
252         acpi_object_type                data_type,
253         u8                              *in_aml_address,
254         char                            **out_name_string,
255         u32                             *out_name_length)
256 {
257         acpi_status                     status = AE_OK;
258         u8                              *aml_address = in_aml_address;
259         char                            *name_string = NULL;
260         u32                             num_segments;
261         u32                             prefix_count = 0;
262         u8                              has_prefix = FALSE;
263
264
265         ACPI_FUNCTION_TRACE_PTR ("ex_get_name_string", aml_address);
266
267
268         if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type  ||
269                 ACPI_TYPE_LOCAL_BANK_FIELD == data_type    ||
270                 ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
271                 /* Disallow prefixes for types associated with field_unit names */
272
273                 name_string = acpi_ex_allocate_name_string (0, 1);
274                 if (!name_string) {
275                         status = AE_NO_MEMORY;
276                 }
277                 else {
278                         status = acpi_ex_name_segment (&aml_address, name_string);
279                 }
280         }
281         else {
282                 /*
283                  * data_type is not a field name.
284                  * Examine first character of name for root or parent prefix operators
285                  */
286                 switch (*aml_address) {
287                 case AML_ROOT_PREFIX:
288
289                         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "root_prefix(\\) at %p\n", aml_address));
290
291                         /*
292                          * Remember that we have a root_prefix --
293                          * see comment in acpi_ex_allocate_name_string()
294                          */
295                         aml_address++;
296                         prefix_count = ACPI_UINT32_MAX;
297                         has_prefix = TRUE;
298                         break;
299
300
301                 case AML_PARENT_PREFIX:
302
303                         /* Increment past possibly multiple parent prefixes */
304
305                         do {
306                                 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "parent_prefix (^) at %p\n", aml_address));
307
308                                 aml_address++;
309                                 prefix_count++;
310
311                         } while (*aml_address == AML_PARENT_PREFIX);
312
313                         has_prefix = TRUE;
314                         break;
315
316
317                 default:
318
319                         /* Not a prefix character */
320
321                         break;
322                 }
323
324
325                 /* Examine first character of name for name segment prefix operator */
326
327                 switch (*aml_address) {
328                 case AML_DUAL_NAME_PREFIX:
329
330                         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "dual_name_prefix at %p\n", aml_address));
331
332                         aml_address++;
333                         name_string = acpi_ex_allocate_name_string (prefix_count, 2);
334                         if (!name_string) {
335                                 status = AE_NO_MEMORY;
336                                 break;
337                         }
338
339                         /* Indicate that we processed a prefix */
340
341                         has_prefix = TRUE;
342
343                         status = acpi_ex_name_segment (&aml_address, name_string);
344                         if (ACPI_SUCCESS (status)) {
345                                 status = acpi_ex_name_segment (&aml_address, name_string);
346                         }
347                         break;
348
349
350                 case AML_MULTI_NAME_PREFIX_OP:
351
352                         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "multi_name_prefix at %p\n", aml_address));
353
354                         /* Fetch count of segments remaining in name path */
355
356                         aml_address++;
357                         num_segments = *aml_address;
358
359                         name_string = acpi_ex_allocate_name_string (prefix_count, num_segments);
360                         if (!name_string) {
361                                 status = AE_NO_MEMORY;
362                                 break;
363                         }
364
365                         /* Indicate that we processed a prefix */
366
367                         aml_address++;
368                         has_prefix = TRUE;
369
370                         while (num_segments &&
371                                         (status = acpi_ex_name_segment (&aml_address, name_string)) == AE_OK) {
372                                 num_segments--;
373                         }
374
375                         break;
376
377
378                 case 0:
379
380                         /* null_name valid as of 8-12-98 ASL/AML Grammar Update */
381
382                         if (prefix_count == ACPI_UINT32_MAX) {
383                                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "name_seg is \"\\\" followed by NULL\n"));
384                         }
385
386                         /* Consume the NULL byte */
387
388                         aml_address++;
389                         name_string = acpi_ex_allocate_name_string (prefix_count, 0);
390                         if (!name_string) {
391                                 status = AE_NO_MEMORY;
392                                 break;
393                         }
394
395                         break;
396
397
398                 default:
399
400                         /* Name segment string */
401
402                         name_string = acpi_ex_allocate_name_string (prefix_count, 1);
403                         if (!name_string) {
404                                 status = AE_NO_MEMORY;
405                                 break;
406                         }
407
408                         status = acpi_ex_name_segment (&aml_address, name_string);
409                         break;
410                 }
411         }
412
413         if (AE_CTRL_PENDING == status && has_prefix) {
414                 /* Ran out of segments after processing a prefix */
415
416                 ACPI_REPORT_ERROR (
417                         ("ex_do_name: Malformed Name at %p\n", name_string));
418                 status = AE_AML_BAD_NAME;
419         }
420
421         *out_name_string = name_string;
422         *out_name_length = (u32) (aml_address - in_aml_address);
423
424         return_ACPI_STATUS (status);
425 }
426
427