xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/executer/exnames.c (revision 37fedaf8494b34aad811abcc49e79aa32943f880)
1 /******************************************************************************
2  *
3  * Module Name: exnames - interpreter/scanner name load/execute
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2013, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 #define __EXNAMES_C__
117 
118 #include "acpi.h"
119 #include "accommon.h"
120 #include "acinterp.h"
121 #include "amlcode.h"
122 
123 #define _COMPONENT          ACPI_EXECUTER
124         ACPI_MODULE_NAME    ("exnames")
125 
126 /* Local prototypes */
127 
128 static char *
129 AcpiExAllocateNameString (
130     UINT32                  PrefixCount,
131     UINT32                  NumNameSegs);
132 
133 static ACPI_STATUS
134 AcpiExNameSegment (
135     UINT8                   **InAmlAddress,
136     char                    *NameString);
137 
138 
139 /*******************************************************************************
140  *
141  * FUNCTION:    AcpiExAllocateNameString
142  *
143  * PARAMETERS:  PrefixCount         - Count of parent levels. Special cases:
144  *                                    (-1)==root,  0==none
145  *              NumNameSegs         - count of 4-character name segments
146  *
147  * RETURN:      A pointer to the allocated string segment. This segment must
148  *              be deleted by the caller.
149  *
150  * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
151  *              string is long enough, and set up prefix if any.
152  *
153  ******************************************************************************/
154 
155 static char *
156 AcpiExAllocateNameString (
157     UINT32                  PrefixCount,
158     UINT32                  NumNameSegs)
159 {
160     char                    *TempPtr;
161     char                    *NameString;
162     UINT32                   SizeNeeded;
163 
164     ACPI_FUNCTION_TRACE (ExAllocateNameString);
165 
166 
167     /*
168      * Allow room for all \ and ^ prefixes, all segments and a MultiNamePrefix.
169      * Also, one byte for the null terminator.
170      * This may actually be somewhat longer than needed.
171      */
172     if (PrefixCount == ACPI_UINT32_MAX)
173     {
174         /* Special case for root */
175 
176         SizeNeeded = 1 + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1;
177     }
178     else
179     {
180         SizeNeeded = PrefixCount + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1;
181     }
182 
183     /*
184      * Allocate a buffer for the name.
185      * This buffer must be deleted by the caller!
186      */
187     NameString = ACPI_ALLOCATE (SizeNeeded);
188     if (!NameString)
189     {
190         ACPI_ERROR ((AE_INFO,
191             "Could not allocate size %u", SizeNeeded));
192         return_PTR (NULL);
193     }
194 
195     TempPtr = NameString;
196 
197     /* Set up Root or Parent prefixes if needed */
198 
199     if (PrefixCount == ACPI_UINT32_MAX)
200     {
201         *TempPtr++ = AML_ROOT_PREFIX;
202     }
203     else
204     {
205         while (PrefixCount--)
206         {
207             *TempPtr++ = AML_PARENT_PREFIX;
208         }
209     }
210 
211 
212     /* Set up Dual or Multi prefixes if needed */
213 
214     if (NumNameSegs > 2)
215     {
216         /* Set up multi prefixes   */
217 
218         *TempPtr++ = AML_MULTI_NAME_PREFIX_OP;
219         *TempPtr++ = (char) NumNameSegs;
220     }
221     else if (2 == NumNameSegs)
222     {
223         /* Set up dual prefixes */
224 
225         *TempPtr++ = AML_DUAL_NAME_PREFIX;
226     }
227 
228     /*
229      * Terminate string following prefixes. AcpiExNameSegment() will
230      * append the segment(s)
231      */
232     *TempPtr = 0;
233 
234     return_PTR (NameString);
235 }
236 
237 /*******************************************************************************
238  *
239  * FUNCTION:    AcpiExNameSegment
240  *
241  * PARAMETERS:  InAmlAddress    - Pointer to the name in the AML code
242  *              NameString      - Where to return the name. The name is appended
243  *                                to any existing string to form a namepath
244  *
245  * RETURN:      Status
246  *
247  * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
248  *
249  ******************************************************************************/
250 
251 static ACPI_STATUS
252 AcpiExNameSegment (
253     UINT8                   **InAmlAddress,
254     char                    *NameString)
255 {
256     char                    *AmlAddress = (void *) *InAmlAddress;
257     ACPI_STATUS             Status = AE_OK;
258     UINT32                  Index;
259     char                    CharBuf[5];
260 
261 
262     ACPI_FUNCTION_TRACE (ExNameSegment);
263 
264 
265     /*
266      * If first character is a digit, then we know that we aren't looking at a
267      * valid name segment
268      */
269     CharBuf[0] = *AmlAddress;
270 
271     if ('0' <= CharBuf[0] && CharBuf[0] <= '9')
272     {
273         ACPI_ERROR ((AE_INFO, "Invalid leading digit: %c", CharBuf[0]));
274         return_ACPI_STATUS (AE_CTRL_PENDING);
275     }
276 
277     ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
278 
279     for (Index = 0;
280         (Index < ACPI_NAME_SIZE) && (AcpiUtValidAcpiChar (*AmlAddress, 0));
281         Index++)
282     {
283         CharBuf[Index] = *AmlAddress++;
284         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", CharBuf[Index]));
285     }
286 
287 
288     /* Valid name segment  */
289 
290     if (Index == 4)
291     {
292         /* Found 4 valid characters */
293 
294         CharBuf[4] = '\0';
295 
296         if (NameString)
297         {
298             ACPI_STRCAT (NameString, CharBuf);
299             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
300                 "Appended to - %s\n", NameString));
301         }
302         else
303         {
304             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
305                 "No Name string - %s\n", CharBuf));
306         }
307     }
308     else if (Index == 0)
309     {
310         /*
311          * First character was not a valid name character,
312          * so we are looking at something other than a name.
313          */
314         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
315             "Leading character is not alpha: %02Xh (not a name)\n",
316             CharBuf[0]));
317         Status = AE_CTRL_PENDING;
318     }
319     else
320     {
321         /*
322          * Segment started with one or more valid characters, but fewer than
323          * the required 4
324          */
325         Status = AE_AML_BAD_NAME;
326         ACPI_ERROR ((AE_INFO,
327             "Bad character 0x%02x in name, at %p",
328             *AmlAddress, AmlAddress));
329     }
330 
331     *InAmlAddress = ACPI_CAST_PTR (UINT8, AmlAddress);
332     return_ACPI_STATUS (Status);
333 }
334 
335 
336 /*******************************************************************************
337  *
338  * FUNCTION:    AcpiExGetNameString
339  *
340  * PARAMETERS:  DataType            - Object type to be associated with this
341  *                                    name
342  *              InAmlAddress        - Pointer to the namestring in the AML code
343  *              OutNameString       - Where the namestring is returned
344  *              OutNameLength       - Length of the returned string
345  *
346  * RETURN:      Status, namestring and length
347  *
348  * DESCRIPTION: Extract a full namepath from the AML byte stream,
349  *              including any prefixes.
350  *
351  ******************************************************************************/
352 
353 ACPI_STATUS
354 AcpiExGetNameString (
355     ACPI_OBJECT_TYPE        DataType,
356     UINT8                   *InAmlAddress,
357     char                    **OutNameString,
358     UINT32                  *OutNameLength)
359 {
360     ACPI_STATUS             Status = AE_OK;
361     UINT8                   *AmlAddress = InAmlAddress;
362     char                    *NameString = NULL;
363     UINT32                  NumSegments;
364     UINT32                  PrefixCount = 0;
365     BOOLEAN                 HasPrefix = FALSE;
366 
367 
368     ACPI_FUNCTION_TRACE_PTR (ExGetNameString, AmlAddress);
369 
370 
371     if (ACPI_TYPE_LOCAL_REGION_FIELD == DataType   ||
372         ACPI_TYPE_LOCAL_BANK_FIELD == DataType     ||
373         ACPI_TYPE_LOCAL_INDEX_FIELD == DataType)
374     {
375         /* Disallow prefixes for types associated with FieldUnit names */
376 
377         NameString = AcpiExAllocateNameString (0, 1);
378         if (!NameString)
379         {
380             Status = AE_NO_MEMORY;
381         }
382         else
383         {
384             Status = AcpiExNameSegment (&AmlAddress, NameString);
385         }
386     }
387     else
388     {
389         /*
390          * DataType is not a field name.
391          * Examine first character of name for root or parent prefix operators
392          */
393         switch (*AmlAddress)
394         {
395         case AML_ROOT_PREFIX:
396 
397             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "RootPrefix(\\) at %p\n",
398                 AmlAddress));
399 
400             /*
401              * Remember that we have a RootPrefix --
402              * see comment in AcpiExAllocateNameString()
403              */
404             AmlAddress++;
405             PrefixCount = ACPI_UINT32_MAX;
406             HasPrefix = TRUE;
407             break;
408 
409         case AML_PARENT_PREFIX:
410 
411             /* Increment past possibly multiple parent prefixes */
412 
413             do
414             {
415                 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n",
416                     AmlAddress));
417 
418                 AmlAddress++;
419                 PrefixCount++;
420 
421             } while (*AmlAddress == AML_PARENT_PREFIX);
422 
423             HasPrefix = TRUE;
424             break;
425 
426         default:
427 
428             /* Not a prefix character */
429 
430             break;
431         }
432 
433         /* Examine first character of name for name segment prefix operator */
434 
435         switch (*AmlAddress)
436         {
437         case AML_DUAL_NAME_PREFIX:
438 
439             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n",
440                 AmlAddress));
441 
442             AmlAddress++;
443             NameString = AcpiExAllocateNameString (PrefixCount, 2);
444             if (!NameString)
445             {
446                 Status = AE_NO_MEMORY;
447                 break;
448             }
449 
450             /* Indicate that we processed a prefix */
451 
452             HasPrefix = TRUE;
453 
454             Status = AcpiExNameSegment (&AmlAddress, NameString);
455             if (ACPI_SUCCESS (Status))
456             {
457                 Status = AcpiExNameSegment (&AmlAddress, NameString);
458             }
459             break;
460 
461         case AML_MULTI_NAME_PREFIX_OP:
462 
463             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n",
464                 AmlAddress));
465 
466             /* Fetch count of segments remaining in name path */
467 
468             AmlAddress++;
469             NumSegments = *AmlAddress;
470 
471             NameString = AcpiExAllocateNameString (PrefixCount, NumSegments);
472             if (!NameString)
473             {
474                 Status = AE_NO_MEMORY;
475                 break;
476             }
477 
478             /* Indicate that we processed a prefix */
479 
480             AmlAddress++;
481             HasPrefix = TRUE;
482 
483             while (NumSegments &&
484                     (Status = AcpiExNameSegment (&AmlAddress, NameString)) ==
485                         AE_OK)
486             {
487                 NumSegments--;
488             }
489 
490             break;
491 
492         case 0:
493 
494             /* NullName valid as of 8-12-98 ASL/AML Grammar Update */
495 
496             if (PrefixCount == ACPI_UINT32_MAX)
497             {
498                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
499                     "NameSeg is \"\\\" followed by NULL\n"));
500             }
501 
502             /* Consume the NULL byte */
503 
504             AmlAddress++;
505             NameString = AcpiExAllocateNameString (PrefixCount, 0);
506             if (!NameString)
507             {
508                 Status = AE_NO_MEMORY;
509                 break;
510             }
511 
512             break;
513 
514         default:
515 
516             /* Name segment string */
517 
518             NameString = AcpiExAllocateNameString (PrefixCount, 1);
519             if (!NameString)
520             {
521                 Status = AE_NO_MEMORY;
522                 break;
523             }
524 
525             Status = AcpiExNameSegment (&AmlAddress, NameString);
526             break;
527         }
528     }
529 
530     if (AE_CTRL_PENDING == Status && HasPrefix)
531     {
532         /* Ran out of segments after processing a prefix */
533 
534         ACPI_ERROR ((AE_INFO,
535             "Malformed Name at %p", NameString));
536         Status = AE_AML_BAD_NAME;
537     }
538 
539     if (ACPI_FAILURE (Status))
540     {
541         if (NameString)
542         {
543             ACPI_FREE (NameString);
544         }
545         return_ACPI_STATUS (Status);
546     }
547 
548     *OutNameString = NameString;
549     *OutNameLength = (UINT32) (AmlAddress - InAmlAddress);
550 
551     return_ACPI_STATUS (Status);
552 }
553