Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: exnames - interpreter/scanner name load/execute
5 : : *
6 : : * Copyright (C) 2000 - 2020, Intel Corp.
7 : : *
8 : : *****************************************************************************/
9 : :
10 : : #include <acpi/acpi.h>
11 : : #include "accommon.h"
12 : : #include "acinterp.h"
13 : : #include "amlcode.h"
14 : :
15 : : #define _COMPONENT ACPI_EXECUTER
16 : : ACPI_MODULE_NAME("exnames")
17 : :
18 : : /* Local prototypes */
19 : : static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
20 : :
21 : : static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
22 : :
23 : : /*******************************************************************************
24 : : *
25 : : * FUNCTION: acpi_ex_allocate_name_string
26 : : *
27 : : * PARAMETERS: prefix_count - Count of parent levels. Special cases:
28 : : * (-1)==root, 0==none
29 : : * num_name_segs - count of 4-character name segments
30 : : *
31 : : * RETURN: A pointer to the allocated string segment. This segment must
32 : : * be deleted by the caller.
33 : : *
34 : : * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
35 : : * string is long enough, and set up prefix if any.
36 : : *
37 : : ******************************************************************************/
38 : :
39 : 3120 : static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
40 : : {
41 : 3120 : char *temp_ptr;
42 : 3120 : char *name_string;
43 : 3120 : u32 size_needed;
44 : :
45 : 3120 : ACPI_FUNCTION_TRACE(ex_allocate_name_string);
46 : :
47 : : /*
48 : : * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
49 : : * Also, one byte for the null terminator.
50 : : * This may actually be somewhat longer than needed.
51 : : */
52 [ + + ]: 3120 : if (prefix_count == ACPI_UINT32_MAX) {
53 : :
54 : : /* Special case for root */
55 : :
56 : 240 : size_needed = 1 + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
57 : : } else {
58 : 2880 : size_needed =
59 : 2880 : prefix_count + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
60 : : }
61 : :
62 : : /*
63 : : * Allocate a buffer for the name.
64 : : * This buffer must be deleted by the caller!
65 : : */
66 : 3120 : name_string = ACPI_ALLOCATE(size_needed);
67 [ - + ]: 3120 : if (!name_string) {
68 : 0 : ACPI_ERROR((AE_INFO,
69 : : "Could not allocate size %u", size_needed));
70 : 0 : return_PTR(NULL);
71 : : }
72 : :
73 : 3120 : temp_ptr = name_string;
74 : :
75 : : /* Set up Root or Parent prefixes if needed */
76 : :
77 [ + + ]: 3120 : if (prefix_count == ACPI_UINT32_MAX) {
78 : 240 : *temp_ptr++ = AML_ROOT_PREFIX;
79 : : } else {
80 [ - + ]: 2880 : while (prefix_count--) {
81 : 0 : *temp_ptr++ = AML_PARENT_PREFIX;
82 : : }
83 : : }
84 : :
85 : : /* Set up Dual or Multi prefixes if needed */
86 : :
87 [ + + ]: 3120 : if (num_name_segs > 2) {
88 : :
89 : : /* Set up multi prefixes */
90 : :
91 : 240 : *temp_ptr++ = AML_MULTI_NAME_PREFIX;
92 : 240 : *temp_ptr++ = (char)num_name_segs;
93 [ - + ]: 2880 : } else if (2 == num_name_segs) {
94 : :
95 : : /* Set up dual prefixes */
96 : :
97 : 0 : *temp_ptr++ = AML_DUAL_NAME_PREFIX;
98 : : }
99 : :
100 : : /*
101 : : * Terminate string following prefixes. acpi_ex_name_segment() will
102 : : * append the segment(s)
103 : : */
104 : 3120 : *temp_ptr = 0;
105 : :
106 : 3120 : return_PTR(name_string);
107 : : }
108 : :
109 : : /*******************************************************************************
110 : : *
111 : : * FUNCTION: acpi_ex_name_segment
112 : : *
113 : : * PARAMETERS: in_aml_address - Pointer to the name in the AML code
114 : : * name_string - Where to return the name. The name is appended
115 : : * to any existing string to form a namepath
116 : : *
117 : : * RETURN: Status
118 : : *
119 : : * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
120 : : *
121 : : ******************************************************************************/
122 : :
123 : 3840 : static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
124 : : {
125 : 3840 : char *aml_address = (void *)*in_aml_address;
126 : 3840 : acpi_status status = AE_OK;
127 : 3840 : u32 index;
128 : 3840 : char char_buf[5];
129 : :
130 : 3840 : ACPI_FUNCTION_TRACE(ex_name_segment);
131 : :
132 : : /*
133 : : * If first character is a digit, then we know that we aren't looking
134 : : * at a valid name segment
135 : : */
136 : 3840 : char_buf[0] = *aml_address;
137 : :
138 [ - + ]: 3840 : if ('0' <= char_buf[0] && char_buf[0] <= '9') {
139 : 0 : ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0]));
140 : 0 : return_ACPI_STATUS(AE_CTRL_PENDING);
141 : : }
142 : :
143 : 19200 : for (index = 0;
144 [ + + ]: 19200 : (index < ACPI_NAMESEG_SIZE)
145 [ + - ]: 15360 : && (acpi_ut_valid_name_char(*aml_address, 0)); index++) {
146 : 15360 : char_buf[index] = *aml_address++;
147 : : }
148 : :
149 : : /* Valid name segment */
150 : :
151 [ + - ]: 3840 : if (index == 4) {
152 : :
153 : : /* Found 4 valid characters */
154 : :
155 : 3840 : char_buf[4] = '\0';
156 : :
157 [ + - ]: 3840 : if (name_string) {
158 : : ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
159 : 3840 : "Appending NameSeg %s\n", char_buf));
160 : 3840 : strcat(name_string, char_buf);
161 : : } else {
162 : : ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
163 : : "No Name string - %s\n", char_buf));
164 : : }
165 [ # # ]: 0 : } else if (index == 0) {
166 : : /*
167 : : * First character was not a valid name character,
168 : : * so we are looking at something other than a name.
169 : : */
170 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
171 : : "Leading character is not alpha: %02Xh (not a name)\n",
172 : : char_buf[0]));
173 : : status = AE_CTRL_PENDING;
174 : : } else {
175 : : /*
176 : : * Segment started with one or more valid characters, but fewer than
177 : : * the required 4
178 : : */
179 : 0 : status = AE_AML_BAD_NAME;
180 : 0 : ACPI_ERROR((AE_INFO,
181 : : "Bad character 0x%02x in name, at %p",
182 : : *aml_address, aml_address));
183 : : }
184 : :
185 : 3840 : *in_aml_address = ACPI_CAST_PTR(u8, aml_address);
186 : 3840 : return_ACPI_STATUS(status);
187 : : }
188 : :
189 : : /*******************************************************************************
190 : : *
191 : : * FUNCTION: acpi_ex_get_name_string
192 : : *
193 : : * PARAMETERS: data_type - Object type to be associated with this
194 : : * name
195 : : * in_aml_address - Pointer to the namestring in the AML code
196 : : * out_name_string - Where the namestring is returned
197 : : * out_name_length - Length of the returned string
198 : : *
199 : : * RETURN: Status, namestring and length
200 : : *
201 : : * DESCRIPTION: Extract a full namepath from the AML byte stream,
202 : : * including any prefixes.
203 : : *
204 : : ******************************************************************************/
205 : :
206 : : acpi_status
207 : 3120 : acpi_ex_get_name_string(acpi_object_type data_type,
208 : : u8 * in_aml_address,
209 : : char **out_name_string, u32 * out_name_length)
210 : : {
211 : 3120 : acpi_status status = AE_OK;
212 : 3120 : u8 *aml_address = in_aml_address;
213 : 3120 : char *name_string = NULL;
214 : 3120 : u32 num_segments;
215 : 3120 : u32 prefix_count = 0;
216 : 3120 : u8 has_prefix = FALSE;
217 : :
218 : 3120 : ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
219 : :
220 : 3120 : if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
221 [ - + ]: 3120 : ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
222 : : ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
223 : :
224 : : /* Disallow prefixes for types associated with field_unit names */
225 : :
226 : 0 : name_string = acpi_ex_allocate_name_string(0, 1);
227 [ # # ]: 0 : if (!name_string) {
228 : : status = AE_NO_MEMORY;
229 : : } else {
230 : 0 : status =
231 : 0 : acpi_ex_name_segment(&aml_address, name_string);
232 : : }
233 : : } else {
234 : : /*
235 : : * data_type is not a field name.
236 : : * Examine first character of name for root or parent prefix operators
237 : : */
238 [ + - + ]: 3120 : switch (*aml_address) {
239 : 240 : case AML_ROOT_PREFIX:
240 : :
241 : : ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
242 : : "RootPrefix(\\) at %p\n",
243 : 240 : aml_address));
244 : :
245 : : /*
246 : : * Remember that we have a root_prefix --
247 : : * see comment in acpi_ex_allocate_name_string()
248 : : */
249 : 240 : aml_address++;
250 : 240 : prefix_count = ACPI_UINT32_MAX;
251 : 240 : has_prefix = TRUE;
252 : 240 : break;
253 : :
254 : 0 : case AML_PARENT_PREFIX:
255 : :
256 : : /* Increment past possibly multiple parent prefixes */
257 : :
258 : 0 : do {
259 : : ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
260 : : "ParentPrefix (^) at %p\n",
261 : 0 : aml_address));
262 : :
263 : 0 : aml_address++;
264 : 0 : prefix_count++;
265 : :
266 [ # # ]: 0 : } while (*aml_address == AML_PARENT_PREFIX);
267 : :
268 : : has_prefix = TRUE;
269 : : break;
270 : :
271 : : default:
272 : :
273 : : /* Not a prefix character */
274 : :
275 : : break;
276 : : }
277 : :
278 : : /* Examine first character of name for name segment prefix operator */
279 : :
280 [ - + - + ]: 3120 : switch (*aml_address) {
281 : 0 : case AML_DUAL_NAME_PREFIX:
282 : :
283 : : ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
284 : : "DualNamePrefix at %p\n",
285 : 0 : aml_address));
286 : :
287 : 0 : aml_address++;
288 : 0 : name_string =
289 : 0 : acpi_ex_allocate_name_string(prefix_count, 2);
290 [ # # ]: 0 : if (!name_string) {
291 : : status = AE_NO_MEMORY;
292 : : break;
293 : : }
294 : :
295 : : /* Indicate that we processed a prefix */
296 : :
297 : 0 : has_prefix = TRUE;
298 : :
299 : 0 : status =
300 : 0 : acpi_ex_name_segment(&aml_address, name_string);
301 [ # # ]: 0 : if (ACPI_SUCCESS(status)) {
302 : 0 : status =
303 : 0 : acpi_ex_name_segment(&aml_address,
304 : : name_string);
305 : : }
306 : : break;
307 : :
308 : 240 : case AML_MULTI_NAME_PREFIX:
309 : :
310 : : ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
311 : : "MultiNamePrefix at %p\n",
312 : 240 : aml_address));
313 : :
314 : : /* Fetch count of segments remaining in name path */
315 : :
316 : 240 : aml_address++;
317 : 240 : num_segments = *aml_address;
318 : :
319 : 240 : name_string =
320 : 240 : acpi_ex_allocate_name_string(prefix_count,
321 : : num_segments);
322 [ + - ]: 240 : if (!name_string) {
323 : : status = AE_NO_MEMORY;
324 : : break;
325 : : }
326 : :
327 : : /* Indicate that we processed a prefix */
328 : :
329 : 240 : aml_address++;
330 : 240 : has_prefix = TRUE;
331 : :
332 [ + + + - ]: 2160 : while (num_segments &&
333 : : (status =
334 : 960 : acpi_ex_name_segment(&aml_address,
335 : : name_string)) == AE_OK) {
336 : 960 : num_segments--;
337 : : }
338 : :
339 : : break;
340 : :
341 : : case 0:
342 : :
343 : : /* null_name valid as of 8-12-98 ASL/AML Grammar Update */
344 : :
345 : 0 : if (prefix_count == ACPI_UINT32_MAX) {
346 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
347 : 0 : "NameSeg is \"\\\" followed by NULL\n"));
348 : : }
349 : :
350 : : /* Consume the NULL byte */
351 : :
352 : 0 : aml_address++;
353 : 0 : name_string =
354 : 0 : acpi_ex_allocate_name_string(prefix_count, 0);
355 [ # # ]: 0 : if (!name_string) {
356 : 0 : status = AE_NO_MEMORY;
357 : 0 : break;
358 : : }
359 : :
360 : : break;
361 : :
362 : 2880 : default:
363 : :
364 : : /* Name segment string */
365 : :
366 : 2880 : name_string =
367 : 2880 : acpi_ex_allocate_name_string(prefix_count, 1);
368 [ + - ]: 2880 : if (!name_string) {
369 : : status = AE_NO_MEMORY;
370 : : break;
371 : : }
372 : :
373 : 2880 : status =
374 : 2880 : acpi_ex_name_segment(&aml_address, name_string);
375 : 2880 : break;
376 : : }
377 : : }
378 : :
379 [ - + ]: 3120 : if (AE_CTRL_PENDING == status && has_prefix) {
380 : :
381 : : /* Ran out of segments after processing a prefix */
382 : :
383 : 0 : ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
384 : 0 : status = AE_AML_BAD_NAME;
385 : : }
386 : :
387 [ - + ]: 3120 : if (ACPI_FAILURE(status)) {
388 [ # # ]: 0 : if (name_string) {
389 : 0 : ACPI_FREE(name_string);
390 : : }
391 : 0 : return_ACPI_STATUS(status);
392 : : }
393 : :
394 : 3120 : *out_name_string = name_string;
395 : 3120 : *out_name_length = (u32) (aml_address - in_aml_address);
396 : :
397 : 3120 : return_ACPI_STATUS(status);
398 : : }
|