aslwalks.c revision 306536
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
56static void
57AnAnalyzeStoreOperator (
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
77ACPI_STATUS
78AnMethodTypingWalkEnd (
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
155ACPI_STATUS
156AnOperandTypecheckWalkEnd (
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
549ACPI_STATUS
550AnOtherSemanticAnalysisWalkBegin (
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
795static void
796AnAnalyzeStoreOperator (
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
866        return;
867
868    case PARSEOP_METHODCALL:
869        /*
870         * A target is not allowed to be a method call.
871         * It is not supported by the ACPICA interpreter, nor is it
872         * supported by the MS ASL compiler or the MS interpreter.
873         * Although legal syntax up until ACPI 6.1, support for this
874         * will be removed for ACPI 6.2 (02/2016)
875         */
876        AslError (ASL_ERROR, ASL_MSG_SYNTAX,
877            TargetOperandOp, "Illegal method invocation as a target operand");
878        return;
879
880    default:
881        break;
882    }
883
884    /*
885     * Ignore typecheck for External() operands of type "UnknownObj",
886     * we don't know the actual type (source or target).
887     */
888    SourceNode = SourceOperandOp->Asl.Node;
889    if (SourceNode &&
890        (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
891        (SourceNode->Type == ACPI_TYPE_ANY))
892    {
893        return;
894    }
895
896    TargetNode = TargetOperandOp->Asl.Node;
897    if (TargetNode &&
898        (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
899        (TargetNode->Type == ACPI_TYPE_ANY))
900    {
901        return;
902    }
903
904    /*
905     * A NULL node with a namepath AML opcode indicates non-existent
906     * name. Just return, the error message is generated elsewhere.
907     */
908    if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
909        (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
910    {
911        return;
912    }
913
914    /*
915     * Simple check for source same as target via NS node.
916     * -- Could be expanded to locals and args.
917     */
918    if (SourceNode && TargetNode)
919    {
920        if (SourceNode == TargetNode)
921        {
922            AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
923                TargetOperandOp, "Source is the same as Target");
924            return;
925        }
926    }
927
928    /* Ignore typecheck if either source or target is a local or arg */
929
930    if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
931        (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
932    {
933        return; /* Cannot type a local/arg at compile time */
934    }
935
936    if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
937        (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
938    {
939        return; /* Cannot type a local/arg at compile time */
940    }
941
942    /*
943     * Package objects are a special case because they cannot by implicitly
944     * converted to/from anything. Check for these two illegal cases:
945     *
946     *      Store (non-package, package)
947     *      Store (package, non-package)
948     */
949    SourceOperandBtype = AnGetBtype (SourceOperandOp);
950    TargetOperandBtype = AnGetBtype (TargetOperandOp);
951
952    /* Check source first for (package, non-package) case */
953
954    if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
955    {
956        /* If Source is PACKAGE-->Target must be PACKAGE */
957
958        if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
959        {
960            AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
961                "Source is [Package], Target must be a package also");
962        }
963    }
964
965    /* Else check target for (non-package, package) case */
966
967    else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
968    {
969        /* If Target is PACKAGE, Source must be PACKAGE */
970
971        if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
972        {
973            AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
974                "Target is [Package], Source must be a package also");
975        }
976    }
977}
978