Merge branches 'acpi-video' and 'acpi-x86'
[sfrench/cifs-2.6.git] / drivers / acpi / acpica / exnames.c
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 - 2019, 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 static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
40 {
41         char *temp_ptr;
42         char *name_string;
43         u32 size_needed;
44
45         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         if (prefix_count == ACPI_UINT32_MAX) {
53
54                 /* Special case for root */
55
56                 size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
57         } else {
58                 size_needed =
59                     prefix_count + (ACPI_NAME_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         name_string = ACPI_ALLOCATE(size_needed);
67         if (!name_string) {
68                 ACPI_ERROR((AE_INFO,
69                             "Could not allocate size %u", size_needed));
70                 return_PTR(NULL);
71         }
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;
79         } else {
80                 while (prefix_count--) {
81                         *temp_ptr++ = AML_PARENT_PREFIX;
82                 }
83         }
84
85         /* Set up Dual or Multi prefixes if needed */
86
87         if (num_name_segs > 2) {
88
89                 /* Set up multi prefixes   */
90
91                 *temp_ptr++ = AML_MULTI_NAME_PREFIX;
92                 *temp_ptr++ = (char)num_name_segs;
93         } else if (2 == num_name_segs) {
94
95                 /* 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
106         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 static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
124 {
125         char *aml_address = (void *)*in_aml_address;
126         acpi_status status = AE_OK;
127         u32 index;
128         char char_buf[5];
129
130         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         char_buf[0] = *aml_address;
137
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);
141         }
142
143         for (index = 0;
144              (index < ACPI_NAME_SIZE)
145              && (acpi_ut_valid_name_char(*aml_address, 0)); index++) {
146                 char_buf[index] = *aml_address++;
147         }
148
149         /* Valid name segment  */
150
151         if (index == 4) {
152
153                 /* Found 4 valid characters */
154
155                 char_buf[4] = '\0';
156
157                 if (name_string) {
158                         ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
159                                           "Appending NameSeg %s\n", char_buf));
160                         strcat(name_string, char_buf);
161                 } else {
162                         ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
163                                           "No Name string - %s\n", char_buf));
164                 }
165         } 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                 status = AE_AML_BAD_NAME;
180                 ACPI_ERROR((AE_INFO,
181                             "Bad character 0x%02x in name, at %p",
182                             *aml_address, aml_address));
183         }
184
185         *in_aml_address = ACPI_CAST_PTR(u8, aml_address);
186         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 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         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;
217
218         ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
219
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) {
223
224                 /* Disallow prefixes for types associated with field_unit names */
225
226                 name_string = acpi_ex_allocate_name_string(0, 1);
227                 if (!name_string) {
228                         status = AE_NO_MEMORY;
229                 } else {
230                         status =
231                             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                 switch (*aml_address) {
239                 case AML_ROOT_PREFIX:
240
241                         ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
242                                           "RootPrefix(\\) at %p\n",
243                                           aml_address));
244
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
254                 case AML_PARENT_PREFIX:
255
256                         /* Increment past possibly multiple parent prefixes */
257
258                         do {
259                                 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
260                                                   "ParentPrefix (^) at %p\n",
261                                                   aml_address));
262
263                                 aml_address++;
264                                 prefix_count++;
265
266                         } 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                 switch (*aml_address) {
281                 case AML_DUAL_NAME_PREFIX:
282
283                         ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
284                                           "DualNamePrefix at %p\n",
285                                           aml_address));
286
287                         aml_address++;
288                         name_string =
289                             acpi_ex_allocate_name_string(prefix_count, 2);
290                         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
299                         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);
305                         }
306                         break;
307
308                 case AML_MULTI_NAME_PREFIX:
309
310                         ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
311                                           "MultiNamePrefix at %p\n",
312                                           aml_address));
313
314                         /* Fetch count of segments remaining in name path */
315
316                         aml_address++;
317                         num_segments = *aml_address;
318
319                         name_string =
320                             acpi_ex_allocate_name_string(prefix_count,
321                                                          num_segments);
322                         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 &&
333                                (status =
334                                 acpi_ex_name_segment(&aml_address,
335                                                      name_string)) == AE_OK) {
336                                 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                         if (prefix_count == ACPI_UINT32_MAX) {
346                                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
347                                                   "NameSeg is \"\\\" followed by NULL\n"));
348                         }
349
350                         /* Consume the NULL byte */
351
352                         aml_address++;
353                         name_string =
354                             acpi_ex_allocate_name_string(prefix_count, 0);
355                         if (!name_string) {
356                                 status = AE_NO_MEMORY;
357                                 break;
358                         }
359
360                         break;
361
362                 default:
363
364                         /* Name segment string */
365
366                         name_string =
367                             acpi_ex_allocate_name_string(prefix_count, 1);
368                         if (!name_string) {
369                                 status = AE_NO_MEMORY;
370                                 break;
371                         }
372
373                         status =
374                             acpi_ex_name_segment(&aml_address, name_string);
375                         break;
376                 }
377         }
378
379         if (AE_CTRL_PENDING == status && has_prefix) {
380
381                 /* Ran out of segments after processing a prefix */
382
383                 ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
384                 status = AE_AML_BAD_NAME;
385         }
386
387         if (ACPI_FAILURE(status)) {
388                 if (name_string) {
389                         ACPI_FREE(name_string);
390                 }
391                 return_ACPI_STATUS(status);
392         }
393
394         *out_name_string = name_string;
395         *out_name_length = (u32) (aml_address - in_aml_address);
396
397         return_ACPI_STATUS(status);
398 }