aslanalyze.c revision 216471
1
2/******************************************************************************
3 *
4 * Module Name: aslanalyze.c - check for semantic errors
5 *
6 *****************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#include <contrib/dev/acpica/compiler/aslcompiler.h>
119#include "aslcompiler.y.h"
120#include <contrib/dev/acpica/include/acparser.h>
121#include <contrib/dev/acpica/include/amlcode.h>
122
123#define _COMPONENT          ACPI_COMPILER
124        ACPI_MODULE_NAME    ("aslanalyze")
125
126/* Local prototypes */
127
128static UINT32
129AnMapArgTypeToBtype (
130    UINT32                  ArgType);
131
132static UINT32
133AnMapEtypeToBtype (
134    UINT32                  Etype);
135
136static void
137AnFormatBtype (
138    char                    *Buffer,
139    UINT32                  Btype);
140
141static UINT32
142AnGetBtype (
143    ACPI_PARSE_OBJECT       *Op);
144
145static UINT32
146AnMapObjTypeToBtype (
147    ACPI_PARSE_OBJECT       *Op);
148
149static BOOLEAN
150AnLastStatementIsReturn (
151    ACPI_PARSE_OBJECT       *Op);
152
153static void
154AnCheckMethodReturnValue (
155    ACPI_PARSE_OBJECT       *Op,
156    const ACPI_OPCODE_INFO  *OpInfo,
157    ACPI_PARSE_OBJECT       *ArgOp,
158    UINT32                  RequiredBtypes,
159    UINT32                  ThisNodeBtype);
160
161static BOOLEAN
162AnIsInternalMethod (
163    ACPI_PARSE_OBJECT       *Op);
164
165static UINT32
166AnGetInternalMethodReturnType (
167    ACPI_PARSE_OBJECT       *Op);
168
169static BOOLEAN
170AnIsResultUsed (
171    ACPI_PARSE_OBJECT       *Op);
172
173
174/*******************************************************************************
175 *
176 * FUNCTION:    AnIsInternalMethod
177 *
178 * PARAMETERS:  Op              - Current op
179 *
180 * RETURN:      Boolean
181 *
182 * DESCRIPTION: Check for an internal control method.
183 *
184 ******************************************************************************/
185
186static BOOLEAN
187AnIsInternalMethod (
188    ACPI_PARSE_OBJECT       *Op)
189{
190
191    if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) ||
192        (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI")))
193    {
194        return (TRUE);
195    }
196
197    return (FALSE);
198}
199
200
201/*******************************************************************************
202 *
203 * FUNCTION:    AnGetInternalMethodReturnType
204 *
205 * PARAMETERS:  Op              - Current op
206 *
207 * RETURN:      Btype
208 *
209 * DESCRIPTION: Get the return type of an internal method
210 *
211 ******************************************************************************/
212
213static UINT32
214AnGetInternalMethodReturnType (
215    ACPI_PARSE_OBJECT       *Op)
216{
217
218    if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) ||
219        (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI")))
220    {
221        return (ACPI_BTYPE_STRING);
222    }
223
224    return (0);
225}
226
227
228/*******************************************************************************
229 *
230 * FUNCTION:    AnMapArgTypeToBtype
231 *
232 * PARAMETERS:  ArgType      - The ARGI required type(s) for this argument,
233 *                             from the opcode info table
234 *
235 * RETURN:      The corresponding Bit-encoded types
236 *
237 * DESCRIPTION: Convert an encoded ARGI required argument type code into a
238 *              bitfield type code. Implements the implicit source conversion
239 *              rules.
240 *
241 ******************************************************************************/
242
243static UINT32
244AnMapArgTypeToBtype (
245    UINT32                  ArgType)
246{
247
248    switch (ArgType)
249    {
250
251    /* Simple types */
252
253    case ARGI_ANYTYPE:
254        return (ACPI_BTYPE_OBJECTS_AND_REFS);
255
256    case ARGI_PACKAGE:
257        return (ACPI_BTYPE_PACKAGE);
258
259    case ARGI_EVENT:
260        return (ACPI_BTYPE_EVENT);
261
262    case ARGI_MUTEX:
263        return (ACPI_BTYPE_MUTEX);
264
265    case ARGI_DDBHANDLE:
266        /*
267         * DDBHandleObject := SuperName
268         * ACPI_BTYPE_REFERENCE: Index reference as parameter of Load/Unload
269         */
270        return (ACPI_BTYPE_DDB_HANDLE | ACPI_BTYPE_REFERENCE);
271
272    /* Interchangeable types */
273    /*
274     * Source conversion rules:
275     * Integer, String, and Buffer are all interchangeable
276     */
277    case ARGI_INTEGER:
278    case ARGI_STRING:
279    case ARGI_BUFFER:
280    case ARGI_BUFFER_OR_STRING:
281    case ARGI_COMPUTEDATA:
282        return (ACPI_BTYPE_COMPUTE_DATA);
283
284    /* References */
285
286    case ARGI_INTEGER_REF:
287        return (ACPI_BTYPE_INTEGER);
288
289    case ARGI_OBJECT_REF:
290        return (ACPI_BTYPE_ALL_OBJECTS);
291
292    case ARGI_DEVICE_REF:
293        return (ACPI_BTYPE_DEVICE_OBJECTS);
294
295    case ARGI_REFERENCE:
296        return (ACPI_BTYPE_REFERENCE);
297
298    case ARGI_TARGETREF:
299    case ARGI_FIXED_TARGET:
300    case ARGI_SIMPLE_TARGET:
301        return (ACPI_BTYPE_OBJECTS_AND_REFS);
302
303    /* Complex types */
304
305    case ARGI_DATAOBJECT:
306
307        /*
308         * Buffer, string, package or reference to a Op -
309         * Used only by SizeOf operator
310         */
311        return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER |
312            ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE);
313
314    case ARGI_COMPLEXOBJ:
315
316        /* Buffer, String, or package */
317
318        return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | ACPI_BTYPE_PACKAGE);
319
320    case ARGI_REF_OR_STRING:
321        return (ACPI_BTYPE_STRING | ACPI_BTYPE_REFERENCE);
322
323    case ARGI_REGION_OR_BUFFER:
324
325        /* Used by Load() only. Allow buffers in addition to regions/fields */
326
327        return (ACPI_BTYPE_REGION | ACPI_BTYPE_BUFFER | ACPI_BTYPE_FIELD_UNIT);
328
329    case ARGI_DATAREFOBJ:
330        return (ACPI_BTYPE_INTEGER |ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER |
331            ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE);
332
333    default:
334        break;
335    }
336
337    return (ACPI_BTYPE_OBJECTS_AND_REFS);
338}
339
340
341/*******************************************************************************
342 *
343 * FUNCTION:    AnMapEtypeToBtype
344 *
345 * PARAMETERS:  Etype           - Encoded ACPI Type
346 *
347 * RETURN:      Btype corresponding to the Etype
348 *
349 * DESCRIPTION: Convert an encoded ACPI type to a bitfield type applying the
350 *              operand conversion rules. In other words, returns the type(s)
351 *              this Etype is implicitly converted to during interpretation.
352 *
353 ******************************************************************************/
354
355static UINT32
356AnMapEtypeToBtype (
357    UINT32                  Etype)
358{
359
360
361    if (Etype == ACPI_TYPE_ANY)
362    {
363        return ACPI_BTYPE_OBJECTS_AND_REFS;
364    }
365
366    /* Try the standard ACPI data types */
367
368    if (Etype <= ACPI_TYPE_EXTERNAL_MAX)
369    {
370        /*
371         * This switch statement implements the allowed operand conversion
372         * rules as per the "ASL Data Types" section of the ACPI
373         * specification.
374         */
375        switch (Etype)
376        {
377        case ACPI_TYPE_INTEGER:
378            return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_DDB_HANDLE);
379
380        case ACPI_TYPE_STRING:
381        case ACPI_TYPE_BUFFER:
382            return (ACPI_BTYPE_COMPUTE_DATA);
383
384        case ACPI_TYPE_PACKAGE:
385            return (ACPI_BTYPE_PACKAGE);
386
387        case ACPI_TYPE_FIELD_UNIT:
388            return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT);
389
390        case ACPI_TYPE_BUFFER_FIELD:
391            return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_BUFFER_FIELD);
392
393        case ACPI_TYPE_DDB_HANDLE:
394            return (ACPI_BTYPE_INTEGER | ACPI_BTYPE_DDB_HANDLE);
395
396        case ACPI_BTYPE_DEBUG_OBJECT:
397
398            /* Cannot be used as a source operand */
399
400            return (0);
401
402        default:
403            return (1 << (Etype - 1));
404        }
405    }
406
407    /* Try the internal data types */
408
409    switch (Etype)
410    {
411    case ACPI_TYPE_LOCAL_REGION_FIELD:
412    case ACPI_TYPE_LOCAL_BANK_FIELD:
413    case ACPI_TYPE_LOCAL_INDEX_FIELD:
414
415        /* Named fields can be either Integer/Buffer/String */
416
417        return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT);
418
419    case ACPI_TYPE_LOCAL_ALIAS:
420
421        return (ACPI_BTYPE_INTEGER);
422
423
424    case ACPI_TYPE_LOCAL_RESOURCE:
425    case ACPI_TYPE_LOCAL_RESOURCE_FIELD:
426
427        return (ACPI_BTYPE_REFERENCE);
428
429    default:
430        printf ("Unhandled encoded type: %X\n", Etype);
431        return (0);
432    }
433}
434
435
436/*******************************************************************************
437 *
438 * FUNCTION:    AnFormatBtype
439 *
440 * PARAMETERS:  Btype               - Bitfield of ACPI types
441 *              Buffer              - Where to put the ascii string
442 *
443 * RETURN:      None.
444 *
445 * DESCRIPTION: Convert a Btype to a string of ACPI types
446 *
447 ******************************************************************************/
448
449static void
450AnFormatBtype (
451    char                    *Buffer,
452    UINT32                  Btype)
453{
454    UINT32                  Type;
455    BOOLEAN                 First = TRUE;
456
457
458    *Buffer = 0;
459
460    if (Btype == 0)
461    {
462        strcat (Buffer, "NoReturnValue");
463        return;
464    }
465
466    for (Type = 1; Type <= ACPI_TYPE_EXTERNAL_MAX; Type++)
467    {
468        if (Btype & 0x00000001)
469        {
470            if (!First)
471            {
472                strcat (Buffer, "|");
473            }
474            First = FALSE;
475            strcat (Buffer, AcpiUtGetTypeName (Type));
476        }
477        Btype >>= 1;
478    }
479
480    if (Btype & 0x00000001)
481    {
482        if (!First)
483        {
484            strcat (Buffer, "|");
485        }
486        First = FALSE;
487        strcat (Buffer, "Reference");
488    }
489
490    Btype >>= 1;
491    if (Btype & 0x00000001)
492    {
493        if (!First)
494        {
495            strcat (Buffer, "|");
496        }
497        First = FALSE;
498        strcat (Buffer, "Resource");
499    }
500}
501
502
503/*******************************************************************************
504 *
505 * FUNCTION:    AnGetBtype
506 *
507 * PARAMETERS:  Op          - Parse node whose type will be returned.
508 *
509 * RETURN:      The Btype associated with the Op.
510 *
511 * DESCRIPTION: Get the (bitfield) ACPI type associated with the parse node.
512 *              Handles the case where the node is a name or method call and
513 *              the actual type must be obtained from the namespace node.
514 *
515 ******************************************************************************/
516
517static UINT32
518AnGetBtype (
519    ACPI_PARSE_OBJECT       *Op)
520{
521    ACPI_NAMESPACE_NODE     *Node;
522    ACPI_PARSE_OBJECT       *ReferencedNode;
523    UINT32                  ThisNodeBtype = 0;
524
525
526    if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG)     ||
527        (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING)  ||
528        (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
529    {
530        Node = Op->Asl.Node;
531        if (!Node)
532        {
533            DbgPrint (ASL_DEBUG_OUTPUT,
534                "No attached Nsnode: [%s] at line %u name [%s], ignoring typecheck\n",
535                Op->Asl.ParseOpName, Op->Asl.LineNumber,
536                Op->Asl.ExternalName);
537            return ACPI_UINT32_MAX;
538        }
539
540        ThisNodeBtype = AnMapEtypeToBtype (Node->Type);
541        if (!ThisNodeBtype)
542        {
543            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
544                "could not map type");
545        }
546
547        /*
548         * Since it was a named reference, enable the
549         * reference bit also
550         */
551        ThisNodeBtype |= ACPI_BTYPE_REFERENCE;
552
553        if (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)
554        {
555            ReferencedNode = Node->Op;
556            if (!ReferencedNode)
557            {
558                /* Check for an internal method */
559
560                if (AnIsInternalMethod (Op))
561                {
562                    return (AnGetInternalMethodReturnType (Op));
563                }
564
565                AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
566                    "null Op pointer");
567                return ACPI_UINT32_MAX;
568            }
569
570            if (ReferencedNode->Asl.CompileFlags & NODE_METHOD_TYPED)
571            {
572                ThisNodeBtype = ReferencedNode->Asl.AcpiBtype;
573            }
574            else
575            {
576                return (ACPI_UINT32_MAX -1);
577            }
578        }
579    }
580    else
581    {
582        ThisNodeBtype = Op->Asl.AcpiBtype;
583    }
584
585    return (ThisNodeBtype);
586}
587
588
589/*******************************************************************************
590 *
591 * FUNCTION:    AnMapObjTypeToBtype
592 *
593 * PARAMETERS:  Op              - A parse node
594 *
595 * RETURN:      A Btype
596 *
597 * DESCRIPTION: Map object to the associated "Btype"
598 *
599 ******************************************************************************/
600
601static UINT32
602AnMapObjTypeToBtype (
603    ACPI_PARSE_OBJECT       *Op)
604{
605
606    switch (Op->Asl.ParseOpcode)
607    {
608    case PARSEOP_OBJECTTYPE_BFF:        /* "BuffFieldObj" */
609        return (ACPI_BTYPE_BUFFER_FIELD);
610
611    case PARSEOP_OBJECTTYPE_BUF:        /* "BuffObj" */
612        return (ACPI_BTYPE_BUFFER);
613
614    case PARSEOP_OBJECTTYPE_DDB:        /* "DDBHandleObj" */
615        return (ACPI_BTYPE_DDB_HANDLE);
616
617    case PARSEOP_OBJECTTYPE_DEV:        /* "DeviceObj" */
618        return (ACPI_BTYPE_DEVICE);
619
620    case PARSEOP_OBJECTTYPE_EVT:        /* "EventObj" */
621        return (ACPI_BTYPE_EVENT);
622
623    case PARSEOP_OBJECTTYPE_FLD:        /* "FieldUnitObj" */
624        return (ACPI_BTYPE_FIELD_UNIT);
625
626    case PARSEOP_OBJECTTYPE_INT:        /* "IntObj" */
627        return (ACPI_BTYPE_INTEGER);
628
629    case PARSEOP_OBJECTTYPE_MTH:        /* "MethodObj" */
630        return (ACPI_BTYPE_METHOD);
631
632    case PARSEOP_OBJECTTYPE_MTX:        /* "MutexObj" */
633        return (ACPI_BTYPE_MUTEX);
634
635    case PARSEOP_OBJECTTYPE_OPR:        /* "OpRegionObj" */
636        return (ACPI_BTYPE_REGION);
637
638    case PARSEOP_OBJECTTYPE_PKG:        /* "PkgObj" */
639        return (ACPI_BTYPE_PACKAGE);
640
641    case PARSEOP_OBJECTTYPE_POW:        /* "PowerResObj" */
642        return (ACPI_BTYPE_POWER);
643
644    case PARSEOP_OBJECTTYPE_STR:        /* "StrObj" */
645        return (ACPI_BTYPE_STRING);
646
647    case PARSEOP_OBJECTTYPE_THZ:        /* "ThermalZoneObj" */
648        return (ACPI_BTYPE_THERMAL);
649
650    case PARSEOP_OBJECTTYPE_UNK:        /* "UnknownObj" */
651        return (ACPI_BTYPE_OBJECTS_AND_REFS);
652
653    default:
654        return (0);
655    }
656}
657
658
659/*******************************************************************************
660 *
661 * FUNCTION:    AnCheckId
662 *
663 * PARAMETERS:  Op                  - Current parse op
664 *              Type                - HID or CID
665 *
666 * RETURN:      None
667 *
668 * DESCRIPTION: Perform various checks on _HID and _CID strings. Only limited
669 *              checks can be performed on _CID strings.
670 *
671 ******************************************************************************/
672
673#define ASL_TYPE_HID        0
674#define ASL_TYPE_CID        1
675#include <string.h>
676
677static void
678AnCheckId (
679    ACPI_PARSE_OBJECT       *Op,
680    ACPI_NAME               Type)
681{
682    UINT32                  i;
683    ACPI_SIZE               Length;
684    UINT32                  AlphaPrefixLength;
685
686
687    /* Only care about string versions of _HID/_CID (integers are legal) */
688
689    if (Op->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)
690    {
691        return;
692    }
693
694    /* For both _HID and _CID, the string must be non-null */
695
696    Length = strlen (Op->Asl.Value.String);
697    if (!Length)
698    {
699        AslError (ASL_ERROR, ASL_MSG_NULL_STRING,
700            Op, NULL);
701        return;
702    }
703
704    /*
705     * One of the things we want to catch here is the use of a leading
706     * asterisk in the string -- an odd construct that certain platform
707     * manufacturers are fond of. Technically, a leading asterisk is OK
708     * for _CID, but a valid use of this has not been seen.
709     */
710    if (*Op->Asl.Value.String == '*')
711    {
712        AslError (ASL_ERROR, ASL_MSG_LEADING_ASTERISK,
713            Op, Op->Asl.Value.String);
714        return;
715    }
716
717    /* _CID strings are bus-specific, no more checks can be performed */
718
719    if (Type == ASL_TYPE_CID)
720    {
721        return;
722    }
723
724    /* For _HID, all characters must be alphanumeric */
725
726    for (i = 0; Op->Asl.Value.String[i]; i++)
727    {
728        if (!isalnum ((int) Op->Asl.Value.String[i]))
729        {
730            AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING,
731                Op, Op->Asl.Value.String);
732            break;
733        }
734    }
735
736    /* _HID String must be of the form "XXX####" or "ACPI####" */
737
738    if ((Length < 7) || (Length > 8))
739    {
740        AslError (ASL_ERROR, ASL_MSG_HID_LENGTH,
741            Op, Op->Asl.Value.String);
742        return;
743    }
744
745    /* _HID Length is valid, now check for uppercase (first 3 or 4 chars) */
746
747    AlphaPrefixLength = 3;
748    if (Length >= 8)
749    {
750        AlphaPrefixLength = 4;
751    }
752
753    /* Ensure the alphabetic prefix is all uppercase */
754
755    for (i = 0; (i < AlphaPrefixLength) && Op->Asl.Value.String[i]; i++)
756    {
757        if (!isupper ((int) Op->Asl.Value.String[i]))
758        {
759            AslError (ASL_ERROR, ASL_MSG_UPPER_CASE,
760                Op, &Op->Asl.Value.String[i]);
761            break;
762        }
763    }
764}
765
766
767/*******************************************************************************
768 *
769 * FUNCTION:    AnMethodAnalysisWalkBegin
770 *
771 * PARAMETERS:  ASL_WALK_CALLBACK
772 *
773 * RETURN:      Status
774 *
775 * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
776 *              1) Initialized local variables
777 *              2) Valid arguments
778 *              3) Return types
779 *
780 ******************************************************************************/
781
782ACPI_STATUS
783AnMethodAnalysisWalkBegin (
784    ACPI_PARSE_OBJECT       *Op,
785    UINT32                  Level,
786    void                    *Context)
787{
788    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
789    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
790    ACPI_PARSE_OBJECT       *Next;
791    UINT32                  RegisterNumber;
792    UINT32                  i;
793    char                    LocalName[] = "Local0";
794    char                    ArgName[] = "Arg0";
795    ACPI_PARSE_OBJECT       *ArgNode;
796    ACPI_PARSE_OBJECT       *NextType;
797    ACPI_PARSE_OBJECT       *NextParamType;
798    UINT8                   ActualArgs = 0;
799
800
801    switch (Op->Asl.ParseOpcode)
802    {
803    case PARSEOP_METHOD:
804
805        TotalMethods++;
806
807        /* Create and init method info */
808
809        MethodInfo       = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
810        MethodInfo->Next = WalkInfo->MethodStack;
811        MethodInfo->Op = Op;
812
813        WalkInfo->MethodStack = MethodInfo;
814
815        /* Get the name node, ignored here */
816
817        Next = Op->Asl.Child;
818
819        /* Get the NumArguments node */
820
821        Next = Next->Asl.Next;
822        MethodInfo->NumArguments = (UINT8)
823            (((UINT8) Next->Asl.Value.Integer) & 0x07);
824
825        /* Get the SerializeRule and SyncLevel nodes, ignored here */
826
827        Next = Next->Asl.Next;
828        Next = Next->Asl.Next;
829        ArgNode = Next;
830
831        /* Get the ReturnType node */
832
833        Next = Next->Asl.Next;
834
835        NextType = Next->Asl.Child;
836        while (NextType)
837        {
838            /* Get and map each of the ReturnTypes */
839
840            MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
841            NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
842            NextType = NextType->Asl.Next;
843        }
844
845        /* Get the ParameterType node */
846
847        Next = Next->Asl.Next;
848
849        NextType = Next->Asl.Child;
850        while (NextType)
851        {
852            if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
853            {
854                NextParamType = NextType->Asl.Child;
855                while (NextParamType)
856                {
857                    MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
858                    NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
859                    NextParamType = NextParamType->Asl.Next;
860                }
861            }
862            else
863            {
864                MethodInfo->ValidArgTypes[ActualArgs] =
865                    AnMapObjTypeToBtype (NextType);
866                NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
867                ActualArgs++;
868            }
869
870            NextType = NextType->Asl.Next;
871        }
872
873        if ((MethodInfo->NumArguments) &&
874            (MethodInfo->NumArguments != ActualArgs))
875        {
876            /* error: Param list did not match number of args */
877        }
878
879        /* Allow numarguments == 0 for Function() */
880
881        if ((!MethodInfo->NumArguments) && (ActualArgs))
882        {
883            MethodInfo->NumArguments = ActualArgs;
884            ArgNode->Asl.Value.Integer |= ActualArgs;
885        }
886
887        /*
888         * Actual arguments are initialized at method entry.
889         * All other ArgX "registers" can be used as locals, so we
890         * track their initialization.
891         */
892        for (i = 0; i < MethodInfo->NumArguments; i++)
893        {
894            MethodInfo->ArgInitialized[i] = TRUE;
895        }
896        break;
897
898
899    case PARSEOP_METHODCALL:
900
901        if (MethodInfo &&
902           (Op->Asl.Node == MethodInfo->Op->Asl.Node))
903        {
904            AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
905        }
906        break;
907
908
909    case PARSEOP_LOCAL0:
910    case PARSEOP_LOCAL1:
911    case PARSEOP_LOCAL2:
912    case PARSEOP_LOCAL3:
913    case PARSEOP_LOCAL4:
914    case PARSEOP_LOCAL5:
915    case PARSEOP_LOCAL6:
916    case PARSEOP_LOCAL7:
917
918        if (!MethodInfo)
919        {
920            /*
921             * Local was used outside a control method, or there was an error
922             * in the method declaration.
923             */
924            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
925            return (AE_ERROR);
926        }
927
928        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
929
930        /*
931         * If the local is being used as a target, mark the local
932         * initialized
933         */
934        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
935        {
936            MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
937        }
938
939        /*
940         * Otherwise, this is a reference, check if the local
941         * has been previously initialized.
942         *
943         * The only operator that accepts an uninitialized value is ObjectType()
944         */
945        else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
946                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
947        {
948            LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
949            AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
950        }
951        break;
952
953
954    case PARSEOP_ARG0:
955    case PARSEOP_ARG1:
956    case PARSEOP_ARG2:
957    case PARSEOP_ARG3:
958    case PARSEOP_ARG4:
959    case PARSEOP_ARG5:
960    case PARSEOP_ARG6:
961
962        if (!MethodInfo)
963        {
964            /*
965             * Arg was used outside a control method, or there was an error
966             * in the method declaration.
967             */
968            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
969            return (AE_ERROR);
970        }
971
972        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
973        ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
974
975        /*
976         * If the Arg is being used as a target, mark the local
977         * initialized
978         */
979        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
980        {
981            MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
982        }
983
984        /*
985         * Otherwise, this is a reference, check if the Arg
986         * has been previously initialized.
987         *
988         * The only operator that accepts an uninitialized value is ObjectType()
989         */
990        else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
991                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
992        {
993            AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
994        }
995
996        /* Flag this arg if it is not a "real" argument to the method */
997
998        if (RegisterNumber >= MethodInfo->NumArguments)
999        {
1000            AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
1001        }
1002        break;
1003
1004
1005    case PARSEOP_RETURN:
1006
1007        if (!MethodInfo)
1008        {
1009            /*
1010             * Probably was an error in the method declaration,
1011             * no additional error here
1012             */
1013            ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
1014            return (AE_ERROR);
1015        }
1016
1017        /* Child indicates a return value */
1018
1019        if ((Op->Asl.Child) &&
1020            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
1021        {
1022            MethodInfo->NumReturnWithValue++;
1023        }
1024        else
1025        {
1026            MethodInfo->NumReturnNoValue++;
1027        }
1028        break;
1029
1030
1031    case PARSEOP_BREAK:
1032    case PARSEOP_CONTINUE:
1033
1034        Next = Op->Asl.Parent;
1035        while (Next)
1036        {
1037            if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
1038            {
1039                break;
1040            }
1041            Next = Next->Asl.Parent;
1042        }
1043
1044        if (!Next)
1045        {
1046            AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
1047        }
1048        break;
1049
1050
1051    case PARSEOP_STALL:
1052
1053        /* We can range check if the argument is an integer */
1054
1055        if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
1056            (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
1057        {
1058            AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
1059        }
1060        break;
1061
1062
1063    case PARSEOP_DEVICE:
1064    case PARSEOP_EVENT:
1065    case PARSEOP_MUTEX:
1066    case PARSEOP_OPERATIONREGION:
1067    case PARSEOP_POWERRESOURCE:
1068    case PARSEOP_PROCESSOR:
1069    case PARSEOP_THERMALZONE:
1070
1071        /*
1072         * The first operand is a name to be created in the namespace.
1073         * Check against the reserved list.
1074         */
1075        i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
1076        if (i < ACPI_VALID_RESERVED_NAME_MAX)
1077        {
1078            AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
1079        }
1080        break;
1081
1082
1083    case PARSEOP_NAME:
1084
1085        /* Typecheck any predefined names statically defined with Name() */
1086
1087        ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
1088
1089        /* Special typechecking for _HID */
1090
1091        if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
1092        {
1093            Next = Op->Asl.Child->Asl.Next;
1094            AnCheckId (Next, ASL_TYPE_HID);
1095        }
1096
1097        /* Special typechecking for _CID */
1098
1099        else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
1100        {
1101            Next = Op->Asl.Child->Asl.Next;
1102
1103            if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
1104                (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
1105            {
1106                Next = Next->Asl.Child;
1107                while (Next)
1108                {
1109                    AnCheckId (Next, ASL_TYPE_CID);
1110                    Next = Next->Asl.Next;
1111                }
1112            }
1113            else
1114            {
1115                AnCheckId (Next, ASL_TYPE_CID);
1116            }
1117        }
1118        break;
1119
1120
1121    default:
1122        break;
1123    }
1124
1125    return AE_OK;
1126}
1127
1128
1129/*******************************************************************************
1130 *
1131 * FUNCTION:    AnLastStatementIsReturn
1132 *
1133 * PARAMETERS:  Op            - A method parse node
1134 *
1135 * RETURN:      TRUE if last statement is an ASL RETURN. False otherwise
1136 *
1137 * DESCRIPTION: Walk down the list of top level statements within a method
1138 *              to find the last one. Check if that last statement is in
1139 *              fact a RETURN statement.
1140 *
1141 ******************************************************************************/
1142
1143static BOOLEAN
1144AnLastStatementIsReturn (
1145    ACPI_PARSE_OBJECT       *Op)
1146{
1147    ACPI_PARSE_OBJECT       *Next;
1148
1149
1150    /*
1151     * Check if last statement is a return
1152     */
1153    Next = ASL_GET_CHILD_NODE (Op);
1154    while (Next)
1155    {
1156        if ((!Next->Asl.Next) &&
1157            (Next->Asl.ParseOpcode == PARSEOP_RETURN))
1158        {
1159            return TRUE;
1160        }
1161
1162        Next = ASL_GET_PEER_NODE (Next);
1163    }
1164
1165    return FALSE;
1166}
1167
1168
1169/*******************************************************************************
1170 *
1171 * FUNCTION:    AnMethodAnalysisWalkEnd
1172 *
1173 * PARAMETERS:  ASL_WALK_CALLBACK
1174 *
1175 * RETURN:      Status
1176 *
1177 * DESCRIPTION: Ascending callback for analysis walk. Complete method
1178 *              return analysis.
1179 *
1180 ******************************************************************************/
1181
1182ACPI_STATUS
1183AnMethodAnalysisWalkEnd (
1184    ACPI_PARSE_OBJECT       *Op,
1185    UINT32                  Level,
1186    void                    *Context)
1187{
1188    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
1189    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
1190
1191
1192    switch (Op->Asl.ParseOpcode)
1193    {
1194    case PARSEOP_METHOD:
1195    case PARSEOP_RETURN:
1196        if (!MethodInfo)
1197        {
1198            printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
1199            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
1200                "No method info for this method");
1201            CmCleanupAndExit ();
1202            return (AE_AML_INTERNAL);
1203        }
1204        break;
1205
1206    default:
1207        break;
1208    }
1209
1210    switch (Op->Asl.ParseOpcode)
1211    {
1212    case PARSEOP_METHOD:
1213
1214        WalkInfo->MethodStack = MethodInfo->Next;
1215
1216        /*
1217         * Check if there is no return statement at the end of the
1218         * method AND we can actually get there -- i.e., the execution
1219         * of the method can possibly terminate without a return statement.
1220         */
1221        if ((!AnLastStatementIsReturn (Op)) &&
1222            (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
1223        {
1224            /*
1225             * No return statement, and execution can possibly exit
1226             * via this path. This is equivalent to Return ()
1227             */
1228            MethodInfo->NumReturnNoValue++;
1229        }
1230
1231        /*
1232         * Check for case where some return statements have a return value
1233         * and some do not. Exit without a return statement is a return with
1234         * no value
1235         */
1236        if (MethodInfo->NumReturnNoValue &&
1237            MethodInfo->NumReturnWithValue)
1238        {
1239            AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
1240                Op->Asl.ExternalName);
1241        }
1242
1243        /*
1244         * If there are any RETURN() statements with no value, or there is a
1245         * control path that allows the method to exit without a return value,
1246         * we mark the method as a method that does not return a value. This
1247         * knowledge can be used to check method invocations that expect a
1248         * returned value.
1249         */
1250        if (MethodInfo->NumReturnNoValue)
1251        {
1252            if (MethodInfo->NumReturnWithValue)
1253            {
1254                Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
1255            }
1256            else
1257            {
1258                Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
1259            }
1260        }
1261
1262        /*
1263         * Check predefined method names for correct return behavior
1264         * and correct number of arguments
1265         */
1266        ApCheckForPredefinedMethod (Op, MethodInfo);
1267        ACPI_FREE (MethodInfo);
1268        break;
1269
1270
1271    case PARSEOP_RETURN:
1272
1273        /*
1274         * If the parent is a predefined method name, attempt to typecheck
1275         * the return value. Only static types can be validated.
1276         */
1277        ApCheckPredefinedReturnValue (Op, MethodInfo);
1278
1279        /*
1280         * The parent block does not "exit" and continue execution -- the
1281         * method is terminated here with the Return() statement.
1282         */
1283        Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
1284
1285        /* Used in the "typing" pass later */
1286
1287        Op->Asl.ParentMethod = MethodInfo->Op;
1288
1289        /*
1290         * If there is a peer node after the return statement, then this
1291         * node is unreachable code -- i.e., it won't be executed because of
1292         * the preceeding Return() statement.
1293         */
1294        if (Op->Asl.Next)
1295        {
1296            AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
1297        }
1298        break;
1299
1300
1301    case PARSEOP_IF:
1302
1303        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
1304            (Op->Asl.Next) &&
1305            (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
1306        {
1307            /*
1308             * This IF has a corresponding ELSE. The IF block has no exit,
1309             * (it contains an unconditional Return)
1310             * mark the ELSE block to remember this fact.
1311             */
1312            Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
1313        }
1314        break;
1315
1316
1317    case PARSEOP_ELSE:
1318
1319        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
1320            (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
1321        {
1322            /*
1323             * This ELSE block has no exit and the corresponding IF block
1324             * has no exit either. Therefore, the parent node has no exit.
1325             */
1326            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
1327        }
1328        break;
1329
1330
1331    default:
1332
1333        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
1334            (Op->Asl.Parent))
1335        {
1336            /* If this node has no exit, then the parent has no exit either */
1337
1338            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
1339        }
1340        break;
1341    }
1342
1343    return AE_OK;
1344}
1345
1346
1347/*******************************************************************************
1348 *
1349 * FUNCTION:    AnMethodTypingWalkBegin
1350 *
1351 * PARAMETERS:  ASL_WALK_CALLBACK
1352 *
1353 * RETURN:      Status
1354 *
1355 * DESCRIPTION: Descending callback for the typing walk.
1356 *
1357 ******************************************************************************/
1358
1359ACPI_STATUS
1360AnMethodTypingWalkBegin (
1361    ACPI_PARSE_OBJECT       *Op,
1362    UINT32                  Level,
1363    void                    *Context)
1364{
1365
1366    return AE_OK;
1367}
1368
1369
1370/*******************************************************************************
1371 *
1372 * FUNCTION:    AnMethodTypingWalkEnd
1373 *
1374 * PARAMETERS:  ASL_WALK_CALLBACK
1375 *
1376 * RETURN:      Status
1377 *
1378 * DESCRIPTION: Ascending callback for typing walk. Complete the method
1379 *              return analysis. Check methods for:
1380 *              1) Initialized local variables
1381 *              2) Valid arguments
1382 *              3) Return types
1383 *
1384 ******************************************************************************/
1385
1386ACPI_STATUS
1387AnMethodTypingWalkEnd (
1388    ACPI_PARSE_OBJECT       *Op,
1389    UINT32                  Level,
1390    void                    *Context)
1391{
1392    UINT32                  ThisNodeBtype;
1393
1394
1395    switch (Op->Asl.ParseOpcode)
1396    {
1397    case PARSEOP_METHOD:
1398
1399        Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
1400        break;
1401
1402    case PARSEOP_RETURN:
1403
1404        if ((Op->Asl.Child) &&
1405            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
1406        {
1407            ThisNodeBtype = AnGetBtype (Op->Asl.Child);
1408
1409            if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
1410                (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
1411            {
1412                /*
1413                 * The called method is untyped at this time (typically a
1414                 * forward reference).
1415                 *
1416                 * Check for a recursive method call first.
1417                 */
1418                if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
1419                {
1420                    /* We must type the method here */
1421
1422                    TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
1423                        ASL_WALK_VISIT_TWICE, AnMethodTypingWalkBegin,
1424                        AnMethodTypingWalkEnd, NULL);
1425
1426                    ThisNodeBtype = AnGetBtype (Op->Asl.Child);
1427                }
1428            }
1429
1430            /* Returns a value, save the value type */
1431
1432            if (Op->Asl.ParentMethod)
1433            {
1434                Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
1435            }
1436        }
1437        break;
1438
1439    default:
1440        break;
1441    }
1442
1443    return AE_OK;
1444}
1445
1446
1447/*******************************************************************************
1448 *
1449 * FUNCTION:    AnCheckMethodReturnValue
1450 *
1451 * PARAMETERS:  Op                  - Parent
1452 *              OpInfo              - Parent info
1453 *              ArgOp               - Method invocation op
1454 *              RequiredBtypes      - What caller requires
1455 *              ThisNodeBtype       - What this node returns (if anything)
1456 *
1457 * RETURN:      None
1458 *
1459 * DESCRIPTION: Check a method invocation for 1) A return value and if it does
1460 *              in fact return a value, 2) check the type of the return value.
1461 *
1462 ******************************************************************************/
1463
1464static void
1465AnCheckMethodReturnValue (
1466    ACPI_PARSE_OBJECT       *Op,
1467    const ACPI_OPCODE_INFO  *OpInfo,
1468    ACPI_PARSE_OBJECT       *ArgOp,
1469    UINT32                  RequiredBtypes,
1470    UINT32                  ThisNodeBtype)
1471{
1472    ACPI_PARSE_OBJECT       *OwningOp;
1473    ACPI_NAMESPACE_NODE     *Node;
1474
1475
1476    Node = ArgOp->Asl.Node;
1477
1478
1479    /* Examine the parent op of this method */
1480
1481    OwningOp = Node->Op;
1482    if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL)
1483    {
1484        /* Method NEVER returns a value */
1485
1486        AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName);
1487    }
1488    else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL)
1489    {
1490        /* Method SOMETIMES returns a value, SOMETIMES not */
1491
1492        AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, Op, Op->Asl.ExternalName);
1493    }
1494    else if (!(ThisNodeBtype & RequiredBtypes))
1495    {
1496        /* Method returns a value, but the type is wrong */
1497
1498        AnFormatBtype (StringBuffer, ThisNodeBtype);
1499        AnFormatBtype (StringBuffer2, RequiredBtypes);
1500
1501
1502        /*
1503         * The case where the method does not return any value at all
1504         * was already handled in the namespace cross reference
1505         * -- Only issue an error if the method in fact returns a value,
1506         * but it is of the wrong type
1507         */
1508        if (ThisNodeBtype != 0)
1509        {
1510            sprintf (MsgBuffer,
1511                "Method returns [%s], %s operator requires [%s]",
1512                StringBuffer, OpInfo->Name, StringBuffer2);
1513
1514            AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
1515        }
1516    }
1517}
1518
1519
1520/*******************************************************************************
1521 *
1522 * FUNCTION:    AnOperandTypecheckWalkBegin
1523 *
1524 * PARAMETERS:  ASL_WALK_CALLBACK
1525 *
1526 * RETURN:      Status
1527 *
1528 * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
1529 *              1) Initialized local variables
1530 *              2) Valid arguments
1531 *              3) Return types
1532 *
1533 ******************************************************************************/
1534
1535ACPI_STATUS
1536AnOperandTypecheckWalkBegin (
1537    ACPI_PARSE_OBJECT       *Op,
1538    UINT32                  Level,
1539    void                    *Context)
1540{
1541
1542    return AE_OK;
1543}
1544
1545
1546/*******************************************************************************
1547 *
1548 * FUNCTION:    AnOperandTypecheckWalkEnd
1549 *
1550 * PARAMETERS:  ASL_WALK_CALLBACK
1551 *
1552 * RETURN:      Status
1553 *
1554 * DESCRIPTION: Ascending callback for analysis walk. Complete method
1555 *              return analysis.
1556 *
1557 ******************************************************************************/
1558
1559ACPI_STATUS
1560AnOperandTypecheckWalkEnd (
1561    ACPI_PARSE_OBJECT       *Op,
1562    UINT32                  Level,
1563    void                    *Context)
1564{
1565    const ACPI_OPCODE_INFO  *OpInfo;
1566    UINT32                  RuntimeArgTypes;
1567    UINT32                  RuntimeArgTypes2;
1568    UINT32                  RequiredBtypes;
1569    UINT32                  ThisNodeBtype;
1570    UINT32                  CommonBtypes;
1571    UINT32                  OpcodeClass;
1572    ACPI_PARSE_OBJECT       *ArgOp;
1573    UINT32                  ArgType;
1574
1575
1576    switch (Op->Asl.AmlOpcode)
1577    {
1578    case AML_RAW_DATA_BYTE:
1579    case AML_RAW_DATA_WORD:
1580    case AML_RAW_DATA_DWORD:
1581    case AML_RAW_DATA_QWORD:
1582    case AML_RAW_DATA_BUFFER:
1583    case AML_RAW_DATA_CHAIN:
1584    case AML_PACKAGE_LENGTH:
1585    case AML_UNASSIGNED_OPCODE:
1586    case AML_DEFAULT_ARG_OP:
1587
1588        /* Ignore the internal (compiler-only) AML opcodes */
1589
1590        return (AE_OK);
1591
1592    default:
1593        break;
1594    }
1595
1596    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1597    if (!OpInfo)
1598    {
1599        return (AE_OK);
1600    }
1601
1602    ArgOp           = Op->Asl.Child;
1603    RuntimeArgTypes = OpInfo->RuntimeArgs;
1604    OpcodeClass     = OpInfo->Class;
1605
1606#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
1607    /*
1608     * Update 11/2008: In practice, we can't perform this check. A simple
1609     * analysis is not sufficient. Also, it can cause errors when compiling
1610     * disassembled code because of the way Switch operators are implemented
1611     * (a While(One) loop with a named temp variable created within.)
1612     */
1613
1614    /*
1615     * If we are creating a named object, check if we are within a while loop
1616     * by checking if the parent is a WHILE op. This is a simple analysis, but
1617     * probably sufficient for many cases.
1618     *
1619     * Allow Scope(), Buffer(), and Package().
1620     */
1621    if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
1622        ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
1623    {
1624        if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
1625        {
1626            AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
1627        }
1628    }
1629#endif
1630
1631    /*
1632     * Special case for control opcodes IF/RETURN/WHILE since they
1633     * have no runtime arg list (at this time)
1634     */
1635    switch (Op->Asl.AmlOpcode)
1636    {
1637    case AML_IF_OP:
1638    case AML_WHILE_OP:
1639    case AML_RETURN_OP:
1640
1641        if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
1642        {
1643            /* Check for an internal method */
1644
1645            if (AnIsInternalMethod (ArgOp))
1646            {
1647                return (AE_OK);
1648            }
1649
1650            /* The lone arg is a method call, check it */
1651
1652            RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
1653            if (Op->Asl.AmlOpcode == AML_RETURN_OP)
1654            {
1655                RequiredBtypes = 0xFFFFFFFF;
1656            }
1657
1658            ThisNodeBtype = AnGetBtype (ArgOp);
1659            if (ThisNodeBtype == ACPI_UINT32_MAX)
1660            {
1661                return (AE_OK);
1662            }
1663            AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
1664                RequiredBtypes, ThisNodeBtype);
1665        }
1666        return (AE_OK);
1667
1668    default:
1669        break;
1670    }
1671
1672    /* Ignore the non-executable opcodes */
1673
1674    if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
1675    {
1676        return (AE_OK);
1677    }
1678
1679    switch (OpcodeClass)
1680    {
1681    case AML_CLASS_EXECUTE:
1682    case AML_CLASS_CREATE:
1683    case AML_CLASS_CONTROL:
1684    case AML_CLASS_RETURN_VALUE:
1685
1686        /* TBD: Change class or fix typechecking for these */
1687
1688        if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
1689            (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
1690            (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
1691        {
1692            break;
1693        }
1694
1695        /* Reverse the runtime argument list */
1696
1697        RuntimeArgTypes2 = 0;
1698        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
1699        {
1700            RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
1701            RuntimeArgTypes2 |= ArgType;
1702            INCREMENT_ARG_LIST (RuntimeArgTypes);
1703        }
1704
1705        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
1706        {
1707            RequiredBtypes = AnMapArgTypeToBtype (ArgType);
1708
1709            ThisNodeBtype = AnGetBtype (ArgOp);
1710            if (ThisNodeBtype == ACPI_UINT32_MAX)
1711            {
1712                goto NextArgument;
1713            }
1714
1715            /* Examine the arg based on the required type of the arg */
1716
1717            switch (ArgType)
1718            {
1719            case ARGI_TARGETREF:
1720
1721                if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
1722                {
1723                    /* ZERO is the placeholder for "don't store result" */
1724
1725                    ThisNodeBtype = RequiredBtypes;
1726                    break;
1727                }
1728
1729                if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
1730                {
1731                    /*
1732                     * This is the case where an original reference to a resource
1733                     * descriptor field has been replaced by an (Integer) offset.
1734                     * These named fields are supported at compile-time only;
1735                     * the names are not passed to the interpreter (via the AML).
1736                     */
1737                    if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
1738                        (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
1739                    {
1740                        AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
1741                    }
1742                    else
1743                    {
1744                        AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
1745                    }
1746                    break;
1747                }
1748
1749                if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
1750                    (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
1751                {
1752                    break;
1753                }
1754
1755                ThisNodeBtype = RequiredBtypes;
1756                break;
1757
1758
1759            case ARGI_REFERENCE:            /* References */
1760            case ARGI_INTEGER_REF:
1761            case ARGI_OBJECT_REF:
1762            case ARGI_DEVICE_REF:
1763
1764                switch (ArgOp->Asl.ParseOpcode)
1765                {
1766                case PARSEOP_LOCAL0:
1767                case PARSEOP_LOCAL1:
1768                case PARSEOP_LOCAL2:
1769                case PARSEOP_LOCAL3:
1770                case PARSEOP_LOCAL4:
1771                case PARSEOP_LOCAL5:
1772                case PARSEOP_LOCAL6:
1773                case PARSEOP_LOCAL7:
1774
1775                    /* TBD: implement analysis of current value (type) of the local */
1776                    /* For now, just treat any local as a typematch */
1777
1778                    /*ThisNodeBtype = RequiredBtypes;*/
1779                    break;
1780
1781                case PARSEOP_ARG0:
1782                case PARSEOP_ARG1:
1783                case PARSEOP_ARG2:
1784                case PARSEOP_ARG3:
1785                case PARSEOP_ARG4:
1786                case PARSEOP_ARG5:
1787                case PARSEOP_ARG6:
1788
1789                    /* Hard to analyze argument types, sow we won't */
1790                    /* For now, just treat any arg as a typematch */
1791
1792                    /* ThisNodeBtype = RequiredBtypes; */
1793                    break;
1794
1795                case PARSEOP_DEBUG:
1796                    break;
1797
1798                case PARSEOP_REFOF:
1799                case PARSEOP_INDEX:
1800                default:
1801                    break;
1802
1803                }
1804                break;
1805
1806            case ARGI_INTEGER:
1807            default:
1808                break;
1809            }
1810
1811
1812            CommonBtypes = ThisNodeBtype & RequiredBtypes;
1813
1814            if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
1815            {
1816                if (AnIsInternalMethod (ArgOp))
1817                {
1818                    return (AE_OK);
1819                }
1820
1821                /* Check a method call for a valid return value */
1822
1823                AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
1824                    RequiredBtypes, ThisNodeBtype);
1825            }
1826
1827            /*
1828             * Now check if the actual type(s) match at least one
1829             * bit to the required type
1830             */
1831            else if (!CommonBtypes)
1832            {
1833                /* No match -- this is a type mismatch error */
1834
1835                AnFormatBtype (StringBuffer, ThisNodeBtype);
1836                AnFormatBtype (StringBuffer2, RequiredBtypes);
1837
1838                sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
1839                            StringBuffer, OpInfo->Name, StringBuffer2);
1840
1841                AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
1842            }
1843
1844        NextArgument:
1845            ArgOp = ArgOp->Asl.Next;
1846            INCREMENT_ARG_LIST (RuntimeArgTypes2);
1847        }
1848        break;
1849
1850    default:
1851        break;
1852    }
1853
1854    return (AE_OK);
1855}
1856
1857
1858/*******************************************************************************
1859 *
1860 * FUNCTION:    AnIsResultUsed
1861 *
1862 * PARAMETERS:  Op              - Parent op for the operator
1863 *
1864 * RETURN:      TRUE if result from this operation is actually consumed
1865 *
1866 * DESCRIPTION: Determine if the function result value from an operator is
1867 *              used.
1868 *
1869 ******************************************************************************/
1870
1871static BOOLEAN
1872AnIsResultUsed (
1873    ACPI_PARSE_OBJECT       *Op)
1874{
1875    ACPI_PARSE_OBJECT       *Parent;
1876
1877
1878    switch (Op->Asl.ParseOpcode)
1879    {
1880    case PARSEOP_INCREMENT:
1881    case PARSEOP_DECREMENT:
1882
1883        /* These are standalone operators, no return value */
1884
1885        return (TRUE);
1886
1887    default:
1888        break;
1889    }
1890
1891    /* Examine parent to determine if the return value is used */
1892
1893    Parent = Op->Asl.Parent;
1894    switch (Parent->Asl.ParseOpcode)
1895    {
1896    /* If/While - check if the operator is the predicate */
1897
1898    case PARSEOP_IF:
1899    case PARSEOP_WHILE:
1900
1901        /* First child is the predicate */
1902
1903        if (Parent->Asl.Child == Op)
1904        {
1905            return (TRUE);
1906        }
1907        return (FALSE);
1908
1909    /* Not used if one of these is the parent */
1910
1911    case PARSEOP_METHOD:
1912    case PARSEOP_DEFINITIONBLOCK:
1913    case PARSEOP_ELSE:
1914
1915        return (FALSE);
1916
1917    default:
1918        /* Any other type of parent means that the result is used */
1919
1920        return (TRUE);
1921    }
1922}
1923
1924
1925/*******************************************************************************
1926 *
1927 * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
1928 *
1929 * PARAMETERS:  ASL_WALK_CALLBACK
1930 *
1931 * RETURN:      Status
1932 *
1933 * DESCRIPTION: Descending callback for the analysis walk. Checks for
1934 *              miscellaneous issues in the code.
1935 *
1936 ******************************************************************************/
1937
1938ACPI_STATUS
1939AnOtherSemanticAnalysisWalkBegin (
1940    ACPI_PARSE_OBJECT       *Op,
1941    UINT32                  Level,
1942    void                    *Context)
1943{
1944    ACPI_PARSE_OBJECT       *ArgNode;
1945    ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
1946    const ACPI_OPCODE_INFO  *OpInfo;
1947
1948
1949    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1950
1951    /*
1952     * Determine if an execution class operator actually does something by
1953     * checking if it has a target and/or the function return value is used.
1954     * (Target is optional, so a standalone statement can actually do nothing.)
1955     */
1956    if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
1957        (OpInfo->Flags & AML_HAS_RETVAL) &&
1958        (!AnIsResultUsed (Op)))
1959    {
1960        if (OpInfo->Flags & AML_HAS_TARGET)
1961        {
1962            /*
1963             * Find the target node, it is always the last child. If the traget
1964             * is not specified in the ASL, a default node of type Zero was
1965             * created by the parser.
1966             */
1967            ArgNode = Op->Asl.Child;
1968            while (ArgNode->Asl.Next)
1969            {
1970                PrevArgNode = ArgNode;
1971                ArgNode = ArgNode->Asl.Next;
1972            }
1973
1974            /* Divide() is the only weird case, it has two targets */
1975
1976            if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
1977            {
1978                if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
1979                    (PrevArgNode) &&
1980                    (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
1981                {
1982                    AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
1983                }
1984            }
1985            else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
1986            {
1987                AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
1988            }
1989        }
1990        else
1991        {
1992            /*
1993             * Has no target and the result is not used. Only a couple opcodes
1994             * can have this combination.
1995             */
1996            switch (Op->Asl.ParseOpcode)
1997            {
1998            case PARSEOP_ACQUIRE:
1999            case PARSEOP_WAIT:
2000            case PARSEOP_LOADTABLE:
2001                break;
2002
2003            default:
2004                AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
2005                break;
2006            }
2007        }
2008    }
2009
2010
2011    /*
2012     * Semantic checks for individual ASL operators
2013     */
2014    switch (Op->Asl.ParseOpcode)
2015    {
2016    case PARSEOP_ACQUIRE:
2017    case PARSEOP_WAIT:
2018        /*
2019         * Emit a warning if the timeout parameter for these operators is not
2020         * ACPI_WAIT_FOREVER, and the result value from the operator is not
2021         * checked, meaning that a timeout could happen, but the code
2022         * would not know about it.
2023         */
2024
2025        /* First child is the namepath, 2nd child is timeout */
2026
2027        ArgNode = Op->Asl.Child;
2028        ArgNode = ArgNode->Asl.Next;
2029
2030        /*
2031         * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
2032         * 0xFFFF or greater
2033         */
2034        if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
2035             (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
2036             (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
2037        {
2038            break;
2039        }
2040
2041        /*
2042         * The operation could timeout. If the return value is not used
2043         * (indicates timeout occurred), issue a warning
2044         */
2045        if (!AnIsResultUsed (Op))
2046        {
2047            AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, Op->Asl.ExternalName);
2048        }
2049        break;
2050
2051    case PARSEOP_CREATEFIELD:
2052        /*
2053         * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
2054         */
2055        ArgNode = Op->Asl.Child;
2056        ArgNode = ArgNode->Asl.Next;
2057        ArgNode = ArgNode->Asl.Next;
2058
2059        if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
2060           ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
2061            (ArgNode->Asl.Value.Integer == 0)))
2062        {
2063            AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
2064        }
2065        break;
2066
2067    default:
2068        break;
2069    }
2070
2071    return AE_OK;
2072}
2073
2074
2075/*******************************************************************************
2076 *
2077 * FUNCTION:    AnOtherSemanticAnalysisWalkEnd
2078 *
2079 * PARAMETERS:  ASL_WALK_CALLBACK
2080 *
2081 * RETURN:      Status
2082 *
2083 * DESCRIPTION: Ascending callback for analysis walk. Complete method
2084 *              return analysis.
2085 *
2086 ******************************************************************************/
2087
2088ACPI_STATUS
2089AnOtherSemanticAnalysisWalkEnd (
2090    ACPI_PARSE_OBJECT       *Op,
2091    UINT32                  Level,
2092    void                    *Context)
2093{
2094
2095    return AE_OK;
2096
2097}
2098
2099
2100#ifdef ACPI_OBSOLETE_FUNCTIONS
2101/*******************************************************************************
2102 *
2103 * FUNCTION:    AnMapBtypeToEtype
2104 *
2105 * PARAMETERS:  Btype               - Bitfield of ACPI types
2106 *
2107 * RETURN:      The Etype corresponding the the Btype
2108 *
2109 * DESCRIPTION: Convert a bitfield type to an encoded type
2110 *
2111 ******************************************************************************/
2112
2113UINT32
2114AnMapBtypeToEtype (
2115    UINT32              Btype)
2116{
2117    UINT32              i;
2118    UINT32              Etype;
2119
2120
2121    if (Btype == 0)
2122    {
2123        return 0;
2124    }
2125
2126    Etype = 1;
2127    for (i = 1; i < Btype; i *= 2)
2128    {
2129        Etype++;
2130    }
2131
2132    return (Etype);
2133}
2134#endif
2135
2136