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