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