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