1 /******************************************************************************
2  *
3  * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 /* Local prototypes */
55 
56 static void
57 AnAnalyzeStoreOperator (
58     ACPI_PARSE_OBJECT       *Op);
59 
60 static BOOLEAN
61 AnIsValidBufferConstant (
62     ACPI_PARSE_OBJECT       *Op);
63 
64 static void
65 AnValidateCreateBufferField (
66     ACPI_PARSE_OBJECT       *CreateBufferFieldOp);
67 
68 
69 /*******************************************************************************
70  *
71  * FUNCTION:    AnMethodTypingWalkEnd
72  *
73  * PARAMETERS:  ASL_WALK_CALLBACK
74  *
75  * RETURN:      Status
76  *
77  * DESCRIPTION: Ascending callback for typing walk. Complete the method
78  *              return analysis. Check methods for:
79  *              1) Initialized local variables
80  *              2) Valid arguments
81  *              3) Return types
82  *
83  ******************************************************************************/
84 
85 ACPI_STATUS
AnMethodTypingWalkEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)86 AnMethodTypingWalkEnd (
87     ACPI_PARSE_OBJECT       *Op,
88     UINT32                  Level,
89     void                    *Context)
90 {
91     UINT32                  ThisOpBtype;
92 
93 
94     switch (Op->Asl.ParseOpcode)
95     {
96     case PARSEOP_METHOD:
97 
98         Op->Asl.CompileFlags |= OP_METHOD_TYPED;
99         break;
100 
101     case PARSEOP_RETURN:
102 
103         if ((Op->Asl.Child) &&
104             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
105         {
106             ThisOpBtype = AnGetBtype (Op->Asl.Child);
107 
108             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
109                 (ThisOpBtype == (ACPI_UINT32_MAX -1)))
110             {
111                 /*
112                  * The called method is untyped at this time (typically a
113                  * forward reference).
114                  *
115                  * Check for a recursive method call first. Note: the
116                  * Child->Node will be null if the method has not been
117                  * resolved.
118                  */
119                 if (Op->Asl.Child->Asl.Node &&
120                     (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
121                 {
122                     /* We must type the method here */
123 
124                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
125                         ASL_WALK_VISIT_UPWARD, NULL,
126                         AnMethodTypingWalkEnd, NULL);
127 
128                     ThisOpBtype = AnGetBtype (Op->Asl.Child);
129                 }
130             }
131 
132             /* Returns a value, save the value type */
133 
134             if (Op->Asl.ParentMethod)
135             {
136                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype;
137             }
138         }
139         break;
140 
141     default:
142 
143         break;
144     }
145 
146     return (AE_OK);
147 }
148 
149 
150 /*******************************************************************************
151  *
152  * FUNCTION:    AnOperandTypecheckWalkEnd
153  *
154  * PARAMETERS:  ASL_WALK_CALLBACK
155  *
156  * RETURN:      Status
157  *
158  * DESCRIPTION: Ascending callback for analysis walk. Complete method
159  *              return analysis.
160  *
161  ******************************************************************************/
162 
163 ACPI_STATUS
AnOperandTypecheckWalkEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)164 AnOperandTypecheckWalkEnd (
165     ACPI_PARSE_OBJECT       *Op,
166     UINT32                  Level,
167     void                    *Context)
168 {
169     const ACPI_OPCODE_INFO  *OpInfo;
170     UINT32                  RuntimeArgTypes;
171     UINT32                  RuntimeArgTypes2;
172     UINT32                  RequiredBtypes;
173     UINT32                  ThisNodeBtype;
174     UINT32                  CommonBtypes;
175     UINT32                  OpcodeClass;
176     ACPI_PARSE_OBJECT       *ArgOp;
177     UINT32                  ArgType;
178 
179 
180     switch (Op->Asl.AmlOpcode)
181     {
182     case AML_RAW_DATA_BYTE:
183     case AML_RAW_DATA_WORD:
184     case AML_RAW_DATA_DWORD:
185     case AML_RAW_DATA_QWORD:
186     case AML_RAW_DATA_BUFFER:
187     case AML_RAW_DATA_CHAIN:
188     case AML_PACKAGE_LENGTH:
189     case AML_UNASSIGNED_OPCODE:
190     case AML_DEFAULT_ARG_OP:
191 
192         /* Ignore the internal (compiler-only) AML opcodes */
193 
194         return (AE_OK);
195 
196     default:
197 
198         break;
199     }
200 
201     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
202     if (!OpInfo)
203     {
204         return (AE_OK);
205     }
206 
207     ArgOp = Op->Asl.Child;
208     OpcodeClass = OpInfo->Class;
209     RuntimeArgTypes = OpInfo->RuntimeArgs;
210 
211 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
212     /*
213      * Update 11/2008: In practice, we can't perform this check. A simple
214      * analysis is not sufficient. Also, it can cause errors when compiling
215      * disassembled code because of the way Switch operators are implemented
216      * (a While(One) loop with a named temp variable created within.)
217      */
218 
219     /*
220      * If we are creating a named object, check if we are within a while loop
221      * by checking if the parent is a WHILE op. This is a simple analysis, but
222      * probably sufficient for many cases.
223      *
224      * Allow Scope(), Buffer(), and Package().
225      */
226     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
227         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
228     {
229         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
230         {
231             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
232         }
233     }
234 #endif
235 
236     /*
237      * Special case for control opcodes IF/RETURN/WHILE since they
238      * have no runtime arg list (at this time)
239      */
240     switch (Op->Asl.AmlOpcode)
241     {
242     case AML_IF_OP:
243     case AML_WHILE_OP:
244     case AML_RETURN_OP:
245 
246         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
247         {
248             /* Check for an internal method */
249 
250             if (AnIsInternalMethod (ArgOp))
251             {
252                 return (AE_OK);
253             }
254 
255             /* The lone arg is a method call, check it */
256 
257             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
258             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
259             {
260                 RequiredBtypes = 0xFFFFFFFF;
261             }
262 
263             ThisNodeBtype = AnGetBtype (ArgOp);
264             if (ThisNodeBtype == ACPI_UINT32_MAX)
265             {
266                 return (AE_OK);
267             }
268 
269             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
270                 RequiredBtypes, ThisNodeBtype);
271         }
272         return (AE_OK);
273 
274     case AML_EXTERNAL_OP:
275         /*
276          * Not really a "runtime" opcode since it used by disassembler only.
277          * The parser will find any issues with the operands.
278          */
279         return (AE_OK);
280 
281     default:
282 
283         break;
284     }
285 
286     /* Ignore the non-executable opcodes */
287 
288     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
289     {
290         return (AE_OK);
291     }
292 
293     /*
294      * Special handling for certain opcodes.
295      */
296     switch (Op->Asl.AmlOpcode)
297     {
298         /* BankField has one TermArg */
299 
300     case AML_BANK_FIELD_OP:
301 
302         OpcodeClass = AML_CLASS_EXECUTE;
303         ArgOp = ArgOp->Asl.Next;
304         ArgOp = ArgOp->Asl.Next;
305         break;
306 
307         /* Operation Region has 2 TermArgs */
308 
309     case AML_REGION_OP:
310 
311         OpcodeClass = AML_CLASS_EXECUTE;
312         ArgOp = ArgOp->Asl.Next;
313         ArgOp = ArgOp->Asl.Next;
314         break;
315 
316         /* DataTableRegion has 3 TermArgs */
317 
318     case AML_DATA_REGION_OP:
319 
320         OpcodeClass = AML_CLASS_EXECUTE;
321         ArgOp = ArgOp->Asl.Next;
322         break;
323 
324         /* Buffers/Packages have a length that is a TermArg */
325 
326     case AML_BUFFER_OP:
327     case AML_PACKAGE_OP:
328     case AML_VARIABLE_PACKAGE_OP:
329 
330             /* If length is a constant, we are done */
331 
332         if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
333             (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA))
334         {
335             return (AE_OK);
336         }
337         break;
338 
339         /* Store can write any object to the Debug object */
340 
341     case AML_STORE_OP:
342         /*
343          * If this is a Store() to the Debug object, we don't need
344          * to perform any further validation -- because a Store of
345          * any object to Debug is permitted and supported.
346          */
347         if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP)
348         {
349             return (AE_OK);
350         }
351         break;
352 
353     default:
354         break;
355     }
356 
357     switch (OpcodeClass)
358     {
359     case AML_CLASS_EXECUTE:
360     case AML_CLASS_CREATE:
361     case AML_CLASS_CONTROL:
362     case AML_CLASS_RETURN_VALUE:
363 
364         /* Reverse the runtime argument list */
365 
366         RuntimeArgTypes2 = 0;
367         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
368         {
369             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
370             RuntimeArgTypes2 |= ArgType;
371             INCREMENT_ARG_LIST (RuntimeArgTypes);
372         }
373 
374         /* Typecheck each argument */
375 
376         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
377         {
378             /* Get the required type(s) for the argument */
379 
380             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
381 
382             if (!ArgOp)
383             {
384                 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
385                     "Null ArgOp in argument loop");
386                 AslAbort ();
387             }
388 
389             /* Get the actual type of the argument */
390 
391             ThisNodeBtype = AnGetBtype (ArgOp);
392             if (ThisNodeBtype == ACPI_UINT32_MAX)
393             {
394                 goto NextArgument;
395             }
396 
397             /* Examine the arg based on the required type of the arg */
398 
399             switch (ArgType)
400             {
401             case ARGI_TARGETREF:
402 
403                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
404                 {
405                     /* ZERO is the placeholder for "don't store result" */
406 
407                     ThisNodeBtype = RequiredBtypes;
408                     break;
409                 }
410 
411                 ACPI_FALLTHROUGH;
412 
413             case ARGI_STORE_TARGET:
414 
415                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
416                 {
417                     /*
418                      * This is the case where an original reference to a resource
419                      * descriptor field has been replaced by an (Integer) offset.
420                      * These named fields are supported at compile-time only;
421                      * the names are not passed to the interpreter (via the AML).
422                      */
423                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
424                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
425                     {
426                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD,
427                             ArgOp, NULL);
428                     }
429                     else
430                     {
431                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
432                             ArgOp, NULL);
433                     }
434                 }
435                 break;
436 
437 
438 #ifdef __FUTURE_IMPLEMENTATION
439 /*
440  * Possible future typechecking support
441  */
442             case ARGI_REFERENCE:            /* References */
443             case ARGI_INTEGER_REF:
444             case ARGI_OBJECT_REF:
445             case ARGI_DEVICE_REF:
446 
447                 switch (ArgOp->Asl.ParseOpcode)
448                 {
449                 case PARSEOP_LOCAL0:
450                 case PARSEOP_LOCAL1:
451                 case PARSEOP_LOCAL2:
452                 case PARSEOP_LOCAL3:
453                 case PARSEOP_LOCAL4:
454                 case PARSEOP_LOCAL5:
455                 case PARSEOP_LOCAL6:
456                 case PARSEOP_LOCAL7:
457 
458                     /* TBD: implement analysis of current value (type) of the local */
459                     /* For now, just treat any local as a typematch */
460 
461                     /*ThisNodeBtype = RequiredBtypes;*/
462                     break;
463 
464                 case PARSEOP_ARG0:
465                 case PARSEOP_ARG1:
466                 case PARSEOP_ARG2:
467                 case PARSEOP_ARG3:
468                 case PARSEOP_ARG4:
469                 case PARSEOP_ARG5:
470                 case PARSEOP_ARG6:
471 
472                     /* Hard to analyze argument types, so we won't */
473                     /* for now. Just treat any arg as a typematch */
474 
475                     /* ThisNodeBtype = RequiredBtypes; */
476                     break;
477 
478                 case PARSEOP_DEBUG:
479                 case PARSEOP_REFOF:
480                 case PARSEOP_INDEX:
481                 default:
482 
483                     break;
484                 }
485                 break;
486 #endif
487             case ARGI_INTEGER:
488             default:
489 
490                 break;
491             }
492 
493 
494             /* Check for a type mismatch (required versus actual) */
495 
496             CommonBtypes = ThisNodeBtype & RequiredBtypes;
497 
498             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
499             {
500                 if (AnIsInternalMethod (ArgOp))
501                 {
502                     return (AE_OK);
503                 }
504 
505                 /* Check a method call for a valid return value */
506 
507                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
508                     RequiredBtypes, ThisNodeBtype);
509             }
510 
511             /*
512              * Now check if the actual type(s) match at least one
513              * bit to the required type
514              */
515             else if (!CommonBtypes)
516             {
517                 /* No match -- this is a type mismatch error */
518 
519                 AnFormatBtype (AslGbl_StringBuffer, ThisNodeBtype);
520                 AnFormatBtype (AslGbl_StringBuffer2, RequiredBtypes);
521 
522                 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "[%s] found, %s operator requires [%s]",
523                     AslGbl_StringBuffer, OpInfo->Name, AslGbl_StringBuffer2);
524 
525                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
526                     ArgOp, AslGbl_MsgBuffer);
527             }
528 
529         NextArgument:
530             ArgOp = ArgOp->Asl.Next;
531             INCREMENT_ARG_LIST (RuntimeArgTypes2);
532         }
533         break;
534 
535     default:
536 
537         break;
538     }
539 
540     return (AE_OK);
541 }
542 
543 
544 /*******************************************************************************
545  *
546  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
547  *
548  * PARAMETERS:  ASL_WALK_CALLBACK
549  *
550  * RETURN:      Status
551  *
552  * DESCRIPTION: Descending callback for the analysis walk. Checks for
553  *              miscellaneous issues in the code.
554  *
555  ******************************************************************************/
556 
557 ACPI_STATUS
AnOtherSemanticAnalysisWalkBegin(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)558 AnOtherSemanticAnalysisWalkBegin (
559     ACPI_PARSE_OBJECT       *Op,
560     UINT32                  Level,
561     void                    *Context)
562 {
563     ACPI_PARSE_OBJECT       *ArgOp;
564     ACPI_PARSE_OBJECT       *PrevArgOp = NULL;
565     const ACPI_OPCODE_INFO  *OpInfo;
566     ACPI_NAMESPACE_NODE     *Node;
567 
568 
569     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
570 
571 
572     if (OpInfo->Flags & AML_CREATE)
573     {
574         /* This group contains all of the Create Buffer Field operators */
575 
576         AnValidateCreateBufferField (Op);
577         return (AE_OK);
578     }
579 
580     /*
581      * Determine if an execution class operator actually does something by
582      * checking if it has a target and/or the function return value is used.
583      * (Target is optional, so a standalone statement can actually do nothing.)
584      */
585     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
586         (OpInfo->Flags & AML_HAS_RETVAL) &&
587         (!AnIsResultUsed (Op)))
588     {
589         if (OpInfo->Flags & AML_HAS_TARGET)
590         {
591             /*
592              * Find the target node, it is always the last child. If the target
593              * is not specified in the ASL, a default node of type Zero was
594              * created by the parser.
595              */
596             ArgOp = Op->Asl.Child;
597             while (ArgOp->Asl.Next)
598             {
599                 PrevArgOp = ArgOp;
600                 ArgOp = ArgOp->Asl.Next;
601             }
602 
603             /* Divide() is the only weird case, it has two targets */
604 
605             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
606             {
607                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) &&
608                     (PrevArgOp) &&
609                     (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO))
610                 {
611                     AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
612                         Op, Op->Asl.ExternalName);
613                 }
614             }
615 
616             else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
617             {
618                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
619                     Op, Op->Asl.ExternalName);
620             }
621         }
622         else
623         {
624             /*
625              * Has no target and the result is not used. Only a couple opcodes
626              * can have this combination.
627              */
628             switch (Op->Asl.ParseOpcode)
629             {
630             case PARSEOP_ACQUIRE:
631             case PARSEOP_WAIT:
632             case PARSEOP_LOADTABLE:
633 
634                 break;
635 
636             default:
637 
638                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
639                     Op, Op->Asl.ExternalName);
640                 break;
641             }
642         }
643     }
644 
645     /*
646      * Semantic checks for individual ASL operators
647      */
648 
649     switch (Op->Asl.ParseOpcode)
650     {
651     case PARSEOP_STORE:
652 
653         if (AslGbl_DoTypechecking)
654         {
655             AnAnalyzeStoreOperator (Op);
656         }
657         break;
658 
659 
660     case PARSEOP_ACQUIRE:
661     case PARSEOP_WAIT:
662         /*
663          * Emit a warning if the timeout parameter for these operators is not
664          * ACPI_WAIT_FOREVER, and the result value from the operator is not
665          * checked, meaning that a timeout could happen, but the code
666          * would not know about it.
667          */
668 
669         /* First child is the namepath, 2nd child is timeout */
670 
671         ArgOp = Op->Asl.Child;
672         ArgOp = ArgOp->Asl.Next;
673 
674         /*
675          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
676          * 0xFFFF or greater
677          */
678         if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
679              (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
680              (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
681         {
682             break;
683         }
684 
685         /*
686          * The operation could timeout. If the return value is not used
687          * (indicates timeout occurred), issue a warning
688          */
689         if (!AnIsResultUsed (Op))
690         {
691             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp,
692                 Op->Asl.ExternalName);
693         }
694         break;
695 
696     case PARSEOP_CONNECTION:
697         /*
698          * Ensure that the referenced operation region has the correct SPACE_ID.
699          * From the grammar/parser, we know the parent is a FIELD definition.
700          */
701         ArgOp = Op->Asl.Parent;     /* Field definition */
702         ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
703         Node = ArgOp->Asl.Node;     /* OpRegion namespace node */
704         if (!Node)
705         {
706             break;
707         }
708 
709         ArgOp = Node->Op;           /* OpRegion definition */
710         ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
711         ArgOp = ArgOp->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
712 
713         /*
714          * The Connection() operator is only valid for the following operation
715          * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
716          */
717         if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
718             (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
719         {
720             AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
721         }
722         break;
723 
724     case PARSEOP_FIELD:
725         /*
726          * Ensure that fields for GeneralPurposeIo and GenericSerialBus
727          * contain at least one Connection() operator
728          */
729         ArgOp = Op->Asl.Child;      /* 1st child is the OpRegion Name */
730         Node = ArgOp->Asl.Node;     /* OpRegion namespace node */
731         if (!Node)
732         {
733             break;
734         }
735 
736         ArgOp = Node->Op;           /* OpRegion definition */
737         ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
738         ArgOp = ArgOp->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
739 
740         /* We are only interested in GeneralPurposeIo and GenericSerialBus */
741 
742         if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
743             (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
744         {
745             break;
746         }
747 
748         ArgOp = Op->Asl.Child;      /* 1st child is the OpRegion Name */
749         ArgOp = ArgOp->Asl.Next;    /* AccessType */
750         ArgOp = ArgOp->Asl.Next;    /* LockRule */
751         ArgOp = ArgOp->Asl.Next;    /* UpdateRule */
752         ArgOp = ArgOp->Asl.Next;    /* Start of FieldUnitList */
753 
754         /* Walk the FieldUnitList */
755 
756         while (ArgOp)
757         {
758             if (ArgOp->Asl.ParseOpcode == PARSEOP_CONNECTION)
759             {
760                 break;
761             }
762             else if (ArgOp->Asl.ParseOpcode == PARSEOP_NAMESEG)
763             {
764                 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgOp, NULL);
765                 break;
766             }
767 
768             ArgOp = ArgOp->Asl.Next;
769         }
770         break;
771 
772     default:
773 
774         break;
775     }
776 
777     return (AE_OK);
778 }
779 
780 
781 /*******************************************************************************
782  *
783  * FUNCTION:    AnValidateCreateBufferField
784  *
785  * PARAMETERS:  Op                  - A create buffer field operator
786  *
787  * RETURN:      None
788  *
789  * DESCRIPTION: Check if a buffer index argument to a create buffer field
790  *              operation is beyond the end of the target buffer.
791  *
792  *  Validates these AML operators:
793  *
794  *  AML_CREATE_FIELD_OP
795  *  AML_CREATE_BIT_FIELD_OP
796  *  AML_CREATE_BYTE_FIELD_OP
797  *  AML_CREATE_WORD_FIELD_OP
798  *  AML_CREATE_DWORD_FIELD_OP
799  *  AML_CREATE_QWORD_FIELD_OP
800  *
801  *  There are two conditions that must be satisfied in order to enable
802  *  validation at compile time:
803  *
804  *  1) The length of the target buffer must be an integer constant
805  *  2) The index specified in the create* must be an integer constant
806  *  3) For CreateField, the bit length argument must be non-zero.
807  *
808  ******************************************************************************/
809 
810 static void
AnValidateCreateBufferField(ACPI_PARSE_OBJECT * CreateBufferFieldOp)811 AnValidateCreateBufferField (
812     ACPI_PARSE_OBJECT       *CreateBufferFieldOp)
813 {
814     ACPI_PARSE_OBJECT       *TargetBufferOp;
815     ACPI_PARSE_OBJECT       *ArgOp;
816     UINT32                  TargetBufferLength;
817     UINT32                  LastFieldByteIndex;
818 
819 
820     /*
821      * 1) Get the length of the target buffer
822      */
823     ArgOp = CreateBufferFieldOp->Asl.Child;     /* Reference to target buffer */
824 
825     /*
826      * If no attached Node, the target buffer may be something like an
827      * ArgX or LocalX and cannot be evaluated at compile time.
828      */
829     if (!ArgOp->Asl.Node)
830     {
831         return;
832     }
833 
834     TargetBufferOp = ArgOp->Asl.Node->Op;
835     TargetBufferOp = TargetBufferOp->Asl.Child; /* Target buffer */
836     TargetBufferOp = TargetBufferOp->Asl.Next;  /* "Buffer" keyword */
837     if (!TargetBufferOp)
838     {
839         /* Not a statement of the form NAME(XXXX, Buffer.... */
840 
841         return;
842     }
843 
844     /* Get the buffer length argument. It must be an integer constant */
845 
846     ArgOp = TargetBufferOp->Asl.Child;
847     if (!AnIsValidBufferConstant (ArgOp))
848     {
849         return;
850     }
851 
852     TargetBufferLength = (UINT32) ArgOp->Asl.Value.Integer;
853 
854     /*
855      * 2) Get the value of the buffer index argument. It must be
856      * an integer constant.
857      */
858     ArgOp = CreateBufferFieldOp->Asl.Child;     /* Reference to target buffer */
859     ArgOp = ArgOp->Asl.Next;                    /* Buffer Index argument*/
860     if (!AnIsValidBufferConstant (ArgOp))
861     {
862         return;
863     }
864 
865     LastFieldByteIndex =
866         (UINT32) ArgOp->Asl.Value.Integer;      /* Index can be in either bytes or bits */
867 
868     /*
869      * 3) Get the length of the new buffer field, in bytes. Also,
870      * create the final target buffer index for the last byte of the field
871      */
872     switch (CreateBufferFieldOp->Asl.ParseOpcode)
873     {
874     case PARSEOP_CREATEBITFIELD:                /* A one bit field */
875 
876         LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex);
877         break;
878 
879     case PARSEOP_CREATEBYTEFIELD:
880         break;
881 
882     case PARSEOP_CREATEWORDFIELD:
883 
884         LastFieldByteIndex += (sizeof (UINT16) - 1);
885         break;
886 
887     case PARSEOP_CREATEDWORDFIELD:
888 
889         LastFieldByteIndex += (sizeof (UINT32) - 1);
890         break;
891 
892     case PARSEOP_CREATEQWORDFIELD:
893 
894         LastFieldByteIndex += (sizeof (UINT64) - 1);
895         break;
896 
897     case PARSEOP_CREATEFIELD:                   /* Multi-bit field */
898 
899         ArgOp = ArgOp->Asl.Next;                /* Length argument, in bits */
900         if (!AnIsValidBufferConstant (ArgOp))
901         {
902             return;
903         }
904 
905         /* The buffer field length is not allowed to be zero */
906 
907         if (ArgOp->Asl.Value.Integer == 0)
908         {
909             AslError (ASL_WARNING,  ASL_MSG_BUFFER_FIELD_LENGTH, ArgOp, NULL);
910             return;
911         }
912 
913         LastFieldByteIndex +=
914             ((UINT32) ArgOp->Asl.Value.Integer - 1);    /* Create final bit index */
915 
916         /* Convert bit index to a byte index */
917 
918         LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex);
919         break;
920 
921     default:
922         return;
923     }
924 
925     /*
926      * 4) Check for an access (index) beyond the end of the target buffer,
927      * or a zero length target buffer.
928      */
929     if (!TargetBufferLength || (LastFieldByteIndex >= TargetBufferLength))
930     {
931         AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_OVERFLOW, ArgOp, NULL);
932     }
933 }
934 
935 
936 /*******************************************************************************
937  *
938  * FUNCTION:    AnIsValidBufferConstant
939  *
940  * PARAMETERS:  Op                  - A buffer-related operand
941  *
942  * RETURN:      TRUE if operand is valid constant, FALSE otherwise
943  *
944  * DESCRIPTION: Check if the input Op is valid constant that can be used
945  *              in compile-time analysis.
946  *
947  ******************************************************************************/
948 
949 static BOOLEAN
AnIsValidBufferConstant(ACPI_PARSE_OBJECT * Op)950 AnIsValidBufferConstant (
951     ACPI_PARSE_OBJECT       *Op)
952 {
953     if (!Op)
954     {
955         return (FALSE);
956     }
957 
958     if ((Op->Asl.ParseOpcode == PARSEOP_INTEGER) ||
959         (Op->Asl.ParseOpcode == PARSEOP_ZERO)    ||
960         (Op->Asl.ParseOpcode == PARSEOP_ONE))
961     {
962         return (TRUE);
963     }
964 
965     return (FALSE);
966 }
967 
968 
969 /*******************************************************************************
970  *
971  * FUNCTION:    AnAnalyzeStoreOperator
972  *
973  * PARAMETERS:  Op                  - Store() operator
974  *
975  * RETURN:      None
976  *
977  * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package
978  *              objects where there are more restrictions than other data
979  *              types.
980  *
981  ******************************************************************************/
982 
983 static void
AnAnalyzeStoreOperator(ACPI_PARSE_OBJECT * Op)984 AnAnalyzeStoreOperator (
985     ACPI_PARSE_OBJECT       *Op)
986 {
987     ACPI_NAMESPACE_NODE     *SourceNode;
988     ACPI_NAMESPACE_NODE     *TargetNode;
989     ACPI_PARSE_OBJECT       *SourceOperandOp;
990     ACPI_PARSE_OBJECT       *TargetOperandOp;
991     UINT32                  SourceOperandBtype;
992     UINT32                  TargetOperandBtype;
993 
994 
995     /* Extract the two operands for STORE */
996 
997     SourceOperandOp = Op->Asl.Child;
998     TargetOperandOp = SourceOperandOp->Asl.Next;
999 
1000     /*
1001      * Ignore these Source operand opcodes, they cannot be typechecked,
1002      * the actual result is unknown here.
1003      */
1004     switch (SourceOperandOp->Asl.ParseOpcode)
1005     {
1006     /* For these, type of the returned value is unknown at compile time */
1007 
1008     case PARSEOP_DEREFOF:
1009     case PARSEOP_METHODCALL:
1010     case PARSEOP_STORE:
1011     case PARSEOP_COPYOBJECT:
1012 
1013         return;
1014 
1015     case PARSEOP_INDEX:
1016     case PARSEOP_REFOF:
1017 
1018         if (!AslGbl_EnableReferenceTypechecking)
1019         {
1020             return;
1021         }
1022 
1023         /*
1024          * These opcodes always return an object reference, and thus
1025          * the result can only be stored to a Local, Arg, or Debug.
1026          */
1027         if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP)
1028         {
1029             return;
1030         }
1031 
1032         if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) ||
1033             (TargetOperandOp->Asl.AmlOpcode > AML_ARG6))
1034         {
1035             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
1036                 "Source [Reference], Target must be [Local/Arg/Debug]");
1037         }
1038         return;
1039 
1040     default:
1041         break;
1042     }
1043 
1044     /*
1045      * Ignore these Target operand opcodes, they cannot be typechecked
1046      */
1047     switch (TargetOperandOp->Asl.ParseOpcode)
1048     {
1049     case PARSEOP_DEBUG:
1050     case PARSEOP_DEREFOF:
1051     case PARSEOP_REFOF:
1052     case PARSEOP_INDEX:
1053     case PARSEOP_STORE:
1054 
1055         return;
1056 
1057     default:
1058         break;
1059     }
1060 
1061     /*
1062      * Ignore typecheck for External() operands of type "UnknownObj",
1063      * we don't know the actual type (source or target).
1064      */
1065     SourceNode = SourceOperandOp->Asl.Node;
1066     if (SourceNode &&
1067         (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
1068         (SourceNode->Type == ACPI_TYPE_ANY))
1069     {
1070         return;
1071     }
1072 
1073     TargetNode = TargetOperandOp->Asl.Node;
1074     if (TargetNode &&
1075         (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
1076         (TargetNode->Type == ACPI_TYPE_ANY))
1077     {
1078         return;
1079     }
1080 
1081     /*
1082      * A NULL node with a namepath AML opcode indicates non-existent
1083      * name. Just return, the error message is generated elsewhere.
1084      */
1085     if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
1086         (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
1087     {
1088         return;
1089     }
1090 
1091     /*
1092      * Simple check for source same as target via NS node.
1093      * -- Could be expanded to locals and args.
1094      */
1095     if (SourceNode && TargetNode)
1096     {
1097         if (SourceNode == TargetNode)
1098         {
1099             AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
1100                 TargetOperandOp, "Source is the same as Target");
1101             return;
1102         }
1103     }
1104 
1105     /* Ignore typecheck if either source or target is a local or arg */
1106 
1107     if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
1108         (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
1109     {
1110         return; /* Cannot type a local/arg at compile time */
1111     }
1112 
1113     if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
1114         (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
1115     {
1116         return; /* Cannot type a local/arg at compile time */
1117     }
1118 
1119     /*
1120      * Package objects are a special case because they cannot by implicitly
1121      * converted to/from anything. Check for these two illegal cases:
1122      *
1123      *      Store (non-package, package)
1124      *      Store (package, non-package)
1125      */
1126     SourceOperandBtype = AnGetBtype (SourceOperandOp);
1127     TargetOperandBtype = AnGetBtype (TargetOperandOp);
1128 
1129     /* Check source first for (package, non-package) case */
1130 
1131     if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
1132     {
1133         /* If Source is PACKAGE-->Target must be PACKAGE */
1134 
1135         if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
1136         {
1137             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
1138                 "Source is [Package], Target must be a package also");
1139         }
1140     }
1141 
1142     /* Else check target for (non-package, package) case */
1143 
1144     else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
1145     {
1146         /* If Target is PACKAGE, Source must be PACKAGE */
1147 
1148         if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
1149         {
1150             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
1151                 "Target is [Package], Source must be a package also");
1152         }
1153     }
1154 }
1155