Bring in acpica 20110211, still not ok anyway
[dragonfly.git] / sys / contrib / dev / acpica-unix / compiler / aslanalyze.c
1 /******************************************************************************
2  *
3  * Module Name: aslanalyze.c - Support functions for parse tree walks
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2011, 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
117 #include "aslcompiler.h"
118 #include "aslcompiler.y.h"
119 #include <string.h>
120
121
122 #define _COMPONENT          ACPI_COMPILER
123         ACPI_MODULE_NAME    ("aslanalyze")
124
125
126 /*******************************************************************************
127  *
128  * FUNCTION:    AnIsInternalMethod
129  *
130  * PARAMETERS:  Op                  - Current op
131  *
132  * RETURN:      Boolean
133  *
134  * DESCRIPTION: Check for an internal control method.
135  *
136  ******************************************************************************/
137
138 BOOLEAN
139 AnIsInternalMethod (
140     ACPI_PARSE_OBJECT       *Op)
141 {
142
143     if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) ||
144         (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI")))
145     {
146         return (TRUE);
147     }
148
149     return (FALSE);
150 }
151
152
153 /*******************************************************************************
154  *
155  * FUNCTION:    AnGetInternalMethodReturnType
156  *
157  * PARAMETERS:  Op                  - Current op
158  *
159  * RETURN:      Btype
160  *
161  * DESCRIPTION: Get the return type of an internal method
162  *
163  ******************************************************************************/
164
165 UINT32
166 AnGetInternalMethodReturnType (
167     ACPI_PARSE_OBJECT       *Op)
168 {
169
170     if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) ||
171         (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI")))
172     {
173         return (ACPI_BTYPE_STRING);
174     }
175
176     return (0);
177 }
178
179
180 /*******************************************************************************
181  *
182  * FUNCTION:    AnCheckId
183  *
184  * PARAMETERS:  Op                  - Current parse op
185  *              Type                - HID or CID
186  *
187  * RETURN:      None
188  *
189  * DESCRIPTION: Perform various checks on _HID and _CID strings. Only limited
190  *              checks can be performed on _CID strings.
191  *
192  ******************************************************************************/
193
194 void
195 AnCheckId (
196     ACPI_PARSE_OBJECT       *Op,
197     ACPI_NAME               Type)
198 {
199     UINT32                  i;
200     ACPI_SIZE               Length;
201     UINT32                  AlphaPrefixLength;
202
203
204     /* Only care about string versions of _HID/_CID (integers are legal) */
205
206     if (Op->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)
207     {
208         return;
209     }
210
211     /* For both _HID and _CID, the string must be non-null */
212
213     Length = strlen (Op->Asl.Value.String);
214     if (!Length)
215     {
216         AslError (ASL_ERROR, ASL_MSG_NULL_STRING,
217             Op, NULL);
218         return;
219     }
220
221     /*
222      * One of the things we want to catch here is the use of a leading
223      * asterisk in the string -- an odd construct that certain platform
224      * manufacturers are fond of. Technically, a leading asterisk is OK
225      * for _CID, but a valid use of this has not been seen.
226      */
227     if (*Op->Asl.Value.String == '*')
228     {
229         AslError (ASL_ERROR, ASL_MSG_LEADING_ASTERISK,
230             Op, Op->Asl.Value.String);
231         return;
232     }
233
234     /* _CID strings are bus-specific, no more checks can be performed */
235
236     if (Type == ASL_TYPE_CID)
237     {
238         return;
239     }
240
241     /* For _HID, all characters must be alphanumeric */
242
243     for (i = 0; Op->Asl.Value.String[i]; i++)
244     {
245         if (!isalnum ((int) Op->Asl.Value.String[i]))
246         {
247             AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING,
248                 Op, Op->Asl.Value.String);
249             break;
250         }
251     }
252
253     /* _HID String must be of the form "XXX####" or "ACPI####" */
254
255     if ((Length < 7) || (Length > 8))
256     {
257         AslError (ASL_ERROR, ASL_MSG_HID_LENGTH,
258             Op, Op->Asl.Value.String);
259         return;
260     }
261
262     /* _HID Length is valid, now check for uppercase (first 3 or 4 chars) */
263
264     AlphaPrefixLength = 3;
265     if (Length >= 8)
266     {
267         AlphaPrefixLength = 4;
268     }
269
270     /* Ensure the alphabetic prefix is all uppercase */
271
272     for (i = 0; (i < AlphaPrefixLength) && Op->Asl.Value.String[i]; i++)
273     {
274         if (!isupper ((int) Op->Asl.Value.String[i]))
275         {
276             AslError (ASL_ERROR, ASL_MSG_UPPER_CASE,
277                 Op, &Op->Asl.Value.String[i]);
278             break;
279         }
280     }
281 }
282
283
284 /*******************************************************************************
285  *
286  * FUNCTION:    AnLastStatementIsReturn
287  *
288  * PARAMETERS:  Op                  - A method parse node
289  *
290  * RETURN:      TRUE if last statement is an ASL RETURN. False otherwise
291  *
292  * DESCRIPTION: Walk down the list of top level statements within a method
293  *              to find the last one. Check if that last statement is in
294  *              fact a RETURN statement.
295  *
296  ******************************************************************************/
297
298 BOOLEAN
299 AnLastStatementIsReturn (
300     ACPI_PARSE_OBJECT       *Op)
301 {
302     ACPI_PARSE_OBJECT       *Next;
303
304
305     /* Check if last statement is a return */
306
307     Next = ASL_GET_CHILD_NODE (Op);
308     while (Next)
309     {
310         if ((!Next->Asl.Next) &&
311             (Next->Asl.ParseOpcode == PARSEOP_RETURN))
312         {
313             return (TRUE);
314         }
315
316         Next = ASL_GET_PEER_NODE (Next);
317     }
318
319     return (FALSE);
320 }
321
322
323 /*******************************************************************************
324  *
325  * FUNCTION:    AnCheckMethodReturnValue
326  *
327  * PARAMETERS:  Op                  - Parent
328  *              OpInfo              - Parent info
329  *              ArgOp               - Method invocation op
330  *              RequiredBtypes      - What caller requires
331  *              ThisNodeBtype       - What this node returns (if anything)
332  *
333  * RETURN:      None
334  *
335  * DESCRIPTION: Check a method invocation for 1) A return value and if it does
336  *              in fact return a value, 2) check the type of the return value.
337  *
338  ******************************************************************************/
339
340 void
341 AnCheckMethodReturnValue (
342     ACPI_PARSE_OBJECT       *Op,
343     const ACPI_OPCODE_INFO  *OpInfo,
344     ACPI_PARSE_OBJECT       *ArgOp,
345     UINT32                  RequiredBtypes,
346     UINT32                  ThisNodeBtype)
347 {
348     ACPI_PARSE_OBJECT       *OwningOp;
349     ACPI_NAMESPACE_NODE     *Node;
350
351
352     Node = ArgOp->Asl.Node;
353
354
355     /* Examine the parent op of this method */
356
357     OwningOp = Node->Op;
358     if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL)
359     {
360         /* Method NEVER returns a value */
361
362         AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName);
363     }
364     else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL)
365     {
366         /* Method SOMETIMES returns a value, SOMETIMES not */
367
368         AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, Op, Op->Asl.ExternalName);
369     }
370     else if (!(ThisNodeBtype & RequiredBtypes))
371     {
372         /* Method returns a value, but the type is wrong */
373
374         AnFormatBtype (StringBuffer, ThisNodeBtype);
375         AnFormatBtype (StringBuffer2, RequiredBtypes);
376
377         /*
378          * The case where the method does not return any value at all
379          * was already handled in the namespace cross reference
380          * -- Only issue an error if the method in fact returns a value,
381          * but it is of the wrong type
382          */
383         if (ThisNodeBtype != 0)
384         {
385             sprintf (MsgBuffer,
386                 "Method returns [%s], %s operator requires [%s]",
387                 StringBuffer, OpInfo->Name, StringBuffer2);
388
389             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
390         }
391     }
392 }
393
394
395 /*******************************************************************************
396  *
397  * FUNCTION:    AnIsResultUsed
398  *
399  * PARAMETERS:  Op                  - Parent op for the operator
400  *
401  * RETURN:      TRUE if result from this operation is actually consumed
402  *
403  * DESCRIPTION: Determine if the function result value from an operator is
404  *              used.
405  *
406  ******************************************************************************/
407
408 BOOLEAN
409 AnIsResultUsed (
410     ACPI_PARSE_OBJECT       *Op)
411 {
412     ACPI_PARSE_OBJECT       *Parent;
413
414
415     switch (Op->Asl.ParseOpcode)
416     {
417     case PARSEOP_INCREMENT:
418     case PARSEOP_DECREMENT:
419
420         /* These are standalone operators, no return value */
421
422         return (TRUE);
423
424     default:
425         break;
426     }
427
428     /* Examine parent to determine if the return value is used */
429
430     Parent = Op->Asl.Parent;
431     switch (Parent->Asl.ParseOpcode)
432     {
433     /* If/While - check if the operator is the predicate */
434
435     case PARSEOP_IF:
436     case PARSEOP_WHILE:
437
438         /* First child is the predicate */
439
440         if (Parent->Asl.Child == Op)
441         {
442             return (TRUE);
443         }
444         return (FALSE);
445
446     /* Not used if one of these is the parent */
447
448     case PARSEOP_METHOD:
449     case PARSEOP_DEFINITIONBLOCK:
450     case PARSEOP_ELSE:
451
452         return (FALSE);
453
454     default:
455         /* Any other type of parent means that the result is used */
456
457         return (TRUE);
458     }
459 }
460
461
462 /*******************************************************************************
463  *
464  * FUNCTION:    ApCheckForGpeNameConflict
465  *
466  * PARAMETERS:  Op                  - Current parse op
467  *
468  * RETURN:      None
469  *
470  * DESCRIPTION: Check for a conflict between GPE names within this scope.
471  *              Conflict means two GPE names with the same GPE number, but
472  *              different types -- such as _L1C and _E1C.
473  *
474  ******************************************************************************/
475
476 void
477 ApCheckForGpeNameConflict (
478     ACPI_PARSE_OBJECT       *Op)
479 {
480     ACPI_PARSE_OBJECT       *NextOp;
481     UINT32                  GpeNumber;
482     char                    Name[ACPI_NAME_SIZE + 1];
483     char                    Target[ACPI_NAME_SIZE];
484
485
486     /* Need a null-terminated string version of NameSeg */
487
488     ACPI_MOVE_32_TO_32 (Name, &Op->Asl.NameSeg);
489     Name[ACPI_NAME_SIZE] = 0;
490
491     /*
492      * For a GPE method:
493      * 1st char must be underscore
494      * 2nd char must be L or E
495      * 3rd/4th chars must be a hex number
496      */
497     if ((Name[0] != '_') ||
498        ((Name[1] != 'L') && (Name[1] != 'E')))
499     {
500         return;
501     }
502
503     /* Verify 3rd/4th chars are a valid hex value */
504
505     GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16);
506     if (GpeNumber == ACPI_UINT32_MAX)
507     {
508         return;
509     }
510
511     /*
512      * We are now sure we have an _Lxx or _Exx.
513      * Create the target name that would cause collision (Flip E/L)
514      */
515     ACPI_MOVE_32_TO_32 (Target, Name);
516
517     /* Inject opposite letter ("L" versus "E") */
518
519     if (Name[1] == 'L')
520     {
521         Target[1] = 'E';
522     }
523     else /* Name[1] == 'E' */
524     {
525         Target[1] = 'L';
526     }
527
528     /* Search all peers (objects within this scope) for target match */
529
530     NextOp = Op->Asl.Next;
531     while (NextOp)
532     {
533         /*
534          * We mostly care about methods, but check Name() constructs also,
535          * even though they will get another error for not being a method.
536          * All GPE names must be defined as control methods.
537          */
538         if ((NextOp->Asl.ParseOpcode == PARSEOP_METHOD) ||
539             (NextOp->Asl.ParseOpcode == PARSEOP_NAME))
540         {
541             if (ACPI_COMPARE_NAME (Target, NextOp->Asl.NameSeg))
542             {
543                 /* Found both _Exy and _Lxy in the same scope, error */
544
545                 AslError (ASL_ERROR, ASL_MSG_GPE_NAME_CONFLICT, NextOp,
546                     Name);
547                 return;
548             }
549         }
550
551         NextOp = NextOp->Asl.Next;
552     }
553
554     /* OK, no conflict found */
555
556     return;
557 }