Home | History | Annotate | Line # | Download | only in compiler
aslanalyze.c revision 1.1
      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 "aslcompiler.h"
    119 #include "aslcompiler.y.h"
    120 #include "acparser.h"
    121 #include "amlcode.h"
    122 
    123 #define _COMPONENT          ACPI_COMPILER
    124         ACPI_MODULE_NAME    ("aslanalyze")
    125 
    126 /* Local prototypes */
    127 
    128 static UINT32
    129 AnMapArgTypeToBtype (
    130     UINT32                  ArgType);
    131 
    132 static UINT32
    133 AnMapEtypeToBtype (
    134     UINT32                  Etype);
    135 
    136 static void
    137 AnFormatBtype (
    138     char                    *Buffer,
    139     UINT32                  Btype);
    140 
    141 static UINT32
    142 AnGetBtype (
    143     ACPI_PARSE_OBJECT       *Op);
    144 
    145 static UINT32
    146 AnMapObjTypeToBtype (
    147     ACPI_PARSE_OBJECT       *Op);
    148 
    149 static BOOLEAN
    150 AnLastStatementIsReturn (
    151     ACPI_PARSE_OBJECT       *Op);
    152 
    153 static void
    154 AnCheckMethodReturnValue (
    155     ACPI_PARSE_OBJECT       *Op,
    156     const ACPI_OPCODE_INFO  *OpInfo,
    157     ACPI_PARSE_OBJECT       *ArgOp,
    158     UINT32                  RequiredBtypes,
    159     UINT32                  ThisNodeBtype);
    160 
    161 static BOOLEAN
    162 AnIsInternalMethod (
    163     ACPI_PARSE_OBJECT       *Op);
    164 
    165 static UINT32
    166 AnGetInternalMethodReturnType (
    167     ACPI_PARSE_OBJECT       *Op);
    168 
    169 BOOLEAN
    170 AnIsResultUsed (
    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 
    186 static BOOLEAN
    187 AnIsInternalMethod (
    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 
    213 static UINT32
    214 AnGetInternalMethodReturnType (
    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 
    243 static UINT32
    244 AnMapArgTypeToBtype (
    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 
    355 static UINT32
    356 AnMapEtypeToBtype (
    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 
    449 static void
    450 AnFormatBtype (
    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 
    517 static UINT32
    518 AnGetBtype (
    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 
    601 static UINT32
    602 AnMapObjTypeToBtype (
    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:    AnMethodAnalysisWalkBegin
    662  *
    663  * PARAMETERS:  ASL_WALK_CALLBACK
    664  *
    665  * RETURN:      Status
    666  *
    667  * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
    668  *              1) Initialized local variables
    669  *              2) Valid arguments
    670  *              3) Return types
    671  *
    672  ******************************************************************************/
    673 
    674 ACPI_STATUS
    675 AnMethodAnalysisWalkBegin (
    676     ACPI_PARSE_OBJECT       *Op,
    677     UINT32                  Level,
    678     void                    *Context)
    679 {
    680     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
    681     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
    682     ACPI_PARSE_OBJECT       *Next;
    683     UINT32                  RegisterNumber;
    684     UINT32                  i;
    685     char                    LocalName[] = "Local0";
    686     char                    ArgName[] = "Arg0";
    687     ACPI_PARSE_OBJECT       *ArgNode;
    688     ACPI_PARSE_OBJECT       *NextType;
    689     ACPI_PARSE_OBJECT       *NextParamType;
    690     UINT8                   ActualArgs = 0;
    691 
    692 
    693     switch (Op->Asl.ParseOpcode)
    694     {
    695     case PARSEOP_METHOD:
    696 
    697         TotalMethods++;
    698 
    699         /* Create and init method info */
    700 
    701         MethodInfo       = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
    702         MethodInfo->Next = WalkInfo->MethodStack;
    703         MethodInfo->Op = Op;
    704 
    705         WalkInfo->MethodStack = MethodInfo;
    706 
    707         /* Get the name node, ignored here */
    708 
    709         Next = Op->Asl.Child;
    710 
    711         /* Get the NumArguments node */
    712 
    713         Next = Next->Asl.Next;
    714         MethodInfo->NumArguments = (UINT8)
    715             (((UINT8) Next->Asl.Value.Integer) & 0x07);
    716 
    717         /* Get the SerializeRule and SyncLevel nodes, ignored here */
    718 
    719         Next = Next->Asl.Next;
    720         Next = Next->Asl.Next;
    721         ArgNode = Next;
    722 
    723         /* Get the ReturnType node */
    724 
    725         Next = Next->Asl.Next;
    726 
    727         NextType = Next->Asl.Child;
    728         while (NextType)
    729         {
    730             /* Get and map each of the ReturnTypes */
    731 
    732             MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
    733             NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    734             NextType = NextType->Asl.Next;
    735         }
    736 
    737         /* Get the ParameterType node */
    738 
    739         Next = Next->Asl.Next;
    740 
    741         NextType = Next->Asl.Child;
    742         while (NextType)
    743         {
    744             if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
    745             {
    746                 NextParamType = NextType->Asl.Child;
    747                 while (NextParamType)
    748                 {
    749                     MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
    750                     NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    751                     NextParamType = NextParamType->Asl.Next;
    752                 }
    753             }
    754             else
    755             {
    756                 MethodInfo->ValidArgTypes[ActualArgs] =
    757                     AnMapObjTypeToBtype (NextType);
    758                 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    759                 ActualArgs++;
    760             }
    761 
    762             NextType = NextType->Asl.Next;
    763         }
    764 
    765         if ((MethodInfo->NumArguments) &&
    766             (MethodInfo->NumArguments != ActualArgs))
    767         {
    768             /* error: Param list did not match number of args */
    769         }
    770 
    771         /* Allow numarguments == 0 for Function() */
    772 
    773         if ((!MethodInfo->NumArguments) && (ActualArgs))
    774         {
    775             MethodInfo->NumArguments = ActualArgs;
    776             ArgNode->Asl.Value.Integer |= ActualArgs;
    777         }
    778 
    779         /*
    780          * Actual arguments are initialized at method entry.
    781          * All other ArgX "registers" can be used as locals, so we
    782          * track their initialization.
    783          */
    784         for (i = 0; i < MethodInfo->NumArguments; i++)
    785         {
    786             MethodInfo->ArgInitialized[i] = TRUE;
    787         }
    788         break;
    789 
    790 
    791     case PARSEOP_METHODCALL:
    792 
    793         if (MethodInfo &&
    794            (Op->Asl.Node == MethodInfo->Op->Asl.Node))
    795         {
    796             AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
    797         }
    798         break;
    799 
    800 
    801     case PARSEOP_LOCAL0:
    802     case PARSEOP_LOCAL1:
    803     case PARSEOP_LOCAL2:
    804     case PARSEOP_LOCAL3:
    805     case PARSEOP_LOCAL4:
    806     case PARSEOP_LOCAL5:
    807     case PARSEOP_LOCAL6:
    808     case PARSEOP_LOCAL7:
    809 
    810         if (!MethodInfo)
    811         {
    812             /*
    813              * Local was used outside a control method, or there was an error
    814              * in the method declaration.
    815              */
    816             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
    817             return (AE_ERROR);
    818         }
    819 
    820         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
    821 
    822         /*
    823          * If the local is being used as a target, mark the local
    824          * initialized
    825          */
    826         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    827         {
    828             MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
    829         }
    830 
    831         /*
    832          * Otherwise, this is a reference, check if the local
    833          * has been previously initialized.
    834          *
    835          * The only operator that accepts an uninitialized value is ObjectType()
    836          */
    837         else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
    838                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
    839         {
    840             LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
    841             AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
    842         }
    843         break;
    844 
    845 
    846     case PARSEOP_ARG0:
    847     case PARSEOP_ARG1:
    848     case PARSEOP_ARG2:
    849     case PARSEOP_ARG3:
    850     case PARSEOP_ARG4:
    851     case PARSEOP_ARG5:
    852     case PARSEOP_ARG6:
    853 
    854         if (!MethodInfo)
    855         {
    856             /*
    857              * Arg was used outside a control method, or there was an error
    858              * in the method declaration.
    859              */
    860             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
    861             return (AE_ERROR);
    862         }
    863 
    864         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
    865         ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
    866 
    867         /*
    868          * If the Arg is being used as a target, mark the local
    869          * initialized
    870          */
    871         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    872         {
    873             MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
    874         }
    875 
    876         /*
    877          * Otherwise, this is a reference, check if the Arg
    878          * has been previously initialized.
    879          *
    880          * The only operator that accepts an uninitialized value is ObjectType()
    881          */
    882         else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
    883                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
    884         {
    885             AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
    886         }
    887 
    888         /* Flag this arg if it is not a "real" argument to the method */
    889 
    890         if (RegisterNumber >= MethodInfo->NumArguments)
    891         {
    892             AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
    893         }
    894         break;
    895 
    896 
    897     case PARSEOP_RETURN:
    898 
    899         if (!MethodInfo)
    900         {
    901             /*
    902              * Probably was an error in the method declaration,
    903              * no additional error here
    904              */
    905             ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
    906             return (AE_ERROR);
    907         }
    908 
    909         /* Child indicates a return value */
    910 
    911         if ((Op->Asl.Child) &&
    912             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
    913         {
    914             MethodInfo->NumReturnWithValue++;
    915         }
    916         else
    917         {
    918             MethodInfo->NumReturnNoValue++;
    919         }
    920         break;
    921 
    922 
    923     case PARSEOP_BREAK:
    924     case PARSEOP_CONTINUE:
    925 
    926         Next = Op->Asl.Parent;
    927         while (Next)
    928         {
    929             if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
    930             {
    931                 break;
    932             }
    933             Next = Next->Asl.Parent;
    934         }
    935 
    936         if (!Next)
    937         {
    938             AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
    939         }
    940         break;
    941 
    942 
    943     case PARSEOP_STALL:
    944 
    945         /* We can range check if the argument is an integer */
    946 
    947         if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    948             (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
    949         {
    950             AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
    951         }
    952         break;
    953 
    954 
    955     case PARSEOP_DEVICE:
    956     case PARSEOP_EVENT:
    957     case PARSEOP_MUTEX:
    958     case PARSEOP_OPERATIONREGION:
    959     case PARSEOP_POWERRESOURCE:
    960     case PARSEOP_PROCESSOR:
    961     case PARSEOP_THERMALZONE:
    962 
    963         /*
    964          * The first operand is a name to be created in the namespace.
    965          * Check against the reserved list.
    966          */
    967         i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
    968         if (i < ACPI_VALID_RESERVED_NAME_MAX)
    969         {
    970             AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
    971         }
    972         break;
    973 
    974 
    975     case PARSEOP_NAME:
    976 
    977         /* Typecheck any predefined names statically defined with Name() */
    978 
    979         ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
    980 
    981         /* Special typechecking for _HID */
    982 
    983         if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
    984         {
    985             Next = Op->Asl.Child->Asl.Next;
    986             if (Next->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
    987             {
    988                 /*
    989                  * _HID is a string, all characters must be alphanumeric.
    990                  * One of the things we want to catch here is the use of
    991                  * a leading asterisk in the string.
    992                  */
    993                 for (i = 0; Next->Asl.Value.String[i]; i++)
    994                 {
    995                     if (!isalnum ((int) Next->Asl.Value.String[i]))
    996                     {
    997                         AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING,
    998                             Next, Next->Asl.Value.String);
    999                         break;
   1000                     }
   1001                 }
   1002             }
   1003         }
   1004         break;
   1005 
   1006 
   1007     default:
   1008         break;
   1009     }
   1010 
   1011     return AE_OK;
   1012 }
   1013 
   1014 
   1015 /*******************************************************************************
   1016  *
   1017  * FUNCTION:    AnLastStatementIsReturn
   1018  *
   1019  * PARAMETERS:  Op            - A method parse node
   1020  *
   1021  * RETURN:      TRUE if last statement is an ASL RETURN. False otherwise
   1022  *
   1023  * DESCRIPTION: Walk down the list of top level statements within a method
   1024  *              to find the last one. Check if that last statement is in
   1025  *              fact a RETURN statement.
   1026  *
   1027  ******************************************************************************/
   1028 
   1029 static BOOLEAN
   1030 AnLastStatementIsReturn (
   1031     ACPI_PARSE_OBJECT       *Op)
   1032 {
   1033     ACPI_PARSE_OBJECT       *Next;
   1034 
   1035 
   1036     /*
   1037      * Check if last statement is a return
   1038      */
   1039     Next = ASL_GET_CHILD_NODE (Op);
   1040     while (Next)
   1041     {
   1042         if ((!Next->Asl.Next) &&
   1043             (Next->Asl.ParseOpcode == PARSEOP_RETURN))
   1044         {
   1045             return TRUE;
   1046         }
   1047 
   1048         Next = ASL_GET_PEER_NODE (Next);
   1049     }
   1050 
   1051     return FALSE;
   1052 }
   1053 
   1054 
   1055 /*******************************************************************************
   1056  *
   1057  * FUNCTION:    AnMethodAnalysisWalkEnd
   1058  *
   1059  * PARAMETERS:  ASL_WALK_CALLBACK
   1060  *
   1061  * RETURN:      Status
   1062  *
   1063  * DESCRIPTION: Ascending callback for analysis walk. Complete method
   1064  *              return analysis.
   1065  *
   1066  ******************************************************************************/
   1067 
   1068 ACPI_STATUS
   1069 AnMethodAnalysisWalkEnd (
   1070     ACPI_PARSE_OBJECT       *Op,
   1071     UINT32                  Level,
   1072     void                    *Context)
   1073 {
   1074     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
   1075     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
   1076 
   1077 
   1078     switch (Op->Asl.ParseOpcode)
   1079     {
   1080     case PARSEOP_METHOD:
   1081     case PARSEOP_RETURN:
   1082         if (!MethodInfo)
   1083         {
   1084             printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
   1085             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
   1086                 "No method info for this method");
   1087             CmCleanupAndExit ();
   1088             return (AE_AML_INTERNAL);
   1089         }
   1090         break;
   1091 
   1092     default:
   1093         break;
   1094     }
   1095 
   1096     switch (Op->Asl.ParseOpcode)
   1097     {
   1098     case PARSEOP_METHOD:
   1099 
   1100         WalkInfo->MethodStack = MethodInfo->Next;
   1101 
   1102         /*
   1103          * Check if there is no return statement at the end of the
   1104          * method AND we can actually get there -- i.e., the execution
   1105          * of the method can possibly terminate without a return statement.
   1106          */
   1107         if ((!AnLastStatementIsReturn (Op)) &&
   1108             (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
   1109         {
   1110             /*
   1111              * No return statement, and execution can possibly exit
   1112              * via this path. This is equivalent to Return ()
   1113              */
   1114             MethodInfo->NumReturnNoValue++;
   1115         }
   1116 
   1117         /*
   1118          * Check for case where some return statements have a return value
   1119          * and some do not. Exit without a return statement is a return with
   1120          * no value
   1121          */
   1122         if (MethodInfo->NumReturnNoValue &&
   1123             MethodInfo->NumReturnWithValue)
   1124         {
   1125             AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
   1126                 Op->Asl.ExternalName);
   1127         }
   1128 
   1129         /*
   1130          * If there are any RETURN() statements with no value, or there is a
   1131          * control path that allows the method to exit without a return value,
   1132          * we mark the method as a method that does not return a value. This
   1133          * knowledge can be used to check method invocations that expect a
   1134          * returned value.
   1135          */
   1136         if (MethodInfo->NumReturnNoValue)
   1137         {
   1138             if (MethodInfo->NumReturnWithValue)
   1139             {
   1140                 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
   1141             }
   1142             else
   1143             {
   1144                 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
   1145             }
   1146         }
   1147 
   1148         /*
   1149          * Check predefined method names for correct return behavior
   1150          * and correct number of arguments
   1151          */
   1152         ApCheckForPredefinedMethod (Op, MethodInfo);
   1153         ACPI_FREE (MethodInfo);
   1154         break;
   1155 
   1156 
   1157     case PARSEOP_RETURN:
   1158 
   1159         /*
   1160          * If the parent is a predefined method name, attempt to typecheck
   1161          * the return value. Only static types can be validated.
   1162          */
   1163         ApCheckPredefinedReturnValue (Op, MethodInfo);
   1164 
   1165         /*
   1166          * The parent block does not "exit" and continue execution -- the
   1167          * method is terminated here with the Return() statement.
   1168          */
   1169         Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
   1170 
   1171         /* Used in the "typing" pass later */
   1172 
   1173         Op->Asl.ParentMethod = MethodInfo->Op;
   1174 
   1175         /*
   1176          * If there is a peer node after the return statement, then this
   1177          * node is unreachable code -- i.e., it won't be executed because of
   1178          * the preceeding Return() statement.
   1179          */
   1180         if (Op->Asl.Next)
   1181         {
   1182             AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
   1183         }
   1184         break;
   1185 
   1186 
   1187     case PARSEOP_IF:
   1188 
   1189         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
   1190             (Op->Asl.Next) &&
   1191             (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
   1192         {
   1193             /*
   1194              * This IF has a corresponding ELSE. The IF block has no exit,
   1195              * (it contains an unconditional Return)
   1196              * mark the ELSE block to remember this fact.
   1197              */
   1198             Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
   1199         }
   1200         break;
   1201 
   1202 
   1203     case PARSEOP_ELSE:
   1204 
   1205         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
   1206             (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
   1207         {
   1208             /*
   1209              * This ELSE block has no exit and the corresponding IF block
   1210              * has no exit either. Therefore, the parent node has no exit.
   1211              */
   1212             Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
   1213         }
   1214         break;
   1215 
   1216 
   1217     default:
   1218 
   1219         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
   1220             (Op->Asl.Parent))
   1221         {
   1222             /* If this node has no exit, then the parent has no exit either */
   1223 
   1224             Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
   1225         }
   1226         break;
   1227     }
   1228 
   1229     return AE_OK;
   1230 }
   1231 
   1232 
   1233 /*******************************************************************************
   1234  *
   1235  * FUNCTION:    AnMethodTypingWalkBegin
   1236  *
   1237  * PARAMETERS:  ASL_WALK_CALLBACK
   1238  *
   1239  * RETURN:      Status
   1240  *
   1241  * DESCRIPTION: Descending callback for the typing walk.
   1242  *
   1243  ******************************************************************************/
   1244 
   1245 ACPI_STATUS
   1246 AnMethodTypingWalkBegin (
   1247     ACPI_PARSE_OBJECT       *Op,
   1248     UINT32                  Level,
   1249     void                    *Context)
   1250 {
   1251 
   1252     return AE_OK;
   1253 }
   1254 
   1255 
   1256 /*******************************************************************************
   1257  *
   1258  * FUNCTION:    AnMethodTypingWalkEnd
   1259  *
   1260  * PARAMETERS:  ASL_WALK_CALLBACK
   1261  *
   1262  * RETURN:      Status
   1263  *
   1264  * DESCRIPTION: Ascending callback for typing walk. Complete the method
   1265  *              return analysis. Check methods for:
   1266  *              1) Initialized local variables
   1267  *              2) Valid arguments
   1268  *              3) Return types
   1269  *
   1270  ******************************************************************************/
   1271 
   1272 ACPI_STATUS
   1273 AnMethodTypingWalkEnd (
   1274     ACPI_PARSE_OBJECT       *Op,
   1275     UINT32                  Level,
   1276     void                    *Context)
   1277 {
   1278     UINT32                  ThisNodeBtype;
   1279 
   1280 
   1281     switch (Op->Asl.ParseOpcode)
   1282     {
   1283     case PARSEOP_METHOD:
   1284 
   1285         Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
   1286         break;
   1287 
   1288     case PARSEOP_RETURN:
   1289 
   1290         if ((Op->Asl.Child) &&
   1291             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
   1292         {
   1293             ThisNodeBtype = AnGetBtype (Op->Asl.Child);
   1294 
   1295             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
   1296                 (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
   1297             {
   1298                 /*
   1299                  * The called method is untyped at this time (typically a
   1300                  * forward reference).
   1301                  *
   1302                  * Check for a recursive method call first.
   1303                  */
   1304                 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
   1305                 {
   1306                     /* We must type the method here */
   1307 
   1308                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
   1309                         ASL_WALK_VISIT_TWICE, AnMethodTypingWalkBegin,
   1310                         AnMethodTypingWalkEnd, NULL);
   1311 
   1312                     ThisNodeBtype = AnGetBtype (Op->Asl.Child);
   1313                 }
   1314             }
   1315 
   1316             /* Returns a value, save the value type */
   1317 
   1318             if (Op->Asl.ParentMethod)
   1319             {
   1320                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
   1321             }
   1322         }
   1323         break;
   1324 
   1325     default:
   1326         break;
   1327     }
   1328 
   1329     return AE_OK;
   1330 }
   1331 
   1332 
   1333 /*******************************************************************************
   1334  *
   1335  * FUNCTION:    AnCheckMethodReturnValue
   1336  *
   1337  * PARAMETERS:  Op                  - Parent
   1338  *              OpInfo              - Parent info
   1339  *              ArgOp               - Method invocation op
   1340  *              RequiredBtypes      - What caller requires
   1341  *              ThisNodeBtype       - What this node returns (if anything)
   1342  *
   1343  * RETURN:      None
   1344  *
   1345  * DESCRIPTION: Check a method invocation for 1) A return value and if it does
   1346  *              in fact return a value, 2) check the type of the return value.
   1347  *
   1348  ******************************************************************************/
   1349 
   1350 static void
   1351 AnCheckMethodReturnValue (
   1352     ACPI_PARSE_OBJECT       *Op,
   1353     const ACPI_OPCODE_INFO  *OpInfo,
   1354     ACPI_PARSE_OBJECT       *ArgOp,
   1355     UINT32                  RequiredBtypes,
   1356     UINT32                  ThisNodeBtype)
   1357 {
   1358     ACPI_PARSE_OBJECT       *OwningOp;
   1359     ACPI_NAMESPACE_NODE     *Node;
   1360 
   1361 
   1362     Node = ArgOp->Asl.Node;
   1363 
   1364 
   1365     /* Examine the parent op of this method */
   1366 
   1367     OwningOp = Node->Op;
   1368     if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL)
   1369     {
   1370         /* Method NEVER returns a value */
   1371 
   1372         AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName);
   1373     }
   1374     else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL)
   1375     {
   1376         /* Method SOMETIMES returns a value, SOMETIMES not */
   1377 
   1378         AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, Op, Op->Asl.ExternalName);
   1379     }
   1380     else if (!(ThisNodeBtype & RequiredBtypes))
   1381     {
   1382         /* Method returns a value, but the type is wrong */
   1383 
   1384         AnFormatBtype (StringBuffer, ThisNodeBtype);
   1385         AnFormatBtype (StringBuffer2, RequiredBtypes);
   1386 
   1387 
   1388         /*
   1389          * The case where the method does not return any value at all
   1390          * was already handled in the namespace cross reference
   1391          * -- Only issue an error if the method in fact returns a value,
   1392          * but it is of the wrong type
   1393          */
   1394         if (ThisNodeBtype != 0)
   1395         {
   1396             sprintf (MsgBuffer,
   1397                 "Method returns [%s], %s operator requires [%s]",
   1398                 StringBuffer, OpInfo->Name, StringBuffer2);
   1399 
   1400             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
   1401         }
   1402     }
   1403 }
   1404 
   1405 
   1406 /*******************************************************************************
   1407  *
   1408  * FUNCTION:    AnOperandTypecheckWalkBegin
   1409  *
   1410  * PARAMETERS:  ASL_WALK_CALLBACK
   1411  *
   1412  * RETURN:      Status
   1413  *
   1414  * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
   1415  *              1) Initialized local variables
   1416  *              2) Valid arguments
   1417  *              3) Return types
   1418  *
   1419  ******************************************************************************/
   1420 
   1421 ACPI_STATUS
   1422 AnOperandTypecheckWalkBegin (
   1423     ACPI_PARSE_OBJECT       *Op,
   1424     UINT32                  Level,
   1425     void                    *Context)
   1426 {
   1427 
   1428     return AE_OK;
   1429 }
   1430 
   1431 
   1432 /*******************************************************************************
   1433  *
   1434  * FUNCTION:    AnOperandTypecheckWalkEnd
   1435  *
   1436  * PARAMETERS:  ASL_WALK_CALLBACK
   1437  *
   1438  * RETURN:      Status
   1439  *
   1440  * DESCRIPTION: Ascending callback for analysis walk. Complete method
   1441  *              return analysis.
   1442  *
   1443  ******************************************************************************/
   1444 
   1445 ACPI_STATUS
   1446 AnOperandTypecheckWalkEnd (
   1447     ACPI_PARSE_OBJECT       *Op,
   1448     UINT32                  Level,
   1449     void                    *Context)
   1450 {
   1451     const ACPI_OPCODE_INFO  *OpInfo;
   1452     UINT32                  RuntimeArgTypes;
   1453     UINT32                  RuntimeArgTypes2;
   1454     UINT32                  RequiredBtypes;
   1455     UINT32                  ThisNodeBtype;
   1456     UINT32                  CommonBtypes;
   1457     UINT32                  OpcodeClass;
   1458     ACPI_PARSE_OBJECT       *ArgOp;
   1459     UINT32                  ArgType;
   1460 
   1461 
   1462     switch (Op->Asl.AmlOpcode)
   1463     {
   1464     case AML_RAW_DATA_BYTE:
   1465     case AML_RAW_DATA_WORD:
   1466     case AML_RAW_DATA_DWORD:
   1467     case AML_RAW_DATA_QWORD:
   1468     case AML_RAW_DATA_BUFFER:
   1469     case AML_RAW_DATA_CHAIN:
   1470     case AML_PACKAGE_LENGTH:
   1471     case AML_UNASSIGNED_OPCODE:
   1472     case AML_DEFAULT_ARG_OP:
   1473 
   1474         /* Ignore the internal (compiler-only) AML opcodes */
   1475 
   1476         return (AE_OK);
   1477 
   1478     default:
   1479         break;
   1480     }
   1481 
   1482     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
   1483     if (!OpInfo)
   1484     {
   1485         return (AE_OK);
   1486     }
   1487 
   1488     ArgOp           = Op->Asl.Child;
   1489     RuntimeArgTypes = OpInfo->RuntimeArgs;
   1490     OpcodeClass     = OpInfo->Class;
   1491 
   1492 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
   1493     /*
   1494      * Update 11/2008: In practice, we can't perform this check. A simple
   1495      * analysis is not sufficient. Also, it can cause errors when compiling
   1496      * disassembled code because of the way Switch operators are implemented
   1497      * (a While(One) loop with a named temp variable created within.)
   1498      */
   1499 
   1500     /*
   1501      * If we are creating a named object, check if we are within a while loop
   1502      * by checking if the parent is a WHILE op. This is a simple analysis, but
   1503      * probably sufficient for many cases.
   1504      *
   1505      * Allow Scope(), Buffer(), and Package().
   1506      */
   1507     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
   1508         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
   1509     {
   1510         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
   1511         {
   1512             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
   1513         }
   1514     }
   1515 #endif
   1516 
   1517     /*
   1518      * Special case for control opcodes IF/RETURN/WHILE since they
   1519      * have no runtime arg list (at this time)
   1520      */
   1521     switch (Op->Asl.AmlOpcode)
   1522     {
   1523     case AML_IF_OP:
   1524     case AML_WHILE_OP:
   1525     case AML_RETURN_OP:
   1526 
   1527         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
   1528         {
   1529             /* Check for an internal method */
   1530 
   1531             if (AnIsInternalMethod (ArgOp))
   1532             {
   1533                 return (AE_OK);
   1534             }
   1535 
   1536             /* The lone arg is a method call, check it */
   1537 
   1538             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
   1539             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
   1540             {
   1541                 RequiredBtypes = 0xFFFFFFFF;
   1542             }
   1543 
   1544             ThisNodeBtype = AnGetBtype (ArgOp);
   1545             if (ThisNodeBtype == ACPI_UINT32_MAX)
   1546             {
   1547                 return (AE_OK);
   1548             }
   1549             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
   1550                 RequiredBtypes, ThisNodeBtype);
   1551         }
   1552         return (AE_OK);
   1553 
   1554     default:
   1555         break;
   1556     }
   1557 
   1558     /* Ignore the non-executable opcodes */
   1559 
   1560     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
   1561     {
   1562         return (AE_OK);
   1563     }
   1564 
   1565     switch (OpcodeClass)
   1566     {
   1567     case AML_CLASS_EXECUTE:
   1568     case AML_CLASS_CREATE:
   1569     case AML_CLASS_CONTROL:
   1570     case AML_CLASS_RETURN_VALUE:
   1571 
   1572         /* TBD: Change class or fix typechecking for these */
   1573 
   1574         if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
   1575             (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
   1576             (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
   1577         {
   1578             break;
   1579         }
   1580 
   1581         /* Reverse the runtime argument list */
   1582 
   1583         RuntimeArgTypes2 = 0;
   1584         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
   1585         {
   1586             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
   1587             RuntimeArgTypes2 |= ArgType;
   1588             INCREMENT_ARG_LIST (RuntimeArgTypes);
   1589         }
   1590 
   1591         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
   1592         {
   1593             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
   1594 
   1595             ThisNodeBtype = AnGetBtype (ArgOp);
   1596             if (ThisNodeBtype == ACPI_UINT32_MAX)
   1597             {
   1598                 goto NextArgument;
   1599             }
   1600 
   1601             /* Examine the arg based on the required type of the arg */
   1602 
   1603             switch (ArgType)
   1604             {
   1605             case ARGI_TARGETREF:
   1606 
   1607                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
   1608                 {
   1609                     /* ZERO is the placeholder for "don't store result" */
   1610 
   1611                     ThisNodeBtype = RequiredBtypes;
   1612                     break;
   1613                 }
   1614 
   1615                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
   1616                 {
   1617                     /*
   1618                      * This is the case where an original reference to a resource
   1619                      * descriptor field has been replaced by an (Integer) offset.
   1620                      * These named fields are supported at compile-time only;
   1621                      * the names are not passed to the interpreter (via the AML).
   1622                      */
   1623                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
   1624                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
   1625                     {
   1626                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
   1627                     }
   1628                     else
   1629                     {
   1630                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
   1631                     }
   1632                     break;
   1633                 }
   1634 
   1635                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
   1636                     (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
   1637                 {
   1638                     break;
   1639                 }
   1640 
   1641                 ThisNodeBtype = RequiredBtypes;
   1642                 break;
   1643 
   1644 
   1645             case ARGI_REFERENCE:            /* References */
   1646             case ARGI_INTEGER_REF:
   1647             case ARGI_OBJECT_REF:
   1648             case ARGI_DEVICE_REF:
   1649 
   1650                 switch (ArgOp->Asl.ParseOpcode)
   1651                 {
   1652                 case PARSEOP_LOCAL0:
   1653                 case PARSEOP_LOCAL1:
   1654                 case PARSEOP_LOCAL2:
   1655                 case PARSEOP_LOCAL3:
   1656                 case PARSEOP_LOCAL4:
   1657                 case PARSEOP_LOCAL5:
   1658                 case PARSEOP_LOCAL6:
   1659                 case PARSEOP_LOCAL7:
   1660 
   1661                     /* TBD: implement analysis of current value (type) of the local */
   1662                     /* For now, just treat any local as a typematch */
   1663 
   1664                     /*ThisNodeBtype = RequiredBtypes;*/
   1665                     break;
   1666 
   1667                 case PARSEOP_ARG0:
   1668                 case PARSEOP_ARG1:
   1669                 case PARSEOP_ARG2:
   1670                 case PARSEOP_ARG3:
   1671                 case PARSEOP_ARG4:
   1672                 case PARSEOP_ARG5:
   1673                 case PARSEOP_ARG6:
   1674 
   1675                     /* Hard to analyze argument types, sow we won't */
   1676                     /* For now, just treat any arg as a typematch */
   1677 
   1678                     /* ThisNodeBtype = RequiredBtypes; */
   1679                     break;
   1680 
   1681                 case PARSEOP_DEBUG:
   1682                     break;
   1683 
   1684                 case PARSEOP_REFOF:
   1685                 case PARSEOP_INDEX:
   1686                 default:
   1687                     break;
   1688 
   1689                 }
   1690                 break;
   1691 
   1692             case ARGI_INTEGER:
   1693             default:
   1694                 break;
   1695             }
   1696 
   1697 
   1698             CommonBtypes = ThisNodeBtype & RequiredBtypes;
   1699 
   1700             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
   1701             {
   1702                 if (AnIsInternalMethod (ArgOp))
   1703                 {
   1704                     return (AE_OK);
   1705                 }
   1706 
   1707                 /* Check a method call for a valid return value */
   1708 
   1709                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
   1710                     RequiredBtypes, ThisNodeBtype);
   1711             }
   1712 
   1713             /*
   1714              * Now check if the actual type(s) match at least one
   1715              * bit to the required type
   1716              */
   1717             else if (!CommonBtypes)
   1718             {
   1719                 /* No match -- this is a type mismatch error */
   1720 
   1721                 AnFormatBtype (StringBuffer, ThisNodeBtype);
   1722                 AnFormatBtype (StringBuffer2, RequiredBtypes);
   1723 
   1724                 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
   1725                             StringBuffer, OpInfo->Name, StringBuffer2);
   1726 
   1727                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
   1728             }
   1729 
   1730         NextArgument:
   1731             ArgOp = ArgOp->Asl.Next;
   1732             INCREMENT_ARG_LIST (RuntimeArgTypes2);
   1733         }
   1734         break;
   1735 
   1736     default:
   1737         break;
   1738     }
   1739 
   1740     return (AE_OK);
   1741 }
   1742 
   1743 
   1744 /*******************************************************************************
   1745  *
   1746  * FUNCTION:    AnIsResultUsed
   1747  *
   1748  * PARAMETERS:  Op              - Parent op for the operator
   1749  *
   1750  * RETURN:      TRUE if result from this operation is actually consumed
   1751  *
   1752  * DESCRIPTION: Determine if the function result value from an operator is
   1753  *              used.
   1754  *
   1755  ******************************************************************************/
   1756 
   1757 BOOLEAN
   1758 AnIsResultUsed (
   1759     ACPI_PARSE_OBJECT       *Op)
   1760 {
   1761     ACPI_PARSE_OBJECT       *Parent;
   1762 
   1763 
   1764     switch (Op->Asl.ParseOpcode)
   1765     {
   1766     case PARSEOP_INCREMENT:
   1767     case PARSEOP_DECREMENT:
   1768 
   1769         /* These are standalone operators, no return value */
   1770 
   1771         return (TRUE);
   1772 
   1773     default:
   1774         break;
   1775     }
   1776 
   1777     /* Examine parent to determine if the return value is used */
   1778 
   1779     Parent = Op->Asl.Parent;
   1780     switch (Parent->Asl.ParseOpcode)
   1781     {
   1782     /* If/While - check if the operator is the predicate */
   1783 
   1784     case PARSEOP_IF:
   1785     case PARSEOP_WHILE:
   1786 
   1787         /* First child is the predicate */
   1788 
   1789         if (Parent->Asl.Child == Op)
   1790         {
   1791             return (TRUE);
   1792         }
   1793         return (FALSE);
   1794 
   1795     /* Not used if one of these is the parent */
   1796 
   1797     case PARSEOP_METHOD:
   1798     case PARSEOP_DEFINITIONBLOCK:
   1799     case PARSEOP_ELSE:
   1800 
   1801         return (FALSE);
   1802 
   1803     default:
   1804         /* Any other type of parent means that the result is used */
   1805 
   1806         return (TRUE);
   1807     }
   1808 }
   1809 
   1810 
   1811 /*******************************************************************************
   1812  *
   1813  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
   1814  *
   1815  * PARAMETERS:  ASL_WALK_CALLBACK
   1816  *
   1817  * RETURN:      Status
   1818  *
   1819  * DESCRIPTION: Descending callback for the analysis walk. Checks for
   1820  *              miscellaneous issues in the code.
   1821  *
   1822  ******************************************************************************/
   1823 
   1824 ACPI_STATUS
   1825 AnOtherSemanticAnalysisWalkBegin (
   1826     ACPI_PARSE_OBJECT       *Op,
   1827     UINT32                  Level,
   1828     void                    *Context)
   1829 {
   1830     ACPI_PARSE_OBJECT       *ArgNode;
   1831     ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
   1832     const ACPI_OPCODE_INFO  *OpInfo;
   1833 
   1834 
   1835     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
   1836 
   1837     /*
   1838      * Determine if an execution class operator actually does something by
   1839      * checking if it has a target and/or the function return value is used.
   1840      * (Target is optional, so a standalone statement can actually do nothing.)
   1841      */
   1842     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
   1843         (OpInfo->Flags & AML_HAS_RETVAL) &&
   1844         (!AnIsResultUsed (Op)))
   1845     {
   1846         if (OpInfo->Flags & AML_HAS_TARGET)
   1847         {
   1848             /*
   1849              * Find the target node, it is always the last child. If the traget
   1850              * is not specified in the ASL, a default node of type Zero was
   1851              * created by the parser.
   1852              */
   1853             ArgNode = Op->Asl.Child;
   1854             while (ArgNode->Asl.Next)
   1855             {
   1856                 PrevArgNode = ArgNode;
   1857                 ArgNode = ArgNode->Asl.Next;
   1858             }
   1859 
   1860             /* Divide() is the only weird case, it has two targets */
   1861 
   1862             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
   1863             {
   1864                 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
   1865                     (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
   1866                 {
   1867                     AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
   1868                 }
   1869             }
   1870             else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
   1871             {
   1872                 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
   1873             }
   1874         }
   1875         else
   1876         {
   1877             /*
   1878              * Has no target and the result is not used. Only a couple opcodes
   1879              * can have this combination.
   1880              */
   1881             switch (Op->Asl.ParseOpcode)
   1882             {
   1883             case PARSEOP_ACQUIRE:
   1884             case PARSEOP_WAIT:
   1885             case PARSEOP_LOADTABLE:
   1886                 break;
   1887 
   1888             default:
   1889                 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
   1890                 break;
   1891             }
   1892         }
   1893     }
   1894 
   1895 
   1896     /*
   1897      * Semantic checks for individual ASL operators
   1898      */
   1899     switch (Op->Asl.ParseOpcode)
   1900     {
   1901     case PARSEOP_ACQUIRE:
   1902     case PARSEOP_WAIT:
   1903         /*
   1904          * Emit a warning if the timeout parameter for these operators is not
   1905          * ACPI_WAIT_FOREVER, and the result value from the operator is not
   1906          * checked, meaning that a timeout could happen, but the code
   1907          * would not know about it.
   1908          */
   1909 
   1910         /* First child is the namepath, 2nd child is timeout */
   1911 
   1912         ArgNode = Op->Asl.Child;
   1913         ArgNode = ArgNode->Asl.Next;
   1914 
   1915         /*
   1916          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
   1917          * 0xFFFF or greater
   1918          */
   1919         if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
   1920              (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
   1921              (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
   1922         {
   1923             break;
   1924         }
   1925 
   1926         /*
   1927          * The operation could timeout. If the return value is not used
   1928          * (indicates timeout occurred), issue a warning
   1929          */
   1930         if (!AnIsResultUsed (Op))
   1931         {
   1932             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, Op->Asl.ExternalName);
   1933         }
   1934         break;
   1935 
   1936     case PARSEOP_CREATEFIELD:
   1937         /*
   1938          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
   1939          */
   1940         ArgNode = Op->Asl.Child;
   1941         ArgNode = ArgNode->Asl.Next;
   1942         ArgNode = ArgNode->Asl.Next;
   1943 
   1944         if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
   1945            ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
   1946             (ArgNode->Asl.Value.Integer == 0)))
   1947         {
   1948             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
   1949         }
   1950         break;
   1951 
   1952     default:
   1953         break;
   1954     }
   1955 
   1956     return AE_OK;
   1957 }
   1958 
   1959 
   1960 /*******************************************************************************
   1961  *
   1962  * FUNCTION:    AnOtherSemanticAnalysisWalkEnd
   1963  *
   1964  * PARAMETERS:  ASL_WALK_CALLBACK
   1965  *
   1966  * RETURN:      Status
   1967  *
   1968  * DESCRIPTION: Ascending callback for analysis walk. Complete method
   1969  *              return analysis.
   1970  *
   1971  ******************************************************************************/
   1972 
   1973 ACPI_STATUS
   1974 AnOtherSemanticAnalysisWalkEnd (
   1975     ACPI_PARSE_OBJECT       *Op,
   1976     UINT32                  Level,
   1977     void                    *Context)
   1978 {
   1979 
   1980     return AE_OK;
   1981 
   1982 }
   1983 
   1984 
   1985 #ifdef ACPI_OBSOLETE_FUNCTIONS
   1986 /*******************************************************************************
   1987  *
   1988  * FUNCTION:    AnMapBtypeToEtype
   1989  *
   1990  * PARAMETERS:  Btype               - Bitfield of ACPI types
   1991  *
   1992  * RETURN:      The Etype corresponding the the Btype
   1993  *
   1994  * DESCRIPTION: Convert a bitfield type to an encoded type
   1995  *
   1996  ******************************************************************************/
   1997 
   1998 UINT32
   1999 AnMapBtypeToEtype (
   2000     UINT32              Btype)
   2001 {
   2002     UINT32              i;
   2003     UINT32              Etype;
   2004 
   2005 
   2006     if (Btype == 0)
   2007     {
   2008         return 0;
   2009     }
   2010 
   2011     Etype = 1;
   2012     for (i = 1; i < Btype; i *= 2)
   2013     {
   2014         Etype++;
   2015     }
   2016 
   2017     return (Etype);
   2018 }
   2019 #endif
   2020 
   2021