xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/executer/exnames.c (revision 90ae2e54f6ccaca73c011a2aa4cdd660417108ad)
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 - 2012, 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 
410         case AML_PARENT_PREFIX:
411 
412             /* Increment past possibly multiple parent prefixes */
413 
414             do
415             {
416                 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n",
417                     AmlAddress));
418 
419                 AmlAddress++;
420                 PrefixCount++;
421 
422             } while (*AmlAddress == AML_PARENT_PREFIX);
423 
424             HasPrefix = TRUE;
425             break;
426 
427 
428         default:
429 
430             /* Not a prefix character */
431 
432             break;
433         }
434 
435         /* Examine first character of name for name segment prefix operator */
436 
437         switch (*AmlAddress)
438         {
439         case AML_DUAL_NAME_PREFIX:
440 
441             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n",
442                 AmlAddress));
443 
444             AmlAddress++;
445             NameString = AcpiExAllocateNameString (PrefixCount, 2);
446             if (!NameString)
447             {
448                 Status = AE_NO_MEMORY;
449                 break;
450             }
451 
452             /* Indicate that we processed a prefix */
453 
454             HasPrefix = TRUE;
455 
456             Status = AcpiExNameSegment (&AmlAddress, NameString);
457             if (ACPI_SUCCESS (Status))
458             {
459                 Status = AcpiExNameSegment (&AmlAddress, NameString);
460             }
461             break;
462 
463 
464         case AML_MULTI_NAME_PREFIX_OP:
465 
466             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n",
467                 AmlAddress));
468 
469             /* Fetch count of segments remaining in name path */
470 
471             AmlAddress++;
472             NumSegments = *AmlAddress;
473 
474             NameString = AcpiExAllocateNameString (PrefixCount, NumSegments);
475             if (!NameString)
476             {
477                 Status = AE_NO_MEMORY;
478                 break;
479             }
480 
481             /* Indicate that we processed a prefix */
482 
483             AmlAddress++;
484             HasPrefix = TRUE;
485 
486             while (NumSegments &&
487                     (Status = AcpiExNameSegment (&AmlAddress, NameString)) ==
488                         AE_OK)
489             {
490                 NumSegments--;
491             }
492 
493             break;
494 
495 
496         case 0:
497 
498             /* NullName valid as of 8-12-98 ASL/AML Grammar Update */
499 
500             if (PrefixCount == ACPI_UINT32_MAX)
501             {
502                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
503                     "NameSeg is \"\\\" followed by NULL\n"));
504             }
505 
506             /* Consume the NULL byte */
507 
508             AmlAddress++;
509             NameString = AcpiExAllocateNameString (PrefixCount, 0);
510             if (!NameString)
511             {
512                 Status = AE_NO_MEMORY;
513                 break;
514             }
515 
516             break;
517 
518 
519         default:
520 
521             /* Name segment string */
522 
523             NameString = AcpiExAllocateNameString (PrefixCount, 1);
524             if (!NameString)
525             {
526                 Status = AE_NO_MEMORY;
527                 break;
528             }
529 
530             Status = AcpiExNameSegment (&AmlAddress, NameString);
531             break;
532         }
533     }
534 
535     if (AE_CTRL_PENDING == Status && HasPrefix)
536     {
537         /* Ran out of segments after processing a prefix */
538 
539         ACPI_ERROR ((AE_INFO,
540             "Malformed Name at %p", NameString));
541         Status = AE_AML_BAD_NAME;
542     }
543 
544     if (ACPI_FAILURE (Status))
545     {
546         if (NameString)
547         {
548             ACPI_FREE (NameString);
549         }
550         return_ACPI_STATUS (Status);
551     }
552 
553     *OutNameString = NameString;
554     *OutNameLength = (UINT32) (AmlAddress - InAmlAddress);
555 
556     return_ACPI_STATUS (Status);
557 }
558