- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / interpreter / amnames.c
blobea4c26e088f52b03d77ea4c3a105ec37a7007591
2 /******************************************************************************
4 * Module Name: amnames - interpreter/scanner name load/execute
5 * $Revision: 71 $
7 *****************************************************************************/
9 /*
10 * Copyright (C) 2000 R. Byron Moore
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "acpi.h"
29 #include "acinterp.h"
30 #include "amlcode.h"
31 #include "acnamesp.h"
33 #define _COMPONENT INTERPRETER
34 MODULE_NAME ("amnames")
37 /* AML Package Length encodings */
39 #define ACPI_AML_PACKAGE_TYPE1 0x40
40 #define ACPI_AML_PACKAGE_TYPE2 0x4000
41 #define ACPI_AML_PACKAGE_TYPE3 0x400000
42 #define ACPI_AML_PACKAGE_TYPE4 0x40000000
45 /*******************************************************************************
47 * FUNCTION: Acpi_aml_allocate_name_string
49 * PARAMETERS: Prefix_count - Count of parent levels. Special cases:
50 * (-1) = root, 0 = none
51 * Num_name_segs - count of 4-character name segments
53 * RETURN: A pointer to the allocated string segment. This segment must
54 * be deleted by the caller.
56 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
57 * string is long enough, and set up prefix if any.
59 ******************************************************************************/
61 NATIVE_CHAR *
62 acpi_aml_allocate_name_string (
63 u32 prefix_count,
64 u32 num_name_segs)
66 NATIVE_CHAR *temp_ptr;
67 NATIVE_CHAR *name_string;
68 u32 size_needed;
72 * Allow room for all \ and ^ prefixes, all segments, and a Multi_name_prefix.
73 * Also, one byte for the null terminator.
74 * This may actually be somewhat longer than needed.
77 if (prefix_count == (u32) -1) {
78 /* Special case for root */
80 size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
82 else {
83 size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
87 * Allocate a buffer for the name.
88 * This buffer must be deleted by the caller!
91 name_string = acpi_cm_allocate (size_needed);
92 if (!name_string) {
93 REPORT_ERROR (("Aml_allocate_name_string: name allocation failure\n"));
94 return (NULL);
97 temp_ptr = name_string;
99 /* Set up Root or Parent prefixes if needed */
101 if (prefix_count == (u32) -1) {
102 *temp_ptr++ = AML_ROOT_PREFIX;
105 else {
106 while (prefix_count--) {
107 *temp_ptr++ = AML_PARENT_PREFIX;
112 /* Set up Dual or Multi prefixes if needed */
114 if (num_name_segs > 2) {
115 /* Set up multi prefixes */
117 *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
118 *temp_ptr++ = (char) num_name_segs;
121 else if (2 == num_name_segs) {
122 /* Set up dual prefixes */
124 *temp_ptr++ = AML_DUAL_NAME_PREFIX;
128 * Terminate string following prefixes. Acpi_aml_exec_name_segment() will
129 * append the segment(s)
132 *temp_ptr = 0;
134 return (name_string);
137 /*******************************************************************************
139 * FUNCTION: Acpi_aml_exec_name_segment
141 * PARAMETERS: Interpreter_mode - Current running mode (load1/Load2/Exec)
143 * RETURN: Status
145 * DESCRIPTION: Execute a name segment (4 bytes)
147 ******************************************************************************/
149 ACPI_STATUS
150 acpi_aml_exec_name_segment (
151 u8 **in_aml_address,
152 NATIVE_CHAR *name_string)
154 u8 *aml_address = *in_aml_address;
155 ACPI_STATUS status = AE_OK;
156 u32 index;
157 NATIVE_CHAR char_buf[5];
161 * If first character is a digit, then we know that we aren't looking at a
162 * valid name segment
165 char_buf[0] = *aml_address;
167 if ('0' <= char_buf[0] && char_buf[0] <= '9') {
168 return (AE_CTRL_PENDING);
171 for (index = 4;
172 (index > 0) && (acpi_cm_valid_acpi_character (*aml_address));
173 --index)
175 char_buf[4 - index] = *aml_address++;
179 /* Valid name segment */
181 if (0 == index) {
182 /* Found 4 valid characters */
184 char_buf[4] = '\0';
186 if (name_string) {
187 STRCAT (name_string, char_buf);
192 else if (4 == index) {
194 * First character was not a valid name character,
195 * so we are looking at something other than a name.
197 status = AE_CTRL_PENDING;
200 else {
201 /* Segment started with one or more valid characters, but fewer than 4 */
203 status = AE_AML_BAD_NAME;
206 *in_aml_address = aml_address;
208 return (status);
212 /*******************************************************************************
214 * FUNCTION: Acpi_aml_get_name_string
216 * PARAMETERS: Data_type - Data type to be associated with this name
218 * RETURN: Status
220 * DESCRIPTION: Get a name, including any prefixes.
222 ******************************************************************************/
225 ACPI_STATUS
226 acpi_aml_get_name_string (
227 OBJECT_TYPE_INTERNAL data_type,
228 u8 *in_aml_address,
229 NATIVE_CHAR **out_name_string,
230 u32 *out_name_length)
232 ACPI_STATUS status = AE_OK;
233 u8 *aml_address = in_aml_address;
234 NATIVE_CHAR *name_string = NULL;
235 u32 num_segments;
236 u32 prefix_count = 0;
237 u8 prefix = 0;
238 u8 has_prefix = FALSE;
241 if (INTERNAL_TYPE_DEF_FIELD == data_type ||
242 INTERNAL_TYPE_BANK_FIELD == data_type ||
243 INTERNAL_TYPE_INDEX_FIELD == data_type)
245 /* Disallow prefixes for types associated with field names */
247 name_string = acpi_aml_allocate_name_string (0, 1);
248 if (!name_string) {
249 status = AE_NO_MEMORY;
251 else {
252 status = acpi_aml_exec_name_segment (&aml_address, name_string);
256 else {
258 * Data_type is not a field name.
259 * Examine first character of name for root or parent prefix operators
262 switch (*aml_address)
265 case AML_ROOT_PREFIX:
267 prefix = *aml_address++;
269 * Remember that we have a Root_prefix --
270 * see comment in Acpi_aml_allocate_name_string()
272 prefix_count = (u32) -1;
273 has_prefix = TRUE;
274 break;
277 case AML_PARENT_PREFIX:
279 /* Increment past possibly multiple parent prefixes */
283 prefix = *aml_address++;
284 ++prefix_count;
286 } while (*aml_address == AML_PARENT_PREFIX);
287 has_prefix = TRUE;
288 break;
291 default:
293 break;
297 /* Examine first character of name for name segment prefix operator */
299 switch (*aml_address)
302 case AML_DUAL_NAME_PREFIX:
304 prefix = *aml_address++;
305 name_string = acpi_aml_allocate_name_string (prefix_count, 2);
306 if (!name_string) {
307 status = AE_NO_MEMORY;
308 break;
311 /* Indicate that we processed a prefix */
312 has_prefix = TRUE;
314 status = acpi_aml_exec_name_segment (&aml_address, name_string);
315 if (ACPI_SUCCESS (status)) {
316 status = acpi_aml_exec_name_segment (&aml_address, name_string);
318 break;
321 case AML_MULTI_NAME_PREFIX_OP:
323 prefix = *aml_address++;
324 /* Fetch count of segments remaining in name path */
326 num_segments = *aml_address++;
328 name_string = acpi_aml_allocate_name_string (prefix_count, num_segments);
329 if (!name_string) {
330 status = AE_NO_MEMORY;
331 break;
334 /* Indicate that we processed a prefix */
335 has_prefix = TRUE;
337 while (num_segments &&
338 (status = acpi_aml_exec_name_segment (&aml_address, name_string)) == AE_OK)
340 --num_segments;
343 break;
346 case 0:
348 /* Null_name valid as of 8-12-98 ASL/AML Grammar Update */
351 /* Consume the NULL byte */
353 aml_address++;
354 name_string = acpi_aml_allocate_name_string (prefix_count, 0);
355 if (!name_string) {
356 status = AE_NO_MEMORY;
357 break;
360 break;
363 default:
365 /* Name segment string */
367 name_string = acpi_aml_allocate_name_string (prefix_count, 1);
368 if (!name_string) {
369 status = AE_NO_MEMORY;
370 break;
373 status = acpi_aml_exec_name_segment (&aml_address, name_string);
374 break;
376 } /* Switch (Peek_op ()) */
380 if (AE_CTRL_PENDING == status && has_prefix) {
381 /* Ran out of segments after processing a prefix */
383 REPORT_ERROR (
384 ("Aml_do_name: Malformed Name at %p\n", name_string));
385 status = AE_AML_BAD_NAME;
389 *out_name_string = name_string;
390 *out_name_length = (u32) (aml_address - in_aml_address);
392 return (status);