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