1 2 /****************************************************************************** 3 * 4 * Module Name: aslanalyze.c - check for semantic errors 5 * $Revision: 1.96 $ 6 * 7 *****************************************************************************/ 8 9 /****************************************************************************** 10 * 11 * 1. Copyright Notice 12 * 13 * Some or all of this work - Copyright (c) 1999 - 2005, 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 175 /******************************************************************************* 176 * 177 * FUNCTION: AnMapArgTypeToBtype 178 * 179 * PARAMETERS: ArgType - The ARGI required type(s) for this argument, 180 * from the opcode info table 181 * 182 * RETURN: The corresponding Bit-encoded types 183 * 184 * DESCRIPTION: Convert an encoded ARGI required argument type code into a 185 * bitfield type code. Implements the implicit source conversion 186 * rules. 187 * 188 ******************************************************************************/ 189 190 static UINT32 191 AnMapArgTypeToBtype ( 192 UINT32 ArgType) 193 { 194 195 switch (ArgType) 196 { 197 198 /* Simple types */ 199 200 case ARGI_ANYTYPE: 201 return (ACPI_BTYPE_OBJECTS_AND_REFS); 202 203 case ARGI_PACKAGE: 204 return (ACPI_BTYPE_PACKAGE); 205 206 case ARGI_EVENT: 207 return (ACPI_BTYPE_EVENT); 208 209 case ARGI_MUTEX: 210 return (ACPI_BTYPE_MUTEX); 211 212 case ARGI_DDBHANDLE: 213 return (ACPI_BTYPE_DDB_HANDLE); 214 215 /* Interchangeable types */ 216 /* 217 * Source conversion rules: 218 * Integer, String, and Buffer are all interchangeable 219 */ 220 case ARGI_INTEGER: 221 case ARGI_STRING: 222 case ARGI_BUFFER: 223 case ARGI_BUFFER_OR_STRING: 224 case ARGI_COMPUTEDATA: 225 return (ACPI_BTYPE_COMPUTE_DATA); 226 227 /* References */ 228 229 case ARGI_INTEGER_REF: 230 return (ACPI_BTYPE_INTEGER); 231 232 case ARGI_OBJECT_REF: 233 return (ACPI_BTYPE_ALL_OBJECTS); 234 235 case ARGI_DEVICE_REF: 236 return (ACPI_BTYPE_DEVICE_OBJECTS); 237 238 case ARGI_REFERENCE: 239 return (ACPI_BTYPE_REFERENCE); 240 241 case ARGI_TARGETREF: 242 case ARGI_FIXED_TARGET: 243 case ARGI_SIMPLE_TARGET: 244 return (ACPI_BTYPE_OBJECTS_AND_REFS); 245 246 /* Complex types */ 247 248 case ARGI_DATAOBJECT: 249 250 /* 251 * Buffer, string, package or reference to a Op - 252 * Used only by SizeOf operator 253 */ 254 return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | 255 ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE); 256 257 case ARGI_COMPLEXOBJ: 258 259 /* Buffer, String, or package */ 260 261 return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | ACPI_BTYPE_PACKAGE); 262 263 case ARGI_REF_OR_STRING: 264 return (ACPI_BTYPE_STRING | ACPI_BTYPE_REFERENCE); 265 266 case ARGI_REGION_OR_FIELD: 267 return (ACPI_BTYPE_REGION | ACPI_BTYPE_FIELD_UNIT); 268 269 case ARGI_DATAREFOBJ: 270 return (ACPI_BTYPE_INTEGER |ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | 271 ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE); 272 273 default: 274 break; 275 } 276 277 return (ACPI_BTYPE_OBJECTS_AND_REFS); 278 } 279 280 281 /******************************************************************************* 282 * 283 * FUNCTION: AnMapEtypeToBtype 284 * 285 * PARAMETERS: Etype - Encoded ACPI Type 286 * 287 * RETURN: Btype corresponding to the Etype 288 * 289 * DESCRIPTION: Convert an encoded ACPI type to a bitfield type applying the 290 * operand conversion rules. In other words, returns the type(s) 291 * this Etype is implicitly converted to during interpretation. 292 * 293 ******************************************************************************/ 294 295 static UINT32 296 AnMapEtypeToBtype ( 297 UINT32 Etype) 298 { 299 300 301 if (Etype == ACPI_TYPE_ANY) 302 { 303 return ACPI_BTYPE_OBJECTS_AND_REFS; 304 } 305 306 /* Try the standard ACPI data types */ 307 308 if (Etype <= ACPI_TYPE_EXTERNAL_MAX) 309 { 310 /* 311 * This switch statement implements the allowed operand conversion 312 * rules as per the "ASL Data Types" section of the ACPI 313 * specification. 314 */ 315 switch (Etype) 316 { 317 case ACPI_TYPE_INTEGER: 318 return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_DDB_HANDLE); 319 320 case ACPI_TYPE_STRING: 321 case ACPI_TYPE_BUFFER: 322 return (ACPI_BTYPE_COMPUTE_DATA); 323 324 case ACPI_TYPE_PACKAGE: 325 return (ACPI_BTYPE_PACKAGE); 326 327 case ACPI_TYPE_FIELD_UNIT: 328 return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT); 329 330 case ACPI_TYPE_BUFFER_FIELD: 331 return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_BUFFER_FIELD); 332 333 case ACPI_TYPE_DDB_HANDLE: 334 return (ACPI_BTYPE_INTEGER | ACPI_BTYPE_DDB_HANDLE); 335 336 case ACPI_BTYPE_DEBUG_OBJECT: 337 338 /* Cannot be used as a source operand */ 339 340 return (0); 341 342 default: 343 return (1 << (Etype - 1)); 344 } 345 } 346 347 /* Try the internal data types */ 348 349 switch (Etype) 350 { 351 case ACPI_TYPE_LOCAL_REGION_FIELD: 352 case ACPI_TYPE_LOCAL_BANK_FIELD: 353 case ACPI_TYPE_LOCAL_INDEX_FIELD: 354 355 /* Named fields can be either Integer/Buffer/String */ 356 357 return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT); 358 359 case ACPI_TYPE_LOCAL_ALIAS: 360 361 return (ACPI_BTYPE_INTEGER); 362 363 364 case ACPI_TYPE_LOCAL_RESOURCE: 365 case ACPI_TYPE_LOCAL_RESOURCE_FIELD: 366 367 return (ACPI_BTYPE_REFERENCE); 368 369 default: 370 printf ("Unhandled encoded type: %X\n", Etype); 371 return (0); 372 } 373 } 374 375 376 /******************************************************************************* 377 * 378 * FUNCTION: AnFormatBtype 379 * 380 * PARAMETERS: Btype - Bitfield of ACPI types 381 * Buffer - Where to put the ascii string 382 * 383 * RETURN: None. 384 * 385 * DESCRIPTION: Convert a Btype to a string of ACPI types 386 * 387 ******************************************************************************/ 388 389 static void 390 AnFormatBtype ( 391 char *Buffer, 392 UINT32 Btype) 393 { 394 UINT32 Type; 395 BOOLEAN First = TRUE; 396 397 398 *Buffer = 0; 399 400 if (Btype == 0) 401 { 402 strcat (Buffer, "NoReturnValue"); 403 return; 404 } 405 406 for (Type = 1; Type <= ACPI_TYPE_EXTERNAL_MAX; Type++) 407 { 408 if (Btype & 0x00000001) 409 { 410 if (!First) 411 { 412 strcat (Buffer, "|"); 413 } 414 First = FALSE; 415 strcat (Buffer, AcpiUtGetTypeName (Type)); 416 } 417 Btype >>= 1; 418 } 419 420 if (Btype & 0x00000001) 421 { 422 if (!First) 423 { 424 strcat (Buffer, "|"); 425 } 426 First = FALSE; 427 strcat (Buffer, "Reference"); 428 } 429 430 Btype >>= 1; 431 if (Btype & 0x00000001) 432 { 433 if (!First) 434 { 435 strcat (Buffer, "|"); 436 } 437 First = FALSE; 438 strcat (Buffer, "Resource"); 439 } 440 } 441 442 443 /******************************************************************************* 444 * 445 * FUNCTION: AnGetBtype 446 * 447 * PARAMETERS: Op - Parse node whose type will be returned. 448 * 449 * RETURN: The Btype associated with the Op. 450 * 451 * DESCRIPTION: Get the (bitfield) ACPI type associated with the parse node. 452 * Handles the case where the node is a name or method call and 453 * the actual type must be obtained from the namespace node. 454 * 455 ******************************************************************************/ 456 457 static UINT32 458 AnGetBtype ( 459 ACPI_PARSE_OBJECT *Op) 460 { 461 ACPI_NAMESPACE_NODE *Node; 462 ACPI_PARSE_OBJECT *ReferencedNode; 463 UINT32 ThisNodeBtype = 0; 464 465 466 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) || 467 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) || 468 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)) 469 { 470 Node = Op->Asl.Node; 471 if (!Node) 472 { 473 DbgPrint (ASL_DEBUG_OUTPUT, 474 "No attached Nsnode: [%s] at line %d name [%s], ignoring typecheck\n", 475 Op->Asl.ParseOpName, Op->Asl.LineNumber, 476 Op->Asl.ExternalName); 477 return ACPI_UINT32_MAX; 478 } 479 480 ThisNodeBtype = AnMapEtypeToBtype (Node->Type); 481 if (!ThisNodeBtype) 482 { 483 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, NULL); 484 } 485 486 /* 487 * Since it was a named reference, enable the 488 * reference bit also 489 */ 490 ThisNodeBtype |= ACPI_BTYPE_REFERENCE; 491 492 if (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) 493 { 494 ReferencedNode = Node->Op; 495 if (!ReferencedNode) 496 { 497 printf ("No back ptr to Op: type %X\n", Node->Type); 498 return ACPI_UINT32_MAX; 499 } 500 501 if (ReferencedNode->Asl.CompileFlags & NODE_METHOD_TYPED) 502 { 503 ThisNodeBtype = ReferencedNode->Asl.AcpiBtype; 504 } 505 else 506 { 507 return (ACPI_UINT32_MAX -1); 508 } 509 } 510 } 511 else 512 { 513 ThisNodeBtype = Op->Asl.AcpiBtype; 514 } 515 516 return (ThisNodeBtype); 517 } 518 519 520 /******************************************************************************* 521 * 522 * FUNCTION: AnCheckForReservedName 523 * 524 * PARAMETERS: Op - A parse node 525 * Name - NameSeg to check 526 * 527 * RETURN: None 528 * 529 * DESCRIPTION: Check a NameSeg against the reserved list. 530 * 531 ******************************************************************************/ 532 533 static UINT32 534 AnCheckForReservedName ( 535 ACPI_PARSE_OBJECT *Op, 536 char *Name) 537 { 538 UINT32 i; 539 540 541 if (Name[0] == 0) 542 { 543 AcpiOsPrintf ("Found a null name, external = %s\n", 544 Op->Asl.ExternalName); 545 } 546 547 /* All reserved names are prefixed with a single underscore */ 548 549 if (Name[0] != '_') 550 { 551 return (ACPI_NOT_RESERVED_NAME); 552 } 553 554 /* Check for a standard reserved method name */ 555 556 for (i = 0; ReservedMethods[i].Name; i++) 557 { 558 if (!ACPI_STRNCMP (Name, ReservedMethods[i].Name, ACPI_NAME_SIZE)) 559 { 560 if (ReservedMethods[i].Flags & ASL_RSVD_SCOPE) 561 { 562 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, 563 Op->Asl.ExternalName); 564 return (ACPI_PREDEFINED_NAME); 565 } 566 else if (ReservedMethods[i].Flags & ASL_RSVD_RESOURCE_NAME) 567 { 568 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, 569 Op->Asl.ExternalName); 570 return (ACPI_PREDEFINED_NAME); 571 } 572 573 /* Return index into reserved array */ 574 575 return i; 576 } 577 } 578 579 /* 580 * Now check for the "special" reserved names -- 581 * GPE: _Lxx 582 * GPE: _Exx 583 * EC: _Qxx 584 */ 585 if ((Name[1] == 'L') || 586 (Name[1] == 'E') || 587 (Name[1] == 'Q')) 588 { 589 /* The next two characters must be hex digits */ 590 591 if ((isxdigit (Name[2])) && 592 (isxdigit (Name[3]))) 593 { 594 return (ACPI_EVENT_RESERVED_NAME); 595 } 596 } 597 598 599 /* Check for the names reserved for the compiler itself: _T_x */ 600 601 else if ((Op->Asl.ExternalName[1] == 'T') && 602 (Op->Asl.ExternalName[2] == '_')) 603 { 604 /* Ignore if actually emitted by the compiler */ 605 606 if (Op->Asl.CompileFlags & NODE_COMPILER_EMITTED) 607 { 608 return (ACPI_NOT_RESERVED_NAME); 609 } 610 611 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, Op->Asl.ExternalName); 612 return (ACPI_COMPILER_RESERVED_NAME); 613 } 614 615 /* 616 * The name didn't match any of the known reserved names. Flag it as a 617 * warning, since the entire namespace starting with an underscore is 618 * reserved by the ACPI spec. 619 */ 620 AslError (ASL_WARNING, ASL_MSG_UNKNOWN_RESERVED_NAME, Op, 621 Op->Asl.ExternalName); 622 623 return (ACPI_NOT_RESERVED_NAME); 624 } 625 626 627 /******************************************************************************* 628 * 629 * FUNCTION: AnCheckForReservedMethod 630 * 631 * PARAMETERS: Op - A parse node of type "METHOD". 632 * MethodInfo - Saved info about this method 633 * 634 * RETURN: None 635 * 636 * DESCRIPTION: If method is a reserved name, check that the number of arguments 637 * and the return type (returns a value or not) is correct. 638 * 639 ******************************************************************************/ 640 641 static void 642 AnCheckForReservedMethod ( 643 ACPI_PARSE_OBJECT *Op, 644 ASL_METHOD_INFO *MethodInfo) 645 { 646 UINT32 Index; 647 648 649 /* Check for a match against the reserved name list */ 650 651 Index = AnCheckForReservedName (Op, Op->Asl.NameSeg); 652 653 switch (Index) 654 { 655 case ACPI_NOT_RESERVED_NAME: 656 case ACPI_PREDEFINED_NAME: 657 case ACPI_COMPILER_RESERVED_NAME: 658 659 /* Just return, nothing to do */ 660 break; 661 662 663 case ACPI_EVENT_RESERVED_NAME: 664 665 Gbl_ReservedMethods++; 666 667 /* NumArguments must be zero for all _Lxx, _Exx, and _Qxx methods */ 668 669 if (MethodInfo->NumArguments != 0) 670 { 671 sprintf (MsgBuffer, " %s requires %d", 672 Op->Asl.ExternalName, 0); 673 674 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, MsgBuffer); 675 } 676 break; 677 678 679 default: 680 681 Gbl_ReservedMethods++; 682 683 /* Matched a reserved method name */ 684 685 if (MethodInfo->NumArguments != ReservedMethods[Index].NumArguments) 686 { 687 sprintf (MsgBuffer, " %s requires %d", 688 ReservedMethods[Index].Name, 689 ReservedMethods[Index].NumArguments); 690 691 if (MethodInfo->NumArguments > ReservedMethods[Index].NumArguments) 692 { 693 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, 694 MsgBuffer); 695 } 696 else 697 { 698 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_LO, Op, 699 MsgBuffer); 700 } 701 } 702 703 if (MethodInfo->NumReturnNoValue && 704 ReservedMethods[Index].Flags & ASL_RSVD_RETURN_VALUE) 705 { 706 sprintf (MsgBuffer, "%s", ReservedMethods[Index].Name); 707 708 AslError (ASL_WARNING, ASL_MSG_RESERVED_RETURN_VALUE, Op, MsgBuffer); 709 } 710 break; 711 } 712 } 713 714 715 /******************************************************************************* 716 * 717 * FUNCTION: AnMapObjTypeToBtype 718 * 719 * PARAMETERS: Op - A parse node 720 * 721 * RETURN: A Btype 722 * 723 * DESCRIPTION: Map object to the associated "Btype" 724 * 725 ******************************************************************************/ 726 727 static UINT32 728 AnMapObjTypeToBtype ( 729 ACPI_PARSE_OBJECT *Op) 730 { 731 732 switch (Op->Asl.ParseOpcode) 733 { 734 case PARSEOP_OBJECTTYPE_BFF: /* "BuffFieldObj" */ 735 return (ACPI_BTYPE_BUFFER_FIELD); 736 737 case PARSEOP_OBJECTTYPE_BUF: /* "BuffObj" */ 738 return (ACPI_BTYPE_BUFFER); 739 740 case PARSEOP_OBJECTTYPE_DDB: /* "DDBHandleObj" */ 741 return (ACPI_BTYPE_DDB_HANDLE); 742 743 case PARSEOP_OBJECTTYPE_DEV: /* "DeviceObj" */ 744 return (ACPI_BTYPE_DEVICE); 745 746 case PARSEOP_OBJECTTYPE_EVT: /* "EventObj" */ 747 return (ACPI_BTYPE_EVENT); 748 749 case PARSEOP_OBJECTTYPE_FLD: /* "FieldUnitObj" */ 750 return (ACPI_BTYPE_FIELD_UNIT); 751 752 case PARSEOP_OBJECTTYPE_INT: /* "IntObj" */ 753 return (ACPI_BTYPE_INTEGER); 754 755 case PARSEOP_OBJECTTYPE_MTH: /* "MethodObj" */ 756 return (ACPI_BTYPE_METHOD); 757 758 case PARSEOP_OBJECTTYPE_MTX: /* "MutexObj" */ 759 return (ACPI_BTYPE_MUTEX); 760 761 case PARSEOP_OBJECTTYPE_OPR: /* "OpRegionObj" */ 762 return (ACPI_BTYPE_REGION); 763 764 case PARSEOP_OBJECTTYPE_PKG: /* "PkgObj" */ 765 return (ACPI_BTYPE_PACKAGE); 766 767 case PARSEOP_OBJECTTYPE_POW: /* "PowerResObj" */ 768 return (ACPI_BTYPE_POWER); 769 770 case PARSEOP_OBJECTTYPE_STR: /* "StrObj" */ 771 return (ACPI_BTYPE_STRING); 772 773 case PARSEOP_OBJECTTYPE_THZ: /* "ThermalZoneObj" */ 774 return (ACPI_BTYPE_THERMAL); 775 776 case PARSEOP_OBJECTTYPE_UNK: /* "UnknownObj" */ 777 return (ACPI_BTYPE_OBJECTS_AND_REFS); 778 779 default: 780 return (0); 781 } 782 } 783 784 785 /******************************************************************************* 786 * 787 * FUNCTION: AnMethodAnalysisWalkBegin 788 * 789 * PARAMETERS: ASL_WALK_CALLBACK 790 * 791 * RETURN: Status 792 * 793 * DESCRIPTION: Descending callback for the analysis walk. Check methods for : 794 * 1) Initialized local variables 795 * 2) Valid arguments 796 * 3) Return types 797 * 798 ******************************************************************************/ 799 800 ACPI_STATUS 801 AnMethodAnalysisWalkBegin ( 802 ACPI_PARSE_OBJECT *Op, 803 UINT32 Level, 804 void *Context) 805 { 806 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 807 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 808 ACPI_PARSE_OBJECT *Next; 809 UINT32 RegisterNumber; 810 UINT32 i; 811 char LocalName[] = "Local0"; 812 char ArgName[] = "Arg0"; 813 ACPI_PARSE_OBJECT *ArgNode; 814 ACPI_PARSE_OBJECT *NextType; 815 ACPI_PARSE_OBJECT *NextParamType; 816 UINT8 ActualArgs = 0; 817 818 819 ACPI_FUNCTION_NAME ("AnMethodAnalysisWalkBegin"); 820 821 822 switch (Op->Asl.ParseOpcode) 823 { 824 case PARSEOP_METHOD: 825 826 TotalMethods++; 827 828 /* Create and init method info */ 829 830 MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); 831 MethodInfo->Next = WalkInfo->MethodStack; 832 MethodInfo->Op = Op; 833 834 WalkInfo->MethodStack = MethodInfo; 835 836 /* Get the name node, ignored here */ 837 838 Next = Op->Asl.Child; 839 840 /* Get the NumArguments node */ 841 842 Next = Next->Asl.Next; 843 MethodInfo->NumArguments = (UINT8) 844 (((UINT8) Next->Asl.Value.Integer) & 0x07); 845 846 /* Get the SerializeRule and SyncLevel nodes, ignored here */ 847 848 Next = Next->Asl.Next; 849 Next = Next->Asl.Next; 850 ArgNode = Next; 851 852 /* Get the ReturnType node */ 853 854 Next = Next->Asl.Next; 855 856 NextType = Next->Asl.Child; 857 while (NextType) 858 { 859 /* Get and map each of the ReturnTypes */ 860 861 MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); 862 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 863 NextType = NextType->Asl.Next; 864 } 865 866 /* Get the ParameterType node */ 867 868 Next = Next->Asl.Next; 869 870 NextType = Next->Asl.Child; 871 while (NextType) 872 { 873 if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 874 { 875 NextParamType = NextType->Asl.Child; 876 while (NextParamType) 877 { 878 MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType); 879 NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 880 NextParamType = NextParamType->Asl.Next; 881 } 882 } 883 else 884 { 885 MethodInfo->ValidArgTypes[ActualArgs] = 886 AnMapObjTypeToBtype (NextType); 887 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 888 } 889 890 ActualArgs++; 891 NextType = NextType->Asl.Next; 892 } 893 894 if ((MethodInfo->NumArguments) && 895 (MethodInfo->NumArguments != ActualArgs)) 896 { 897 /* error: Param list did not match number of args */ 898 } 899 900 /* Allow numarguments == 0 for Function() */ 901 902 if ((!MethodInfo->NumArguments) && (ActualArgs)) 903 { 904 MethodInfo->NumArguments = ActualArgs; 905 ArgNode->Asl.Value.Integer |= ActualArgs; 906 } 907 908 /* 909 * Actual arguments are initialized at method entry. 910 * All other ArgX "registers" can be used as locals, so we 911 * track their initialization. 912 */ 913 for (i = 0; i < MethodInfo->NumArguments; i++) 914 { 915 MethodInfo->ArgInitialized[i] = TRUE; 916 } 917 break; 918 919 920 case PARSEOP_METHODCALL: 921 922 if (MethodInfo && 923 (Op->Asl.Node == MethodInfo->Op->Asl.Node)) 924 { 925 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); 926 } 927 break; 928 929 930 case PARSEOP_LOCAL0: 931 case PARSEOP_LOCAL1: 932 case PARSEOP_LOCAL2: 933 case PARSEOP_LOCAL3: 934 case PARSEOP_LOCAL4: 935 case PARSEOP_LOCAL5: 936 case PARSEOP_LOCAL6: 937 case PARSEOP_LOCAL7: 938 939 if (!MethodInfo) 940 { 941 /* 942 * Probably was an error in the method declaration, 943 * no additional error here 944 */ 945 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 946 return (AE_ERROR); 947 } 948 949 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); 950 951 /* 952 * If the local is being used as a target, mark the local 953 * initialized 954 */ 955 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 956 { 957 MethodInfo->LocalInitialized[RegisterNumber] = TRUE; 958 } 959 960 /* 961 * Otherwise, this is a reference, check if the local 962 * has been previously initialized. 963 * 964 * The only operator that accepts an uninitialized value is ObjectType() 965 */ 966 else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && 967 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 968 { 969 LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); 970 AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); 971 } 972 break; 973 974 975 case PARSEOP_ARG0: 976 case PARSEOP_ARG1: 977 case PARSEOP_ARG2: 978 case PARSEOP_ARG3: 979 case PARSEOP_ARG4: 980 case PARSEOP_ARG5: 981 case PARSEOP_ARG6: 982 983 if (!MethodInfo) 984 { 985 /* 986 * Probably was an error in the method declaration, 987 * no additional error here 988 */ 989 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 990 return (AE_ERROR); 991 } 992 993 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; 994 ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); 995 996 /* 997 * If the Arg is being used as a target, mark the local 998 * initialized 999 */ 1000 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 1001 { 1002 MethodInfo->ArgInitialized[RegisterNumber] = TRUE; 1003 } 1004 1005 /* 1006 * Otherwise, this is a reference, check if the Arg 1007 * has been previously initialized. 1008 * 1009 * The only operator that accepts an uninitialized value is ObjectType() 1010 */ 1011 else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && 1012 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 1013 { 1014 AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); 1015 } 1016 1017 /* Flag this arg if it is not a "real" argument to the method */ 1018 1019 if (RegisterNumber >= MethodInfo->NumArguments) 1020 { 1021 AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); 1022 } 1023 break; 1024 1025 1026 case PARSEOP_RETURN: 1027 1028 if (!MethodInfo) 1029 { 1030 /* 1031 * Probably was an error in the method declaration, 1032 * no additional error here 1033 */ 1034 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 1035 return (AE_ERROR); 1036 } 1037 1038 /* Child indicates a return value */ 1039 1040 if ((Op->Asl.Child) && 1041 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 1042 { 1043 MethodInfo->NumReturnWithValue++; 1044 } 1045 else 1046 { 1047 MethodInfo->NumReturnNoValue++; 1048 } 1049 break; 1050 1051 1052 case PARSEOP_BREAK: 1053 case PARSEOP_CONTINUE: 1054 1055 Next = Op->Asl.Parent; 1056 while (Next) 1057 { 1058 if (Next->Asl.ParseOpcode == PARSEOP_WHILE) 1059 { 1060 break; 1061 } 1062 Next = Next->Asl.Parent; 1063 } 1064 1065 if (!Next) 1066 { 1067 AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); 1068 } 1069 break; 1070 1071 1072 case PARSEOP_STALL: 1073 1074 /* We can range check if the argument is an integer */ 1075 1076 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 1077 (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) 1078 { 1079 AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); 1080 } 1081 break; 1082 1083 1084 case PARSEOP_DEVICE: 1085 case PARSEOP_EVENT: 1086 case PARSEOP_MUTEX: 1087 case PARSEOP_OPERATIONREGION: 1088 case PARSEOP_POWERRESOURCE: 1089 case PARSEOP_PROCESSOR: 1090 case PARSEOP_THERMALZONE: 1091 1092 /* 1093 * The first operand is a name to be created in the namespace. 1094 * Check against the reserved list. 1095 */ 1096 i = AnCheckForReservedName (Op, Op->Asl.NameSeg); 1097 if (i < ACPI_VALID_RESERVED_NAME_MAX) 1098 { 1099 AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); 1100 } 1101 break; 1102 1103 1104 case PARSEOP_NAME: 1105 1106 i = AnCheckForReservedName (Op, Op->Asl.NameSeg); 1107 if (i < ACPI_VALID_RESERVED_NAME_MAX) 1108 { 1109 if (ReservedMethods[i].NumArguments > 0) 1110 { 1111 /* 1112 * This reserved name must be a control method because 1113 * it must have arguments 1114 */ 1115 AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, 1116 "with arguments"); 1117 } 1118 1119 /* Typechecking for _HID */ 1120 1121 else if (!ACPI_STRCMP (METHOD_NAME__HID, ReservedMethods[i].Name)) 1122 { 1123 /* Examine the second operand to typecheck it */ 1124 1125 Next = Op->Asl.Child->Asl.Next; 1126 1127 if ((Next->Asl.ParseOpcode != PARSEOP_INTEGER) && 1128 (Next->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)) 1129 { 1130 /* _HID must be a string or an integer */ 1131 1132 AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Next, 1133 "String or Integer"); 1134 } 1135 1136 if (Next->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) 1137 { 1138 /* 1139 * _HID is a string, all characters must be alphanumeric. 1140 * One of the things we want to catch here is the use of 1141 * a leading asterisk in the string. 1142 */ 1143 for (i = 0; Next->Asl.Value.String[i]; i++) 1144 { 1145 if (!isalnum (Next->Asl.Value.String[i])) 1146 { 1147 AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING, 1148 Next, Next->Asl.Value.String); 1149 break; 1150 } 1151 } 1152 } 1153 } 1154 } 1155 1156 break; 1157 1158 1159 default: 1160 break; 1161 } 1162 1163 return AE_OK; 1164 } 1165 1166 1167 /******************************************************************************* 1168 * 1169 * FUNCTION: AnLastStatementIsReturn 1170 * 1171 * PARAMETERS: Op - A method parse node 1172 * 1173 * RETURN: TRUE if last statement is an ASL RETURN. False otherwise 1174 * 1175 * DESCRIPTION: Walk down the list of top level statements within a method 1176 * to find the last one. Check if that last statement is in 1177 * fact a RETURN statement. 1178 * 1179 ******************************************************************************/ 1180 1181 static BOOLEAN 1182 AnLastStatementIsReturn ( 1183 ACPI_PARSE_OBJECT *Op) 1184 { 1185 ACPI_PARSE_OBJECT *Next; 1186 1187 1188 /* 1189 * Check if last statement is a return 1190 */ 1191 Next = ASL_GET_CHILD_NODE (Op); 1192 while (Next) 1193 { 1194 if ((!Next->Asl.Next) && 1195 (Next->Asl.ParseOpcode == PARSEOP_RETURN)) 1196 { 1197 return TRUE; 1198 } 1199 1200 Next = ASL_GET_PEER_NODE (Next); 1201 } 1202 1203 return FALSE; 1204 } 1205 1206 1207 /******************************************************************************* 1208 * 1209 * FUNCTION: AnMethodAnalysisWalkEnd 1210 * 1211 * PARAMETERS: ASL_WALK_CALLBACK 1212 * 1213 * RETURN: Status 1214 * 1215 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1216 * return analysis. 1217 * 1218 ******************************************************************************/ 1219 1220 ACPI_STATUS 1221 AnMethodAnalysisWalkEnd ( 1222 ACPI_PARSE_OBJECT *Op, 1223 UINT32 Level, 1224 void *Context) 1225 { 1226 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 1227 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 1228 1229 1230 switch (Op->Asl.ParseOpcode) 1231 { 1232 case PARSEOP_METHOD: 1233 case PARSEOP_RETURN: 1234 if (!MethodInfo) 1235 { 1236 printf ("No method info for method! [%s]\n", Op->Asl.Namepath); 1237 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, 1238 "No method info for this method"); 1239 CmCleanupAndExit (); 1240 return (AE_AML_INTERNAL); 1241 } 1242 break; 1243 1244 default: 1245 break; 1246 } 1247 1248 switch (Op->Asl.ParseOpcode) 1249 { 1250 case PARSEOP_METHOD: 1251 1252 WalkInfo->MethodStack = MethodInfo->Next; 1253 1254 /* 1255 * Check if there is no return statement at the end of the 1256 * method AND we can actually get there -- i.e., the execution 1257 * of the method can possibly terminate without a return statement. 1258 */ 1259 if ((!AnLastStatementIsReturn (Op)) && 1260 (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) 1261 { 1262 /* 1263 * No return statement, and execution can possibly exit 1264 * via this path. This is equivalent to Return () 1265 */ 1266 MethodInfo->NumReturnNoValue++; 1267 } 1268 1269 /* 1270 * Check for case where some return statements have a return value 1271 * and some do not. Exit without a return statement is a return with 1272 * no value 1273 */ 1274 if (MethodInfo->NumReturnNoValue && 1275 MethodInfo->NumReturnWithValue) 1276 { 1277 AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, 1278 Op->Asl.ExternalName); 1279 } 1280 1281 /* 1282 * If there are any RETURN() statements with no value, or there is a 1283 * control path that allows the method to exit without a return value, 1284 * we mark the method as a method that does not return a value. This 1285 * knowledge can be used to check method invocations that expect a 1286 * returned value. 1287 */ 1288 if (MethodInfo->NumReturnNoValue) 1289 { 1290 if (MethodInfo->NumReturnWithValue) 1291 { 1292 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; 1293 } 1294 else 1295 { 1296 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; 1297 } 1298 } 1299 1300 /* 1301 * Check predefined method names for correct return behavior 1302 * and correct number of arguments 1303 */ 1304 AnCheckForReservedMethod (Op, MethodInfo); 1305 ACPI_MEM_FREE (MethodInfo); 1306 break; 1307 1308 1309 case PARSEOP_RETURN: 1310 1311 /* 1312 * The parent block does not "exit" and continue execution -- the 1313 * method is terminated here with the Return() statement. 1314 */ 1315 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1316 1317 /* Used in the "typing" pass later */ 1318 1319 Op->Asl.ParentMethod = MethodInfo->Op; 1320 1321 /* 1322 * If there is a peer node after the return statement, then this 1323 * node is unreachable code -- i.e., it won't be executed because of 1324 * thepreceeding Return() statement. 1325 */ 1326 if (Op->Asl.Next) 1327 { 1328 AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); 1329 } 1330 break; 1331 1332 1333 case PARSEOP_IF: 1334 1335 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1336 (Op->Asl.Next) && 1337 (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) 1338 { 1339 /* 1340 * This IF has a corresponding ELSE. The IF block has no exit, 1341 * (it contains an unconditional Return) 1342 * mark the ELSE block to remember this fact. 1343 */ 1344 Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; 1345 } 1346 break; 1347 1348 1349 case PARSEOP_ELSE: 1350 1351 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1352 (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) 1353 { 1354 /* 1355 * This ELSE block has no exit and the corresponding IF block 1356 * has no exit either. Therefore, the parent node has no exit. 1357 */ 1358 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1359 } 1360 break; 1361 1362 1363 default: 1364 1365 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1366 (Op->Asl.Parent)) 1367 { 1368 /* If this node has no exit, then the parent has no exit either */ 1369 1370 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1371 } 1372 break; 1373 } 1374 1375 return AE_OK; 1376 } 1377 1378 1379 /******************************************************************************* 1380 * 1381 * FUNCTION: AnMethodTypingWalkBegin 1382 * 1383 * PARAMETERS: ASL_WALK_CALLBACK 1384 * 1385 * RETURN: Status 1386 * 1387 * DESCRIPTION: Descending callback for the typing walk. 1388 * 1389 ******************************************************************************/ 1390 1391 ACPI_STATUS 1392 AnMethodTypingWalkBegin ( 1393 ACPI_PARSE_OBJECT *Op, 1394 UINT32 Level, 1395 void *Context) 1396 { 1397 1398 return AE_OK; 1399 } 1400 1401 1402 /******************************************************************************* 1403 * 1404 * FUNCTION: AnMethodTypingWalkEnd 1405 * 1406 * PARAMETERS: ASL_WALK_CALLBACK 1407 * 1408 * RETURN: Status 1409 * 1410 * DESCRIPTION: Ascending callback for typing walk. Complete method 1411 * return analysis. Check methods for : 1412 * 1) Initialized local variables 1413 * 2) Valid arguments 1414 * 3) Return types 1415 * 1416 ******************************************************************************/ 1417 1418 ACPI_STATUS 1419 AnMethodTypingWalkEnd ( 1420 ACPI_PARSE_OBJECT *Op, 1421 UINT32 Level, 1422 void *Context) 1423 { 1424 UINT32 ThisNodeBtype; 1425 1426 1427 switch (Op->Asl.ParseOpcode) 1428 { 1429 case PARSEOP_METHOD: 1430 1431 Op->Asl.CompileFlags |= NODE_METHOD_TYPED; 1432 break; 1433 1434 case PARSEOP_RETURN: 1435 1436 if ((Op->Asl.Child) && 1437 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 1438 { 1439 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 1440 1441 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && 1442 (ThisNodeBtype == (ACPI_UINT32_MAX -1))) 1443 { 1444 /* 1445 * The method is untyped at this time (typically a forward 1446 * reference). We must recursively type the method here 1447 */ 1448 TrWalkParseTree (Op->Asl.Child->Asl.Node->Op, 1449 ASL_WALK_VISIT_TWICE, AnMethodTypingWalkBegin, 1450 AnMethodTypingWalkEnd, NULL); 1451 1452 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 1453 } 1454 1455 /* Returns a value, get it's type */ 1456 1457 if (Op->Asl.ParentMethod) 1458 { 1459 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; 1460 } 1461 } 1462 break; 1463 1464 default: 1465 break; 1466 } 1467 1468 return AE_OK; 1469 } 1470 1471 1472 /******************************************************************************* 1473 * 1474 * FUNCTION: AnCheckMethodReturnValue 1475 * 1476 * PARAMETERS: Op - Parent 1477 * OpInfo - Parent info 1478 * ArgOp - Method invocation op 1479 * RequiredBtypes - What caller requires 1480 * ThisNodeBtype - What this node returns (if anything) 1481 * 1482 * RETURN: None 1483 * 1484 * DESCRIPTION: Check a method invocation for 1) A return value and if it does 1485 * in fact return a value, 2) check the type of the return value. 1486 * 1487 ******************************************************************************/ 1488 1489 static void 1490 AnCheckMethodReturnValue ( 1491 ACPI_PARSE_OBJECT *Op, 1492 const ACPI_OPCODE_INFO *OpInfo, 1493 ACPI_PARSE_OBJECT *ArgOp, 1494 UINT32 RequiredBtypes, 1495 UINT32 ThisNodeBtype) 1496 { 1497 ACPI_PARSE_OBJECT *OwningOp; 1498 ACPI_NAMESPACE_NODE *Node; 1499 1500 1501 Node = ArgOp->Asl.Node; 1502 1503 1504 /* Examine the parent op of this method */ 1505 1506 OwningOp = Node->Op; 1507 if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL) 1508 { 1509 /* Method NEVER returns a value */ 1510 1511 AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName); 1512 } 1513 else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL) 1514 { 1515 /* Method SOMETIMES returns a value, SOMETIMES not */ 1516 1517 AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, Op, Op->Asl.ExternalName); 1518 } 1519 else if (!(ThisNodeBtype & RequiredBtypes)) 1520 { 1521 /* Method returns a value, but the type is wrong */ 1522 1523 AnFormatBtype (StringBuffer, ThisNodeBtype); 1524 AnFormatBtype (StringBuffer2, RequiredBtypes); 1525 1526 1527 /* 1528 * The case where the method does not return any value at all 1529 * was already handled in the namespace cross reference 1530 * -- Only issue an error if the method in fact returns a value, 1531 * but it is of the wrong type 1532 */ 1533 if (ThisNodeBtype != 0) 1534 { 1535 sprintf (MsgBuffer, 1536 "Method returns [%s], %s operator requires [%s]", 1537 StringBuffer, OpInfo->Name, StringBuffer2); 1538 1539 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 1540 } 1541 } 1542 } 1543 1544 1545 /******************************************************************************* 1546 * 1547 * FUNCTION: AnOperandTypecheckWalkBegin 1548 * 1549 * PARAMETERS: ASL_WALK_CALLBACK 1550 * 1551 * RETURN: Status 1552 * 1553 * DESCRIPTION: Descending callback for the analysis walk. Check methods for: 1554 * 1) Initialized local variables 1555 * 2) Valid arguments 1556 * 3) Return types 1557 * 1558 ******************************************************************************/ 1559 1560 ACPI_STATUS 1561 AnOperandTypecheckWalkBegin ( 1562 ACPI_PARSE_OBJECT *Op, 1563 UINT32 Level, 1564 void *Context) 1565 { 1566 1567 return AE_OK; 1568 } 1569 1570 1571 /******************************************************************************* 1572 * 1573 * FUNCTION: AnOperandTypecheckWalkEnd 1574 * 1575 * PARAMETERS: ASL_WALK_CALLBACK 1576 * 1577 * RETURN: Status 1578 * 1579 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1580 * return analysis. 1581 * 1582 ******************************************************************************/ 1583 1584 ACPI_STATUS 1585 AnOperandTypecheckWalkEnd ( 1586 ACPI_PARSE_OBJECT *Op, 1587 UINT32 Level, 1588 void *Context) 1589 { 1590 const ACPI_OPCODE_INFO *OpInfo; 1591 UINT32 RuntimeArgTypes; 1592 UINT32 RuntimeArgTypes2; 1593 UINT32 RequiredBtypes; 1594 UINT32 ThisNodeBtype; 1595 UINT32 CommonBtypes; 1596 UINT32 OpcodeClass; 1597 ACPI_PARSE_OBJECT *ArgOp; 1598 UINT32 ArgType; 1599 1600 1601 switch (Op->Asl.AmlOpcode) 1602 { 1603 case AML_RAW_DATA_BYTE: 1604 case AML_RAW_DATA_WORD: 1605 case AML_RAW_DATA_DWORD: 1606 case AML_RAW_DATA_QWORD: 1607 case AML_RAW_DATA_BUFFER: 1608 case AML_RAW_DATA_CHAIN: 1609 case AML_PACKAGE_LENGTH: 1610 case AML_UNASSIGNED_OPCODE: 1611 case AML_DEFAULT_ARG_OP: 1612 1613 /* Ignore the internal (compiler-only) AML opcodes */ 1614 1615 return (AE_OK); 1616 1617 default: 1618 break; 1619 } 1620 1621 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1622 if (!OpInfo) 1623 { 1624 return (AE_OK); 1625 } 1626 1627 ArgOp = Op->Asl.Child; 1628 RuntimeArgTypes = OpInfo->RuntimeArgs; 1629 OpcodeClass = OpInfo->Class; 1630 1631 1632 /* 1633 * Special case for control opcodes IF/RETURN/WHILE since they 1634 * have no runtime arg list (at this time) 1635 */ 1636 switch (Op->Asl.AmlOpcode) 1637 { 1638 case AML_IF_OP: 1639 case AML_WHILE_OP: 1640 case AML_RETURN_OP: 1641 1642 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 1643 { 1644 if (!ACPI_STRCMP (ArgOp->Asl.ExternalName, "\\_OSI")) 1645 { 1646 return (AE_OK); 1647 } 1648 1649 /* The lone arg is a method call, check it */ 1650 1651 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); 1652 if (Op->Asl.AmlOpcode == AML_RETURN_OP) 1653 { 1654 RequiredBtypes = 0xFFFFFFFF; 1655 } 1656 1657 ThisNodeBtype = AnGetBtype (ArgOp); 1658 if (ThisNodeBtype == ACPI_UINT32_MAX) 1659 { 1660 return (AE_OK); 1661 } 1662 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 1663 RequiredBtypes, ThisNodeBtype); 1664 } 1665 return (AE_OK); 1666 1667 default: 1668 break; 1669 } 1670 1671 /* Ignore the non-executable opcodes */ 1672 1673 if (RuntimeArgTypes == ARGI_INVALID_OPCODE) 1674 { 1675 return (AE_OK); 1676 } 1677 1678 switch (OpcodeClass) 1679 { 1680 case AML_CLASS_EXECUTE: 1681 case AML_CLASS_CREATE: 1682 case AML_CLASS_CONTROL: 1683 case AML_CLASS_RETURN_VALUE: 1684 1685 /* TBD: Change class or fix typechecking for these */ 1686 1687 if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || 1688 (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || 1689 (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) 1690 { 1691 break; 1692 } 1693 1694 /* Reverse the runtime argument list */ 1695 1696 RuntimeArgTypes2 = 0; 1697 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) 1698 { 1699 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; 1700 RuntimeArgTypes2 |= ArgType; 1701 INCREMENT_ARG_LIST (RuntimeArgTypes); 1702 } 1703 1704 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) 1705 { 1706 RequiredBtypes = AnMapArgTypeToBtype (ArgType); 1707 1708 ThisNodeBtype = AnGetBtype (ArgOp); 1709 if (ThisNodeBtype == ACPI_UINT32_MAX) 1710 { 1711 goto NextArgument; 1712 } 1713 1714 /* Examine the arg based on the required type of the arg */ 1715 1716 switch (ArgType) 1717 { 1718 case ARGI_TARGETREF: 1719 1720 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 1721 { 1722 /* ZERO is the placeholder for "don't store result" */ 1723 1724 ThisNodeBtype = RequiredBtypes; 1725 break; 1726 } 1727 1728 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) 1729 { 1730 /* 1731 * This is the case where an original reference to a resource 1732 * descriptor field has been replaced by an (Integer) offset. 1733 * These named fields are supported at compile-time only; 1734 * the names are not passed to the interpreter (via the AML). 1735 */ 1736 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 1737 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 1738 { 1739 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); 1740 } 1741 else 1742 { 1743 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); 1744 } 1745 break; 1746 } 1747 1748 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || 1749 (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) 1750 { 1751 break; 1752 } 1753 1754 ThisNodeBtype = RequiredBtypes; 1755 break; 1756 1757 1758 case ARGI_REFERENCE: /* References */ 1759 case ARGI_INTEGER_REF: 1760 case ARGI_OBJECT_REF: 1761 case ARGI_DEVICE_REF: 1762 1763 switch (ArgOp->Asl.ParseOpcode) 1764 { 1765 case PARSEOP_LOCAL0: 1766 case PARSEOP_LOCAL1: 1767 case PARSEOP_LOCAL2: 1768 case PARSEOP_LOCAL3: 1769 case PARSEOP_LOCAL4: 1770 case PARSEOP_LOCAL5: 1771 case PARSEOP_LOCAL6: 1772 case PARSEOP_LOCAL7: 1773 1774 /* TBD: implement analysis of current value (type) of the local */ 1775 /* For now, just treat any local as a typematch */ 1776 1777 /*ThisNodeBtype = RequiredBtypes;*/ 1778 break; 1779 1780 case PARSEOP_ARG0: 1781 case PARSEOP_ARG1: 1782 case PARSEOP_ARG2: 1783 case PARSEOP_ARG3: 1784 case PARSEOP_ARG4: 1785 case PARSEOP_ARG5: 1786 case PARSEOP_ARG6: 1787 1788 /* Hard to analyze argument types, sow we won't */ 1789 /* For now, just treat any arg as a typematch */ 1790 1791 /* ThisNodeBtype = RequiredBtypes; */ 1792 break; 1793 1794 case PARSEOP_DEBUG: 1795 break; 1796 1797 case PARSEOP_REFOF: 1798 case PARSEOP_INDEX: 1799 default: 1800 break; 1801 1802 } 1803 break; 1804 1805 case ARGI_INTEGER: 1806 default: 1807 break; 1808 } 1809 1810 1811 CommonBtypes = ThisNodeBtype & RequiredBtypes; 1812 1813 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 1814 { 1815 /* Check a method call for a valid return value */ 1816 1817 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 1818 RequiredBtypes, ThisNodeBtype); 1819 } 1820 1821 /* 1822 * Now check if the actual type(s) match at least one 1823 * bit to the required type 1824 */ 1825 else if (!CommonBtypes) 1826 { 1827 /* No match -- this is a type mismatch error */ 1828 1829 AnFormatBtype (StringBuffer, ThisNodeBtype); 1830 AnFormatBtype (StringBuffer2, RequiredBtypes); 1831 1832 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", 1833 StringBuffer, OpInfo->Name, StringBuffer2); 1834 1835 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 1836 } 1837 1838 NextArgument: 1839 ArgOp = ArgOp->Asl.Next; 1840 INCREMENT_ARG_LIST (RuntimeArgTypes2); 1841 } 1842 break; 1843 1844 default: 1845 break; 1846 } 1847 1848 return (AE_OK); 1849 } 1850 1851 1852 /******************************************************************************* 1853 * 1854 * FUNCTION: AnOtherSemanticAnalysisWalkBegin 1855 * 1856 * PARAMETERS: ASL_WALK_CALLBACK 1857 * 1858 * RETURN: Status 1859 * 1860 * DESCRIPTION: Descending callback for the analysis walk. Check methods for : 1861 * 1) Initialized local variables 1862 * 2) Valid arguments 1863 * 3) Return types 1864 * 1865 ******************************************************************************/ 1866 1867 ACPI_STATUS 1868 AnOtherSemanticAnalysisWalkBegin ( 1869 ACPI_PARSE_OBJECT *Op, 1870 UINT32 Level, 1871 void *Context) 1872 { 1873 1874 return AE_OK; 1875 } 1876 1877 1878 /******************************************************************************* 1879 * 1880 * FUNCTION: AnOtherSemanticAnalysisWalkEnd 1881 * 1882 * PARAMETERS: ASL_WALK_CALLBACK 1883 * 1884 * RETURN: Status 1885 * 1886 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1887 * return analysis. 1888 * 1889 ******************************************************************************/ 1890 1891 ACPI_STATUS 1892 AnOtherSemanticAnalysisWalkEnd ( 1893 ACPI_PARSE_OBJECT *Op, 1894 UINT32 Level, 1895 void *Context) 1896 { 1897 1898 return AE_OK; 1899 1900 } 1901 1902 1903 #ifdef ACPI_OBSOLETE_FUNCTIONS 1904 /******************************************************************************* 1905 * 1906 * FUNCTION: AnMapBtypeToEtype 1907 * 1908 * PARAMETERS: Btype - Bitfield of ACPI types 1909 * 1910 * RETURN: The Etype corresponding the the Btype 1911 * 1912 * DESCRIPTION: Convert a bitfield type to an encoded type 1913 * 1914 ******************************************************************************/ 1915 1916 UINT32 1917 AnMapBtypeToEtype ( 1918 UINT32 Btype) 1919 { 1920 UINT32 i; 1921 UINT32 Etype; 1922 1923 1924 if (Btype == 0) 1925 { 1926 return 0; 1927 } 1928 1929 Etype = 1; 1930 for (i = 1; i < Btype; i *= 2) 1931 { 1932 Etype++; 1933 } 1934 1935 return (Etype); 1936 } 1937 #endif 1938 1939