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