1 /****************************************************************************** 2 * 3 * Module Name: aslwalks.c - major analytical parse tree walks 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 45 #include <contrib/dev/acpica/compiler/aslcompiler.h> 46 #include "aslcompiler.y.h" 47 #include <contrib/dev/acpica/include/acparser.h> 48 #include <contrib/dev/acpica/include/amlcode.h> 49 50 51 #define _COMPONENT ACPI_COMPILER 52 ACPI_MODULE_NAME ("aslwalks") 53 54 55 /******************************************************************************* 56 * 57 * FUNCTION: AnMethodAnalysisWalkBegin 58 * 59 * PARAMETERS: ASL_WALK_CALLBACK 60 * 61 * RETURN: Status 62 * 63 * DESCRIPTION: Descending callback for the analysis walk. Check methods for: 64 * 1) Initialized local variables 65 * 2) Valid arguments 66 * 3) Return types 67 * 68 ******************************************************************************/ 69 70 ACPI_STATUS 71 AnMethodAnalysisWalkBegin ( 72 ACPI_PARSE_OBJECT *Op, 73 UINT32 Level, 74 void *Context) 75 { 76 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 77 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 78 ACPI_PARSE_OBJECT *Next; 79 UINT32 RegisterNumber; 80 UINT32 i; 81 char LocalName[] = "Local0"; 82 char ArgName[] = "Arg0"; 83 ACPI_PARSE_OBJECT *ArgNode; 84 ACPI_PARSE_OBJECT *NextType; 85 ACPI_PARSE_OBJECT *NextParamType; 86 UINT8 ActualArgs = 0; 87 88 89 switch (Op->Asl.ParseOpcode) 90 { 91 case PARSEOP_METHOD: 92 93 TotalMethods++; 94 95 /* Create and init method info */ 96 97 MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); 98 MethodInfo->Next = WalkInfo->MethodStack; 99 MethodInfo->Op = Op; 100 101 WalkInfo->MethodStack = MethodInfo; 102 103 /* Get the name node, ignored here */ 104 105 Next = Op->Asl.Child; 106 107 /* Get the NumArguments node */ 108 109 Next = Next->Asl.Next; 110 MethodInfo->NumArguments = (UINT8) 111 (((UINT8) Next->Asl.Value.Integer) & 0x07); 112 113 /* Get the SerializeRule and SyncLevel nodes, ignored here */ 114 115 Next = Next->Asl.Next; 116 Next = Next->Asl.Next; 117 ArgNode = Next; 118 119 /* Get the ReturnType node */ 120 121 Next = Next->Asl.Next; 122 123 NextType = Next->Asl.Child; 124 while (NextType) 125 { 126 /* Get and map each of the ReturnTypes */ 127 128 MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); 129 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 130 NextType = NextType->Asl.Next; 131 } 132 133 /* Get the ParameterType node */ 134 135 Next = Next->Asl.Next; 136 137 NextType = Next->Asl.Child; 138 while (NextType) 139 { 140 if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 141 { 142 NextParamType = NextType->Asl.Child; 143 while (NextParamType) 144 { 145 MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType); 146 NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 147 NextParamType = NextParamType->Asl.Next; 148 } 149 } 150 else 151 { 152 MethodInfo->ValidArgTypes[ActualArgs] = 153 AnMapObjTypeToBtype (NextType); 154 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 155 ActualArgs++; 156 } 157 158 NextType = NextType->Asl.Next; 159 } 160 161 if ((MethodInfo->NumArguments) && 162 (MethodInfo->NumArguments != ActualArgs)) 163 { 164 /* error: Param list did not match number of args */ 165 } 166 167 /* Allow numarguments == 0 for Function() */ 168 169 if ((!MethodInfo->NumArguments) && (ActualArgs)) 170 { 171 MethodInfo->NumArguments = ActualArgs; 172 ArgNode->Asl.Value.Integer |= ActualArgs; 173 } 174 175 /* 176 * Actual arguments are initialized at method entry. 177 * All other ArgX "registers" can be used as locals, so we 178 * track their initialization. 179 */ 180 for (i = 0; i < MethodInfo->NumArguments; i++) 181 { 182 MethodInfo->ArgInitialized[i] = TRUE; 183 } 184 break; 185 186 187 case PARSEOP_METHODCALL: 188 189 if (MethodInfo && 190 (Op->Asl.Node == MethodInfo->Op->Asl.Node)) 191 { 192 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); 193 } 194 break; 195 196 197 case PARSEOP_LOCAL0: 198 case PARSEOP_LOCAL1: 199 case PARSEOP_LOCAL2: 200 case PARSEOP_LOCAL3: 201 case PARSEOP_LOCAL4: 202 case PARSEOP_LOCAL5: 203 case PARSEOP_LOCAL6: 204 case PARSEOP_LOCAL7: 205 206 if (!MethodInfo) 207 { 208 /* 209 * Local was used outside a control method, or there was an error 210 * in the method declaration. 211 */ 212 AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); 213 return (AE_ERROR); 214 } 215 216 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); 217 218 /* 219 * If the local is being used as a target, mark the local 220 * initialized 221 */ 222 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 223 { 224 MethodInfo->LocalInitialized[RegisterNumber] = TRUE; 225 } 226 227 /* 228 * Otherwise, this is a reference, check if the local 229 * has been previously initialized. 230 * 231 * The only operator that accepts an uninitialized value is ObjectType() 232 */ 233 else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && 234 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 235 { 236 LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); 237 AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); 238 } 239 break; 240 241 242 case PARSEOP_ARG0: 243 case PARSEOP_ARG1: 244 case PARSEOP_ARG2: 245 case PARSEOP_ARG3: 246 case PARSEOP_ARG4: 247 case PARSEOP_ARG5: 248 case PARSEOP_ARG6: 249 250 if (!MethodInfo) 251 { 252 /* 253 * Arg was used outside a control method, or there was an error 254 * in the method declaration. 255 */ 256 AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); 257 return (AE_ERROR); 258 } 259 260 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; 261 ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); 262 263 /* 264 * If the Arg is being used as a target, mark the local 265 * initialized 266 */ 267 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 268 { 269 MethodInfo->ArgInitialized[RegisterNumber] = TRUE; 270 } 271 272 /* 273 * Otherwise, this is a reference, check if the Arg 274 * has been previously initialized. 275 * 276 * The only operator that accepts an uninitialized value is ObjectType() 277 */ 278 else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && 279 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 280 { 281 AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); 282 } 283 284 /* Flag this arg if it is not a "real" argument to the method */ 285 286 if (RegisterNumber >= MethodInfo->NumArguments) 287 { 288 AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); 289 } 290 break; 291 292 293 case PARSEOP_RETURN: 294 295 if (!MethodInfo) 296 { 297 /* 298 * Probably was an error in the method declaration, 299 * no additional error here 300 */ 301 ACPI_WARNING ((AE_INFO, "%p, No parent method", Op)); 302 return (AE_ERROR); 303 } 304 305 /* 306 * A child indicates a possible return value. A simple Return or 307 * Return() is marked with NODE_IS_NULL_RETURN by the parser so 308 * that it is not counted as a "real" return-with-value, although 309 * the AML code that is actually emitted is Return(0). The AML 310 * definition of Return has a required parameter, so we are 311 * forced to convert a null return to Return(0). 312 */ 313 if ((Op->Asl.Child) && 314 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && 315 (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN))) 316 { 317 MethodInfo->NumReturnWithValue++; 318 } 319 else 320 { 321 MethodInfo->NumReturnNoValue++; 322 } 323 break; 324 325 326 case PARSEOP_BREAK: 327 case PARSEOP_CONTINUE: 328 329 Next = Op->Asl.Parent; 330 while (Next) 331 { 332 if (Next->Asl.ParseOpcode == PARSEOP_WHILE) 333 { 334 break; 335 } 336 Next = Next->Asl.Parent; 337 } 338 339 if (!Next) 340 { 341 AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); 342 } 343 break; 344 345 346 case PARSEOP_STALL: 347 348 /* We can range check if the argument is an integer */ 349 350 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 351 (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) 352 { 353 AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); 354 } 355 break; 356 357 358 case PARSEOP_DEVICE: 359 case PARSEOP_EVENT: 360 case PARSEOP_MUTEX: 361 case PARSEOP_OPERATIONREGION: 362 case PARSEOP_POWERRESOURCE: 363 case PARSEOP_PROCESSOR: 364 case PARSEOP_THERMALZONE: 365 366 /* 367 * The first operand is a name to be created in the namespace. 368 * Check against the reserved list. 369 */ 370 i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); 371 if (i < ACPI_VALID_RESERVED_NAME_MAX) 372 { 373 AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); 374 } 375 break; 376 377 378 case PARSEOP_NAME: 379 380 /* Typecheck any predefined names statically defined with Name() */ 381 382 ApCheckForPredefinedObject (Op, Op->Asl.NameSeg); 383 384 /* Special typechecking for _HID */ 385 386 if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg)) 387 { 388 Next = Op->Asl.Child->Asl.Next; 389 AnCheckId (Next, ASL_TYPE_HID); 390 } 391 392 /* Special typechecking for _CID */ 393 394 else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg)) 395 { 396 Next = Op->Asl.Child->Asl.Next; 397 398 if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) || 399 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) 400 { 401 Next = Next->Asl.Child; 402 while (Next) 403 { 404 AnCheckId (Next, ASL_TYPE_CID); 405 Next = Next->Asl.Next; 406 } 407 } 408 else 409 { 410 AnCheckId (Next, ASL_TYPE_CID); 411 } 412 } 413 break; 414 415 416 default: 417 break; 418 } 419 420 return (AE_OK); 421 } 422 423 424 /******************************************************************************* 425 * 426 * FUNCTION: AnMethodAnalysisWalkEnd 427 * 428 * PARAMETERS: ASL_WALK_CALLBACK 429 * 430 * RETURN: Status 431 * 432 * DESCRIPTION: Ascending callback for analysis walk. Complete method 433 * return analysis. 434 * 435 ******************************************************************************/ 436 437 ACPI_STATUS 438 AnMethodAnalysisWalkEnd ( 439 ACPI_PARSE_OBJECT *Op, 440 UINT32 Level, 441 void *Context) 442 { 443 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 444 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 445 446 447 switch (Op->Asl.ParseOpcode) 448 { 449 case PARSEOP_METHOD: 450 case PARSEOP_RETURN: 451 if (!MethodInfo) 452 { 453 printf ("No method info for method! [%s]\n", Op->Asl.Namepath); 454 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, 455 "No method info for this method"); 456 457 CmCleanupAndExit (); 458 return (AE_AML_INTERNAL); 459 } 460 break; 461 462 default: 463 break; 464 } 465 466 switch (Op->Asl.ParseOpcode) 467 { 468 case PARSEOP_METHOD: 469 470 WalkInfo->MethodStack = MethodInfo->Next; 471 472 /* 473 * Check if there is no return statement at the end of the 474 * method AND we can actually get there -- i.e., the execution 475 * of the method can possibly terminate without a return statement. 476 */ 477 if ((!AnLastStatementIsReturn (Op)) && 478 (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) 479 { 480 /* 481 * No return statement, and execution can possibly exit 482 * via this path. This is equivalent to Return () 483 */ 484 MethodInfo->NumReturnNoValue++; 485 } 486 487 /* 488 * Check for case where some return statements have a return value 489 * and some do not. Exit without a return statement is a return with 490 * no value 491 */ 492 if (MethodInfo->NumReturnNoValue && 493 MethodInfo->NumReturnWithValue) 494 { 495 AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, 496 Op->Asl.ExternalName); 497 } 498 499 /* 500 * If there are any RETURN() statements with no value, or there is a 501 * control path that allows the method to exit without a return value, 502 * we mark the method as a method that does not return a value. This 503 * knowledge can be used to check method invocations that expect a 504 * returned value. 505 */ 506 if (MethodInfo->NumReturnNoValue) 507 { 508 if (MethodInfo->NumReturnWithValue) 509 { 510 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; 511 } 512 else 513 { 514 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; 515 } 516 } 517 518 /* 519 * Check predefined method names for correct return behavior 520 * and correct number of arguments. Also, some special checks 521 * For GPE and _REG methods. 522 */ 523 if (ApCheckForPredefinedMethod (Op, MethodInfo)) 524 { 525 /* Special check for two names like _L01 and _E01 in same scope */ 526 527 ApCheckForGpeNameConflict (Op); 528 529 /* 530 * Special check for _REG: Must have an operation region definition 531 * within the same scope! 532 */ 533 ApCheckRegMethod (Op); 534 } 535 536 ACPI_FREE (MethodInfo); 537 break; 538 539 540 case PARSEOP_NAME: 541 542 /* Special check for two names like _L01 and _E01 in same scope */ 543 544 ApCheckForGpeNameConflict (Op); 545 break; 546 547 548 case PARSEOP_RETURN: 549 550 /* 551 * If the parent is a predefined method name, attempt to typecheck 552 * the return value. Only static types can be validated. 553 */ 554 ApCheckPredefinedReturnValue (Op, MethodInfo); 555 556 /* 557 * The parent block does not "exit" and continue execution -- the 558 * method is terminated here with the Return() statement. 559 */ 560 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 561 562 /* Used in the "typing" pass later */ 563 564 Op->Asl.ParentMethod = MethodInfo->Op; 565 566 /* 567 * If there is a peer node after the return statement, then this 568 * node is unreachable code -- i.e., it won't be executed because of 569 * the preceding Return() statement. 570 */ 571 if (Op->Asl.Next) 572 { 573 AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); 574 } 575 break; 576 577 578 case PARSEOP_IF: 579 580 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 581 (Op->Asl.Next) && 582 (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) 583 { 584 /* 585 * This IF has a corresponding ELSE. The IF block has no exit, 586 * (it contains an unconditional Return) 587 * mark the ELSE block to remember this fact. 588 */ 589 Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; 590 } 591 break; 592 593 594 case PARSEOP_ELSE: 595 596 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 597 (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) 598 { 599 /* 600 * This ELSE block has no exit and the corresponding IF block 601 * has no exit either. Therefore, the parent node has no exit. 602 */ 603 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 604 } 605 break; 606 607 608 default: 609 610 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 611 (Op->Asl.Parent)) 612 { 613 /* If this node has no exit, then the parent has no exit either */ 614 615 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 616 } 617 break; 618 } 619 620 return (AE_OK); 621 } 622 623 624 /******************************************************************************* 625 * 626 * FUNCTION: AnMethodTypingWalkEnd 627 * 628 * PARAMETERS: ASL_WALK_CALLBACK 629 * 630 * RETURN: Status 631 * 632 * DESCRIPTION: Ascending callback for typing walk. Complete the method 633 * return analysis. Check methods for: 634 * 1) Initialized local variables 635 * 2) Valid arguments 636 * 3) Return types 637 * 638 ******************************************************************************/ 639 640 ACPI_STATUS 641 AnMethodTypingWalkEnd ( 642 ACPI_PARSE_OBJECT *Op, 643 UINT32 Level, 644 void *Context) 645 { 646 UINT32 ThisNodeBtype; 647 648 649 switch (Op->Asl.ParseOpcode) 650 { 651 case PARSEOP_METHOD: 652 653 Op->Asl.CompileFlags |= NODE_METHOD_TYPED; 654 break; 655 656 case PARSEOP_RETURN: 657 658 if ((Op->Asl.Child) && 659 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 660 { 661 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 662 663 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && 664 (ThisNodeBtype == (ACPI_UINT32_MAX -1))) 665 { 666 /* 667 * The called method is untyped at this time (typically a 668 * forward reference). 669 * 670 * Check for a recursive method call first. 671 */ 672 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op) 673 { 674 /* We must type the method here */ 675 676 TrWalkParseTree (Op->Asl.Child->Asl.Node->Op, 677 ASL_WALK_VISIT_UPWARD, NULL, 678 AnMethodTypingWalkEnd, NULL); 679 680 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 681 } 682 } 683 684 /* Returns a value, save the value type */ 685 686 if (Op->Asl.ParentMethod) 687 { 688 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; 689 } 690 } 691 break; 692 693 default: 694 break; 695 } 696 697 return (AE_OK); 698 } 699 700 701 /******************************************************************************* 702 * 703 * FUNCTION: AnOperandTypecheckWalkEnd 704 * 705 * PARAMETERS: ASL_WALK_CALLBACK 706 * 707 * RETURN: Status 708 * 709 * DESCRIPTION: Ascending callback for analysis walk. Complete method 710 * return analysis. 711 * 712 ******************************************************************************/ 713 714 ACPI_STATUS 715 AnOperandTypecheckWalkEnd ( 716 ACPI_PARSE_OBJECT *Op, 717 UINT32 Level, 718 void *Context) 719 { 720 const ACPI_OPCODE_INFO *OpInfo; 721 UINT32 RuntimeArgTypes; 722 UINT32 RuntimeArgTypes2; 723 UINT32 RequiredBtypes; 724 UINT32 ThisNodeBtype; 725 UINT32 CommonBtypes; 726 UINT32 OpcodeClass; 727 ACPI_PARSE_OBJECT *ArgOp; 728 UINT32 ArgType; 729 730 731 switch (Op->Asl.AmlOpcode) 732 { 733 case AML_RAW_DATA_BYTE: 734 case AML_RAW_DATA_WORD: 735 case AML_RAW_DATA_DWORD: 736 case AML_RAW_DATA_QWORD: 737 case AML_RAW_DATA_BUFFER: 738 case AML_RAW_DATA_CHAIN: 739 case AML_PACKAGE_LENGTH: 740 case AML_UNASSIGNED_OPCODE: 741 case AML_DEFAULT_ARG_OP: 742 743 /* Ignore the internal (compiler-only) AML opcodes */ 744 745 return (AE_OK); 746 747 default: 748 break; 749 } 750 751 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 752 if (!OpInfo) 753 { 754 return (AE_OK); 755 } 756 757 ArgOp = Op->Asl.Child; 758 RuntimeArgTypes = OpInfo->RuntimeArgs; 759 OpcodeClass = OpInfo->Class; 760 761 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE 762 /* 763 * Update 11/2008: In practice, we can't perform this check. A simple 764 * analysis is not sufficient. Also, it can cause errors when compiling 765 * disassembled code because of the way Switch operators are implemented 766 * (a While(One) loop with a named temp variable created within.) 767 */ 768 769 /* 770 * If we are creating a named object, check if we are within a while loop 771 * by checking if the parent is a WHILE op. This is a simple analysis, but 772 * probably sufficient for many cases. 773 * 774 * Allow Scope(), Buffer(), and Package(). 775 */ 776 if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) || 777 ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE))) 778 { 779 if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP) 780 { 781 AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL); 782 } 783 } 784 #endif 785 786 /* 787 * Special case for control opcodes IF/RETURN/WHILE since they 788 * have no runtime arg list (at this time) 789 */ 790 switch (Op->Asl.AmlOpcode) 791 { 792 case AML_IF_OP: 793 case AML_WHILE_OP: 794 case AML_RETURN_OP: 795 796 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 797 { 798 /* Check for an internal method */ 799 800 if (AnIsInternalMethod (ArgOp)) 801 { 802 return (AE_OK); 803 } 804 805 /* The lone arg is a method call, check it */ 806 807 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); 808 if (Op->Asl.AmlOpcode == AML_RETURN_OP) 809 { 810 RequiredBtypes = 0xFFFFFFFF; 811 } 812 813 ThisNodeBtype = AnGetBtype (ArgOp); 814 if (ThisNodeBtype == ACPI_UINT32_MAX) 815 { 816 return (AE_OK); 817 } 818 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 819 RequiredBtypes, ThisNodeBtype); 820 } 821 return (AE_OK); 822 823 default: 824 break; 825 } 826 827 /* Ignore the non-executable opcodes */ 828 829 if (RuntimeArgTypes == ARGI_INVALID_OPCODE) 830 { 831 return (AE_OK); 832 } 833 834 switch (OpcodeClass) 835 { 836 case AML_CLASS_EXECUTE: 837 case AML_CLASS_CREATE: 838 case AML_CLASS_CONTROL: 839 case AML_CLASS_RETURN_VALUE: 840 841 /* TBD: Change class or fix typechecking for these */ 842 843 if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || 844 (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || 845 (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) 846 { 847 break; 848 } 849 850 /* Reverse the runtime argument list */ 851 852 RuntimeArgTypes2 = 0; 853 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) 854 { 855 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; 856 RuntimeArgTypes2 |= ArgType; 857 INCREMENT_ARG_LIST (RuntimeArgTypes); 858 } 859 860 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) 861 { 862 RequiredBtypes = AnMapArgTypeToBtype (ArgType); 863 864 ThisNodeBtype = AnGetBtype (ArgOp); 865 if (ThisNodeBtype == ACPI_UINT32_MAX) 866 { 867 goto NextArgument; 868 } 869 870 /* Examine the arg based on the required type of the arg */ 871 872 switch (ArgType) 873 { 874 case ARGI_TARGETREF: 875 876 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 877 { 878 /* ZERO is the placeholder for "don't store result" */ 879 880 ThisNodeBtype = RequiredBtypes; 881 break; 882 } 883 884 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) 885 { 886 /* 887 * This is the case where an original reference to a resource 888 * descriptor field has been replaced by an (Integer) offset. 889 * These named fields are supported at compile-time only; 890 * the names are not passed to the interpreter (via the AML). 891 */ 892 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 893 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 894 { 895 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); 896 } 897 else 898 { 899 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); 900 } 901 break; 902 } 903 904 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || 905 (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) 906 { 907 break; 908 } 909 910 ThisNodeBtype = RequiredBtypes; 911 break; 912 913 914 case ARGI_REFERENCE: /* References */ 915 case ARGI_INTEGER_REF: 916 case ARGI_OBJECT_REF: 917 case ARGI_DEVICE_REF: 918 919 switch (ArgOp->Asl.ParseOpcode) 920 { 921 case PARSEOP_LOCAL0: 922 case PARSEOP_LOCAL1: 923 case PARSEOP_LOCAL2: 924 case PARSEOP_LOCAL3: 925 case PARSEOP_LOCAL4: 926 case PARSEOP_LOCAL5: 927 case PARSEOP_LOCAL6: 928 case PARSEOP_LOCAL7: 929 930 /* TBD: implement analysis of current value (type) of the local */ 931 /* For now, just treat any local as a typematch */ 932 933 /*ThisNodeBtype = RequiredBtypes;*/ 934 break; 935 936 case PARSEOP_ARG0: 937 case PARSEOP_ARG1: 938 case PARSEOP_ARG2: 939 case PARSEOP_ARG3: 940 case PARSEOP_ARG4: 941 case PARSEOP_ARG5: 942 case PARSEOP_ARG6: 943 944 /* Hard to analyze argument types, sow we won't */ 945 /* For now, just treat any arg as a typematch */ 946 947 /* ThisNodeBtype = RequiredBtypes; */ 948 break; 949 950 case PARSEOP_DEBUG: 951 break; 952 953 case PARSEOP_REFOF: 954 case PARSEOP_INDEX: 955 default: 956 break; 957 958 } 959 break; 960 961 case ARGI_INTEGER: 962 default: 963 break; 964 } 965 966 967 CommonBtypes = ThisNodeBtype & RequiredBtypes; 968 969 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 970 { 971 if (AnIsInternalMethod (ArgOp)) 972 { 973 return (AE_OK); 974 } 975 976 /* Check a method call for a valid return value */ 977 978 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 979 RequiredBtypes, ThisNodeBtype); 980 } 981 982 /* 983 * Now check if the actual type(s) match at least one 984 * bit to the required type 985 */ 986 else if (!CommonBtypes) 987 { 988 /* No match -- this is a type mismatch error */ 989 990 AnFormatBtype (StringBuffer, ThisNodeBtype); 991 AnFormatBtype (StringBuffer2, RequiredBtypes); 992 993 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", 994 StringBuffer, OpInfo->Name, StringBuffer2); 995 996 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 997 } 998 999 NextArgument: 1000 ArgOp = ArgOp->Asl.Next; 1001 INCREMENT_ARG_LIST (RuntimeArgTypes2); 1002 } 1003 break; 1004 1005 default: 1006 break; 1007 } 1008 1009 return (AE_OK); 1010 } 1011 1012 1013 /******************************************************************************* 1014 * 1015 * FUNCTION: AnOtherSemanticAnalysisWalkBegin 1016 * 1017 * PARAMETERS: ASL_WALK_CALLBACK 1018 * 1019 * RETURN: Status 1020 * 1021 * DESCRIPTION: Descending callback for the analysis walk. Checks for 1022 * miscellaneous issues in the code. 1023 * 1024 ******************************************************************************/ 1025 1026 ACPI_STATUS 1027 AnOtherSemanticAnalysisWalkBegin ( 1028 ACPI_PARSE_OBJECT *Op, 1029 UINT32 Level, 1030 void *Context) 1031 { 1032 ACPI_PARSE_OBJECT *ArgNode; 1033 ACPI_PARSE_OBJECT *PrevArgNode = NULL; 1034 const ACPI_OPCODE_INFO *OpInfo; 1035 ACPI_NAMESPACE_NODE *Node; 1036 1037 1038 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1039 1040 /* 1041 * Determine if an execution class operator actually does something by 1042 * checking if it has a target and/or the function return value is used. 1043 * (Target is optional, so a standalone statement can actually do nothing.) 1044 */ 1045 if ((OpInfo->Class == AML_CLASS_EXECUTE) && 1046 (OpInfo->Flags & AML_HAS_RETVAL) && 1047 (!AnIsResultUsed (Op))) 1048 { 1049 if (OpInfo->Flags & AML_HAS_TARGET) 1050 { 1051 /* 1052 * Find the target node, it is always the last child. If the traget 1053 * is not specified in the ASL, a default node of type Zero was 1054 * created by the parser. 1055 */ 1056 ArgNode = Op->Asl.Child; 1057 while (ArgNode->Asl.Next) 1058 { 1059 PrevArgNode = ArgNode; 1060 ArgNode = ArgNode->Asl.Next; 1061 } 1062 1063 /* Divide() is the only weird case, it has two targets */ 1064 1065 if (Op->Asl.AmlOpcode == AML_DIVIDE_OP) 1066 { 1067 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) && 1068 (PrevArgNode) && 1069 (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO)) 1070 { 1071 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, 1072 Op, Op->Asl.ExternalName); 1073 } 1074 } 1075 else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) 1076 { 1077 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, 1078 Op, Op->Asl.ExternalName); 1079 } 1080 } 1081 else 1082 { 1083 /* 1084 * Has no target and the result is not used. Only a couple opcodes 1085 * can have this combination. 1086 */ 1087 switch (Op->Asl.ParseOpcode) 1088 { 1089 case PARSEOP_ACQUIRE: 1090 case PARSEOP_WAIT: 1091 case PARSEOP_LOADTABLE: 1092 break; 1093 1094 default: 1095 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, 1096 Op, Op->Asl.ExternalName); 1097 break; 1098 } 1099 } 1100 } 1101 1102 1103 /* 1104 * Semantic checks for individual ASL operators 1105 */ 1106 switch (Op->Asl.ParseOpcode) 1107 { 1108 case PARSEOP_ACQUIRE: 1109 case PARSEOP_WAIT: 1110 /* 1111 * Emit a warning if the timeout parameter for these operators is not 1112 * ACPI_WAIT_FOREVER, and the result value from the operator is not 1113 * checked, meaning that a timeout could happen, but the code 1114 * would not know about it. 1115 */ 1116 1117 /* First child is the namepath, 2nd child is timeout */ 1118 1119 ArgNode = Op->Asl.Child; 1120 ArgNode = ArgNode->Asl.Next; 1121 1122 /* 1123 * Check for the WAIT_FOREVER case - defined by the ACPI spec to be 1124 * 0xFFFF or greater 1125 */ 1126 if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) || 1127 (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER)) && 1128 (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER)) 1129 { 1130 break; 1131 } 1132 1133 /* 1134 * The operation could timeout. If the return value is not used 1135 * (indicates timeout occurred), issue a warning 1136 */ 1137 if (!AnIsResultUsed (Op)) 1138 { 1139 AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, 1140 Op->Asl.ExternalName); 1141 } 1142 break; 1143 1144 case PARSEOP_CREATEFIELD: 1145 /* 1146 * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand 1147 */ 1148 ArgNode = Op->Asl.Child; 1149 ArgNode = ArgNode->Asl.Next; 1150 ArgNode = ArgNode->Asl.Next; 1151 1152 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) || 1153 ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) && 1154 (ArgNode->Asl.Value.Integer == 0))) 1155 { 1156 AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL); 1157 } 1158 break; 1159 1160 case PARSEOP_CONNECTION: 1161 /* 1162 * Ensure that the referenced operation region has the correct SPACE_ID. 1163 * From the grammar/parser, we know the parent is a FIELD definition. 1164 */ 1165 ArgNode = Op->Asl.Parent; /* Field definition */ 1166 ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 1167 Node = ArgNode->Asl.Node; /* OpRegion namespace node */ 1168 1169 ArgNode = Node->Op; /* OpRegion definition */ 1170 ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 1171 ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ 1172 1173 /* 1174 * The Connection() operator is only valid for the following operation 1175 * region SpaceIds: GeneralPurposeIo and GenericSerialBus. 1176 */ 1177 if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && 1178 (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) 1179 { 1180 AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL); 1181 } 1182 break; 1183 1184 case PARSEOP_FIELD: 1185 /* 1186 * Ensure that fields for GeneralPurposeIo and GenericSerialBus 1187 * contain at least one Connection() operator 1188 */ 1189 ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ 1190 Node = ArgNode->Asl.Node; /* OpRegion namespace node */ 1191 if (!Node) 1192 { 1193 break; 1194 } 1195 1196 ArgNode = Node->Op; /* OpRegion definition */ 1197 ArgNode = ArgNode->Asl.Child; /* First child is the OpRegion Name */ 1198 ArgNode = ArgNode->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ 1199 1200 /* We are only interested in GeneralPurposeIo and GenericSerialBus */ 1201 1202 if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && 1203 (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) 1204 { 1205 break; 1206 } 1207 1208 ArgNode = Op->Asl.Child; /* 1st child is the OpRegion Name */ 1209 ArgNode = ArgNode->Asl.Next; /* AccessType */ 1210 ArgNode = ArgNode->Asl.Next; /* LockRule */ 1211 ArgNode = ArgNode->Asl.Next; /* UpdateRule */ 1212 ArgNode = ArgNode->Asl.Next; /* Start of FieldUnitList */ 1213 1214 /* Walk the FieldUnitList */ 1215 1216 while (ArgNode) 1217 { 1218 if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION) 1219 { 1220 break; 1221 } 1222 else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG) 1223 { 1224 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL); 1225 break; 1226 } 1227 1228 ArgNode = ArgNode->Asl.Next; 1229 } 1230 break; 1231 1232 default: 1233 break; 1234 } 1235 1236 return (AE_OK); 1237 } 1238