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 145UINT32 146AnMapArgTypeToBtype ( 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 243UINT32 244AnMapEtypeToBtype ( 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 336UINT32 337AnMapBtypeToEtype ( 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 372void 373AnFormatBtype ( 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 440UINT32 441AnGetBtype ( 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 "Null attached Nsnode: [%s] at line %d\n", 458 Op->Asl.ParseOpName, Op->Asl.LineNumber); 459 return ACPI_UINT32_MAX; 460 } 461 462 ThisNodeBtype = AnMapEtypeToBtype (Node->Type); 463 464 /* 465 * Since it was a named reference, enable the 466 * reference bit also 467 */ 468 ThisNodeBtype |= ACPI_BTYPE_REFERENCE; 469 470 if (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) 471 { 472 ReferencedNode = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Node->Object); 473 if (!ReferencedNode) 474 { 475 printf ("No back ptr to Op: type %X\n", Node->Type); 476 return ACPI_UINT32_MAX; 477 } 478 479 if (ReferencedNode->Asl.CompileFlags & NODE_METHOD_TYPED) 480 { 481 ThisNodeBtype = ReferencedNode->Asl.AcpiBtype; 482 } 483 else 484 { 485 return (ACPI_UINT32_MAX -1); 486 } 487 } 488 } 489 else 490 { 491 ThisNodeBtype = Op->Asl.AcpiBtype; 492 } 493 494 return (ThisNodeBtype); 495} 496 497 498/******************************************************************************* 499 * 500 * FUNCTION: AnCheckForReservedName 501 * 502 * PARAMETERS: Op - A parse node 503 * Name - NameSeg to check 504 * 505 * RETURN: None 506 * 507 * DESCRIPTION: Check a NameSeg against the reserved list. 508 * 509 ******************************************************************************/ 510 511#define ACPI_VALID_RESERVED_NAME_MAX 0x80000000 512#define ACPI_NOT_RESERVED_NAME ACPI_UINT32_MAX 513#define ACPI_PREDEFINED_NAME (ACPI_UINT32_MAX - 1) 514#define ACPI_EVENT_RESERVED_NAME (ACPI_UINT32_MAX - 2) 515#define ACPI_COMPILER_RESERVED_NAME (ACPI_UINT32_MAX - 3) 516 517UINT32 518AnCheckForReservedName ( 519 ACPI_PARSE_OBJECT *Op, 520 char *Name) 521{ 522 UINT32 i; 523 524 525 if (Name[0] == 0) 526 { 527 AcpiOsPrintf ("Found a null name, external = %s\n", Op->Asl.ExternalName); 528 } 529 530 /* All reserved names are prefixed with a single underscore */ 531 532 if (Name[0] != '_') 533 { 534 return (ACPI_NOT_RESERVED_NAME); 535 } 536 537 /* Check for a standard reserved method name */ 538 539 for (i = 0; ReservedMethods[i].Name; i++) 540 { 541 if (!ACPI_STRNCMP (Name, ReservedMethods[i].Name, ACPI_NAME_SIZE)) 542 { 543 if (ReservedMethods[i].Flags & ASL_RSVD_SCOPE) 544 { 545 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, Op->Asl.ExternalName); 546 return (ACPI_PREDEFINED_NAME); 547 } 548 else if (ReservedMethods[i].Flags & ASL_RSVD_RESOURCE_NAME) 549 { 550 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, Op->Asl.ExternalName); 551 return (ACPI_PREDEFINED_NAME); 552 } 553 554 /* Return index into reserved array */ 555 556 return i; 557 } 558 } 559 560 /* 561 * Now check for the "special" reserved names -- 562 * GPE: _Lxx 563 * GPE: _Exx 564 * EC: _Qxx 565 */ 566 if ((Name[1] == 'L') || 567 (Name[1] == 'E') || 568 (Name[1] == 'Q')) 569 { 570 /* The next two characters must be hex digits */ 571 572 if ((isxdigit (Name[2])) && 573 (isxdigit (Name[3]))) 574 { 575 return (ACPI_EVENT_RESERVED_NAME); 576 } 577 } 578 579 580 /* Check for the names reserved for the compiler itself: _T_x */ 581 582 else if ((Op->Asl.ExternalName[1] == 'T') && 583 (Op->Asl.ExternalName[2] == '_')) 584 { 585 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, Op->Asl.ExternalName); 586 return (ACPI_COMPILER_RESERVED_NAME); 587 } 588 589 /* 590 * The name didn't match any of the known reserved names. Flag it as a 591 * warning, since the entire namespace starting with an underscore is 592 * reserved by the ACPI spec. 593 */ 594 AslError (ASL_WARNING, ASL_MSG_UNKNOWN_RESERVED_NAME, Op, Op->Asl.ExternalName); 595 596 return (ACPI_NOT_RESERVED_NAME); 597} 598 599 600/******************************************************************************* 601 * 602 * FUNCTION: AnCheckForReservedMethod 603 * 604 * PARAMETERS: Op - A parse node of type "METHOD". 605 * MethodInfo - Saved info about this method 606 * 607 * RETURN: None 608 * 609 * DESCRIPTION: If method is a reserved name, check that the number of arguments 610 * and the return type (returns a value or not) is correct. 611 * 612 ******************************************************************************/ 613 614void 615AnCheckForReservedMethod ( 616 ACPI_PARSE_OBJECT *Op, 617 ASL_METHOD_INFO *MethodInfo) 618{ 619 UINT32 Index; 620 621 622 /* Check for a match against the reserved name list */ 623 624 Index = AnCheckForReservedName (Op, Op->Asl.NameSeg); 625 626 switch (Index) 627 { 628 case ACPI_NOT_RESERVED_NAME: 629 case ACPI_PREDEFINED_NAME: 630 case ACPI_COMPILER_RESERVED_NAME: 631 632 /* Just return, nothing to do */ 633 break; 634 635 636 case ACPI_EVENT_RESERVED_NAME: 637 638 Gbl_ReservedMethods++; 639 640 /* NumArguments must be zero for all _Lxx, _Exx, and _Qxx methods */ 641 642 if (MethodInfo->NumArguments != 0) 643 { 644 sprintf (MsgBuffer, " %s requires %d", 645 Op->Asl.ExternalName, 0); 646 647 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, MsgBuffer); 648 } 649 break; 650 651 652 default: 653 654 Gbl_ReservedMethods++; 655 656 /* Matched a reserved method name */ 657 658 if (MethodInfo->NumArguments != ReservedMethods[Index].NumArguments) 659 { 660 sprintf (MsgBuffer, " %s requires %d", 661 ReservedMethods[Index].Name, 662 ReservedMethods[Index].NumArguments); 663 664 if (MethodInfo->NumArguments > ReservedMethods[Index].NumArguments) 665 { 666 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, MsgBuffer); 667 } 668 else 669 { 670 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_LO, Op, MsgBuffer); 671 } 672 } 673 674 if (MethodInfo->NumReturnNoValue && 675 ReservedMethods[Index].Flags & ASL_RSVD_RETURN_VALUE) 676 { 677 sprintf (MsgBuffer, "%s", ReservedMethods[Index].Name); 678 679 AslError (ASL_WARNING, ASL_MSG_RESERVED_RETURN_VALUE, Op, MsgBuffer); 680 } 681 break; 682 } 683} 684 685 686/******************************************************************************* 687 * 688 * FUNCTION: AnMethodAnalysisWalkBegin 689 * 690 * PARAMETERS: ASL_WALK_CALLBACK 691 * 692 * RETURN: Status 693 * 694 * DESCRIPTION: Descending callback for the analysis walk. Check methods for : 695 * 1) Initialized local variables 696 * 2) Valid arguments 697 * 3) Return types 698 * 699 ******************************************************************************/ 700 701ACPI_STATUS 702AnMethodAnalysisWalkBegin ( 703 ACPI_PARSE_OBJECT *Op, 704 UINT32 Level, 705 void *Context) 706{ 707 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 708 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 709 ACPI_PARSE_OBJECT *Next; 710 UINT32 RegisterNumber; 711 UINT32 i; 712 char LocalName[] = "Local0"; 713 char ArgName[] = "Arg0"; 714 715 716 ACPI_FUNCTION_NAME ("AnMethodAnalysisWalkBegin"); 717 718 719 switch (Op->Asl.ParseOpcode) 720 { 721 case PARSEOP_METHOD: 722 723 TotalMethods++; 724 725 /* 726 * Create and init method info 727 */ 728 MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); 729 MethodInfo->Next = WalkInfo->MethodStack; 730 MethodInfo->Op = Op; 731 732 WalkInfo->MethodStack = MethodInfo; 733 734 /* Get the NumArguments node */ 735 736 Next = Op->Asl.Child; 737 Next = Next->Asl.Next; 738 MethodInfo->NumArguments = (UINT8) (((UINT8) Next->Asl.Value.Integer) & 0x07); 739 740 /* 741 * Actual arguments are initialized at method entry. 742 * All other ArgX "registers" can be used as locals, so we 743 * track their initialization. 744 */ 745 for (i = 0; i < MethodInfo->NumArguments; i++) 746 { 747 MethodInfo->ArgInitialized[i] = TRUE; 748 } 749 750 break; 751 752 753 case PARSEOP_METHODCALL: 754 755 if (MethodInfo && 756 (Op->Asl.Node == MethodInfo->Op->Asl.Node)) 757 { 758 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); 759 } 760 break; 761 762 763 case PARSEOP_LOCAL0: 764 case PARSEOP_LOCAL1: 765 case PARSEOP_LOCAL2: 766 case PARSEOP_LOCAL3: 767 case PARSEOP_LOCAL4: 768 case PARSEOP_LOCAL5: 769 case PARSEOP_LOCAL6: 770 case PARSEOP_LOCAL7: 771 772 if (!MethodInfo) 773 { 774 /* Probably was an error in the method declaration, no additional error here */ 775 776 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 777 return (AE_ERROR); 778 } 779 780 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); 781 782 /* 783 * If the local is being used as a target, mark the local 784 * initialized 785 */ 786 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 787 { 788 MethodInfo->LocalInitialized[RegisterNumber] = TRUE; 789 } 790 791 /* 792 * Otherwise, this is a reference, check if the local 793 * has been previously initialized. 794 */ 795 else if (!MethodInfo->LocalInitialized[RegisterNumber]) 796 { 797 LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); 798 AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); 799 } 800 break; 801 802 803 case PARSEOP_ARG0: 804 case PARSEOP_ARG1: 805 case PARSEOP_ARG2: 806 case PARSEOP_ARG3: 807 case PARSEOP_ARG4: 808 case PARSEOP_ARG5: 809 case PARSEOP_ARG6: 810 811 if (!MethodInfo) 812 { 813 /* Probably was an error in the method declaration, no additional error here */ 814 815 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 816 return (AE_ERROR); 817 } 818 819 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; 820 ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); 821 822 /* 823 * If the Arg is being used as a target, mark the local 824 * initialized 825 */ 826 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 827 { 828 MethodInfo->ArgInitialized[RegisterNumber] = TRUE; 829 } 830 831 /* 832 * Otherwise, this is a reference, check if the Arg 833 * has been previously initialized. 834 */ 835 else if (!MethodInfo->ArgInitialized[RegisterNumber]) 836 { 837 AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); 838 } 839 840 /* Flag this arg if it is not a "real" argument to the method */ 841 842 if (RegisterNumber >= MethodInfo->NumArguments) 843 { 844 AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); 845 } 846 break; 847 848 849 case PARSEOP_RETURN: 850 851 if (!MethodInfo) 852 { 853 /* Probably was an error in the method declaration, no additional error here */ 854 855 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 856 return (AE_ERROR); 857 } 858 859 /* Child indicates a return value */ 860 861 if ((Op->Asl.Child) && 862 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 863 { 864 MethodInfo->NumReturnWithValue++; 865 } 866 else 867 { 868 MethodInfo->NumReturnNoValue++; 869 } 870 break; 871 872 873 case PARSEOP_BREAK: 874 case PARSEOP_CONTINUE: 875 876 Next = Op->Asl.Parent; 877 while (Next) 878 { 879 if (Next->Asl.ParseOpcode == PARSEOP_WHILE) 880 { 881 break; 882 } 883 Next = Next->Asl.Parent; 884 } 885 886 if (!Next) 887 { 888 AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); 889 } 890 break; 891 892 893 case PARSEOP_STALL: 894 895 if (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX) 896 { 897 AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); 898 } 899 break; 900 901 902 case PARSEOP_DEVICE: 903 case PARSEOP_EVENT: 904 case PARSEOP_MUTEX: 905 case PARSEOP_OPERATIONREGION: 906 case PARSEOP_POWERRESOURCE: 907 case PARSEOP_PROCESSOR: 908 case PARSEOP_THERMALZONE: 909 910 /* 911 * The first operand is a name to be created in the namespace. 912 * Check against the reserved list. 913 */ 914 i = AnCheckForReservedName (Op, Op->Asl.NameSeg); 915 if (i < ACPI_VALID_RESERVED_NAME_MAX) 916 { 917 AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); 918 } 919 break; 920 921 922 case PARSEOP_NAME: 923 924 i = AnCheckForReservedName (Op, Op->Asl.NameSeg); 925 if (i < ACPI_VALID_RESERVED_NAME_MAX) 926 { 927 if (ReservedMethods[i].NumArguments > 0) 928 { 929 /* 930 * This reserved name must be a control method because 931 * it must have arguments 932 */ 933 AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, "with arguments"); 934 } 935 936 /* 937 * Typechecking for _HID 938 */ 939 else if (!ACPI_STRCMP (METHOD_NAME__HID, ReservedMethods[i].Name)) 940 { 941 /* Examine the second operand to typecheck it */ 942 943 Next = Op->Asl.Child->Asl.Next; 944 945 if ((Next->Asl.ParseOpcode != PARSEOP_INTEGER) && 946 (Next->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)) 947 { 948 /* _HID must be a string or an integer */ 949 950 AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Next, "String or Integer"); 951 } 952 953 if (Next->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) 954 { 955 /* 956 * _HID is a string, all characters must be alphanumeric. 957 * One of the things we want to catch here is the use of 958 * a leading asterisk in the string. 959 */ 960 for (i = 0; Next->Asl.Value.String[i]; i++) 961 { 962 if (!isalnum (Next->Asl.Value.String[i])) 963 { 964 AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING, Next, Next->Asl.Value.String); 965 break; 966 } 967 } 968 } 969 } 970 } 971 972 break; 973 974 975 default: 976 break; 977 } 978 979 return AE_OK; 980} 981 982 983/******************************************************************************* 984 * 985 * FUNCTION: AnLastStatementIsReturn 986 * 987 * PARAMETERS: Op - A method parse node 988 * 989 * RETURN: TRUE if last statement is an ASL RETURN. False otherwise 990 * 991 * DESCRIPTION: Walk down the list of top level statements within a method 992 * to find the last one. Check if that last statement is in 993 * fact a RETURN statement. 994 * 995 ******************************************************************************/ 996 997BOOLEAN 998AnLastStatementIsReturn ( 999 ACPI_PARSE_OBJECT *Op) 1000{ 1001 ACPI_PARSE_OBJECT *Next; 1002 1003 1004 /* 1005 * Check if last statement is a return 1006 */ 1007 Next = ASL_GET_CHILD_NODE (Op); 1008 while (Next) 1009 { 1010 if ((!Next->Asl.Next) && 1011 (Next->Asl.ParseOpcode == PARSEOP_RETURN)) 1012 { 1013 return TRUE; 1014 } 1015 1016 Next = ASL_GET_PEER_NODE (Next); 1017 } 1018 1019 return FALSE; 1020} 1021 1022 1023/******************************************************************************* 1024 * 1025 * FUNCTION: AnMethodAnalysisWalkEnd 1026 * 1027 * PARAMETERS: ASL_WALK_CALLBACK 1028 * 1029 * RETURN: Status 1030 * 1031 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1032 * return analysis. 1033 * 1034 ******************************************************************************/ 1035 1036ACPI_STATUS 1037AnMethodAnalysisWalkEnd ( 1038 ACPI_PARSE_OBJECT *Op, 1039 UINT32 Level, 1040 void *Context) 1041{ 1042 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 1043 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 1044 1045 1046 switch (Op->Asl.ParseOpcode) 1047 { 1048 case PARSEOP_METHOD: 1049 case PARSEOP_RETURN: 1050 if (!MethodInfo) 1051 { 1052 printf ("No method info for method! [%s]\n", Op->Asl.Namepath); 1053 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, "No method info for this method"); 1054 CmCleanupAndExit (); 1055 return (AE_AML_INTERNAL); 1056 } 1057 break; 1058 1059 default: 1060 break; 1061 } 1062 1063 switch (Op->Asl.ParseOpcode) 1064 { 1065 case PARSEOP_METHOD: 1066 1067 WalkInfo->MethodStack = MethodInfo->Next; 1068 1069 /* 1070 * Check if there is no return statement at the end of the 1071 * method AND we can actually get there -- i.e., the execution 1072 * of the method can possibly terminate without a return statement. 1073 */ 1074 if ((!AnLastStatementIsReturn (Op)) && 1075 (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) 1076 { 1077 /* 1078 * No return statement, and execution can possibly exit 1079 * via this path. This is equivalent to Return () 1080 */ 1081 MethodInfo->NumReturnNoValue++; 1082 } 1083 1084 /* 1085 * Check for case where some return statements have a return value 1086 * and some do not. Exit without a return statement is a return with 1087 * no value 1088 */ 1089 if (MethodInfo->NumReturnNoValue && 1090 MethodInfo->NumReturnWithValue) 1091 { 1092 AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, Op->Asl.ExternalName); 1093 } 1094 1095 /* 1096 * If there are any RETURN() statements with no value, or there is a 1097 * control path that allows the method to exit without a return value, 1098 * we mark the method as a method that does not return a value. This 1099 * knowledge can be used to check method invocations that expect a 1100 * returned value. 1101 */ 1102 if (MethodInfo->NumReturnNoValue) 1103 { 1104 if (MethodInfo->NumReturnWithValue) 1105 { 1106 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; 1107 } 1108 else 1109 { 1110 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; 1111 } 1112 } 1113 1114 /* 1115 * Check predefined method names for correct return behavior 1116 * and correct number of arguments 1117 */ 1118 AnCheckForReservedMethod (Op, MethodInfo); 1119 ACPI_MEM_FREE (MethodInfo); 1120 break; 1121 1122 1123 case PARSEOP_RETURN: 1124 1125 /* 1126 * The parent block does not "exit" and continue execution -- the 1127 * method is terminated here with the Return() statement. 1128 */ 1129 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1130 Op->Asl.ParentMethod = MethodInfo->Op; /* Used in the "typing" pass later */ 1131 1132 /* 1133 * If there is a peer node after the return statement, then this 1134 * node is unreachable code -- i.e., it won't be executed because of the 1135 * preceeding Return() statement. 1136 */ 1137 if (Op->Asl.Next) 1138 { 1139 AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); 1140 } 1141 break; 1142 1143 1144 case PARSEOP_IF: 1145 1146 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1147 (Op->Asl.Next) && 1148 (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) 1149 { 1150 /* 1151 * This IF has a corresponding ELSE. The IF block has no exit, 1152 * (it contains an unconditional Return) 1153 * mark the ELSE block to remember this fact. 1154 */ 1155 Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; 1156 } 1157 break; 1158 1159 1160 case PARSEOP_ELSE: 1161 1162 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1163 (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) 1164 { 1165 /* 1166 * This ELSE block has no exit and the corresponding IF block 1167 * has no exit either. Therefore, the parent node has no exit. 1168 */ 1169 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1170 } 1171 break; 1172 1173 1174 default: 1175 1176 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1177 (Op->Asl.Parent)) 1178 { 1179 /* If this node has no exit, then the parent has no exit either */ 1180 1181 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1182 } 1183 break; 1184 } 1185 1186 return AE_OK; 1187} 1188 1189 1190/******************************************************************************* 1191 * 1192 * FUNCTION: AnMethodTypingWalkBegin 1193 * 1194 * PARAMETERS: ASL_WALK_CALLBACK 1195 * 1196 * RETURN: Status 1197 * 1198 * DESCRIPTION: Descending callback for the typing walk. 1199 * 1200 ******************************************************************************/ 1201 1202ACPI_STATUS 1203AnMethodTypingWalkBegin ( 1204 ACPI_PARSE_OBJECT *Op, 1205 UINT32 Level, 1206 void *Context) 1207{ 1208 1209 return AE_OK; 1210} 1211 1212 1213/******************************************************************************* 1214 * 1215 * FUNCTION: AnMethodTypingWalkEnd 1216 * 1217 * PARAMETERS: ASL_WALK_CALLBACK 1218 * 1219 * RETURN: Status 1220 * 1221 * DESCRIPTION: Ascending callback for typing walk. Complete method 1222 * return analysis. Check methods for : 1223 * 1) Initialized local variables 1224 * 2) Valid arguments 1225 * 3) Return types 1226 * 1227 ******************************************************************************/ 1228 1229ACPI_STATUS 1230AnMethodTypingWalkEnd ( 1231 ACPI_PARSE_OBJECT *Op, 1232 UINT32 Level, 1233 void *Context) 1234{ 1235 UINT32 ThisNodeBtype; 1236 1237 1238 switch (Op->Asl.ParseOpcode) 1239 { 1240 case PARSEOP_METHOD: 1241 1242 Op->Asl.CompileFlags |= NODE_METHOD_TYPED; 1243 break; 1244 1245 case PARSEOP_RETURN: 1246 1247 if ((Op->Asl.Child) && 1248 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 1249 { 1250 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 1251 1252 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && 1253 (ThisNodeBtype == (ACPI_UINT32_MAX -1))) 1254 { 1255 /* 1256 * The method is untyped at this time (typically a forward reference). 1257 * We must recursively type the method here 1258 */ 1259 TrWalkParseTree (ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Op->Asl.Child->Asl.Node->Object), 1260 ASL_WALK_VISIT_TWICE, AnMethodTypingWalkBegin, 1261 AnMethodTypingWalkEnd, NULL); 1262 1263 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 1264 } 1265 1266 /* Returns a value, get it's type */ 1267 1268 if (Op->Asl.ParentMethod) 1269 { 1270 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; 1271 } 1272 } 1273 break; 1274 1275 default: 1276 break; 1277 } 1278 1279 return AE_OK; 1280} 1281 1282 1283/******************************************************************************* 1284 * 1285 * FUNCTION: AnCheckMethodReturnValue 1286 * 1287 * PARAMETERS: Op - Parent 1288 * OpInfo - Parent info 1289 * ArgOp - Method invocation op 1290 * RequiredBtypes - What caller requires 1291 * ThisNodeBtype - What this node returns (if anything) 1292 * 1293 * RETURN: None 1294 * 1295 * DESCRIPTION: Check a method invocation for 1) A return value and if it does 1296 * in fact return a value, 2) check the type of the return value. 1297 * 1298 ******************************************************************************/ 1299 1300void 1301AnCheckMethodReturnValue ( 1302 ACPI_PARSE_OBJECT *Op, 1303 const ACPI_OPCODE_INFO *OpInfo, 1304 ACPI_PARSE_OBJECT *ArgOp, 1305 UINT32 RequiredBtypes, 1306 UINT32 ThisNodeBtype) 1307{ 1308 ACPI_PARSE_OBJECT *OwningOp; 1309 ACPI_NAMESPACE_NODE *Node; 1310 1311 1312 Node = ArgOp->Asl.Node; 1313 1314 1315 /* Examine the parent op of this method */ 1316 1317 OwningOp = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Node->Object); 1318 if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL) 1319 { 1320 /* 1321 * Method NEVER returns a value 1322 */ 1323 AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName); 1324 } 1325 else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL) 1326 { 1327 /* 1328 * Method SOMETIMES returns a value, SOMETIMES not 1329 */ 1330 AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, Op, Op->Asl.ExternalName); 1331 } 1332 else if (!(ThisNodeBtype & RequiredBtypes)) 1333 { 1334 /* 1335 * Method returns a value, but the type is wrong 1336 */ 1337 AnFormatBtype (StringBuffer, ThisNodeBtype); 1338 AnFormatBtype (StringBuffer2, RequiredBtypes); 1339 1340 1341 /* 1342 * The case where the method does not return any value at all 1343 * was already handled in the namespace cross reference 1344 * -- Only issue an error if the method in fact returns a value, 1345 * but it is of the wrong type 1346 */ 1347 if (ThisNodeBtype != 0) 1348 { 1349 sprintf (MsgBuffer, "Method returns [%s], %s operator requires [%s]", 1350 StringBuffer, OpInfo->Name, StringBuffer2); 1351 1352 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 1353 } 1354 } 1355} 1356 1357 1358/******************************************************************************* 1359 * 1360 * FUNCTION: AnOperandTypecheckWalkBegin 1361 * 1362 * PARAMETERS: ASL_WALK_CALLBACK 1363 * 1364 * RETURN: Status 1365 * 1366 * DESCRIPTION: Descending callback for the analysis walk. Check methods for : 1367 * 1) Initialized local variables 1368 * 2) Valid arguments 1369 * 3) Return types 1370 * 1371 ******************************************************************************/ 1372 1373ACPI_STATUS 1374AnOperandTypecheckWalkBegin ( 1375 ACPI_PARSE_OBJECT *Op, 1376 UINT32 Level, 1377 void *Context) 1378{ 1379 1380 return AE_OK; 1381} 1382 1383 1384/******************************************************************************* 1385 * 1386 * FUNCTION: AnOperandTypecheckWalkEnd 1387 * 1388 * PARAMETERS: ASL_WALK_CALLBACK 1389 * 1390 * RETURN: Status 1391 * 1392 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1393 * return analysis. 1394 * 1395 ******************************************************************************/ 1396 1397ACPI_STATUS 1398AnOperandTypecheckWalkEnd ( 1399 ACPI_PARSE_OBJECT *Op, 1400 UINT32 Level, 1401 void *Context) 1402{ 1403 const ACPI_OPCODE_INFO *OpInfo; 1404 UINT32 RuntimeArgTypes; 1405 UINT32 RuntimeArgTypes2; 1406 UINT32 RequiredBtypes; 1407 UINT32 ThisNodeBtype; 1408 UINT32 CommonBtypes; 1409 UINT32 OpcodeClass; 1410 ACPI_PARSE_OBJECT *ArgOp; 1411 UINT32 ArgType; 1412 1413 1414 switch (Op->Asl.AmlOpcode) 1415 { 1416 case AML_RAW_DATA_BYTE: 1417 case AML_RAW_DATA_WORD: 1418 case AML_RAW_DATA_DWORD: 1419 case AML_RAW_DATA_QWORD: 1420 case AML_RAW_DATA_BUFFER: 1421 case AML_RAW_DATA_CHAIN: 1422 case AML_PACKAGE_LENGTH: 1423 case AML_UNASSIGNED_OPCODE: 1424 case AML_DEFAULT_ARG_OP: 1425 1426 /* Ignore the internal (compiler-only) AML opcodes */ 1427 1428 return (AE_OK); 1429 1430 default: 1431 break; 1432 } 1433 1434 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1435 if (!OpInfo) 1436 { 1437 return (AE_OK); 1438 } 1439 1440 ArgOp = Op->Asl.Child; 1441 RuntimeArgTypes = OpInfo->RuntimeArgs; 1442 OpcodeClass = OpInfo->Class; 1443 1444 1445 /* 1446 * Special case for control opcodes IF/RETURN/WHILE since they 1447 * have no runtime arg list (at this time) 1448 */ 1449 switch (Op->Asl.AmlOpcode) 1450 { 1451 case AML_IF_OP: 1452 case AML_WHILE_OP: 1453 case AML_RETURN_OP: 1454 1455 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 1456 { 1457 /* The lone arg is a method call, check it */ 1458 1459 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); 1460 if (Op->Asl.AmlOpcode == AML_RETURN_OP) 1461 { 1462 RequiredBtypes = 0xFFFFFFFF; 1463 } 1464 1465 ThisNodeBtype = AnGetBtype (ArgOp); 1466 if (ThisNodeBtype == ACPI_UINT32_MAX) 1467 { 1468 return (AE_OK); 1469 } 1470 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, RequiredBtypes, ThisNodeBtype); 1471 } 1472 return (AE_OK); 1473 1474 default: 1475 break; 1476 } 1477 1478 /* Ignore the non-executable opcodes */ 1479 1480 if (RuntimeArgTypes == ARGI_INVALID_OPCODE) 1481 { 1482 return (AE_OK); 1483 } 1484 1485 switch (OpcodeClass) 1486 { 1487 case AML_CLASS_EXECUTE: 1488 case AML_CLASS_CREATE: 1489 case AML_CLASS_CONTROL: 1490 case AML_CLASS_RETURN_VALUE: 1491 1492 /* TBD: Change class or fix typechecking for these */ 1493 1494 if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || 1495 (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || 1496 (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) 1497 { 1498 break; 1499 } 1500 1501 /* Reverse the runtime argument list */ 1502 1503 RuntimeArgTypes2 = 0; 1504 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) 1505 { 1506 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; 1507 RuntimeArgTypes2 |= ArgType; 1508 INCREMENT_ARG_LIST (RuntimeArgTypes); 1509 } 1510 1511 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) 1512 { 1513 RequiredBtypes = AnMapArgTypeToBtype (ArgType); 1514 1515 ThisNodeBtype = AnGetBtype (ArgOp); 1516 if (ThisNodeBtype == ACPI_UINT32_MAX) 1517 { 1518 goto NextArgument; 1519 } 1520 1521 /* Examine the arg based on the required type of the arg */ 1522 1523 switch (ArgType) 1524 { 1525 case ARGI_TARGETREF: 1526 1527 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 1528 { 1529 /* ZERO is the placeholder for "don't store result" */ 1530 1531 ThisNodeBtype = RequiredBtypes; 1532 break; 1533 } 1534 1535 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) 1536 { 1537 /* 1538 * This is the case where an original reference to a resource 1539 * descriptor field has been replaced by an (Integer) offset. 1540 * These named fields are supported at compile-time only; 1541 * the names are not passed to the interpreter (via the AML). 1542 */ 1543 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 1544 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 1545 { 1546 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); 1547 } 1548 else 1549 { 1550 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); 1551 } 1552 break; 1553 } 1554 1555 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || 1556 (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) 1557 { 1558 break; 1559 } 1560 1561 ThisNodeBtype = RequiredBtypes; 1562 break; 1563 1564 1565 case ARGI_REFERENCE: /* References */ 1566 case ARGI_INTEGER_REF: 1567 case ARGI_OBJECT_REF: 1568 case ARGI_DEVICE_REF: 1569 1570 switch (ArgOp->Asl.ParseOpcode) 1571 { 1572 case PARSEOP_LOCAL0: 1573 case PARSEOP_LOCAL1: 1574 case PARSEOP_LOCAL2: 1575 case PARSEOP_LOCAL3: 1576 case PARSEOP_LOCAL4: 1577 case PARSEOP_LOCAL5: 1578 case PARSEOP_LOCAL6: 1579 case PARSEOP_LOCAL7: 1580 1581 /* TBD: implement analysis of current value (type) of the local */ 1582 /* For now, just treat any local as a typematch */ 1583 1584 /*ThisNodeBtype = RequiredBtypes;*/ 1585 break; 1586 1587 case PARSEOP_ARG0: 1588 case PARSEOP_ARG1: 1589 case PARSEOP_ARG2: 1590 case PARSEOP_ARG3: 1591 case PARSEOP_ARG4: 1592 case PARSEOP_ARG5: 1593 case PARSEOP_ARG6: 1594 1595 /* Hard to analyze argument types, sow we won't */ 1596 /* For now, just treat any arg as a typematch */ 1597 1598 /* ThisNodeBtype = RequiredBtypes; */ 1599 break; 1600 1601 case PARSEOP_DEBUG: 1602 break; 1603 1604 case PARSEOP_REFOF: 1605 case PARSEOP_INDEX: 1606 default: 1607 break; 1608 1609 } 1610 break; 1611 1612 case ARGI_INTEGER: 1613 default: 1614 break; 1615 } 1616 1617 1618 CommonBtypes = ThisNodeBtype & RequiredBtypes; 1619 1620 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 1621 { 1622 /* Check a method call for a valid return value */ 1623 1624 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, RequiredBtypes, ThisNodeBtype); 1625 } 1626 1627 /* 1628 * Now check if the actual type(s) match at least one 1629 * bit to the required type 1630 */ 1631 else if (!CommonBtypes) 1632 { 1633 /* No match -- this is a type mismatch error */ 1634 1635 AnFormatBtype (StringBuffer, ThisNodeBtype); 1636 AnFormatBtype (StringBuffer2, RequiredBtypes); 1637 1638 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", 1639 StringBuffer, OpInfo->Name, StringBuffer2); 1640 1641 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 1642 } 1643 1644 NextArgument: 1645 ArgOp = ArgOp->Asl.Next; 1646 INCREMENT_ARG_LIST (RuntimeArgTypes2); 1647 } 1648 break; 1649 1650 default: 1651 break; 1652 } 1653 1654 return (AE_OK); 1655} 1656 1657 1658/******************************************************************************* 1659 * 1660 * FUNCTION: AnOtherSemanticAnalysisWalkBegin 1661 * 1662 * PARAMETERS: ASL_WALK_CALLBACK 1663 * 1664 * RETURN: Status 1665 * 1666 * DESCRIPTION: Descending callback for the analysis walk. Check methods for : 1667 * 1) Initialized local variables 1668 * 2) Valid arguments 1669 * 3) Return types 1670 * 1671 ******************************************************************************/ 1672 1673ACPI_STATUS 1674AnOtherSemanticAnalysisWalkBegin ( 1675 ACPI_PARSE_OBJECT *Op, 1676 UINT32 Level, 1677 void *Context) 1678{ 1679 1680 return AE_OK; 1681} 1682 1683 1684/******************************************************************************* 1685 * 1686 * FUNCTION: AnOtherSemanticAnalysisWalkEnd 1687 * 1688 * PARAMETERS: ASL_WALK_CALLBACK 1689 * 1690 * RETURN: Status 1691 * 1692 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1693 * return analysis. 1694 * 1695 ******************************************************************************/ 1696 1697ACPI_STATUS 1698AnOtherSemanticAnalysisWalkEnd ( 1699 ACPI_PARSE_OBJECT *Op, 1700 UINT32 Level, 1701 void *Context) 1702{ 1703 1704 return AE_OK; 1705 1706}
| 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 145UINT32 146AnMapArgTypeToBtype ( 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 243UINT32 244AnMapEtypeToBtype ( 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 336UINT32 337AnMapBtypeToEtype ( 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 372void 373AnFormatBtype ( 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 440UINT32 441AnGetBtype ( 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 "Null attached Nsnode: [%s] at line %d\n", 458 Op->Asl.ParseOpName, Op->Asl.LineNumber); 459 return ACPI_UINT32_MAX; 460 } 461 462 ThisNodeBtype = AnMapEtypeToBtype (Node->Type); 463 464 /* 465 * Since it was a named reference, enable the 466 * reference bit also 467 */ 468 ThisNodeBtype |= ACPI_BTYPE_REFERENCE; 469 470 if (Op->Asl.ParseOpcode == PARSEOP_METHODCALL) 471 { 472 ReferencedNode = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Node->Object); 473 if (!ReferencedNode) 474 { 475 printf ("No back ptr to Op: type %X\n", Node->Type); 476 return ACPI_UINT32_MAX; 477 } 478 479 if (ReferencedNode->Asl.CompileFlags & NODE_METHOD_TYPED) 480 { 481 ThisNodeBtype = ReferencedNode->Asl.AcpiBtype; 482 } 483 else 484 { 485 return (ACPI_UINT32_MAX -1); 486 } 487 } 488 } 489 else 490 { 491 ThisNodeBtype = Op->Asl.AcpiBtype; 492 } 493 494 return (ThisNodeBtype); 495} 496 497 498/******************************************************************************* 499 * 500 * FUNCTION: AnCheckForReservedName 501 * 502 * PARAMETERS: Op - A parse node 503 * Name - NameSeg to check 504 * 505 * RETURN: None 506 * 507 * DESCRIPTION: Check a NameSeg against the reserved list. 508 * 509 ******************************************************************************/ 510 511#define ACPI_VALID_RESERVED_NAME_MAX 0x80000000 512#define ACPI_NOT_RESERVED_NAME ACPI_UINT32_MAX 513#define ACPI_PREDEFINED_NAME (ACPI_UINT32_MAX - 1) 514#define ACPI_EVENT_RESERVED_NAME (ACPI_UINT32_MAX - 2) 515#define ACPI_COMPILER_RESERVED_NAME (ACPI_UINT32_MAX - 3) 516 517UINT32 518AnCheckForReservedName ( 519 ACPI_PARSE_OBJECT *Op, 520 char *Name) 521{ 522 UINT32 i; 523 524 525 if (Name[0] == 0) 526 { 527 AcpiOsPrintf ("Found a null name, external = %s\n", Op->Asl.ExternalName); 528 } 529 530 /* All reserved names are prefixed with a single underscore */ 531 532 if (Name[0] != '_') 533 { 534 return (ACPI_NOT_RESERVED_NAME); 535 } 536 537 /* Check for a standard reserved method name */ 538 539 for (i = 0; ReservedMethods[i].Name; i++) 540 { 541 if (!ACPI_STRNCMP (Name, ReservedMethods[i].Name, ACPI_NAME_SIZE)) 542 { 543 if (ReservedMethods[i].Flags & ASL_RSVD_SCOPE) 544 { 545 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, Op->Asl.ExternalName); 546 return (ACPI_PREDEFINED_NAME); 547 } 548 else if (ReservedMethods[i].Flags & ASL_RSVD_RESOURCE_NAME) 549 { 550 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, Op->Asl.ExternalName); 551 return (ACPI_PREDEFINED_NAME); 552 } 553 554 /* Return index into reserved array */ 555 556 return i; 557 } 558 } 559 560 /* 561 * Now check for the "special" reserved names -- 562 * GPE: _Lxx 563 * GPE: _Exx 564 * EC: _Qxx 565 */ 566 if ((Name[1] == 'L') || 567 (Name[1] == 'E') || 568 (Name[1] == 'Q')) 569 { 570 /* The next two characters must be hex digits */ 571 572 if ((isxdigit (Name[2])) && 573 (isxdigit (Name[3]))) 574 { 575 return (ACPI_EVENT_RESERVED_NAME); 576 } 577 } 578 579 580 /* Check for the names reserved for the compiler itself: _T_x */ 581 582 else if ((Op->Asl.ExternalName[1] == 'T') && 583 (Op->Asl.ExternalName[2] == '_')) 584 { 585 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, Op->Asl.ExternalName); 586 return (ACPI_COMPILER_RESERVED_NAME); 587 } 588 589 /* 590 * The name didn't match any of the known reserved names. Flag it as a 591 * warning, since the entire namespace starting with an underscore is 592 * reserved by the ACPI spec. 593 */ 594 AslError (ASL_WARNING, ASL_MSG_UNKNOWN_RESERVED_NAME, Op, Op->Asl.ExternalName); 595 596 return (ACPI_NOT_RESERVED_NAME); 597} 598 599 600/******************************************************************************* 601 * 602 * FUNCTION: AnCheckForReservedMethod 603 * 604 * PARAMETERS: Op - A parse node of type "METHOD". 605 * MethodInfo - Saved info about this method 606 * 607 * RETURN: None 608 * 609 * DESCRIPTION: If method is a reserved name, check that the number of arguments 610 * and the return type (returns a value or not) is correct. 611 * 612 ******************************************************************************/ 613 614void 615AnCheckForReservedMethod ( 616 ACPI_PARSE_OBJECT *Op, 617 ASL_METHOD_INFO *MethodInfo) 618{ 619 UINT32 Index; 620 621 622 /* Check for a match against the reserved name list */ 623 624 Index = AnCheckForReservedName (Op, Op->Asl.NameSeg); 625 626 switch (Index) 627 { 628 case ACPI_NOT_RESERVED_NAME: 629 case ACPI_PREDEFINED_NAME: 630 case ACPI_COMPILER_RESERVED_NAME: 631 632 /* Just return, nothing to do */ 633 break; 634 635 636 case ACPI_EVENT_RESERVED_NAME: 637 638 Gbl_ReservedMethods++; 639 640 /* NumArguments must be zero for all _Lxx, _Exx, and _Qxx methods */ 641 642 if (MethodInfo->NumArguments != 0) 643 { 644 sprintf (MsgBuffer, " %s requires %d", 645 Op->Asl.ExternalName, 0); 646 647 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, MsgBuffer); 648 } 649 break; 650 651 652 default: 653 654 Gbl_ReservedMethods++; 655 656 /* Matched a reserved method name */ 657 658 if (MethodInfo->NumArguments != ReservedMethods[Index].NumArguments) 659 { 660 sprintf (MsgBuffer, " %s requires %d", 661 ReservedMethods[Index].Name, 662 ReservedMethods[Index].NumArguments); 663 664 if (MethodInfo->NumArguments > ReservedMethods[Index].NumArguments) 665 { 666 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, MsgBuffer); 667 } 668 else 669 { 670 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_LO, Op, MsgBuffer); 671 } 672 } 673 674 if (MethodInfo->NumReturnNoValue && 675 ReservedMethods[Index].Flags & ASL_RSVD_RETURN_VALUE) 676 { 677 sprintf (MsgBuffer, "%s", ReservedMethods[Index].Name); 678 679 AslError (ASL_WARNING, ASL_MSG_RESERVED_RETURN_VALUE, Op, MsgBuffer); 680 } 681 break; 682 } 683} 684 685 686/******************************************************************************* 687 * 688 * FUNCTION: AnMethodAnalysisWalkBegin 689 * 690 * PARAMETERS: ASL_WALK_CALLBACK 691 * 692 * RETURN: Status 693 * 694 * DESCRIPTION: Descending callback for the analysis walk. Check methods for : 695 * 1) Initialized local variables 696 * 2) Valid arguments 697 * 3) Return types 698 * 699 ******************************************************************************/ 700 701ACPI_STATUS 702AnMethodAnalysisWalkBegin ( 703 ACPI_PARSE_OBJECT *Op, 704 UINT32 Level, 705 void *Context) 706{ 707 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 708 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 709 ACPI_PARSE_OBJECT *Next; 710 UINT32 RegisterNumber; 711 UINT32 i; 712 char LocalName[] = "Local0"; 713 char ArgName[] = "Arg0"; 714 715 716 ACPI_FUNCTION_NAME ("AnMethodAnalysisWalkBegin"); 717 718 719 switch (Op->Asl.ParseOpcode) 720 { 721 case PARSEOP_METHOD: 722 723 TotalMethods++; 724 725 /* 726 * Create and init method info 727 */ 728 MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); 729 MethodInfo->Next = WalkInfo->MethodStack; 730 MethodInfo->Op = Op; 731 732 WalkInfo->MethodStack = MethodInfo; 733 734 /* Get the NumArguments node */ 735 736 Next = Op->Asl.Child; 737 Next = Next->Asl.Next; 738 MethodInfo->NumArguments = (UINT8) (((UINT8) Next->Asl.Value.Integer) & 0x07); 739 740 /* 741 * Actual arguments are initialized at method entry. 742 * All other ArgX "registers" can be used as locals, so we 743 * track their initialization. 744 */ 745 for (i = 0; i < MethodInfo->NumArguments; i++) 746 { 747 MethodInfo->ArgInitialized[i] = TRUE; 748 } 749 750 break; 751 752 753 case PARSEOP_METHODCALL: 754 755 if (MethodInfo && 756 (Op->Asl.Node == MethodInfo->Op->Asl.Node)) 757 { 758 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); 759 } 760 break; 761 762 763 case PARSEOP_LOCAL0: 764 case PARSEOP_LOCAL1: 765 case PARSEOP_LOCAL2: 766 case PARSEOP_LOCAL3: 767 case PARSEOP_LOCAL4: 768 case PARSEOP_LOCAL5: 769 case PARSEOP_LOCAL6: 770 case PARSEOP_LOCAL7: 771 772 if (!MethodInfo) 773 { 774 /* Probably was an error in the method declaration, no additional error here */ 775 776 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 777 return (AE_ERROR); 778 } 779 780 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); 781 782 /* 783 * If the local is being used as a target, mark the local 784 * initialized 785 */ 786 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 787 { 788 MethodInfo->LocalInitialized[RegisterNumber] = TRUE; 789 } 790 791 /* 792 * Otherwise, this is a reference, check if the local 793 * has been previously initialized. 794 */ 795 else if (!MethodInfo->LocalInitialized[RegisterNumber]) 796 { 797 LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); 798 AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); 799 } 800 break; 801 802 803 case PARSEOP_ARG0: 804 case PARSEOP_ARG1: 805 case PARSEOP_ARG2: 806 case PARSEOP_ARG3: 807 case PARSEOP_ARG4: 808 case PARSEOP_ARG5: 809 case PARSEOP_ARG6: 810 811 if (!MethodInfo) 812 { 813 /* Probably was an error in the method declaration, no additional error here */ 814 815 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 816 return (AE_ERROR); 817 } 818 819 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; 820 ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); 821 822 /* 823 * If the Arg is being used as a target, mark the local 824 * initialized 825 */ 826 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 827 { 828 MethodInfo->ArgInitialized[RegisterNumber] = TRUE; 829 } 830 831 /* 832 * Otherwise, this is a reference, check if the Arg 833 * has been previously initialized. 834 */ 835 else if (!MethodInfo->ArgInitialized[RegisterNumber]) 836 { 837 AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); 838 } 839 840 /* Flag this arg if it is not a "real" argument to the method */ 841 842 if (RegisterNumber >= MethodInfo->NumArguments) 843 { 844 AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); 845 } 846 break; 847 848 849 case PARSEOP_RETURN: 850 851 if (!MethodInfo) 852 { 853 /* Probably was an error in the method declaration, no additional error here */ 854 855 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "%p, No parent method\n", Op)); 856 return (AE_ERROR); 857 } 858 859 /* Child indicates a return value */ 860 861 if ((Op->Asl.Child) && 862 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 863 { 864 MethodInfo->NumReturnWithValue++; 865 } 866 else 867 { 868 MethodInfo->NumReturnNoValue++; 869 } 870 break; 871 872 873 case PARSEOP_BREAK: 874 case PARSEOP_CONTINUE: 875 876 Next = Op->Asl.Parent; 877 while (Next) 878 { 879 if (Next->Asl.ParseOpcode == PARSEOP_WHILE) 880 { 881 break; 882 } 883 Next = Next->Asl.Parent; 884 } 885 886 if (!Next) 887 { 888 AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); 889 } 890 break; 891 892 893 case PARSEOP_STALL: 894 895 if (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX) 896 { 897 AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); 898 } 899 break; 900 901 902 case PARSEOP_DEVICE: 903 case PARSEOP_EVENT: 904 case PARSEOP_MUTEX: 905 case PARSEOP_OPERATIONREGION: 906 case PARSEOP_POWERRESOURCE: 907 case PARSEOP_PROCESSOR: 908 case PARSEOP_THERMALZONE: 909 910 /* 911 * The first operand is a name to be created in the namespace. 912 * Check against the reserved list. 913 */ 914 i = AnCheckForReservedName (Op, Op->Asl.NameSeg); 915 if (i < ACPI_VALID_RESERVED_NAME_MAX) 916 { 917 AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); 918 } 919 break; 920 921 922 case PARSEOP_NAME: 923 924 i = AnCheckForReservedName (Op, Op->Asl.NameSeg); 925 if (i < ACPI_VALID_RESERVED_NAME_MAX) 926 { 927 if (ReservedMethods[i].NumArguments > 0) 928 { 929 /* 930 * This reserved name must be a control method because 931 * it must have arguments 932 */ 933 AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, "with arguments"); 934 } 935 936 /* 937 * Typechecking for _HID 938 */ 939 else if (!ACPI_STRCMP (METHOD_NAME__HID, ReservedMethods[i].Name)) 940 { 941 /* Examine the second operand to typecheck it */ 942 943 Next = Op->Asl.Child->Asl.Next; 944 945 if ((Next->Asl.ParseOpcode != PARSEOP_INTEGER) && 946 (Next->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)) 947 { 948 /* _HID must be a string or an integer */ 949 950 AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Next, "String or Integer"); 951 } 952 953 if (Next->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) 954 { 955 /* 956 * _HID is a string, all characters must be alphanumeric. 957 * One of the things we want to catch here is the use of 958 * a leading asterisk in the string. 959 */ 960 for (i = 0; Next->Asl.Value.String[i]; i++) 961 { 962 if (!isalnum (Next->Asl.Value.String[i])) 963 { 964 AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING, Next, Next->Asl.Value.String); 965 break; 966 } 967 } 968 } 969 } 970 } 971 972 break; 973 974 975 default: 976 break; 977 } 978 979 return AE_OK; 980} 981 982 983/******************************************************************************* 984 * 985 * FUNCTION: AnLastStatementIsReturn 986 * 987 * PARAMETERS: Op - A method parse node 988 * 989 * RETURN: TRUE if last statement is an ASL RETURN. False otherwise 990 * 991 * DESCRIPTION: Walk down the list of top level statements within a method 992 * to find the last one. Check if that last statement is in 993 * fact a RETURN statement. 994 * 995 ******************************************************************************/ 996 997BOOLEAN 998AnLastStatementIsReturn ( 999 ACPI_PARSE_OBJECT *Op) 1000{ 1001 ACPI_PARSE_OBJECT *Next; 1002 1003 1004 /* 1005 * Check if last statement is a return 1006 */ 1007 Next = ASL_GET_CHILD_NODE (Op); 1008 while (Next) 1009 { 1010 if ((!Next->Asl.Next) && 1011 (Next->Asl.ParseOpcode == PARSEOP_RETURN)) 1012 { 1013 return TRUE; 1014 } 1015 1016 Next = ASL_GET_PEER_NODE (Next); 1017 } 1018 1019 return FALSE; 1020} 1021 1022 1023/******************************************************************************* 1024 * 1025 * FUNCTION: AnMethodAnalysisWalkEnd 1026 * 1027 * PARAMETERS: ASL_WALK_CALLBACK 1028 * 1029 * RETURN: Status 1030 * 1031 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1032 * return analysis. 1033 * 1034 ******************************************************************************/ 1035 1036ACPI_STATUS 1037AnMethodAnalysisWalkEnd ( 1038 ACPI_PARSE_OBJECT *Op, 1039 UINT32 Level, 1040 void *Context) 1041{ 1042 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 1043 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 1044 1045 1046 switch (Op->Asl.ParseOpcode) 1047 { 1048 case PARSEOP_METHOD: 1049 case PARSEOP_RETURN: 1050 if (!MethodInfo) 1051 { 1052 printf ("No method info for method! [%s]\n", Op->Asl.Namepath); 1053 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, "No method info for this method"); 1054 CmCleanupAndExit (); 1055 return (AE_AML_INTERNAL); 1056 } 1057 break; 1058 1059 default: 1060 break; 1061 } 1062 1063 switch (Op->Asl.ParseOpcode) 1064 { 1065 case PARSEOP_METHOD: 1066 1067 WalkInfo->MethodStack = MethodInfo->Next; 1068 1069 /* 1070 * Check if there is no return statement at the end of the 1071 * method AND we can actually get there -- i.e., the execution 1072 * of the method can possibly terminate without a return statement. 1073 */ 1074 if ((!AnLastStatementIsReturn (Op)) && 1075 (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) 1076 { 1077 /* 1078 * No return statement, and execution can possibly exit 1079 * via this path. This is equivalent to Return () 1080 */ 1081 MethodInfo->NumReturnNoValue++; 1082 } 1083 1084 /* 1085 * Check for case where some return statements have a return value 1086 * and some do not. Exit without a return statement is a return with 1087 * no value 1088 */ 1089 if (MethodInfo->NumReturnNoValue && 1090 MethodInfo->NumReturnWithValue) 1091 { 1092 AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, Op->Asl.ExternalName); 1093 } 1094 1095 /* 1096 * If there are any RETURN() statements with no value, or there is a 1097 * control path that allows the method to exit without a return value, 1098 * we mark the method as a method that does not return a value. This 1099 * knowledge can be used to check method invocations that expect a 1100 * returned value. 1101 */ 1102 if (MethodInfo->NumReturnNoValue) 1103 { 1104 if (MethodInfo->NumReturnWithValue) 1105 { 1106 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; 1107 } 1108 else 1109 { 1110 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; 1111 } 1112 } 1113 1114 /* 1115 * Check predefined method names for correct return behavior 1116 * and correct number of arguments 1117 */ 1118 AnCheckForReservedMethod (Op, MethodInfo); 1119 ACPI_MEM_FREE (MethodInfo); 1120 break; 1121 1122 1123 case PARSEOP_RETURN: 1124 1125 /* 1126 * The parent block does not "exit" and continue execution -- the 1127 * method is terminated here with the Return() statement. 1128 */ 1129 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1130 Op->Asl.ParentMethod = MethodInfo->Op; /* Used in the "typing" pass later */ 1131 1132 /* 1133 * If there is a peer node after the return statement, then this 1134 * node is unreachable code -- i.e., it won't be executed because of the 1135 * preceeding Return() statement. 1136 */ 1137 if (Op->Asl.Next) 1138 { 1139 AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); 1140 } 1141 break; 1142 1143 1144 case PARSEOP_IF: 1145 1146 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1147 (Op->Asl.Next) && 1148 (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) 1149 { 1150 /* 1151 * This IF has a corresponding ELSE. The IF block has no exit, 1152 * (it contains an unconditional Return) 1153 * mark the ELSE block to remember this fact. 1154 */ 1155 Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; 1156 } 1157 break; 1158 1159 1160 case PARSEOP_ELSE: 1161 1162 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1163 (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) 1164 { 1165 /* 1166 * This ELSE block has no exit and the corresponding IF block 1167 * has no exit either. Therefore, the parent node has no exit. 1168 */ 1169 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1170 } 1171 break; 1172 1173 1174 default: 1175 1176 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 1177 (Op->Asl.Parent)) 1178 { 1179 /* If this node has no exit, then the parent has no exit either */ 1180 1181 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 1182 } 1183 break; 1184 } 1185 1186 return AE_OK; 1187} 1188 1189 1190/******************************************************************************* 1191 * 1192 * FUNCTION: AnMethodTypingWalkBegin 1193 * 1194 * PARAMETERS: ASL_WALK_CALLBACK 1195 * 1196 * RETURN: Status 1197 * 1198 * DESCRIPTION: Descending callback for the typing walk. 1199 * 1200 ******************************************************************************/ 1201 1202ACPI_STATUS 1203AnMethodTypingWalkBegin ( 1204 ACPI_PARSE_OBJECT *Op, 1205 UINT32 Level, 1206 void *Context) 1207{ 1208 1209 return AE_OK; 1210} 1211 1212 1213/******************************************************************************* 1214 * 1215 * FUNCTION: AnMethodTypingWalkEnd 1216 * 1217 * PARAMETERS: ASL_WALK_CALLBACK 1218 * 1219 * RETURN: Status 1220 * 1221 * DESCRIPTION: Ascending callback for typing walk. Complete method 1222 * return analysis. Check methods for : 1223 * 1) Initialized local variables 1224 * 2) Valid arguments 1225 * 3) Return types 1226 * 1227 ******************************************************************************/ 1228 1229ACPI_STATUS 1230AnMethodTypingWalkEnd ( 1231 ACPI_PARSE_OBJECT *Op, 1232 UINT32 Level, 1233 void *Context) 1234{ 1235 UINT32 ThisNodeBtype; 1236 1237 1238 switch (Op->Asl.ParseOpcode) 1239 { 1240 case PARSEOP_METHOD: 1241 1242 Op->Asl.CompileFlags |= NODE_METHOD_TYPED; 1243 break; 1244 1245 case PARSEOP_RETURN: 1246 1247 if ((Op->Asl.Child) && 1248 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 1249 { 1250 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 1251 1252 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && 1253 (ThisNodeBtype == (ACPI_UINT32_MAX -1))) 1254 { 1255 /* 1256 * The method is untyped at this time (typically a forward reference). 1257 * We must recursively type the method here 1258 */ 1259 TrWalkParseTree (ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Op->Asl.Child->Asl.Node->Object), 1260 ASL_WALK_VISIT_TWICE, AnMethodTypingWalkBegin, 1261 AnMethodTypingWalkEnd, NULL); 1262 1263 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 1264 } 1265 1266 /* Returns a value, get it's type */ 1267 1268 if (Op->Asl.ParentMethod) 1269 { 1270 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; 1271 } 1272 } 1273 break; 1274 1275 default: 1276 break; 1277 } 1278 1279 return AE_OK; 1280} 1281 1282 1283/******************************************************************************* 1284 * 1285 * FUNCTION: AnCheckMethodReturnValue 1286 * 1287 * PARAMETERS: Op - Parent 1288 * OpInfo - Parent info 1289 * ArgOp - Method invocation op 1290 * RequiredBtypes - What caller requires 1291 * ThisNodeBtype - What this node returns (if anything) 1292 * 1293 * RETURN: None 1294 * 1295 * DESCRIPTION: Check a method invocation for 1) A return value and if it does 1296 * in fact return a value, 2) check the type of the return value. 1297 * 1298 ******************************************************************************/ 1299 1300void 1301AnCheckMethodReturnValue ( 1302 ACPI_PARSE_OBJECT *Op, 1303 const ACPI_OPCODE_INFO *OpInfo, 1304 ACPI_PARSE_OBJECT *ArgOp, 1305 UINT32 RequiredBtypes, 1306 UINT32 ThisNodeBtype) 1307{ 1308 ACPI_PARSE_OBJECT *OwningOp; 1309 ACPI_NAMESPACE_NODE *Node; 1310 1311 1312 Node = ArgOp->Asl.Node; 1313 1314 1315 /* Examine the parent op of this method */ 1316 1317 OwningOp = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Node->Object); 1318 if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL) 1319 { 1320 /* 1321 * Method NEVER returns a value 1322 */ 1323 AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName); 1324 } 1325 else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL) 1326 { 1327 /* 1328 * Method SOMETIMES returns a value, SOMETIMES not 1329 */ 1330 AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, Op, Op->Asl.ExternalName); 1331 } 1332 else if (!(ThisNodeBtype & RequiredBtypes)) 1333 { 1334 /* 1335 * Method returns a value, but the type is wrong 1336 */ 1337 AnFormatBtype (StringBuffer, ThisNodeBtype); 1338 AnFormatBtype (StringBuffer2, RequiredBtypes); 1339 1340 1341 /* 1342 * The case where the method does not return any value at all 1343 * was already handled in the namespace cross reference 1344 * -- Only issue an error if the method in fact returns a value, 1345 * but it is of the wrong type 1346 */ 1347 if (ThisNodeBtype != 0) 1348 { 1349 sprintf (MsgBuffer, "Method returns [%s], %s operator requires [%s]", 1350 StringBuffer, OpInfo->Name, StringBuffer2); 1351 1352 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 1353 } 1354 } 1355} 1356 1357 1358/******************************************************************************* 1359 * 1360 * FUNCTION: AnOperandTypecheckWalkBegin 1361 * 1362 * PARAMETERS: ASL_WALK_CALLBACK 1363 * 1364 * RETURN: Status 1365 * 1366 * DESCRIPTION: Descending callback for the analysis walk. Check methods for : 1367 * 1) Initialized local variables 1368 * 2) Valid arguments 1369 * 3) Return types 1370 * 1371 ******************************************************************************/ 1372 1373ACPI_STATUS 1374AnOperandTypecheckWalkBegin ( 1375 ACPI_PARSE_OBJECT *Op, 1376 UINT32 Level, 1377 void *Context) 1378{ 1379 1380 return AE_OK; 1381} 1382 1383 1384/******************************************************************************* 1385 * 1386 * FUNCTION: AnOperandTypecheckWalkEnd 1387 * 1388 * PARAMETERS: ASL_WALK_CALLBACK 1389 * 1390 * RETURN: Status 1391 * 1392 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1393 * return analysis. 1394 * 1395 ******************************************************************************/ 1396 1397ACPI_STATUS 1398AnOperandTypecheckWalkEnd ( 1399 ACPI_PARSE_OBJECT *Op, 1400 UINT32 Level, 1401 void *Context) 1402{ 1403 const ACPI_OPCODE_INFO *OpInfo; 1404 UINT32 RuntimeArgTypes; 1405 UINT32 RuntimeArgTypes2; 1406 UINT32 RequiredBtypes; 1407 UINT32 ThisNodeBtype; 1408 UINT32 CommonBtypes; 1409 UINT32 OpcodeClass; 1410 ACPI_PARSE_OBJECT *ArgOp; 1411 UINT32 ArgType; 1412 1413 1414 switch (Op->Asl.AmlOpcode) 1415 { 1416 case AML_RAW_DATA_BYTE: 1417 case AML_RAW_DATA_WORD: 1418 case AML_RAW_DATA_DWORD: 1419 case AML_RAW_DATA_QWORD: 1420 case AML_RAW_DATA_BUFFER: 1421 case AML_RAW_DATA_CHAIN: 1422 case AML_PACKAGE_LENGTH: 1423 case AML_UNASSIGNED_OPCODE: 1424 case AML_DEFAULT_ARG_OP: 1425 1426 /* Ignore the internal (compiler-only) AML opcodes */ 1427 1428 return (AE_OK); 1429 1430 default: 1431 break; 1432 } 1433 1434 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1435 if (!OpInfo) 1436 { 1437 return (AE_OK); 1438 } 1439 1440 ArgOp = Op->Asl.Child; 1441 RuntimeArgTypes = OpInfo->RuntimeArgs; 1442 OpcodeClass = OpInfo->Class; 1443 1444 1445 /* 1446 * Special case for control opcodes IF/RETURN/WHILE since they 1447 * have no runtime arg list (at this time) 1448 */ 1449 switch (Op->Asl.AmlOpcode) 1450 { 1451 case AML_IF_OP: 1452 case AML_WHILE_OP: 1453 case AML_RETURN_OP: 1454 1455 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 1456 { 1457 /* The lone arg is a method call, check it */ 1458 1459 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); 1460 if (Op->Asl.AmlOpcode == AML_RETURN_OP) 1461 { 1462 RequiredBtypes = 0xFFFFFFFF; 1463 } 1464 1465 ThisNodeBtype = AnGetBtype (ArgOp); 1466 if (ThisNodeBtype == ACPI_UINT32_MAX) 1467 { 1468 return (AE_OK); 1469 } 1470 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, RequiredBtypes, ThisNodeBtype); 1471 } 1472 return (AE_OK); 1473 1474 default: 1475 break; 1476 } 1477 1478 /* Ignore the non-executable opcodes */ 1479 1480 if (RuntimeArgTypes == ARGI_INVALID_OPCODE) 1481 { 1482 return (AE_OK); 1483 } 1484 1485 switch (OpcodeClass) 1486 { 1487 case AML_CLASS_EXECUTE: 1488 case AML_CLASS_CREATE: 1489 case AML_CLASS_CONTROL: 1490 case AML_CLASS_RETURN_VALUE: 1491 1492 /* TBD: Change class or fix typechecking for these */ 1493 1494 if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || 1495 (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || 1496 (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) 1497 { 1498 break; 1499 } 1500 1501 /* Reverse the runtime argument list */ 1502 1503 RuntimeArgTypes2 = 0; 1504 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) 1505 { 1506 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; 1507 RuntimeArgTypes2 |= ArgType; 1508 INCREMENT_ARG_LIST (RuntimeArgTypes); 1509 } 1510 1511 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) 1512 { 1513 RequiredBtypes = AnMapArgTypeToBtype (ArgType); 1514 1515 ThisNodeBtype = AnGetBtype (ArgOp); 1516 if (ThisNodeBtype == ACPI_UINT32_MAX) 1517 { 1518 goto NextArgument; 1519 } 1520 1521 /* Examine the arg based on the required type of the arg */ 1522 1523 switch (ArgType) 1524 { 1525 case ARGI_TARGETREF: 1526 1527 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 1528 { 1529 /* ZERO is the placeholder for "don't store result" */ 1530 1531 ThisNodeBtype = RequiredBtypes; 1532 break; 1533 } 1534 1535 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) 1536 { 1537 /* 1538 * This is the case where an original reference to a resource 1539 * descriptor field has been replaced by an (Integer) offset. 1540 * These named fields are supported at compile-time only; 1541 * the names are not passed to the interpreter (via the AML). 1542 */ 1543 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 1544 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 1545 { 1546 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); 1547 } 1548 else 1549 { 1550 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); 1551 } 1552 break; 1553 } 1554 1555 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || 1556 (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) 1557 { 1558 break; 1559 } 1560 1561 ThisNodeBtype = RequiredBtypes; 1562 break; 1563 1564 1565 case ARGI_REFERENCE: /* References */ 1566 case ARGI_INTEGER_REF: 1567 case ARGI_OBJECT_REF: 1568 case ARGI_DEVICE_REF: 1569 1570 switch (ArgOp->Asl.ParseOpcode) 1571 { 1572 case PARSEOP_LOCAL0: 1573 case PARSEOP_LOCAL1: 1574 case PARSEOP_LOCAL2: 1575 case PARSEOP_LOCAL3: 1576 case PARSEOP_LOCAL4: 1577 case PARSEOP_LOCAL5: 1578 case PARSEOP_LOCAL6: 1579 case PARSEOP_LOCAL7: 1580 1581 /* TBD: implement analysis of current value (type) of the local */ 1582 /* For now, just treat any local as a typematch */ 1583 1584 /*ThisNodeBtype = RequiredBtypes;*/ 1585 break; 1586 1587 case PARSEOP_ARG0: 1588 case PARSEOP_ARG1: 1589 case PARSEOP_ARG2: 1590 case PARSEOP_ARG3: 1591 case PARSEOP_ARG4: 1592 case PARSEOP_ARG5: 1593 case PARSEOP_ARG6: 1594 1595 /* Hard to analyze argument types, sow we won't */ 1596 /* For now, just treat any arg as a typematch */ 1597 1598 /* ThisNodeBtype = RequiredBtypes; */ 1599 break; 1600 1601 case PARSEOP_DEBUG: 1602 break; 1603 1604 case PARSEOP_REFOF: 1605 case PARSEOP_INDEX: 1606 default: 1607 break; 1608 1609 } 1610 break; 1611 1612 case ARGI_INTEGER: 1613 default: 1614 break; 1615 } 1616 1617 1618 CommonBtypes = ThisNodeBtype & RequiredBtypes; 1619 1620 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 1621 { 1622 /* Check a method call for a valid return value */ 1623 1624 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, RequiredBtypes, ThisNodeBtype); 1625 } 1626 1627 /* 1628 * Now check if the actual type(s) match at least one 1629 * bit to the required type 1630 */ 1631 else if (!CommonBtypes) 1632 { 1633 /* No match -- this is a type mismatch error */ 1634 1635 AnFormatBtype (StringBuffer, ThisNodeBtype); 1636 AnFormatBtype (StringBuffer2, RequiredBtypes); 1637 1638 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", 1639 StringBuffer, OpInfo->Name, StringBuffer2); 1640 1641 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 1642 } 1643 1644 NextArgument: 1645 ArgOp = ArgOp->Asl.Next; 1646 INCREMENT_ARG_LIST (RuntimeArgTypes2); 1647 } 1648 break; 1649 1650 default: 1651 break; 1652 } 1653 1654 return (AE_OK); 1655} 1656 1657 1658/******************************************************************************* 1659 * 1660 * FUNCTION: AnOtherSemanticAnalysisWalkBegin 1661 * 1662 * PARAMETERS: ASL_WALK_CALLBACK 1663 * 1664 * RETURN: Status 1665 * 1666 * DESCRIPTION: Descending callback for the analysis walk. Check methods for : 1667 * 1) Initialized local variables 1668 * 2) Valid arguments 1669 * 3) Return types 1670 * 1671 ******************************************************************************/ 1672 1673ACPI_STATUS 1674AnOtherSemanticAnalysisWalkBegin ( 1675 ACPI_PARSE_OBJECT *Op, 1676 UINT32 Level, 1677 void *Context) 1678{ 1679 1680 return AE_OK; 1681} 1682 1683 1684/******************************************************************************* 1685 * 1686 * FUNCTION: AnOtherSemanticAnalysisWalkEnd 1687 * 1688 * PARAMETERS: ASL_WALK_CALLBACK 1689 * 1690 * RETURN: Status 1691 * 1692 * DESCRIPTION: Ascending callback for analysis walk. Complete method 1693 * return analysis. 1694 * 1695 ******************************************************************************/ 1696 1697ACPI_STATUS 1698AnOtherSemanticAnalysisWalkEnd ( 1699 ACPI_PARSE_OBJECT *Op, 1700 UINT32 Level, 1701 void *Context) 1702{ 1703 1704 return AE_OK; 1705 1706}
|