1/******************************************************************************
2 *
3 * Module Name: aslmethod.c - Control method analysis walk
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/acnamesp.h>
155#include <contrib/dev/acpica/include/acparser.h>
156#include <contrib/dev/acpica/include/amlcode.h>
157
158
159#define _COMPONENT          ACPI_COMPILER
160        ACPI_MODULE_NAME    ("aslmethod")
161
162
163/* Local prototypes */
164
165static void
166MtCheckNamedObjectInMethod (
167    ACPI_PARSE_OBJECT       *Op,
168    ASL_METHOD_INFO         *MethodInfo);
169
170static void
171MtCheckStaticOperationRegionInMethod (
172    ACPI_PARSE_OBJECT       *Op);
173
174
175/*******************************************************************************
176 *
177 * FUNCTION:    MtMethodAnalysisWalkBegin
178 *
179 * PARAMETERS:  ASL_WALK_CALLBACK
180 *
181 * RETURN:      Status
182 *
183 * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
184 *              1) Initialized local variables
185 *              2) Valid arguments
186 *              3) Return types
187 *
188 ******************************************************************************/
189
190ACPI_STATUS
191MtMethodAnalysisWalkBegin (
192    ACPI_PARSE_OBJECT       *Op,
193    UINT32                  Level,
194    void                    *Context)
195{
196    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
197    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
198    ACPI_PARSE_OBJECT       *Next;
199    UINT32                  RegisterNumber;
200    UINT32                  i;
201    char                    LocalName[] = "Local0";
202    char                    ArgName[] = "Arg0";
203    ACPI_PARSE_OBJECT       *ArgNode;
204    ACPI_PARSE_OBJECT       *NextType;
205    UINT8                   ActualArgs = 0;
206    BOOLEAN                 HidExists;
207    BOOLEAN                 AdrExists;
208    BOOLEAN                 PrsExists;
209    BOOLEAN                 CrsExists;
210    BOOLEAN                 SrsExists;
211    BOOLEAN                 DisExists;
212
213
214    /* Build cross-reference output file if requested */
215
216    if (AslGbl_CrossReferenceOutput)
217    {
218        OtXrefWalkPart1 (Op, Level, MethodInfo);
219    }
220
221    switch (Op->Asl.ParseOpcode)
222    {
223    case PARSEOP_METHOD:
224
225        AslGbl_TotalMethods++;
226
227        /* Create and init method info */
228
229        MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
230        MethodInfo->Next = WalkInfo->MethodStack;
231        MethodInfo->Op = Op;
232
233        WalkInfo->MethodStack = MethodInfo;
234
235        /*
236         * Special handling for _PSx methods. Dependency rules (same scope):
237         *
238         * 1) _PS0 - One of these must exist: _PS1, _PS2, _PS3
239         * 2) _PS1/_PS2/_PS3: A _PS0 must exist
240         */
241        if (ACPI_COMPARE_NAMESEG (METHOD_NAME__PS0, Op->Asl.NameSeg))
242        {
243            /* For _PS0, one of _PS1/_PS2/_PS3 must exist */
244
245            if ((!ApFindNameInScope (METHOD_NAME__PS1, Op)) &&
246                (!ApFindNameInScope (METHOD_NAME__PS2, Op)) &&
247                (!ApFindNameInScope (METHOD_NAME__PS3, Op)))
248            {
249                AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
250                    "_PS0 requires one of _PS1/_PS2/_PS3 in same scope");
251            }
252        }
253        else if (
254            ACPI_COMPARE_NAMESEG (METHOD_NAME__PS1, Op->Asl.NameSeg) ||
255            ACPI_COMPARE_NAMESEG (METHOD_NAME__PS2, Op->Asl.NameSeg) ||
256            ACPI_COMPARE_NAMESEG (METHOD_NAME__PS3, Op->Asl.NameSeg))
257        {
258            /* For _PS1/_PS2/_PS3, a _PS0 must exist */
259
260            if (!ApFindNameInScope (METHOD_NAME__PS0, Op))
261            {
262                sprintf (AslGbl_MsgBuffer,
263                    "%4.4s requires _PS0 in same scope", Op->Asl.NameSeg);
264
265                AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
266                    AslGbl_MsgBuffer);
267            }
268        }
269
270        /* Get the name node */
271
272        Next = Op->Asl.Child;
273
274        /* Get the NumArguments node */
275
276        Next = Next->Asl.Next;
277        MethodInfo->NumArguments = (UINT8)
278            (((UINT8) Next->Asl.Value.Integer) & 0x07);
279
280        /* Get the SerializeRule and SyncLevel nodes, ignored here */
281
282        Next = Next->Asl.Next;
283        MethodInfo->ShouldBeSerialized = (UINT8) Next->Asl.Value.Integer;
284
285        Next = Next->Asl.Next;
286        ArgNode = Next;
287
288        /* Get the ReturnType node */
289
290        Next = Next->Asl.Next;
291
292        NextType = Next->Asl.Child;
293
294        MethodInfo->ValidReturnTypes = MtProcessTypeOp (NextType);
295        Op->Asl.AcpiBtype |= MethodInfo->ValidReturnTypes;
296
297        /* Get the ParameterType node */
298
299        Next = Next->Asl.Next;
300
301        NextType = Next->Asl.Child;
302        if (!NextType)
303        {
304            /*
305             * The optional parameter types list was omitted  at the source
306             * level. Use the Argument count parameter instead.
307             */
308            ActualArgs = MethodInfo->NumArguments;
309        }
310        else
311        {
312            ActualArgs = MtProcessParameterTypeList (NextType,
313                MethodInfo->ValidArgTypes);
314            MethodInfo->NumArguments = ActualArgs;
315            ArgNode->Asl.Value.Integer |= ActualArgs;
316        }
317
318        if ((MethodInfo->NumArguments) &&
319            (MethodInfo->NumArguments != ActualArgs))
320        {
321            sprintf (AslGbl_MsgBuffer,
322                "Length = %u", ActualArgs);
323            AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_MISMATCH,
324                Op->Asl.Child->Asl.Next, AslGbl_MsgBuffer);
325        }
326
327        /* Allow numarguments == 0 for Function() */
328
329        if ((!MethodInfo->NumArguments) && (ActualArgs))
330        {
331            MethodInfo->NumArguments = ActualArgs;
332            ArgNode->Asl.Value.Integer |= ActualArgs;
333        }
334
335        /*
336         * Actual arguments are initialized at method entry.
337         * All other ArgX "registers" can be used as locals, so we
338         * track their initialization.
339         */
340        for (i = 0; i < MethodInfo->NumArguments; i++)
341        {
342            MethodInfo->ArgInitialized[i] = TRUE;
343        }
344        break;
345
346    case PARSEOP_METHODCALL:
347
348        /* Check for a recursive method call */
349
350        if (MethodInfo &&
351           (Op->Asl.Node == MethodInfo->Op->Asl.Node))
352        {
353            if (MethodInfo->CreatesNamedObjects)
354            {
355                /*
356                 * This is an error, as it will fail at runtime on all ACPI
357                 * implementations. Any named object declarations will be
358                 * executed twice, causing failure the second time. Note,
359                 * this is independent of whether the method is declared
360                 * Serialized, because the same thread is attempting to
361                 * reenter the method, and this will always succeed.
362                 */
363                AslDualParseOpError (ASL_ERROR, ASL_MSG_ILLEGAL_RECURSION, Op,
364                    Op->Asl.Value.String, ASL_MSG_FOUND_HERE, MethodInfo->Op,
365                    MethodInfo->Op->Asl.ExternalName);
366            }
367            else
368            {
369                /* Method does not create objects, issue a remark */
370
371                AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
372            }
373        }
374        break;
375
376    case PARSEOP_LOCAL0:
377    case PARSEOP_LOCAL1:
378    case PARSEOP_LOCAL2:
379    case PARSEOP_LOCAL3:
380    case PARSEOP_LOCAL4:
381    case PARSEOP_LOCAL5:
382    case PARSEOP_LOCAL6:
383    case PARSEOP_LOCAL7:
384
385        if (!MethodInfo)
386        {
387            /*
388             * Local was used outside a control method, or there was an error
389             * in the method declaration.
390             */
391            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
392                Op, Op->Asl.ExternalName);
393            return (AE_ERROR);
394        }
395
396        RegisterNumber = (Op->Asl.AmlOpcode & 0x0007);
397
398        /*
399         * If the local is being used as a target, mark the local
400         * initialized
401         */
402        if (Op->Asl.CompileFlags & OP_IS_TARGET)
403        {
404            MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
405        }
406
407        /*
408         * Otherwise, this is a reference, check if the local
409         * has been previously initialized.
410         *
411         * The only operator that accepts an uninitialized value is ObjectType()
412         */
413        else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
414                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
415        {
416            LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
417            AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
418        }
419        break;
420
421    case PARSEOP_ARG0:
422    case PARSEOP_ARG1:
423    case PARSEOP_ARG2:
424    case PARSEOP_ARG3:
425    case PARSEOP_ARG4:
426    case PARSEOP_ARG5:
427    case PARSEOP_ARG6:
428
429        if (!MethodInfo)
430        {
431            /*
432             * Arg was used outside a control method, or there was an error
433             * in the method declaration.
434             */
435            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
436                Op, Op->Asl.ExternalName);
437            return (AE_ERROR);
438        }
439
440        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
441        ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
442
443        /*
444         * If the Arg is being used as a target, mark the local
445         * initialized
446         */
447        if (Op->Asl.CompileFlags & OP_IS_TARGET)
448        {
449            MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
450        }
451
452        /*
453         * Otherwise, this is a reference, check if the Arg
454         * has been previously initialized.
455         *
456         * The only operator that accepts an uninitialized value is ObjectType()
457         */
458        else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
459            (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
460        {
461            AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
462        }
463
464        /* Flag this arg if it is not a "real" argument to the method */
465
466        if (RegisterNumber >= MethodInfo->NumArguments)
467        {
468            AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
469        }
470        break;
471
472    case PARSEOP_RETURN:
473
474        if (!MethodInfo)
475        {
476            /*
477             * Probably was an error in the method declaration,
478             * no additional error here
479             */
480            ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
481            return (AE_ERROR);
482        }
483
484        /*
485         * A child indicates a possible return value. A simple Return or
486         * Return() is marked with OP_IS_NULL_RETURN by the parser so
487         * that it is not counted as a "real" return-with-value, although
488         * the AML code that is actually emitted is Return(0). The AML
489         * definition of Return has a required parameter, so we are
490         * forced to convert a null return to Return(0).
491         */
492        if ((Op->Asl.Child) &&
493            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
494            (!(Op->Asl.Child->Asl.CompileFlags & OP_IS_NULL_RETURN)))
495        {
496            MethodInfo->NumReturnWithValue++;
497        }
498        else
499        {
500            MethodInfo->NumReturnNoValue++;
501        }
502        break;
503
504    case PARSEOP_BREAK:
505    case PARSEOP_CONTINUE:
506
507        Next = Op->Asl.Parent;
508        while (Next)
509        {
510            if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
511            {
512                break;
513            }
514            Next = Next->Asl.Parent;
515        }
516
517        if (!Next)
518        {
519            AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
520        }
521        break;
522
523    case PARSEOP_STALL:
524
525        /* We can range check if the argument is an integer */
526
527        if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
528            (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
529        {
530            AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
531        }
532        break;
533
534    case PARSEOP_DEVICE:
535
536        /* Check usage of _HID and _ADR objects */
537
538        HidExists = ApFindNameInDeviceTree (METHOD_NAME__HID, Op);
539        AdrExists = ApFindNameInDeviceTree (METHOD_NAME__ADR, Op);
540
541        if (!HidExists && !AdrExists)
542        {
543            AslError (ASL_ERROR, ASL_MSG_MISSING_DEPENDENCY, Op,
544                "Device object requires a _HID or _ADR");
545        }
546        else if (HidExists && AdrExists)
547        {
548            /*
549             * According to the ACPI spec, "A device object must contain
550             * either an _HID object or an _ADR object, but should not contain
551             * both".
552             */
553            AslError (ASL_WARNING, ASL_MSG_MULTIPLE_TYPES, Op,
554                "Device object requires either a _HID or _ADR, but not both");
555        }
556
557        /*
558         * Check usage of _CRS, _DIS, _PRS, and _SRS objects (July 2021).
559         *
560         * Under the Device Object:
561         *
562         * 1) If _PRS present, must have _CRS and _SRS
563         * 2) If _SRS present, must have _PRS (_PRS requires _CRS and _SRS)
564         * 3) If _DIS present, must have _SRS (_SRS requires _PRS, _PRS requires _CRS and _SRS)
565         * 4) If _SRS present, probably should have a _DIS (Remark only)
566         */
567        CrsExists = ApFindNameInDeviceTree (METHOD_NAME__CRS, Op);
568        DisExists = ApFindNameInDeviceTree (METHOD_NAME__DIS, Op);
569        PrsExists = ApFindNameInDeviceTree (METHOD_NAME__PRS, Op);
570        SrsExists = ApFindNameInDeviceTree (METHOD_NAME__SRS, Op);
571
572        /* 1) If _PRS is present, must have a _CRS and _SRS */
573
574        if (PrsExists)
575        {
576            if (!CrsExists)
577            {
578                AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
579                    "Device has a _PRS, missing a _CRS, required");
580            }
581            if (!SrsExists)
582            {
583                AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
584                    "Device has a _PRS, missing a _SRS, required");
585            }
586        }
587
588        /* 2) If _SRS is present, must have _PRS (_PRS requires _CRS and _SRS) */
589
590        if ((SrsExists) && (!PrsExists))
591        {
592            AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
593                "Device has a _SRS, missing a _PRS, required");
594        }
595
596        /* 3) If _DIS is present, must have a _SRS */
597
598        if ((DisExists) && (!SrsExists))
599        {
600            AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
601                "Device has a _DIS, missing a _SRS, required");
602        }
603
604        /*
605         * 4) If _SRS is present, should have a _DIS (_PRS requires _CRS
606         * and _SRS)  Remark only.
607         */
608        if ((SrsExists) && (!DisExists))
609        {
610            AslError (ASL_REMARK, ASL_MSG_MISSING_DEPENDENCY, Op,
611                "Device has a _SRS, no corresponding _DIS");
612        }
613        break;
614
615    case PARSEOP_EVENT:
616    case PARSEOP_MUTEX:
617    case PARSEOP_OPERATIONREGION:
618    case PARSEOP_POWERRESOURCE:
619    case PARSEOP_PROCESSOR:
620    case PARSEOP_THERMALZONE:
621
622        /*
623         * The first operand is a name to be created in the namespace.
624         * Check against the reserved list.
625         */
626        i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
627        if (i < ACPI_VALID_RESERVED_NAME_MAX)
628        {
629            AslError (ASL_ERROR, ASL_MSG_RESERVED_USE,
630                Op, Op->Asl.ExternalName);
631        }
632
633        MtCheckStaticOperationRegionInMethod (Op);
634        break;
635
636    case PARSEOP_NAME:
637
638        /* Typecheck any predefined names statically defined with Name() */
639
640        ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
641
642        /* Special typechecking for _HID */
643
644        if (ACPI_COMPARE_NAMESEG (METHOD_NAME__HID, Op->Asl.NameSeg))
645        {
646            Next = Op->Asl.Child->Asl.Next;
647            AnCheckId (Next, ASL_TYPE_HID);
648        }
649
650        /* Special typechecking for _CID */
651
652        else if (ACPI_COMPARE_NAMESEG (METHOD_NAME__CID, Op->Asl.NameSeg))
653        {
654            Next = Op->Asl.Child->Asl.Next;
655
656            if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
657                (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
658            {
659                Next = Next->Asl.Child;
660                while (Next)
661                {
662                    AnCheckId (Next, ASL_TYPE_CID);
663                    Next = Next->Asl.Next;
664                }
665            }
666            else
667            {
668                AnCheckId (Next, ASL_TYPE_CID);
669            }
670        }
671
672        break;
673
674    default:
675
676        break;
677    }
678
679    /* Check for named object creation within a non-serialized method */
680
681    MtCheckNamedObjectInMethod (Op, MethodInfo);
682    return (AE_OK);
683}
684
685
686/*******************************************************************************
687 *
688 * FUNCTION:    MtProcessTypeOp
689 *
690 * PARAMETERS:  Op                  - Op representing a btype
691 *
692 * RETURN:      Btype represented by Op
693 *
694 * DESCRIPTION: Process a parse object that represents single parameter type or
695 *              a return type in method, function, and external declarations.
696 *
697 ******************************************************************************/
698
699UINT32
700MtProcessTypeOp (
701    ACPI_PARSE_OBJECT       *TypeOp)
702{
703    UINT32                  Btype = ACPI_BTYPE_ANY;
704
705
706    while (TypeOp)
707    {
708        Btype |= AnMapObjTypeToBtype (TypeOp);
709        TypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
710        TypeOp = TypeOp->Asl.Next;
711    }
712
713    return (Btype);
714}
715
716
717/*******************************************************************************
718 *
719 * FUNCTION:    MtProcessParameterTypeList
720 *
721 * PARAMETERS:  Op                  - Op representing a btype
722 *
723 * RETURN:      Btype represented by Op
724 *
725 * DESCRIPTION: Process a parse object that represents a parameter type list in
726 *              method, function, and external declarations.
727 *
728 ******************************************************************************/
729
730UINT8
731MtProcessParameterTypeList (
732    ACPI_PARSE_OBJECT       *ParamTypeOp,
733    UINT32                  *TypeList)
734{
735    UINT8                   ParameterCount = 0;
736
737
738    if (ParamTypeOp && ParamTypeOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
739    {
740        /* Special case for a single parameter without braces */
741
742        TypeList[ParameterCount] =
743            MtProcessTypeOp (ParamTypeOp);
744
745        return (1);
746    }
747
748    while (ParamTypeOp)
749    {
750        TypeList[ParameterCount] =
751            MtProcessTypeOp (ParamTypeOp->Asl.Child);
752
753        ParameterCount++;
754        ParamTypeOp = ParamTypeOp->Asl.Next;
755    }
756
757    return (ParameterCount);
758}
759
760
761/*******************************************************************************
762 *
763 * FUNCTION:    MtCheckNamedObjectInMethod
764 *
765 * PARAMETERS:  Op                  - Current parser op
766 *              MethodInfo          - Info for method being parsed
767 *
768 * RETURN:      None
769 *
770 * DESCRIPTION: Detect if a non-serialized method is creating a named object,
771 *              which could possibly cause problems if two threads execute
772 *              the method concurrently. Emit a remark in this case.
773 *
774 ******************************************************************************/
775
776static void
777MtCheckNamedObjectInMethod (
778    ACPI_PARSE_OBJECT       *Op,
779    ASL_METHOD_INFO         *MethodInfo)
780{
781    const ACPI_OPCODE_INFO  *OpInfo;
782    char                    *ExternalPath;
783
784
785    /* We don't care about actual method declarations or scopes */
786
787    if ((Op->Asl.AmlOpcode == AML_METHOD_OP) ||
788        (Op->Asl.AmlOpcode == AML_SCOPE_OP))
789    {
790        return;
791    }
792
793    /* Determine if we are creating a named object within a method */
794
795    if (!MethodInfo)
796    {
797        return;
798    }
799
800    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
801    if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_FIELD_OP))
802    {
803        /*
804         * 1) Mark the method as a method that creates named objects.
805         *
806         * 2) Issue a remark indicating the inefficiency of creating named
807         * objects within a method (Except for compiler-emitted temporary
808         * variables).
809         *
810         * 3) If the method is non-serialized, emit a remark that the method
811         * should be serialized.
812         *
813         * Reason: If a thread blocks within the method for any reason, and
814         * another thread enters the method, the method will fail because
815         * an attempt will be made to create the same object twice.
816         *
817         * Note: The Field opcode is disallowed here because Field() does not
818         * create a new named object.
819         */
820        ExternalPath = AcpiNsGetNormalizedPathname (MethodInfo->Op->Asl.Node, TRUE);
821
822        /* No error for compiler temp variables (name starts with "_T_") */
823
824        if ((Op->Asl.NameSeg[0] != '_') &&
825            (Op->Asl.NameSeg[1] != 'T') &&
826            (Op->Asl.NameSeg[2] != '_'))
827        {
828            AslError (ASL_REMARK, ASL_MSG_NAMED_OBJECT_CREATION, Op,
829                ExternalPath);
830        }
831
832        MethodInfo->CreatesNamedObjects = TRUE;
833        if (!MethodInfo->ShouldBeSerialized)
834        {
835            AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op,
836                ExternalPath);
837
838            /* Emit message only ONCE per method */
839
840            MethodInfo->ShouldBeSerialized = TRUE;
841        }
842
843        if (ExternalPath)
844        {
845            ACPI_FREE (ExternalPath);
846        }
847    }
848}
849
850
851/*******************************************************************************
852 *
853 * FUNCTION:    MtCheckStaticOperationRegionInMethod
854 *
855 * PARAMETERS:  Op                  - Current parser op
856 *
857 * RETURN:      None
858 *
859 * DESCRIPTION: Warns if an Operation Region with static address or length
860 *              is declared inside a control method
861 *
862 ******************************************************************************/
863
864static void
865MtCheckStaticOperationRegionInMethod(
866    ACPI_PARSE_OBJECT*       Op)
867{
868    ACPI_PARSE_OBJECT*       AddressOp;
869    ACPI_PARSE_OBJECT*       LengthOp;
870
871
872    if (Op->Asl.ParseOpcode != PARSEOP_OPERATIONREGION)
873    {
874        return;
875    }
876
877    /*
878     * OperationRegion should have 4 arguments defined. At this point, we
879     * assume that the parse tree is well-formed.
880     */
881    AddressOp = Op->Asl.Child->Asl.Next->Asl.Next;
882    LengthOp = Op->Asl.Child->Asl.Next->Asl.Next->Asl.Next;
883
884    if (UtGetParentMethodOp (Op) &&
885        AddressOp->Asl.ParseOpcode == PARSEOP_INTEGER &&
886        LengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)
887    {
888        /*
889         * At this point, a static operation region declared inside of a
890         * control method has been found. Throw a warning because this is
891         * highly inefficient.
892         */
893        AslError(ASL_WARNING, ASL_MSG_STATIC_OPREGION_IN_METHOD, Op, NULL);
894    }
895
896    return;
897}
898
899
900/*******************************************************************************
901 *
902 * FUNCTION:    MtMethodAnalysisWalkEnd
903 *
904 * PARAMETERS:  ASL_WALK_CALLBACK
905 *
906 * RETURN:      Status
907 *
908 * DESCRIPTION: Ascending callback for analysis walk. Complete method
909 *              return analysis.
910 *
911 ******************************************************************************/
912
913ACPI_STATUS
914MtMethodAnalysisWalkEnd (
915    ACPI_PARSE_OBJECT       *Op,
916    UINT32                  Level,
917    void                    *Context)
918{
919    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
920    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
921    char                    *ExternalPath;
922
923
924    switch (Op->Asl.ParseOpcode)
925    {
926    case PARSEOP_METHOD:
927    case PARSEOP_RETURN:
928
929        if (!MethodInfo)
930        {
931            printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
932            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
933                "No method info for this method");
934
935            CmCleanupAndExit ();
936            return (AE_AML_INTERNAL);
937        }
938        break;
939
940    default:
941
942        break;
943    }
944
945    switch (Op->Asl.ParseOpcode)
946    {
947    case PARSEOP_METHOD:
948
949        WalkInfo->MethodStack = MethodInfo->Next;
950
951        /*
952         * Check if there is no return statement at the end of the
953         * method AND we can actually get there -- i.e., the execution
954         * of the method can possibly terminate without a return statement.
955         */
956        if ((!AnLastStatementIsReturn (Op)) &&
957            (!(Op->Asl.CompileFlags & OP_HAS_NO_EXIT)))
958        {
959            /*
960             * No return statement, and execution can possibly exit
961             * via this path. This is equivalent to Return ()
962             */
963            MethodInfo->NumReturnNoValue++;
964        }
965
966        /*
967         * Check for case where some return statements have a return value
968         * and some do not. Exit without a return statement is a return with
969         * no value
970         */
971        if (MethodInfo->NumReturnNoValue &&
972            MethodInfo->NumReturnWithValue)
973        {
974            ExternalPath = AcpiNsGetNormalizedPathname (Op->Asl.Node, TRUE);
975
976            AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
977                ExternalPath);
978
979            if (ExternalPath)
980            {
981                ACPI_FREE (ExternalPath);
982            }
983        }
984
985        /*
986         * If there are any RETURN() statements with no value, or there is a
987         * control path that allows the method to exit without a return value,
988         * we mark the method as a method that does not return a value. This
989         * knowledge can be used to check method invocations that expect a
990         * returned value.
991         */
992        if (MethodInfo->NumReturnNoValue)
993        {
994            if (MethodInfo->NumReturnWithValue)
995            {
996                Op->Asl.CompileFlags |= OP_METHOD_SOME_NO_RETVAL;
997            }
998            else
999            {
1000                Op->Asl.CompileFlags |= OP_METHOD_NO_RETVAL;
1001            }
1002        }
1003
1004        /*
1005         * Check predefined method names for correct return behavior
1006         * and correct number of arguments. Also, some special checks
1007         * For GPE and _REG methods.
1008         */
1009        if (ApCheckForPredefinedMethod (Op, MethodInfo))
1010        {
1011            /* Special check for two names like _L01 and _E01 in same scope */
1012
1013            ApCheckForGpeNameConflict (Op);
1014
1015            /*
1016             * Special check for _REG: Must have an operation region definition
1017             * within the same scope!
1018             */
1019            ApCheckRegMethod (Op);
1020        }
1021
1022        ACPI_FREE (MethodInfo);
1023        break;
1024
1025    case PARSEOP_NAME:
1026
1027         /* Special check for two names like _L01 and _E01 in same scope */
1028
1029        ApCheckForGpeNameConflict (Op);
1030        break;
1031
1032    case PARSEOP_RETURN:
1033
1034        /*
1035         * If the parent is a predefined method name, attempt to typecheck
1036         * the return value. Only static types can be validated.
1037         */
1038        ApCheckPredefinedReturnValue (Op, MethodInfo);
1039
1040        /*
1041         * The parent block does not "exit" and continue execution -- the
1042         * method is terminated here with the Return() statement.
1043         */
1044        Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
1045
1046        /* Used in the "typing" pass later */
1047
1048        Op->Asl.ParentMethod = MethodInfo->Op;
1049
1050        /*
1051         * If there is a peer node after the return statement, then this
1052         * node is unreachable code -- i.e., it won't be executed because of
1053         * the preceding Return() statement.
1054         */
1055        if (Op->Asl.Next)
1056        {
1057            AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE,
1058                Op->Asl.Next, NULL);
1059        }
1060        break;
1061
1062    case PARSEOP_IF:
1063
1064        if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
1065            (Op->Asl.Next) &&
1066            (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
1067        {
1068            /*
1069             * This IF has a corresponding ELSE. The IF block has no exit,
1070             * (it contains an unconditional Return)
1071             * mark the ELSE block to remember this fact.
1072             */
1073            Op->Asl.Next->Asl.CompileFlags |= OP_IF_HAS_NO_EXIT;
1074        }
1075        break;
1076
1077    case PARSEOP_ELSE:
1078
1079        if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
1080            (Op->Asl.CompileFlags & OP_IF_HAS_NO_EXIT))
1081        {
1082            /*
1083             * This ELSE block has no exit and the corresponding IF block
1084             * has no exit either. Therefore, the parent node has no exit.
1085             */
1086            Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
1087        }
1088        break;
1089
1090
1091    default:
1092
1093        if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
1094            (Op->Asl.Parent))
1095        {
1096            /* If this node has no exit, then the parent has no exit either */
1097
1098            Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
1099        }
1100        break;
1101    }
1102
1103    return (AE_OK);
1104}
1105