blob: 5283603d078d5ef3c34785f558c7c06e4b544c44 [file] [log] [blame]
Erik Schmauss95857632018-03-14 16:13:07 -07001// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/******************************************************************************
3 *
4 * Module Name: exnames - interpreter/scanner name load/execute
5 *
Bob Moore4441e552021-01-15 10:48:25 -08006 * Copyright (C) 2000 - 2021, Intel Corp.
Linus Torvalds1da177e2005-04-16 15:20:36 -07007 *
Erik Schmauss95857632018-03-14 16:13:07 -07008 *****************************************************************************/
Linus Torvalds1da177e2005-04-16 15:20:36 -07009
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <acpi/acpi.h>
Len Browne2f7a772009-01-09 00:30:03 -050011#include "accommon.h"
12#include "acinterp.h"
13#include "amlcode.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
15#define _COMPONENT ACPI_EXECUTER
Len Brown4be44fc2005-08-05 00:44:28 -040016ACPI_MODULE_NAME("exnames")
Linus Torvalds1da177e2005-04-16 15:20:36 -070017
Robert Moore44f6c012005-04-18 22:49:35 -040018/* Local prototypes */
Len Brown4be44fc2005-08-05 00:44:28 -040019static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
Lv Zheng1f86e8c2012-10-31 02:25:45 +000021static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
23/*******************************************************************************
24 *
25 * FUNCTION: acpi_ex_allocate_name_string
26 *
27 * PARAMETERS: prefix_count - Count of parent levels. Special cases:
Robert Moore44f6c012005-04-18 22:49:35 -040028 * (-1)==root, 0==none
Linus Torvalds1da177e2005-04-16 15:20:36 -070029 * num_name_segs - count of 4-character name segments
30 *
Bob Moore73a30902012-10-31 02:26:55 +000031 * RETURN: A pointer to the allocated string segment. This segment must
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 * 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
Len Brown4be44fc2005-08-05 00:44:28 -040039static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
Linus Torvalds1da177e2005-04-16 15:20:36 -070040{
Len Brown4be44fc2005-08-05 00:44:28 -040041 char *temp_ptr;
42 char *name_string;
43 u32 size_needed;
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Bob Mooreb229cf92006-04-21 17:15:00 -040045 ACPI_FUNCTION_TRACE(ex_allocate_name_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47 /*
Robert Moore44f6c012005-04-18 22:49:35 -040048 * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
Linus Torvalds1da177e2005-04-16 15:20:36 -070049 * Also, one byte for the null terminator.
50 * This may actually be somewhat longer than needed.
51 */
52 if (prefix_count == ACPI_UINT32_MAX) {
Bob Moore52fc0b02006-10-02 00:00:00 -040053
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 /* Special case for root */
55
Bob Moore32786752019-04-08 13:42:25 -070056 size_needed = 1 + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
Len Brown4be44fc2005-08-05 00:44:28 -040057 } else {
58 size_needed =
Bob Moore32786752019-04-08 13:42:25 -070059 prefix_count + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -070060 }
61
62 /*
63 * Allocate a buffer for the name.
64 * This buffer must be deleted by the caller!
65 */
Bob Moore83135242006-10-03 00:00:00 -040066 name_string = ACPI_ALLOCATE(size_needed);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067 if (!name_string) {
Bob Mooreb8e4d892006-01-27 16:43:00 -050068 ACPI_ERROR((AE_INFO,
Bob Mooref6a22b02010-03-05 17:56:40 +080069 "Could not allocate size %u", size_needed));
Len Brown4be44fc2005-08-05 00:44:28 -040070 return_PTR(NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 }
72
73 temp_ptr = name_string;
74
75 /* Set up Root or Parent prefixes if needed */
76
77 if (prefix_count == ACPI_UINT32_MAX) {
78 *temp_ptr++ = AML_ROOT_PREFIX;
Len Brown4be44fc2005-08-05 00:44:28 -040079 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 while (prefix_count--) {
81 *temp_ptr++ = AML_PARENT_PREFIX;
82 }
83 }
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 /* Set up Dual or Multi prefixes if needed */
86
87 if (num_name_segs > 2) {
Bob Moore52fc0b02006-10-02 00:00:00 -040088
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 /* Set up multi prefixes */
90
Bob Moore9ff5a21a2017-04-26 16:18:40 +080091 *temp_ptr++ = AML_MULTI_NAME_PREFIX;
Len Brown4be44fc2005-08-05 00:44:28 -040092 *temp_ptr++ = (char)num_name_segs;
93 } else if (2 == num_name_segs) {
Bob Moore52fc0b02006-10-02 00:00:00 -040094
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 /* Set up dual prefixes */
96
97 *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 *temp_ptr = 0;
105
Len Brown4be44fc2005-08-05 00:44:28 -0400106 return_PTR(name_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107}
108
109/*******************************************************************************
110 *
111 * FUNCTION: acpi_ex_name_segment
112 *
Robert Moore44f6c012005-04-18 22:49:35 -0400113 * 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 *
117 * RETURN: Status
118 *
Robert Moore44f6c012005-04-18 22:49:35 -0400119 * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 *
121 ******************************************************************************/
122
Len Brown4be44fc2005-08-05 00:44:28 -0400123static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124{
Len Brown4be44fc2005-08-05 00:44:28 -0400125 char *aml_address = (void *)*in_aml_address;
126 acpi_status status = AE_OK;
127 u32 index;
128 char char_buf[5];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
Bob Mooreb229cf92006-04-21 17:15:00 -0400130 ACPI_FUNCTION_TRACE(ex_name_segment);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
132 /*
Bob Moore1fad8732015-12-29 13:54:36 +0800133 * If first character is a digit, then we know that we aren't looking
134 * at a valid name segment
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135 */
136 char_buf[0] = *aml_address;
137
138 if ('0' <= char_buf[0] && char_buf[0] <= '9') {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500139 ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0]));
Len Brown4be44fc2005-08-05 00:44:28 -0400140 return_ACPI_STATUS(AE_CTRL_PENDING);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 }
142
Lv Zheng1f86e8c2012-10-31 02:25:45 +0000143 for (index = 0;
Bob Moore32786752019-04-08 13:42:25 -0700144 (index < ACPI_NAMESEG_SIZE)
Bob Moore6a0df322016-05-05 13:00:36 +0800145 && (acpi_ut_valid_name_char(*aml_address, 0)); index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 char_buf[index] = *aml_address++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 }
148
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 /* Valid name segment */
150
151 if (index == 4) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 /* Found 4 valid characters */
154
155 char_buf[4] = '\0';
156
157 if (name_string) {
Len Brown4be44fc2005-08-05 00:44:28 -0400158 ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
Bob Moore1ef63232018-02-15 13:09:28 -0800159 "Appending NameSeg %s\n", char_buf));
160 strcat(name_string, char_buf);
Len Brown4be44fc2005-08-05 00:44:28 -0400161 } else {
162 ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
Bob Moore50eca3e2005-09-30 19:03:00 -0400163 "No Name string - %s\n", char_buf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 }
Len Brown4be44fc2005-08-05 00:44:28 -0400165 } else if (index == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 /*
167 * First character was not a valid name character,
168 * so we are looking at something other than a name.
169 */
Len Brown4be44fc2005-08-05 00:44:28 -0400170 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
171 "Leading character is not alpha: %02Xh (not a name)\n",
172 char_buf[0]));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 status = AE_CTRL_PENDING;
Len Brown4be44fc2005-08-05 00:44:28 -0400174 } else {
Robert Moore44f6c012005-04-18 22:49:35 -0400175 /*
176 * Segment started with one or more valid characters, but fewer than
177 * the required 4
178 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 status = AE_AML_BAD_NAME;
Bob Mooreb8e4d892006-01-27 16:43:00 -0500180 ACPI_ERROR((AE_INFO,
Bob Mooref6a22b02010-03-05 17:56:40 +0800181 "Bad character 0x%02x in name, at %p",
Bob Mooreb8e4d892006-01-27 16:43:00 -0500182 *aml_address, aml_address));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 }
184
Bob Moorec51a4de2005-11-17 13:07:00 -0500185 *in_aml_address = ACPI_CAST_PTR(u8, aml_address);
Len Brown4be44fc2005-08-05 00:44:28 -0400186 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187}
188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189/*******************************************************************************
190 *
191 * FUNCTION: acpi_ex_get_name_string
192 *
Robert Moore44f6c012005-04-18 22:49:35 -0400193 * 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198 *
Robert Moore44f6c012005-04-18 22:49:35 -0400199 * RETURN: Status, namestring and length
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 *
Robert Moore44f6c012005-04-18 22:49:35 -0400201 * DESCRIPTION: Extract a full namepath from the AML byte stream,
202 * including any prefixes.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 *
204 ******************************************************************************/
205
206acpi_status
Len Brown4be44fc2005-08-05 00:44:28 -0400207acpi_ex_get_name_string(acpi_object_type data_type,
208 u8 * in_aml_address,
209 char **out_name_string, u32 * out_name_length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210{
Len Brown4be44fc2005-08-05 00:44:28 -0400211 acpi_status status = AE_OK;
212 u8 *aml_address = in_aml_address;
213 char *name_string = NULL;
214 u32 num_segments;
215 u32 prefix_count = 0;
216 u8 has_prefix = FALSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217
Bob Mooreb229cf92006-04-21 17:15:00 -0400218 ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219
Len Brown4be44fc2005-08-05 00:44:28 -0400220 if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
221 ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
222 ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400223
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 /* Disallow prefixes for types associated with field_unit names */
225
Len Brown4be44fc2005-08-05 00:44:28 -0400226 name_string = acpi_ex_allocate_name_string(0, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 if (!name_string) {
228 status = AE_NO_MEMORY;
Len Brown4be44fc2005-08-05 00:44:28 -0400229 } else {
230 status =
231 acpi_ex_name_segment(&aml_address, name_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 }
Len Brown4be44fc2005-08-05 00:44:28 -0400233 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 /*
235 * data_type is not a field name.
236 * Examine first character of name for root or parent prefix operators
237 */
238 switch (*aml_address) {
239 case AML_ROOT_PREFIX:
240
Len Brown4be44fc2005-08-05 00:44:28 -0400241 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
Bob Mooreb229cf92006-04-21 17:15:00 -0400242 "RootPrefix(\\) at %p\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400243 aml_address));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
245 /*
246 * Remember that we have a root_prefix --
247 * see comment in acpi_ex_allocate_name_string()
248 */
249 aml_address++;
250 prefix_count = ACPI_UINT32_MAX;
251 has_prefix = TRUE;
252 break;
253
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 case AML_PARENT_PREFIX:
255
256 /* Increment past possibly multiple parent prefixes */
257
258 do {
Len Brown4be44fc2005-08-05 00:44:28 -0400259 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
Bob Mooreb229cf92006-04-21 17:15:00 -0400260 "ParentPrefix (^) at %p\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400261 aml_address));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
263 aml_address++;
264 prefix_count++;
265
266 } while (*aml_address == AML_PARENT_PREFIX);
267
268 has_prefix = TRUE;
269 break;
270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 default:
272
273 /* Not a prefix character */
274
275 break;
276 }
277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 /* Examine first character of name for name segment prefix operator */
279
280 switch (*aml_address) {
281 case AML_DUAL_NAME_PREFIX:
282
Len Brown4be44fc2005-08-05 00:44:28 -0400283 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
Bob Mooreb229cf92006-04-21 17:15:00 -0400284 "DualNamePrefix at %p\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400285 aml_address));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
287 aml_address++;
Len Brown4be44fc2005-08-05 00:44:28 -0400288 name_string =
289 acpi_ex_allocate_name_string(prefix_count, 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 if (!name_string) {
291 status = AE_NO_MEMORY;
292 break;
293 }
294
295 /* Indicate that we processed a prefix */
296
297 has_prefix = TRUE;
298
Len Brown4be44fc2005-08-05 00:44:28 -0400299 status =
300 acpi_ex_name_segment(&aml_address, name_string);
301 if (ACPI_SUCCESS(status)) {
302 status =
303 acpi_ex_name_segment(&aml_address,
304 name_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305 }
306 break;
307
Bob Moore9ff5a21a2017-04-26 16:18:40 +0800308 case AML_MULTI_NAME_PREFIX:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309
Len Brown4be44fc2005-08-05 00:44:28 -0400310 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
Bob Mooreb229cf92006-04-21 17:15:00 -0400311 "MultiNamePrefix at %p\n",
Len Brown4be44fc2005-08-05 00:44:28 -0400312 aml_address));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314 /* Fetch count of segments remaining in name path */
315
316 aml_address++;
317 num_segments = *aml_address;
318
Len Brown4be44fc2005-08-05 00:44:28 -0400319 name_string =
320 acpi_ex_allocate_name_string(prefix_count,
321 num_segments);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 if (!name_string) {
323 status = AE_NO_MEMORY;
324 break;
325 }
326
327 /* Indicate that we processed a prefix */
328
329 aml_address++;
330 has_prefix = TRUE;
331
332 while (num_segments &&
Len Brown4be44fc2005-08-05 00:44:28 -0400333 (status =
334 acpi_ex_name_segment(&aml_address,
335 name_string)) == AE_OK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 num_segments--;
337 }
338
339 break;
340
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 case 0:
342
343 /* null_name valid as of 8-12-98 ASL/AML Grammar Update */
344
345 if (prefix_count == ACPI_UINT32_MAX) {
Len Brown4be44fc2005-08-05 00:44:28 -0400346 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
Bob Mooreb229cf92006-04-21 17:15:00 -0400347 "NameSeg is \"\\\" followed by NULL\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 }
349
350 /* Consume the NULL byte */
351
352 aml_address++;
Len Brown4be44fc2005-08-05 00:44:28 -0400353 name_string =
354 acpi_ex_allocate_name_string(prefix_count, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 if (!name_string) {
356 status = AE_NO_MEMORY;
357 break;
358 }
359
360 break;
361
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 default:
363
364 /* Name segment string */
365
Len Brown4be44fc2005-08-05 00:44:28 -0400366 name_string =
367 acpi_ex_allocate_name_string(prefix_count, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 if (!name_string) {
369 status = AE_NO_MEMORY;
370 break;
371 }
372
Len Brown4be44fc2005-08-05 00:44:28 -0400373 status =
374 acpi_ex_name_segment(&aml_address, name_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 break;
376 }
377 }
378
379 if (AE_CTRL_PENDING == status && has_prefix) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400380
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 /* Ran out of segments after processing a prefix */
382
Bob Mooreb8e4d892006-01-27 16:43:00 -0500383 ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 status = AE_AML_BAD_NAME;
385 }
386
Len Brown4be44fc2005-08-05 00:44:28 -0400387 if (ACPI_FAILURE(status)) {
Robert Moore88ac00f2005-05-26 00:00:00 -0400388 if (name_string) {
Bob Moore83135242006-10-03 00:00:00 -0400389 ACPI_FREE(name_string);
Robert Moore88ac00f2005-05-26 00:00:00 -0400390 }
Len Brown4be44fc2005-08-05 00:44:28 -0400391 return_ACPI_STATUS(status);
Robert Moore88ac00f2005-05-26 00:00:00 -0400392 }
393
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 *out_name_string = name_string;
395 *out_name_length = (u32) (aml_address - in_aml_address);
396
Len Brown4be44fc2005-08-05 00:44:28 -0400397 return_ACPI_STATUS(status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398}