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