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