xref: /titanic_50/usr/src/uts/intel/io/acpica/executer/exnames.c (revision 506ea5b80cb420d5edeb6aff19fe035c0a283bb3)
1 
2 /******************************************************************************
3  *
4  * Module Name: exnames - interpreter/scanner name load/execute
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2011, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #define __EXNAMES_C__
46 
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acinterp.h"
50 #include "amlcode.h"
51 
52 #define _COMPONENT          ACPI_EXECUTER
53         ACPI_MODULE_NAME    ("exnames")
54 
55 /* Local prototypes */
56 
57 static char *
58 AcpiExAllocateNameString (
59     UINT32                  PrefixCount,
60     UINT32                  NumNameSegs);
61 
62 static ACPI_STATUS
63 AcpiExNameSegment (
64     UINT8                   **InAmlAddress,
65     char                    *NameString);
66 
67 
68 /*******************************************************************************
69  *
70  * FUNCTION:    AcpiExAllocateNameString
71  *
72  * PARAMETERS:  PrefixCount         - Count of parent levels. Special cases:
73  *                                    (-1)==root,  0==none
74  *              NumNameSegs         - count of 4-character name segments
75  *
76  * RETURN:      A pointer to the allocated string segment.  This segment must
77  *              be deleted by the caller.
78  *
79  * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
80  *              string is long enough, and set up prefix if any.
81  *
82  ******************************************************************************/
83 
84 static char *
85 AcpiExAllocateNameString (
86     UINT32                  PrefixCount,
87     UINT32                  NumNameSegs)
88 {
89     char                    *TempPtr;
90     char                    *NameString;
91     UINT32                   SizeNeeded;
92 
93     ACPI_FUNCTION_TRACE (ExAllocateNameString);
94 
95 
96     /*
97      * Allow room for all \ and ^ prefixes, all segments and a MultiNamePrefix.
98      * Also, one byte for the null terminator.
99      * This may actually be somewhat longer than needed.
100      */
101     if (PrefixCount == ACPI_UINT32_MAX)
102     {
103         /* Special case for root */
104 
105         SizeNeeded = 1 + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1;
106     }
107     else
108     {
109         SizeNeeded = PrefixCount + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1;
110     }
111 
112     /*
113      * Allocate a buffer for the name.
114      * This buffer must be deleted by the caller!
115      */
116     NameString = ACPI_ALLOCATE (SizeNeeded);
117     if (!NameString)
118     {
119         ACPI_ERROR ((AE_INFO,
120             "Could not allocate size %u", SizeNeeded));
121         return_PTR (NULL);
122     }
123 
124     TempPtr = NameString;
125 
126     /* Set up Root or Parent prefixes if needed */
127 
128     if (PrefixCount == ACPI_UINT32_MAX)
129     {
130         *TempPtr++ = AML_ROOT_PREFIX;
131     }
132     else
133     {
134         while (PrefixCount--)
135         {
136             *TempPtr++ = AML_PARENT_PREFIX;
137         }
138     }
139 
140 
141     /* Set up Dual or Multi prefixes if needed */
142 
143     if (NumNameSegs > 2)
144     {
145         /* Set up multi prefixes   */
146 
147         *TempPtr++ = AML_MULTI_NAME_PREFIX_OP;
148         *TempPtr++ = (char) NumNameSegs;
149     }
150     else if (2 == NumNameSegs)
151     {
152         /* Set up dual prefixes */
153 
154         *TempPtr++ = AML_DUAL_NAME_PREFIX;
155     }
156 
157     /*
158      * Terminate string following prefixes. AcpiExNameSegment() will
159      * append the segment(s)
160      */
161     *TempPtr = 0;
162 
163     return_PTR (NameString);
164 }
165 
166 /*******************************************************************************
167  *
168  * FUNCTION:    AcpiExNameSegment
169  *
170  * PARAMETERS:  InAmlAddress    - Pointer to the name in the AML code
171  *              NameString      - Where to return the name. The name is appended
172  *                                to any existing string to form a namepath
173  *
174  * RETURN:      Status
175  *
176  * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
177  *
178  ******************************************************************************/
179 
180 static ACPI_STATUS
181 AcpiExNameSegment (
182     UINT8                   **InAmlAddress,
183     char                    *NameString)
184 {
185     char                    *AmlAddress = (void *) *InAmlAddress;
186     ACPI_STATUS             Status = AE_OK;
187     UINT32                  Index;
188     char                    CharBuf[5];
189 
190 
191     ACPI_FUNCTION_TRACE (ExNameSegment);
192 
193 
194     /*
195      * If first character is a digit, then we know that we aren't looking at a
196      * valid name segment
197      */
198     CharBuf[0] = *AmlAddress;
199 
200     if ('0' <= CharBuf[0] && CharBuf[0] <= '9')
201     {
202         ACPI_ERROR ((AE_INFO, "Invalid leading digit: %c", CharBuf[0]));
203         return_ACPI_STATUS (AE_CTRL_PENDING);
204     }
205 
206     ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
207 
208     for (Index = 0;
209         (Index < ACPI_NAME_SIZE) && (AcpiUtValidAcpiChar (*AmlAddress, 0));
210         Index++)
211     {
212         CharBuf[Index] = *AmlAddress++;
213         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", CharBuf[Index]));
214     }
215 
216 
217     /* Valid name segment  */
218 
219     if (Index == 4)
220     {
221         /* Found 4 valid characters */
222 
223         CharBuf[4] = '\0';
224 
225         if (NameString)
226         {
227             ACPI_STRCAT (NameString, CharBuf);
228             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
229                 "Appended to - %s\n", NameString));
230         }
231         else
232         {
233             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
234                 "No Name string - %s\n", CharBuf));
235         }
236     }
237     else if (Index == 0)
238     {
239         /*
240          * First character was not a valid name character,
241          * so we are looking at something other than a name.
242          */
243         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
244             "Leading character is not alpha: %02Xh (not a name)\n",
245             CharBuf[0]));
246         Status = AE_CTRL_PENDING;
247     }
248     else
249     {
250         /*
251          * Segment started with one or more valid characters, but fewer than
252          * the required 4
253          */
254         Status = AE_AML_BAD_NAME;
255         ACPI_ERROR ((AE_INFO,
256             "Bad character 0x%02x in name, at %p",
257             *AmlAddress, AmlAddress));
258     }
259 
260     *InAmlAddress = ACPI_CAST_PTR (UINT8, AmlAddress);
261     return_ACPI_STATUS (Status);
262 }
263 
264 
265 /*******************************************************************************
266  *
267  * FUNCTION:    AcpiExGetNameString
268  *
269  * PARAMETERS:  DataType            - Object type to be associated with this
270  *                                    name
271  *              InAmlAddress        - Pointer to the namestring in the AML code
272  *              OutNameString       - Where the namestring is returned
273  *              OutNameLength       - Length of the returned string
274  *
275  * RETURN:      Status, namestring and length
276  *
277  * DESCRIPTION: Extract a full namepath from the AML byte stream,
278  *              including any prefixes.
279  *
280  ******************************************************************************/
281 
282 ACPI_STATUS
283 AcpiExGetNameString (
284     ACPI_OBJECT_TYPE        DataType,
285     UINT8                   *InAmlAddress,
286     char                    **OutNameString,
287     UINT32                  *OutNameLength)
288 {
289     ACPI_STATUS             Status = AE_OK;
290     UINT8                   *AmlAddress = InAmlAddress;
291     char                    *NameString = NULL;
292     UINT32                  NumSegments;
293     UINT32                  PrefixCount = 0;
294     BOOLEAN                 HasPrefix = FALSE;
295 
296 
297     ACPI_FUNCTION_TRACE_PTR (ExGetNameString, AmlAddress);
298 
299 
300     if (ACPI_TYPE_LOCAL_REGION_FIELD == DataType   ||
301         ACPI_TYPE_LOCAL_BANK_FIELD == DataType     ||
302         ACPI_TYPE_LOCAL_INDEX_FIELD == DataType)
303     {
304         /* Disallow prefixes for types associated with FieldUnit names */
305 
306         NameString = AcpiExAllocateNameString (0, 1);
307         if (!NameString)
308         {
309             Status = AE_NO_MEMORY;
310         }
311         else
312         {
313             Status = AcpiExNameSegment (&AmlAddress, NameString);
314         }
315     }
316     else
317     {
318         /*
319          * DataType is not a field name.
320          * Examine first character of name for root or parent prefix operators
321          */
322         switch (*AmlAddress)
323         {
324         case AML_ROOT_PREFIX:
325 
326             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "RootPrefix(\\) at %p\n",
327                 AmlAddress));
328 
329             /*
330              * Remember that we have a RootPrefix --
331              * see comment in AcpiExAllocateNameString()
332              */
333             AmlAddress++;
334             PrefixCount = ACPI_UINT32_MAX;
335             HasPrefix = TRUE;
336             break;
337 
338 
339         case AML_PARENT_PREFIX:
340 
341             /* Increment past possibly multiple parent prefixes */
342 
343             do
344             {
345                 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n",
346                     AmlAddress));
347 
348                 AmlAddress++;
349                 PrefixCount++;
350 
351             } while (*AmlAddress == AML_PARENT_PREFIX);
352 
353             HasPrefix = TRUE;
354             break;
355 
356 
357         default:
358 
359             /* Not a prefix character */
360 
361             break;
362         }
363 
364         /* Examine first character of name for name segment prefix operator */
365 
366         switch (*AmlAddress)
367         {
368         case AML_DUAL_NAME_PREFIX:
369 
370             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n",
371                 AmlAddress));
372 
373             AmlAddress++;
374             NameString = AcpiExAllocateNameString (PrefixCount, 2);
375             if (!NameString)
376             {
377                 Status = AE_NO_MEMORY;
378                 break;
379             }
380 
381             /* Indicate that we processed a prefix */
382 
383             HasPrefix = TRUE;
384 
385             Status = AcpiExNameSegment (&AmlAddress, NameString);
386             if (ACPI_SUCCESS (Status))
387             {
388                 Status = AcpiExNameSegment (&AmlAddress, NameString);
389             }
390             break;
391 
392 
393         case AML_MULTI_NAME_PREFIX_OP:
394 
395             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n",
396                 AmlAddress));
397 
398             /* Fetch count of segments remaining in name path */
399 
400             AmlAddress++;
401             NumSegments = *AmlAddress;
402 
403             NameString = AcpiExAllocateNameString (PrefixCount, NumSegments);
404             if (!NameString)
405             {
406                 Status = AE_NO_MEMORY;
407                 break;
408             }
409 
410             /* Indicate that we processed a prefix */
411 
412             AmlAddress++;
413             HasPrefix = TRUE;
414 
415             while (NumSegments &&
416                     (Status = AcpiExNameSegment (&AmlAddress, NameString)) ==
417                         AE_OK)
418             {
419                 NumSegments--;
420             }
421 
422             break;
423 
424 
425         case 0:
426 
427             /* NullName valid as of 8-12-98 ASL/AML Grammar Update */
428 
429             if (PrefixCount == ACPI_UINT32_MAX)
430             {
431                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
432                     "NameSeg is \"\\\" followed by NULL\n"));
433             }
434 
435             /* Consume the NULL byte */
436 
437             AmlAddress++;
438             NameString = AcpiExAllocateNameString (PrefixCount, 0);
439             if (!NameString)
440             {
441                 Status = AE_NO_MEMORY;
442                 break;
443             }
444 
445             break;
446 
447 
448         default:
449 
450             /* Name segment string */
451 
452             NameString = AcpiExAllocateNameString (PrefixCount, 1);
453             if (!NameString)
454             {
455                 Status = AE_NO_MEMORY;
456                 break;
457             }
458 
459             Status = AcpiExNameSegment (&AmlAddress, NameString);
460             break;
461         }
462     }
463 
464     if (AE_CTRL_PENDING == Status && HasPrefix)
465     {
466         /* Ran out of segments after processing a prefix */
467 
468         ACPI_ERROR ((AE_INFO,
469             "Malformed Name at %p", NameString));
470         Status = AE_AML_BAD_NAME;
471     }
472 
473     if (ACPI_FAILURE (Status))
474     {
475         if (NameString)
476         {
477             ACPI_FREE (NameString);
478         }
479         return_ACPI_STATUS (Status);
480     }
481 
482     *OutNameString = NameString;
483     *OutNameLength = (UINT32) (AmlAddress - InAmlAddress);
484 
485     return_ACPI_STATUS (Status);
486 }
487 
488 
489