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