kernel: Sync ACPICA with Intel's version 20140114.
[dragonfly.git] / sys / contrib / dev / acpica / source / compiler / aslwalks.c
1 /******************************************************************************
2  *
3  * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44
45 #include "aslcompiler.h"
46 #include "aslcompiler.y.h"
47 #include "acparser.h"
48 #include "amlcode.h"
49
50
51 #define _COMPONENT          ACPI_COMPILER
52         ACPI_MODULE_NAME    ("aslwalks")
53
54
55 /*******************************************************************************
56  *
57  * FUNCTION:    AnMethodTypingWalkEnd
58  *
59  * PARAMETERS:  ASL_WALK_CALLBACK
60  *
61  * RETURN:      Status
62  *
63  * DESCRIPTION: Ascending callback for typing walk. Complete the method
64  *              return analysis. Check methods for:
65  *              1) Initialized local variables
66  *              2) Valid arguments
67  *              3) Return types
68  *
69  ******************************************************************************/
70
71 ACPI_STATUS
72 AnMethodTypingWalkEnd (
73     ACPI_PARSE_OBJECT       *Op,
74     UINT32                  Level,
75     void                    *Context)
76 {
77     UINT32                  ThisNodeBtype;
78
79
80     switch (Op->Asl.ParseOpcode)
81     {
82     case PARSEOP_METHOD:
83
84         Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
85         break;
86
87     case PARSEOP_RETURN:
88
89         if ((Op->Asl.Child) &&
90             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
91         {
92             ThisNodeBtype = AnGetBtype (Op->Asl.Child);
93
94             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
95                 (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
96             {
97                 /*
98                  * The called method is untyped at this time (typically a
99                  * forward reference).
100                  *
101                  * Check for a recursive method call first.
102                  */
103                 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
104                 {
105                     /* We must type the method here */
106
107                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
108                         ASL_WALK_VISIT_UPWARD, NULL,
109                         AnMethodTypingWalkEnd, NULL);
110
111                     ThisNodeBtype = AnGetBtype (Op->Asl.Child);
112                 }
113             }
114
115             /* Returns a value, save the value type */
116
117             if (Op->Asl.ParentMethod)
118             {
119                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
120             }
121         }
122         break;
123
124     default:
125
126         break;
127     }
128
129     return (AE_OK);
130 }
131
132
133 /*******************************************************************************
134  *
135  * FUNCTION:    AnOperandTypecheckWalkEnd
136  *
137  * PARAMETERS:  ASL_WALK_CALLBACK
138  *
139  * RETURN:      Status
140  *
141  * DESCRIPTION: Ascending callback for analysis walk. Complete method
142  *              return analysis.
143  *
144  ******************************************************************************/
145
146 ACPI_STATUS
147 AnOperandTypecheckWalkEnd (
148     ACPI_PARSE_OBJECT       *Op,
149     UINT32                  Level,
150     void                    *Context)
151 {
152     const ACPI_OPCODE_INFO  *OpInfo;
153     UINT32                  RuntimeArgTypes;
154     UINT32                  RuntimeArgTypes2;
155     UINT32                  RequiredBtypes;
156     UINT32                  ThisNodeBtype;
157     UINT32                  CommonBtypes;
158     UINT32                  OpcodeClass;
159     ACPI_PARSE_OBJECT       *ArgOp;
160     UINT32                  ArgType;
161
162
163     switch (Op->Asl.AmlOpcode)
164     {
165     case AML_RAW_DATA_BYTE:
166     case AML_RAW_DATA_WORD:
167     case AML_RAW_DATA_DWORD:
168     case AML_RAW_DATA_QWORD:
169     case AML_RAW_DATA_BUFFER:
170     case AML_RAW_DATA_CHAIN:
171     case AML_PACKAGE_LENGTH:
172     case AML_UNASSIGNED_OPCODE:
173     case AML_DEFAULT_ARG_OP:
174
175         /* Ignore the internal (compiler-only) AML opcodes */
176
177         return (AE_OK);
178
179     default:
180
181         break;
182     }
183
184     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
185     if (!OpInfo)
186     {
187         return (AE_OK);
188     }
189
190     ArgOp           = Op->Asl.Child;
191     RuntimeArgTypes = OpInfo->RuntimeArgs;
192     OpcodeClass     = OpInfo->Class;
193
194 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
195     /*
196      * Update 11/2008: In practice, we can't perform this check. A simple
197      * analysis is not sufficient. Also, it can cause errors when compiling
198      * disassembled code because of the way Switch operators are implemented
199      * (a While(One) loop with a named temp variable created within.)
200      */
201
202     /*
203      * If we are creating a named object, check if we are within a while loop
204      * by checking if the parent is a WHILE op. This is a simple analysis, but
205      * probably sufficient for many cases.
206      *
207      * Allow Scope(), Buffer(), and Package().
208      */
209     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
210         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
211     {
212         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
213         {
214             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
215         }
216     }
217 #endif
218
219     /*
220      * Special case for control opcodes IF/RETURN/WHILE since they
221      * have no runtime arg list (at this time)
222      */
223     switch (Op->Asl.AmlOpcode)
224     {
225     case AML_IF_OP:
226     case AML_WHILE_OP:
227     case AML_RETURN_OP:
228
229         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
230         {
231             /* Check for an internal method */
232
233             if (AnIsInternalMethod (ArgOp))
234             {
235                 return (AE_OK);
236             }
237
238             /* The lone arg is a method call, check it */
239
240             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
241             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
242             {
243                 RequiredBtypes = 0xFFFFFFFF;
244             }
245
246             ThisNodeBtype = AnGetBtype (ArgOp);
247             if (ThisNodeBtype == ACPI_UINT32_MAX)
248             {
249                 return (AE_OK);
250             }
251             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
252                 RequiredBtypes, ThisNodeBtype);
253         }
254         return (AE_OK);
255
256     default:
257
258         break;
259     }
260
261     /* Ignore the non-executable opcodes */
262
263     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
264     {
265         return (AE_OK);
266     }
267
268     switch (OpcodeClass)
269     {
270     case AML_CLASS_EXECUTE:
271     case AML_CLASS_CREATE:
272     case AML_CLASS_CONTROL:
273     case AML_CLASS_RETURN_VALUE:
274
275         /* TBD: Change class or fix typechecking for these */
276
277         if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
278             (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
279             (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
280         {
281             break;
282         }
283
284         /* Reverse the runtime argument list */
285
286         RuntimeArgTypes2 = 0;
287         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
288         {
289             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
290             RuntimeArgTypes2 |= ArgType;
291             INCREMENT_ARG_LIST (RuntimeArgTypes);
292         }
293
294         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
295         {
296             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
297
298             ThisNodeBtype = AnGetBtype (ArgOp);
299             if (ThisNodeBtype == ACPI_UINT32_MAX)
300             {
301                 goto NextArgument;
302             }
303
304             /* Examine the arg based on the required type of the arg */
305
306             switch (ArgType)
307             {
308             case ARGI_TARGETREF:
309
310                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
311                 {
312                     /* ZERO is the placeholder for "don't store result" */
313
314                     ThisNodeBtype = RequiredBtypes;
315                     break;
316                 }
317
318                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
319                 {
320                     /*
321                      * This is the case where an original reference to a resource
322                      * descriptor field has been replaced by an (Integer) offset.
323                      * These named fields are supported at compile-time only;
324                      * the names are not passed to the interpreter (via the AML).
325                      */
326                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
327                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
328                     {
329                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
330                     }
331                     else
332                     {
333                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
334                     }
335                     break;
336                 }
337
338                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
339                     (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
340                 {
341                     break;
342                 }
343
344                 ThisNodeBtype = RequiredBtypes;
345                 break;
346
347
348             case ARGI_REFERENCE:            /* References */
349             case ARGI_INTEGER_REF:
350             case ARGI_OBJECT_REF:
351             case ARGI_DEVICE_REF:
352
353                 switch (ArgOp->Asl.ParseOpcode)
354                 {
355                 case PARSEOP_LOCAL0:
356                 case PARSEOP_LOCAL1:
357                 case PARSEOP_LOCAL2:
358                 case PARSEOP_LOCAL3:
359                 case PARSEOP_LOCAL4:
360                 case PARSEOP_LOCAL5:
361                 case PARSEOP_LOCAL6:
362                 case PARSEOP_LOCAL7:
363
364                     /* TBD: implement analysis of current value (type) of the local */
365                     /* For now, just treat any local as a typematch */
366
367                     /*ThisNodeBtype = RequiredBtypes;*/
368                     break;
369
370                 case PARSEOP_ARG0:
371                 case PARSEOP_ARG1:
372                 case PARSEOP_ARG2:
373                 case PARSEOP_ARG3:
374                 case PARSEOP_ARG4:
375                 case PARSEOP_ARG5:
376                 case PARSEOP_ARG6:
377
378                     /* Hard to analyze argument types, sow we won't */
379                     /* For now, just treat any arg as a typematch */
380
381                     /* ThisNodeBtype = RequiredBtypes; */
382                     break;
383
384                 case PARSEOP_DEBUG:
385
386                     break;
387
388                 case PARSEOP_REFOF:
389                 case PARSEOP_INDEX:
390                 default:
391
392                     break;
393
394                 }
395                 break;
396
397             case ARGI_INTEGER:
398             default:
399
400                 break;
401             }
402
403
404             CommonBtypes = ThisNodeBtype & RequiredBtypes;
405
406             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
407             {
408                 if (AnIsInternalMethod (ArgOp))
409                 {
410                     return (AE_OK);
411                 }
412
413                 /* Check a method call for a valid return value */
414
415                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
416                     RequiredBtypes, ThisNodeBtype);
417             }
418
419             /*
420              * Now check if the actual type(s) match at least one
421              * bit to the required type
422              */
423             else if (!CommonBtypes)
424             {
425                 /* No match -- this is a type mismatch error */
426
427                 AnFormatBtype (StringBuffer, ThisNodeBtype);
428                 AnFormatBtype (StringBuffer2, RequiredBtypes);
429
430                 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
431                             StringBuffer, OpInfo->Name, StringBuffer2);
432
433                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
434             }
435
436         NextArgument:
437             ArgOp = ArgOp->Asl.Next;
438             INCREMENT_ARG_LIST (RuntimeArgTypes2);
439         }
440         break;
441
442     default:
443
444         break;
445     }
446
447     return (AE_OK);
448 }
449
450
451 /*******************************************************************************
452  *
453  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
454  *
455  * PARAMETERS:  ASL_WALK_CALLBACK
456  *
457  * RETURN:      Status
458  *
459  * DESCRIPTION: Descending callback for the analysis walk. Checks for
460  *              miscellaneous issues in the code.
461  *
462  ******************************************************************************/
463
464 ACPI_STATUS
465 AnOtherSemanticAnalysisWalkBegin (
466     ACPI_PARSE_OBJECT       *Op,
467     UINT32                  Level,
468     void                    *Context)
469 {
470     ACPI_PARSE_OBJECT       *ArgNode;
471     ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
472     const ACPI_OPCODE_INFO  *OpInfo;
473     ACPI_NAMESPACE_NODE     *Node;
474
475
476     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
477
478     /*
479      * Determine if an execution class operator actually does something by
480      * checking if it has a target and/or the function return value is used.
481      * (Target is optional, so a standalone statement can actually do nothing.)
482      */
483     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
484         (OpInfo->Flags & AML_HAS_RETVAL) &&
485         (!AnIsResultUsed (Op)))
486     {
487         if (OpInfo->Flags & AML_HAS_TARGET)
488         {
489             /*
490              * Find the target node, it is always the last child. If the traget
491              * is not specified in the ASL, a default node of type Zero was
492              * created by the parser.
493              */
494             ArgNode = Op->Asl.Child;
495             while (ArgNode->Asl.Next)
496             {
497                 PrevArgNode = ArgNode;
498                 ArgNode = ArgNode->Asl.Next;
499             }
500
501             /* Divide() is the only weird case, it has two targets */
502
503             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
504             {
505                 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
506                     (PrevArgNode) &&
507                     (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
508                 {
509                     AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
510                         Op, Op->Asl.ExternalName);
511                 }
512             }
513             else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
514             {
515                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
516                     Op, Op->Asl.ExternalName);
517             }
518         }
519         else
520         {
521             /*
522              * Has no target and the result is not used. Only a couple opcodes
523              * can have this combination.
524              */
525             switch (Op->Asl.ParseOpcode)
526             {
527             case PARSEOP_ACQUIRE:
528             case PARSEOP_WAIT:
529             case PARSEOP_LOADTABLE:
530
531                 break;
532
533             default:
534
535                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
536                     Op, Op->Asl.ExternalName);
537                 break;
538             }
539         }
540     }
541
542
543     /*
544      * Semantic checks for individual ASL operators
545      */
546     switch (Op->Asl.ParseOpcode)
547     {
548     case PARSEOP_ACQUIRE:
549     case PARSEOP_WAIT:
550         /*
551          * Emit a warning if the timeout parameter for these operators is not
552          * ACPI_WAIT_FOREVER, and the result value from the operator is not
553          * checked, meaning that a timeout could happen, but the code
554          * would not know about it.
555          */
556
557         /* First child is the namepath, 2nd child is timeout */
558
559         ArgNode = Op->Asl.Child;
560         ArgNode = ArgNode->Asl.Next;
561
562         /*
563          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
564          * 0xFFFF or greater
565          */
566         if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
567              (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
568              (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
569         {
570             break;
571         }
572
573         /*
574          * The operation could timeout. If the return value is not used
575          * (indicates timeout occurred), issue a warning
576          */
577         if (!AnIsResultUsed (Op))
578         {
579             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
580                 Op->Asl.ExternalName);
581         }
582         break;
583
584     case PARSEOP_CREATEFIELD:
585         /*
586          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
587          */
588         ArgNode = Op->Asl.Child;
589         ArgNode = ArgNode->Asl.Next;
590         ArgNode = ArgNode->Asl.Next;
591
592         if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
593            ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
594             (ArgNode->Asl.Value.Integer == 0)))
595         {
596             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
597         }
598         break;
599
600     case PARSEOP_CONNECTION:
601         /*
602          * Ensure that the referenced operation region has the correct SPACE_ID.
603          * From the grammar/parser, we know the parent is a FIELD definition.
604          */
605         ArgNode = Op->Asl.Parent;       /* Field definition */
606         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
607         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
608         if (!Node)
609         {
610             break;
611         }
612
613         ArgNode = Node->Op;             /* OpRegion definition */
614         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
615         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
616
617         /*
618          * The Connection() operator is only valid for the following operation
619          * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
620          */
621         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
622             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
623         {
624             AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
625         }
626         break;
627
628     case PARSEOP_FIELD:
629         /*
630          * Ensure that fields for GeneralPurposeIo and GenericSerialBus
631          * contain at least one Connection() operator
632          */
633         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
634         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
635         if (!Node)
636         {
637             break;
638         }
639
640         ArgNode = Node->Op;             /* OpRegion definition */
641         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
642         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
643
644         /* We are only interested in GeneralPurposeIo and GenericSerialBus */
645
646         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
647             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
648         {
649             break;
650         }
651
652         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
653         ArgNode = ArgNode->Asl.Next;    /* AccessType */
654         ArgNode = ArgNode->Asl.Next;    /* LockRule */
655         ArgNode = ArgNode->Asl.Next;    /* UpdateRule */
656         ArgNode = ArgNode->Asl.Next;    /* Start of FieldUnitList */
657
658         /* Walk the FieldUnitList */
659
660         while (ArgNode)
661         {
662             if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION)
663             {
664                 break;
665             }
666             else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG)
667             {
668                 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL);
669                 break;
670             }
671
672             ArgNode = ArgNode->Asl.Next;
673         }
674         break;
675
676     default:
677
678         break;
679     }
680
681     return (AE_OK);
682 }