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 *
acpi_ex_allocate_name_string(u32 prefix_count,u32 num_name_segs)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
acpi_ex_name_segment(u8 ** in_aml_address,char * name_string)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
acpi_ex_get_name_string(acpi_object_type data_type,u8 * in_aml_address,char ** out_name_string,u32 * out_name_length)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 
428