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