xref: /freebsd/sys/contrib/dev/acpica/compiler/aslwalks.c (revision 1cc50d6b6a02d2c48cb9b812432a492d284c6dd1)
1 /******************************************************************************
2  *
3  * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include "aslcompiler.y.h"
46 #include <contrib/dev/acpica/include/acparser.h>
47 #include <contrib/dev/acpica/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 
61 /*******************************************************************************
62  *
63  * FUNCTION:    AnMethodTypingWalkEnd
64  *
65  * PARAMETERS:  ASL_WALK_CALLBACK
66  *
67  * RETURN:      Status
68  *
69  * DESCRIPTION: Ascending callback for typing walk. Complete the method
70  *              return analysis. Check methods for:
71  *              1) Initialized local variables
72  *              2) Valid arguments
73  *              3) Return types
74  *
75  ******************************************************************************/
76 
77 ACPI_STATUS
78 AnMethodTypingWalkEnd (
79     ACPI_PARSE_OBJECT       *Op,
80     UINT32                  Level,
81     void                    *Context)
82 {
83     UINT32                  ThisOpBtype;
84 
85 
86     switch (Op->Asl.ParseOpcode)
87     {
88     case PARSEOP_METHOD:
89 
90         Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
91         break;
92 
93     case PARSEOP_RETURN:
94 
95         if ((Op->Asl.Child) &&
96             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
97         {
98             ThisOpBtype = AnGetBtype (Op->Asl.Child);
99 
100             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
101                 (ThisOpBtype == (ACPI_UINT32_MAX -1)))
102             {
103                 /*
104                  * The called method is untyped at this time (typically a
105                  * forward reference).
106                  *
107                  * Check for a recursive method call first. Note: the
108                  * Child->Node will be null if the method has not been
109                  * resolved.
110                  */
111                 if (Op->Asl.Child->Asl.Node &&
112                     (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
113                 {
114                     /* We must type the method here */
115 
116                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
117                         ASL_WALK_VISIT_UPWARD, NULL,
118                         AnMethodTypingWalkEnd, NULL);
119 
120                     ThisOpBtype = AnGetBtype (Op->Asl.Child);
121                 }
122             }
123 
124             /* Returns a value, save the value type */
125 
126             if (Op->Asl.ParentMethod)
127             {
128                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype;
129             }
130         }
131         break;
132 
133     default:
134 
135         break;
136     }
137 
138     return (AE_OK);
139 }
140 
141 
142 /*******************************************************************************
143  *
144  * FUNCTION:    AnOperandTypecheckWalkEnd
145  *
146  * PARAMETERS:  ASL_WALK_CALLBACK
147  *
148  * RETURN:      Status
149  *
150  * DESCRIPTION: Ascending callback for analysis walk. Complete method
151  *              return analysis.
152  *
153  ******************************************************************************/
154 
155 ACPI_STATUS
156 AnOperandTypecheckWalkEnd (
157     ACPI_PARSE_OBJECT       *Op,
158     UINT32                  Level,
159     void                    *Context)
160 {
161     const ACPI_OPCODE_INFO  *OpInfo;
162     UINT32                  RuntimeArgTypes;
163     UINT32                  RuntimeArgTypes2;
164     UINT32                  RequiredBtypes;
165     UINT32                  ThisNodeBtype;
166     UINT32                  CommonBtypes;
167     UINT32                  OpcodeClass;
168     ACPI_PARSE_OBJECT       *ArgOp;
169     UINT32                  ArgType;
170 
171 
172     switch (Op->Asl.AmlOpcode)
173     {
174     case AML_RAW_DATA_BYTE:
175     case AML_RAW_DATA_WORD:
176     case AML_RAW_DATA_DWORD:
177     case AML_RAW_DATA_QWORD:
178     case AML_RAW_DATA_BUFFER:
179     case AML_RAW_DATA_CHAIN:
180     case AML_PACKAGE_LENGTH:
181     case AML_UNASSIGNED_OPCODE:
182     case AML_DEFAULT_ARG_OP:
183 
184         /* Ignore the internal (compiler-only) AML opcodes */
185 
186         return (AE_OK);
187 
188     default:
189 
190         break;
191     }
192 
193     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
194     if (!OpInfo)
195     {
196         return (AE_OK);
197     }
198 
199     ArgOp = Op->Asl.Child;
200     OpcodeClass = OpInfo->Class;
201     RuntimeArgTypes = OpInfo->RuntimeArgs;
202 
203 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
204     /*
205      * Update 11/2008: In practice, we can't perform this check. A simple
206      * analysis is not sufficient. Also, it can cause errors when compiling
207      * disassembled code because of the way Switch operators are implemented
208      * (a While(One) loop with a named temp variable created within.)
209      */
210 
211     /*
212      * If we are creating a named object, check if we are within a while loop
213      * by checking if the parent is a WHILE op. This is a simple analysis, but
214      * probably sufficient for many cases.
215      *
216      * Allow Scope(), Buffer(), and Package().
217      */
218     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
219         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
220     {
221         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
222         {
223             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
224         }
225     }
226 #endif
227 
228     /*
229      * Special case for control opcodes IF/RETURN/WHILE since they
230      * have no runtime arg list (at this time)
231      */
232     switch (Op->Asl.AmlOpcode)
233     {
234     case AML_IF_OP:
235     case AML_WHILE_OP:
236     case AML_RETURN_OP:
237 
238         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
239         {
240             /* Check for an internal method */
241 
242             if (AnIsInternalMethod (ArgOp))
243             {
244                 return (AE_OK);
245             }
246 
247             /* The lone arg is a method call, check it */
248 
249             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
250             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
251             {
252                 RequiredBtypes = 0xFFFFFFFF;
253             }
254 
255             ThisNodeBtype = AnGetBtype (ArgOp);
256             if (ThisNodeBtype == ACPI_UINT32_MAX)
257             {
258                 return (AE_OK);
259             }
260 
261             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
262                 RequiredBtypes, ThisNodeBtype);
263         }
264         return (AE_OK);
265 
266     case AML_EXTERNAL_OP:
267         /*
268          * Not really a "runtime" opcode since it used by disassembler only.
269          * The parser will find any issues with the operands.
270          */
271         return (AE_OK);
272 
273     default:
274 
275         break;
276     }
277 
278     /* Ignore the non-executable opcodes */
279 
280     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
281     {
282         return (AE_OK);
283     }
284 
285     /*
286      * Special handling for certain opcodes.
287      */
288     switch (Op->Asl.AmlOpcode)
289     {
290         /* BankField has one TermArg */
291 
292     case AML_BANK_FIELD_OP:
293 
294         OpcodeClass = AML_CLASS_EXECUTE;
295         ArgOp = ArgOp->Asl.Next;
296         ArgOp = ArgOp->Asl.Next;
297         break;
298 
299         /* Operation Region has 2 TermArgs */
300 
301     case AML_REGION_OP:
302 
303         OpcodeClass = AML_CLASS_EXECUTE;
304         ArgOp = ArgOp->Asl.Next;
305         ArgOp = ArgOp->Asl.Next;
306         break;
307 
308         /* DataTableRegion has 3 TermArgs */
309 
310     case AML_DATA_REGION_OP:
311 
312         OpcodeClass = AML_CLASS_EXECUTE;
313         ArgOp = ArgOp->Asl.Next;
314         break;
315 
316         /* Buffers/Packages have a length that is a TermArg */
317 
318     case AML_BUFFER_OP:
319     case AML_PACKAGE_OP:
320     case AML_VAR_PACKAGE_OP:
321 
322             /* If length is a constant, we are done */
323 
324         if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
325             (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA))
326         {
327             return (AE_OK);
328         }
329         break;
330 
331         /* Store can write any object to the Debug object */
332 
333     case AML_STORE_OP:
334         /*
335          * If this is a Store() to the Debug object, we don't need
336          * to perform any further validation -- because a Store of
337          * any object to Debug is permitted and supported.
338          */
339         if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP)
340         {
341             return (AE_OK);
342         }
343         break;
344 
345     default:
346         break;
347     }
348 
349     switch (OpcodeClass)
350     {
351     case AML_CLASS_EXECUTE:
352     case AML_CLASS_CREATE:
353     case AML_CLASS_CONTROL:
354     case AML_CLASS_RETURN_VALUE:
355 
356         /* Reverse the runtime argument list */
357 
358         RuntimeArgTypes2 = 0;
359         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
360         {
361             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
362             RuntimeArgTypes2 |= ArgType;
363             INCREMENT_ARG_LIST (RuntimeArgTypes);
364         }
365 
366         /* Typecheck each argument */
367 
368         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
369         {
370             /* Get the required type(s) for the argument */
371 
372             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
373 
374             if (!ArgOp)
375             {
376                 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
377                     "Null ArgOp in argument loop");
378                 AslAbort ();
379             }
380 
381             /* Get the actual type of the argument */
382 
383             ThisNodeBtype = AnGetBtype (ArgOp);
384             if (ThisNodeBtype == ACPI_UINT32_MAX)
385             {
386                 goto NextArgument;
387             }
388 
389             /* Examine the arg based on the required type of the arg */
390 
391             switch (ArgType)
392             {
393             case ARGI_TARGETREF:
394 
395                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
396                 {
397                     /* ZERO is the placeholder for "don't store result" */
398 
399                     ThisNodeBtype = RequiredBtypes;
400                     break;
401                 }
402 
403             /* Fallthrough */
404 
405             case ARGI_STORE_TARGET:
406 
407                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
408                 {
409                     /*
410                      * This is the case where an original reference to a resource
411                      * descriptor field has been replaced by an (Integer) offset.
412                      * These named fields are supported at compile-time only;
413                      * the names are not passed to the interpreter (via the AML).
414                      */
415                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
416                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
417                     {
418                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD,
419                             ArgOp, NULL);
420                     }
421                     else
422                     {
423                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
424                             ArgOp, NULL);
425                     }
426                 }
427                 break;
428 
429 
430 #ifdef __FUTURE_IMPLEMENTATION
431 /*
432  * Possible future typechecking support
433  */
434             case ARGI_REFERENCE:            /* References */
435             case ARGI_INTEGER_REF:
436             case ARGI_OBJECT_REF:
437             case ARGI_DEVICE_REF:
438 
439                 switch (ArgOp->Asl.ParseOpcode)
440                 {
441                 case PARSEOP_LOCAL0:
442                 case PARSEOP_LOCAL1:
443                 case PARSEOP_LOCAL2:
444                 case PARSEOP_LOCAL3:
445                 case PARSEOP_LOCAL4:
446                 case PARSEOP_LOCAL5:
447                 case PARSEOP_LOCAL6:
448                 case PARSEOP_LOCAL7:
449 
450                     /* TBD: implement analysis of current value (type) of the local */
451                     /* For now, just treat any local as a typematch */
452 
453                     /*ThisNodeBtype = RequiredBtypes;*/
454                     break;
455 
456                 case PARSEOP_ARG0:
457                 case PARSEOP_ARG1:
458                 case PARSEOP_ARG2:
459                 case PARSEOP_ARG3:
460                 case PARSEOP_ARG4:
461                 case PARSEOP_ARG5:
462                 case PARSEOP_ARG6:
463 
464                     /* Hard to analyze argument types, so we won't */
465                     /* for now. Just treat any arg as a typematch */
466 
467                     /* ThisNodeBtype = RequiredBtypes; */
468                     break;
469 
470                 case PARSEOP_DEBUG:
471                 case PARSEOP_REFOF:
472                 case PARSEOP_INDEX:
473                 default:
474 
475                     break;
476                 }
477                 break;
478 #endif
479             case ARGI_INTEGER:
480             default:
481 
482                 break;
483             }
484 
485 
486             /* Check for a type mismatch (required versus actual) */
487 
488             CommonBtypes = ThisNodeBtype & RequiredBtypes;
489 
490             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
491             {
492                 if (AnIsInternalMethod (ArgOp))
493                 {
494                     return (AE_OK);
495                 }
496 
497                 /* Check a method call for a valid return value */
498 
499                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
500                     RequiredBtypes, ThisNodeBtype);
501             }
502 
503             /*
504              * Now check if the actual type(s) match at least one
505              * bit to the required type
506              */
507             else if (!CommonBtypes)
508             {
509                 /* No match -- this is a type mismatch error */
510 
511                 AnFormatBtype (StringBuffer, ThisNodeBtype);
512                 AnFormatBtype (StringBuffer2, RequiredBtypes);
513 
514                 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
515                     StringBuffer, OpInfo->Name, StringBuffer2);
516 
517                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
518                     ArgOp, MsgBuffer);
519             }
520 
521         NextArgument:
522             ArgOp = ArgOp->Asl.Next;
523             INCREMENT_ARG_LIST (RuntimeArgTypes2);
524         }
525         break;
526 
527     default:
528 
529         break;
530     }
531 
532     return (AE_OK);
533 }
534 
535 
536 /*******************************************************************************
537  *
538  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
539  *
540  * PARAMETERS:  ASL_WALK_CALLBACK
541  *
542  * RETURN:      Status
543  *
544  * DESCRIPTION: Descending callback for the analysis walk. Checks for
545  *              miscellaneous issues in the code.
546  *
547  ******************************************************************************/
548 
549 ACPI_STATUS
550 AnOtherSemanticAnalysisWalkBegin (
551     ACPI_PARSE_OBJECT       *Op,
552     UINT32                  Level,
553     void                    *Context)
554 {
555     ACPI_PARSE_OBJECT       *ArgOp;
556     ACPI_PARSE_OBJECT       *PrevArgOp = NULL;
557     const ACPI_OPCODE_INFO  *OpInfo;
558     ACPI_NAMESPACE_NODE     *Node;
559 
560 
561     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
562 
563 
564     /*
565      * Determine if an execution class operator actually does something by
566      * checking if it has a target and/or the function return value is used.
567      * (Target is optional, so a standalone statement can actually do nothing.)
568      */
569     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
570         (OpInfo->Flags & AML_HAS_RETVAL) &&
571         (!AnIsResultUsed (Op)))
572     {
573         if (OpInfo->Flags & AML_HAS_TARGET)
574         {
575             /*
576              * Find the target node, it is always the last child. If the target
577              * is not specified in the ASL, a default node of type Zero was
578              * created by the parser.
579              */
580             ArgOp = Op->Asl.Child;
581             while (ArgOp->Asl.Next)
582             {
583                 PrevArgOp = ArgOp;
584                 ArgOp = ArgOp->Asl.Next;
585             }
586 
587             /* Divide() is the only weird case, it has two targets */
588 
589             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
590             {
591                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) &&
592                     (PrevArgOp) &&
593                     (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO))
594                 {
595                     AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
596                         Op, Op->Asl.ExternalName);
597                 }
598             }
599 
600             else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
601             {
602                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
603                     Op, Op->Asl.ExternalName);
604             }
605         }
606         else
607         {
608             /*
609              * Has no target and the result is not used. Only a couple opcodes
610              * can have this combination.
611              */
612             switch (Op->Asl.ParseOpcode)
613             {
614             case PARSEOP_ACQUIRE:
615             case PARSEOP_WAIT:
616             case PARSEOP_LOADTABLE:
617 
618                 break;
619 
620             default:
621 
622                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
623                     Op, Op->Asl.ExternalName);
624                 break;
625             }
626         }
627     }
628 
629 
630     /*
631      * Semantic checks for individual ASL operators
632      */
633     switch (Op->Asl.ParseOpcode)
634     {
635     case PARSEOP_STORE:
636 
637         if (Gbl_DoTypechecking)
638         {
639             AnAnalyzeStoreOperator (Op);
640         }
641         break;
642 
643 
644     case PARSEOP_ACQUIRE:
645     case PARSEOP_WAIT:
646         /*
647          * Emit a warning if the timeout parameter for these operators is not
648          * ACPI_WAIT_FOREVER, and the result value from the operator is not
649          * checked, meaning that a timeout could happen, but the code
650          * would not know about it.
651          */
652 
653         /* First child is the namepath, 2nd child is timeout */
654 
655         ArgOp = Op->Asl.Child;
656         ArgOp = ArgOp->Asl.Next;
657 
658         /*
659          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
660          * 0xFFFF or greater
661          */
662         if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
663              (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
664              (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
665         {
666             break;
667         }
668 
669         /*
670          * The operation could timeout. If the return value is not used
671          * (indicates timeout occurred), issue a warning
672          */
673         if (!AnIsResultUsed (Op))
674         {
675             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp,
676                 Op->Asl.ExternalName);
677         }
678         break;
679 
680     case PARSEOP_CREATEFIELD:
681         /*
682          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
683          */
684         ArgOp = Op->Asl.Child;
685         ArgOp = ArgOp->Asl.Next;
686         ArgOp = ArgOp->Asl.Next;
687 
688         if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) ||
689            ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) &&
690             (ArgOp->Asl.Value.Integer == 0)))
691         {
692             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgOp, NULL);
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:    AnAnalyzeStoreOperator
784  *
785  * PARAMETERS:  Op                  - Store() operator
786  *
787  * RETURN:      None
788  *
789  * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package
790  *              objects where there are more restrictions than other data
791  *              types.
792  *
793  ******************************************************************************/
794 
795 static void
796 AnAnalyzeStoreOperator (
797     ACPI_PARSE_OBJECT       *Op)
798 {
799     ACPI_NAMESPACE_NODE     *SourceNode;
800     ACPI_NAMESPACE_NODE     *TargetNode;
801     ACPI_PARSE_OBJECT       *SourceOperandOp;
802     ACPI_PARSE_OBJECT       *TargetOperandOp;
803     UINT32                  SourceOperandBtype;
804     UINT32                  TargetOperandBtype;
805 
806 
807     /* Extract the two operands for STORE */
808 
809     SourceOperandOp = Op->Asl.Child;
810     TargetOperandOp = SourceOperandOp->Asl.Next;
811 
812     /*
813      * Ignore these Source operand opcodes, they cannot be typechecked,
814      * the actual result is unknown here.
815      */
816     switch (SourceOperandOp->Asl.ParseOpcode)
817     {
818     /* For these, type of the returned value is unknown at compile time */
819 
820     case PARSEOP_DEREFOF:
821     case PARSEOP_METHODCALL:
822     case PARSEOP_STORE:
823     case PARSEOP_COPYOBJECT:
824 
825         return;
826 
827     case PARSEOP_INDEX:
828     case PARSEOP_REFOF:
829 
830         if (!Gbl_EnableReferenceTypechecking)
831         {
832             return;
833         }
834 
835         /*
836          * These opcodes always return an object reference, and thus
837          * the result can only be stored to a Local, Arg, or Debug.
838          */
839         if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP)
840         {
841             return;
842         }
843 
844         if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) ||
845             (TargetOperandOp->Asl.AmlOpcode > AML_ARG6))
846         {
847             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
848                 "Source [Reference], Target must be [Local/Arg/Debug]");
849         }
850         return;
851 
852     default:
853         break;
854     }
855 
856     /*
857      * Ignore these Target operand opcodes, they cannot be typechecked
858      */
859     switch (TargetOperandOp->Asl.ParseOpcode)
860     {
861     case PARSEOP_DEBUG:
862     case PARSEOP_DEREFOF:
863     case PARSEOP_REFOF:
864     case PARSEOP_INDEX:
865     case PARSEOP_STORE:
866 
867         return;
868 
869     default:
870         break;
871     }
872 
873     /*
874      * Ignore typecheck for External() operands of type "UnknownObj",
875      * we don't know the actual type (source or target).
876      */
877     SourceNode = SourceOperandOp->Asl.Node;
878     if (SourceNode &&
879         (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
880         (SourceNode->Type == ACPI_TYPE_ANY))
881     {
882         return;
883     }
884 
885     TargetNode = TargetOperandOp->Asl.Node;
886     if (TargetNode &&
887         (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
888         (TargetNode->Type == ACPI_TYPE_ANY))
889     {
890         return;
891     }
892 
893     /*
894      * A NULL node with a namepath AML opcode indicates non-existent
895      * name. Just return, the error message is generated elsewhere.
896      */
897     if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
898         (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
899     {
900         return;
901     }
902 
903     /*
904      * Simple check for source same as target via NS node.
905      * -- Could be expanded to locals and args.
906      */
907     if (SourceNode && TargetNode)
908     {
909         if (SourceNode == TargetNode)
910         {
911             AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
912                 TargetOperandOp, "Source is the same as Target");
913             return;
914         }
915     }
916 
917     /* Ignore typecheck if either source or target is a local or arg */
918 
919     if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
920         (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
921     {
922         return; /* Cannot type a local/arg at compile time */
923     }
924 
925     if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
926         (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
927     {
928         return; /* Cannot type a local/arg at compile time */
929     }
930 
931     /*
932      * Package objects are a special case because they cannot by implicitly
933      * converted to/from anything. Check for these two illegal cases:
934      *
935      *      Store (non-package, package)
936      *      Store (package, non-package)
937      */
938     SourceOperandBtype = AnGetBtype (SourceOperandOp);
939     TargetOperandBtype = AnGetBtype (TargetOperandOp);
940 
941     /* Check source first for (package, non-package) case */
942 
943     if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
944     {
945         /* If Source is PACKAGE-->Target must be PACKAGE */
946 
947         if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
948         {
949             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
950                 "Source is [Package], Target must be a package also");
951         }
952     }
953 
954     /* Else check target for (non-package, package) case */
955 
956     else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
957     {
958         /* If Target is PACKAGE, Source must be PACKAGE */
959 
960         if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
961         {
962             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
963                 "Target is [Package], Source must be a package also");
964         }
965     }
966 }
967