1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: exnames - interpreter/scanner name load/execute
6 * Copyright (C) 2000 - 2018, Intel Corp.
8 *****************************************************************************/
10 #include <acpi/acpi.h>
15 #define _COMPONENT ACPI_EXECUTER
16 ACPI_MODULE_NAME("exnames")
18 /* Local prototypes */
19 static char *acpi_ex_allocate_name_string(u32 prefix_count
, u32 num_name_segs
);
21 static acpi_status
acpi_ex_name_segment(u8
**in_aml_address
, char *name_string
);
23 /*******************************************************************************
25 * FUNCTION: acpi_ex_allocate_name_string
27 * PARAMETERS: prefix_count - Count of parent levels. Special cases:
29 * num_name_segs - count of 4-character name segments
31 * RETURN: A pointer to the allocated string segment. This segment must
32 * be deleted by the caller.
34 * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
35 * string is long enough, and set up prefix if any.
37 ******************************************************************************/
39 static char *acpi_ex_allocate_name_string(u32 prefix_count
, u32 num_name_segs
)
45 ACPI_FUNCTION_TRACE(ex_allocate_name_string
);
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.
52 if (prefix_count
== ACPI_UINT32_MAX
) {
54 /* Special case for root */
56 size_needed
= 1 + (ACPI_NAME_SIZE
* num_name_segs
) + 2 + 1;
59 prefix_count
+ (ACPI_NAME_SIZE
* num_name_segs
) + 2 + 1;
63 * Allocate a buffer for the name.
64 * This buffer must be deleted by the caller!
66 name_string
= ACPI_ALLOCATE(size_needed
);
69 "Could not allocate size %u", size_needed
));
73 temp_ptr
= name_string
;
75 /* Set up Root or Parent prefixes if needed */
77 if (prefix_count
== ACPI_UINT32_MAX
) {
78 *temp_ptr
++ = AML_ROOT_PREFIX
;
80 while (prefix_count
--) {
81 *temp_ptr
++ = AML_PARENT_PREFIX
;
85 /* Set up Dual or Multi prefixes if needed */
87 if (num_name_segs
> 2) {
89 /* Set up multi prefixes */
91 *temp_ptr
++ = AML_MULTI_NAME_PREFIX
;
92 *temp_ptr
++ = (char)num_name_segs
;
93 } else if (2 == num_name_segs
) {
95 /* Set up dual prefixes */
97 *temp_ptr
++ = AML_DUAL_NAME_PREFIX
;
101 * Terminate string following prefixes. acpi_ex_name_segment() will
102 * append the segment(s)
106 return_PTR(name_string
);
109 /*******************************************************************************
111 * FUNCTION: acpi_ex_name_segment
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
119 * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
121 ******************************************************************************/
123 static acpi_status
acpi_ex_name_segment(u8
** in_aml_address
, char *name_string
)
125 char *aml_address
= (void *)*in_aml_address
;
126 acpi_status status
= AE_OK
;
130 ACPI_FUNCTION_TRACE(ex_name_segment
);
133 * If first character is a digit, then we know that we aren't looking
134 * at a valid name segment
136 char_buf
[0] = *aml_address
;
138 if ('0' <= char_buf
[0] && char_buf
[0] <= '9') {
139 ACPI_ERROR((AE_INFO
, "Invalid leading digit: %c", char_buf
[0]));
140 return_ACPI_STATUS(AE_CTRL_PENDING
);
144 (index
< ACPI_NAME_SIZE
)
145 && (acpi_ut_valid_name_char(*aml_address
, 0)); index
++) {
146 char_buf
[index
] = *aml_address
++;
149 /* Valid name segment */
153 /* Found 4 valid characters */
158 ACPI_DEBUG_PRINT((ACPI_DB_NAMES
,
159 "Appending NameSeg %s\n", char_buf
));
160 strcat(name_string
, char_buf
);
162 ACPI_DEBUG_PRINT((ACPI_DB_NAMES
,
163 "No Name string - %s\n", char_buf
));
165 } else if (index
== 0) {
167 * First character was not a valid name character,
168 * so we are looking at something other than a name.
170 ACPI_DEBUG_PRINT((ACPI_DB_INFO
,
171 "Leading character is not alpha: %02Xh (not a name)\n",
173 status
= AE_CTRL_PENDING
;
176 * Segment started with one or more valid characters, but fewer than
179 status
= AE_AML_BAD_NAME
;
181 "Bad character 0x%02x in name, at %p",
182 *aml_address
, aml_address
));
185 *in_aml_address
= ACPI_CAST_PTR(u8
, aml_address
);
186 return_ACPI_STATUS(status
);
189 /*******************************************************************************
191 * FUNCTION: acpi_ex_get_name_string
193 * PARAMETERS: data_type - Object type to be associated with this
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
199 * RETURN: Status, namestring and length
201 * DESCRIPTION: Extract a full namepath from the AML byte stream,
202 * including any prefixes.
204 ******************************************************************************/
207 acpi_ex_get_name_string(acpi_object_type data_type
,
209 char **out_name_string
, u32
* out_name_length
)
211 acpi_status status
= AE_OK
;
212 u8
*aml_address
= in_aml_address
;
213 char *name_string
= NULL
;
215 u32 prefix_count
= 0;
216 u8 has_prefix
= FALSE
;
218 ACPI_FUNCTION_TRACE_PTR(ex_get_name_string
, aml_address
);
220 if (ACPI_TYPE_LOCAL_REGION_FIELD
== data_type
||
221 ACPI_TYPE_LOCAL_BANK_FIELD
== data_type
||
222 ACPI_TYPE_LOCAL_INDEX_FIELD
== data_type
) {
224 /* Disallow prefixes for types associated with field_unit names */
226 name_string
= acpi_ex_allocate_name_string(0, 1);
228 status
= AE_NO_MEMORY
;
231 acpi_ex_name_segment(&aml_address
, name_string
);
235 * data_type is not a field name.
236 * Examine first character of name for root or parent prefix operators
238 switch (*aml_address
) {
239 case AML_ROOT_PREFIX
:
241 ACPI_DEBUG_PRINT((ACPI_DB_LOAD
,
242 "RootPrefix(\\) at %p\n",
246 * Remember that we have a root_prefix --
247 * see comment in acpi_ex_allocate_name_string()
250 prefix_count
= ACPI_UINT32_MAX
;
254 case AML_PARENT_PREFIX
:
256 /* Increment past possibly multiple parent prefixes */
259 ACPI_DEBUG_PRINT((ACPI_DB_LOAD
,
260 "ParentPrefix (^) at %p\n",
266 } while (*aml_address
== AML_PARENT_PREFIX
);
273 /* Not a prefix character */
278 /* Examine first character of name for name segment prefix operator */
280 switch (*aml_address
) {
281 case AML_DUAL_NAME_PREFIX
:
283 ACPI_DEBUG_PRINT((ACPI_DB_LOAD
,
284 "DualNamePrefix at %p\n",
289 acpi_ex_allocate_name_string(prefix_count
, 2);
291 status
= AE_NO_MEMORY
;
295 /* Indicate that we processed a prefix */
300 acpi_ex_name_segment(&aml_address
, name_string
);
301 if (ACPI_SUCCESS(status
)) {
303 acpi_ex_name_segment(&aml_address
,
308 case AML_MULTI_NAME_PREFIX
:
310 ACPI_DEBUG_PRINT((ACPI_DB_LOAD
,
311 "MultiNamePrefix at %p\n",
314 /* Fetch count of segments remaining in name path */
317 num_segments
= *aml_address
;
320 acpi_ex_allocate_name_string(prefix_count
,
323 status
= AE_NO_MEMORY
;
327 /* Indicate that we processed a prefix */
332 while (num_segments
&&
334 acpi_ex_name_segment(&aml_address
,
335 name_string
)) == AE_OK
) {
343 /* null_name valid as of 8-12-98 ASL/AML Grammar Update */
345 if (prefix_count
== ACPI_UINT32_MAX
) {
346 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
,
347 "NameSeg is \"\\\" followed by NULL\n"));
350 /* Consume the NULL byte */
354 acpi_ex_allocate_name_string(prefix_count
, 0);
356 status
= AE_NO_MEMORY
;
364 /* Name segment string */
367 acpi_ex_allocate_name_string(prefix_count
, 1);
369 status
= AE_NO_MEMORY
;
374 acpi_ex_name_segment(&aml_address
, name_string
);
379 if (AE_CTRL_PENDING
== status
&& has_prefix
) {
381 /* Ran out of segments after processing a prefix */
383 ACPI_ERROR((AE_INFO
, "Malformed Name at %p", name_string
));
384 status
= AE_AML_BAD_NAME
;
387 if (ACPI_FAILURE(status
)) {
389 ACPI_FREE(name_string
);
391 return_ACPI_STATUS(status
);
394 *out_name_string
= name_string
;
395 *out_name_length
= (u32
) (aml_address
- in_aml_address
);
397 return_ACPI_STATUS(status
);