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