1 /****************************************************************************** 2 * 3 * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2026, 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 MERCHANTABILITY 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 #include "aslcompiler.h" 45 #include "aslcompiler.y.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 49 50 #define _COMPONENT ACPI_COMPILER 51 ACPI_MODULE_NAME ("aslwalks") 52 53 54 /* Local prototypes */ 55 56 static void 57 AnAnalyzeStoreOperator ( 58 ACPI_PARSE_OBJECT *Op); 59 60 static BOOLEAN 61 AnIsValidBufferConstant ( 62 ACPI_PARSE_OBJECT *Op); 63 64 static void 65 AnValidateCreateBufferField ( 66 ACPI_PARSE_OBJECT *CreateBufferFieldOp); 67 68 69 /******************************************************************************* 70 * 71 * FUNCTION: AnMethodTypingWalkEnd 72 * 73 * PARAMETERS: ASL_WALK_CALLBACK 74 * 75 * RETURN: Status 76 * 77 * DESCRIPTION: Ascending callback for typing walk. Complete the method 78 * return analysis. Check methods for: 79 * 1) Initialized local variables 80 * 2) Valid arguments 81 * 3) Return types 82 * 83 ******************************************************************************/ 84 85 ACPI_STATUS 86 AnMethodTypingWalkEnd ( 87 ACPI_PARSE_OBJECT *Op, 88 UINT32 Level, 89 void *Context) 90 { 91 UINT32 ThisOpBtype; 92 ACPI_PARSE_OBJECT *TargetMethodOp; 93 94 95 switch (Op->Asl.ParseOpcode) 96 { 97 case PARSEOP_METHOD: 98 99 Op->Asl.CompileFlags |= OP_METHOD_TYPED; 100 break; 101 102 case PARSEOP_RETURN: 103 104 if ((Op->Asl.Child) && 105 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 106 { 107 ThisOpBtype = AnGetBtype (Op->Asl.Child); 108 109 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && 110 (ThisOpBtype == (ACPI_UINT32_MAX -1))) 111 { 112 /* 113 * The called method is untyped at this time (typically a 114 * forward reference). 115 * 116 * Check for a recursive method call first. Note: the 117 * Child->Node will be null if the method has not been 118 * resolved. 119 */ 120 if (Op->Asl.Child->Asl.Node && 121 (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)) 122 { 123 TargetMethodOp = Op->Asl.Child->Asl.Node->Op; 124 125 /* Break mutual-recursion loops during typing */ 126 if (TargetMethodOp->Asl.CompileFlags & OP_VISITED) 127 { 128 break; 129 } 130 131 TargetMethodOp->Asl.CompileFlags |= OP_VISITED; 132 133 /* We must type the method here */ 134 135 TrWalkParseTree (TargetMethodOp, 136 ASL_WALK_VISIT_UPWARD, NULL, 137 AnMethodTypingWalkEnd, NULL); 138 139 TargetMethodOp->Asl.CompileFlags &= ~OP_VISITED; 140 141 ThisOpBtype = AnGetBtype (Op->Asl.Child); 142 } 143 } 144 145 /* Returns a value, save the value type */ 146 147 if (Op->Asl.ParentMethod) 148 { 149 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype; 150 } 151 } 152 break; 153 154 default: 155 156 break; 157 } 158 159 return (AE_OK); 160 } 161 162 163 /******************************************************************************* 164 * 165 * FUNCTION: AnOperandTypecheckWalkEnd 166 * 167 * PARAMETERS: ASL_WALK_CALLBACK 168 * 169 * RETURN: Status 170 * 171 * DESCRIPTION: Ascending callback for analysis walk. Complete method 172 * return analysis. 173 * 174 ******************************************************************************/ 175 176 ACPI_STATUS 177 AnOperandTypecheckWalkEnd ( 178 ACPI_PARSE_OBJECT *Op, 179 UINT32 Level, 180 void *Context) 181 { 182 const ACPI_OPCODE_INFO *OpInfo; 183 UINT32 RuntimeArgTypes; 184 UINT32 RuntimeArgTypes2; 185 UINT32 RequiredBtypes; 186 UINT32 ThisNodeBtype; 187 UINT32 CommonBtypes; 188 UINT32 OpcodeClass; 189 ACPI_PARSE_OBJECT *ArgOp; 190 UINT32 ArgType; 191 192 193 switch (Op->Asl.AmlOpcode) 194 { 195 case AML_RAW_DATA_BYTE: 196 case AML_RAW_DATA_WORD: 197 case AML_RAW_DATA_DWORD: 198 case AML_RAW_DATA_QWORD: 199 case AML_RAW_DATA_BUFFER: 200 case AML_RAW_DATA_CHAIN: 201 case AML_PACKAGE_LENGTH: 202 case AML_UNASSIGNED_OPCODE: 203 case AML_DEFAULT_ARG_OP: 204 205 /* Ignore the internal (compiler-only) AML opcodes */ 206 207 return (AE_OK); 208 209 default: 210 211 break; 212 } 213 214 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 215 if (!OpInfo) 216 { 217 return (AE_OK); 218 } 219 220 ArgOp = Op->Asl.Child; 221 OpcodeClass = OpInfo->Class; 222 RuntimeArgTypes = OpInfo->RuntimeArgs; 223 224 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE 225 /* 226 * Update 11/2008: In practice, we can't perform this check. A simple 227 * analysis is not sufficient. Also, it can cause errors when compiling 228 * disassembled code because of the way Switch operators are implemented 229 * (a While(One) loop with a named temp variable created within.) 230 */ 231 232 /* 233 * If we are creating a named object, check if we are within a while loop 234 * by checking if the parent is a WHILE op. This is a simple analysis, but 235 * probably sufficient for many cases. 236 * 237 * Allow Scope(), Buffer(), and Package(). 238 */ 239 if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) || 240 ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE))) 241 { 242 if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP) 243 { 244 AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL); 245 } 246 } 247 #endif 248 249 /* 250 * Special case for control opcodes IF/RETURN/WHILE since they 251 * have no runtime arg list (at this time) 252 */ 253 switch (Op->Asl.AmlOpcode) 254 { 255 case AML_IF_OP: 256 case AML_WHILE_OP: 257 case AML_RETURN_OP: 258 259 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 260 { 261 /* Check for an internal method */ 262 263 if (AnIsInternalMethod (ArgOp)) 264 { 265 return (AE_OK); 266 } 267 268 /* The lone arg is a method call, check it */ 269 270 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); 271 if (Op->Asl.AmlOpcode == AML_RETURN_OP) 272 { 273 RequiredBtypes = 0xFFFFFFFF; 274 } 275 276 ThisNodeBtype = AnGetBtype (ArgOp); 277 if (ThisNodeBtype == ACPI_UINT32_MAX) 278 { 279 return (AE_OK); 280 } 281 282 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 283 RequiredBtypes, ThisNodeBtype); 284 } 285 return (AE_OK); 286 287 case AML_EXTERNAL_OP: 288 /* 289 * Not really a "runtime" opcode since it used by disassembler only. 290 * The parser will find any issues with the operands. 291 */ 292 return (AE_OK); 293 294 default: 295 296 break; 297 } 298 299 /* Ignore the non-executable opcodes */ 300 301 if (RuntimeArgTypes == ARGI_INVALID_OPCODE) 302 { 303 return (AE_OK); 304 } 305 306 /* 307 * Special handling for certain opcodes. 308 */ 309 switch (Op->Asl.AmlOpcode) 310 { 311 /* BankField has one TermArg */ 312 313 case AML_BANK_FIELD_OP: 314 315 OpcodeClass = AML_CLASS_EXECUTE; 316 ArgOp = ArgOp->Asl.Next; 317 ArgOp = ArgOp->Asl.Next; 318 break; 319 320 /* Operation Region has 2 TermArgs */ 321 322 case AML_REGION_OP: 323 324 OpcodeClass = AML_CLASS_EXECUTE; 325 ArgOp = ArgOp->Asl.Next; 326 ArgOp = ArgOp->Asl.Next; 327 break; 328 329 /* DataTableRegion has 3 TermArgs */ 330 331 case AML_DATA_REGION_OP: 332 333 OpcodeClass = AML_CLASS_EXECUTE; 334 ArgOp = ArgOp->Asl.Next; 335 break; 336 337 /* Buffers/Packages have a length that is a TermArg */ 338 339 case AML_BUFFER_OP: 340 case AML_PACKAGE_OP: 341 case AML_VARIABLE_PACKAGE_OP: 342 343 /* If length is a constant, we are done */ 344 345 if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) || 346 (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA)) 347 { 348 return (AE_OK); 349 } 350 break; 351 352 /* Store can write any object to the Debug object */ 353 354 case AML_STORE_OP: 355 /* 356 * If this is a Store() to the Debug object, we don't need 357 * to perform any further validation -- because a Store of 358 * any object to Debug is permitted and supported. 359 */ 360 if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP) 361 { 362 return (AE_OK); 363 } 364 break; 365 366 default: 367 break; 368 } 369 370 switch (OpcodeClass) 371 { 372 case AML_CLASS_EXECUTE: 373 case AML_CLASS_CREATE: 374 case AML_CLASS_CONTROL: 375 case AML_CLASS_RETURN_VALUE: 376 377 /* Reverse the runtime argument list */ 378 379 RuntimeArgTypes2 = 0; 380 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) 381 { 382 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; 383 RuntimeArgTypes2 |= ArgType; 384 INCREMENT_ARG_LIST (RuntimeArgTypes); 385 } 386 387 /* Typecheck each argument */ 388 389 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) 390 { 391 /* Get the required type(s) for the argument */ 392 393 RequiredBtypes = AnMapArgTypeToBtype (ArgType); 394 395 if (!ArgOp) 396 { 397 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, 398 "Null ArgOp in argument loop"); 399 AslAbort (); 400 } 401 402 /* Get the actual type of the argument */ 403 404 ThisNodeBtype = AnGetBtype (ArgOp); 405 if (ThisNodeBtype == ACPI_UINT32_MAX) 406 { 407 goto NextArgument; 408 } 409 410 /* Examine the arg based on the required type of the arg */ 411 412 switch (ArgType) 413 { 414 case ARGI_TARGETREF: 415 416 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 417 { 418 /* ZERO is the placeholder for "don't store result" */ 419 420 ThisNodeBtype = RequiredBtypes; 421 break; 422 } 423 424 ACPI_FALLTHROUGH; 425 426 case ARGI_STORE_TARGET: 427 428 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) 429 { 430 /* 431 * This is the case where an original reference to a resource 432 * descriptor field has been replaced by an (Integer) offset. 433 * These named fields are supported at compile-time only; 434 * the names are not passed to the interpreter (via the AML). 435 */ 436 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 437 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 438 { 439 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, 440 ArgOp, NULL); 441 } 442 else 443 { 444 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, 445 ArgOp, NULL); 446 } 447 } 448 break; 449 450 451 #ifdef __FUTURE_IMPLEMENTATION 452 /* 453 * Possible future typechecking support 454 */ 455 case ARGI_REFERENCE: /* References */ 456 case ARGI_INTEGER_REF: 457 case ARGI_OBJECT_REF: 458 case ARGI_DEVICE_REF: 459 460 switch (ArgOp->Asl.ParseOpcode) 461 { 462 case PARSEOP_LOCAL0: 463 case PARSEOP_LOCAL1: 464 case PARSEOP_LOCAL2: 465 case PARSEOP_LOCAL3: 466 case PARSEOP_LOCAL4: 467 case PARSEOP_LOCAL5: 468 case PARSEOP_LOCAL6: 469 case PARSEOP_LOCAL7: 470 471 /* TBD: implement analysis of current value (type) of the local */ 472 /* For now, just treat any local as a typematch */ 473 474 /*ThisNodeBtype = RequiredBtypes;*/ 475 break; 476 477 case PARSEOP_ARG0: 478 case PARSEOP_ARG1: 479 case PARSEOP_ARG2: 480 case PARSEOP_ARG3: 481 case PARSEOP_ARG4: 482 case PARSEOP_ARG5: 483 case PARSEOP_ARG6: 484 485 /* Hard to analyze argument types, so we won't */ 486 /* for now. Just treat any arg as a typematch */ 487 488 /* ThisNodeBtype = RequiredBtypes; */ 489 break; 490 491 case PARSEOP_DEBUG: 492 case PARSEOP_REFOF: 493 case PARSEOP_INDEX: 494 default: 495 496 break; 497 } 498 break; 499 #endif 500 case ARGI_INTEGER: 501 default: 502 503 break; 504 } 505 506 507 /* Check for a type mismatch (required versus actual) */ 508 509 CommonBtypes = ThisNodeBtype & RequiredBtypes; 510 511 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 512 { 513 if (AnIsInternalMethod (ArgOp)) 514 { 515 return (AE_OK); 516 } 517 518 /* Check a method call for a valid return value */ 519 520 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 521 RequiredBtypes, ThisNodeBtype); 522 } 523 524 /* 525 * Now check if the actual type(s) match at least one 526 * bit to the required type 527 */ 528 else if (!CommonBtypes) 529 { 530 /* No match -- this is a type mismatch error */ 531 532 AnFormatBtype (AslGbl_StringBuffer, ThisNodeBtype); 533 AnFormatBtype (AslGbl_StringBuffer2, RequiredBtypes); 534 535 snprintf (AslGbl_MsgBuffer, sizeof(AslGbl_MsgBuffer), "[%s] found, %s operator requires [%s]", 536 AslGbl_StringBuffer, OpInfo->Name, AslGbl_StringBuffer2); 537 538 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, 539 ArgOp, AslGbl_MsgBuffer); 540 } 541 542 NextArgument: 543 ArgOp = ArgOp->Asl.Next; 544 INCREMENT_ARG_LIST (RuntimeArgTypes2); 545 } 546 break; 547 548 default: 549 550 break; 551 } 552 553 return (AE_OK); 554 } 555 556 557 /******************************************************************************* 558 * 559 * FUNCTION: AnOtherSemanticAnalysisWalkBegin 560 * 561 * PARAMETERS: ASL_WALK_CALLBACK 562 * 563 * RETURN: Status 564 * 565 * DESCRIPTION: Descending callback for the analysis walk. Checks for 566 * miscellaneous issues in the code. 567 * 568 ******************************************************************************/ 569 570 ACPI_STATUS 571 AnOtherSemanticAnalysisWalkBegin ( 572 ACPI_PARSE_OBJECT *Op, 573 UINT32 Level, 574 void *Context) 575 { 576 ACPI_PARSE_OBJECT *ArgOp; 577 ACPI_PARSE_OBJECT *PrevArgOp = NULL; 578 const ACPI_OPCODE_INFO *OpInfo; 579 ACPI_NAMESPACE_NODE *Node; 580 581 582 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 583 584 585 if (OpInfo->Flags & AML_CREATE) 586 { 587 /* This group contains all of the Create Buffer Field operators */ 588 589 AnValidateCreateBufferField (Op); 590 return (AE_OK); 591 } 592 593 /* 594 * Determine if an execution class operator actually does something by 595 * checking if it has a target and/or the function return value is used. 596 * (Target is optional, so a standalone statement can actually do nothing.) 597 */ 598 if ((OpInfo->Class == AML_CLASS_EXECUTE) && 599 (OpInfo->Flags & AML_HAS_RETVAL) && 600 (!AnIsResultUsed (Op))) 601 { 602 if (OpInfo->Flags & AML_HAS_TARGET) 603 { 604 /* 605 * Find the target node, it is always the last child. If the target 606 * is not specified in the ASL, a default node of type Zero was 607 * created by the parser. 608 */ 609 ArgOp = Op->Asl.Child; 610 while (ArgOp->Asl.Next) 611 { 612 PrevArgOp = ArgOp; 613 ArgOp = ArgOp->Asl.Next; 614 } 615 616 /* Divide() is the only weird case, it has two targets */ 617 618 if (Op->Asl.AmlOpcode == AML_DIVIDE_OP) 619 { 620 if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) && 621 (PrevArgOp) && 622 (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO)) 623 { 624 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 625 Op, Op->Asl.ExternalName); 626 } 627 } 628 629 else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 630 { 631 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 632 Op, Op->Asl.ExternalName); 633 } 634 } 635 else 636 { 637 /* 638 * Has no target and the result is not used. Only a couple opcodes 639 * can have this combination. 640 */ 641 switch (Op->Asl.ParseOpcode) 642 { 643 case PARSEOP_ACQUIRE: 644 case PARSEOP_WAIT: 645 case PARSEOP_LOADTABLE: 646 647 break; 648 649 default: 650 651 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED, 652 Op, Op->Asl.ExternalName); 653 break; 654 } 655 } 656 } 657 658 /* 659 * Semantic checks for individual ASL operators 660 */ 661 662 switch (Op->Asl.ParseOpcode) 663 { 664 case PARSEOP_STORE: 665 666 if (AslGbl_DoTypechecking) 667 { 668 AnAnalyzeStoreOperator (Op); 669 } 670 break; 671 672 673 case PARSEOP_ACQUIRE: 674 case PARSEOP_WAIT: 675 /* 676 * Emit a warning if the timeout parameter for these operators is not 677 * ACPI_WAIT_FOREVER, and the result value from the operator is not 678 * checked, meaning that a timeout could happen, but the code 679 * would not know about it. 680 */ 681 682 /* First child is the namepath, 2nd child is timeout */ 683 684 ArgOp = Op->Asl.Child; 685 ArgOp = ArgOp->Asl.Next; 686 687 /* 688 * Check for the WAIT_FOREVER case - defined by the ACPI spec to be 689 * 0xFFFF or greater 690 */ 691 if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) || 692 (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)) && 693 (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER)) 694 { 695 break; 696 } 697 698 /* 699 * The operation could timeout. If the return value is not used 700 * (indicates timeout occurred), issue a warning 701 */ 702 if (!AnIsResultUsed (Op)) 703 { 704 AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp, 705 Op->Asl.ExternalName); 706 } 707 break; 708 709 case PARSEOP_CONNECTION: 710 /* 711 * Ensure that the referenced operation region has the correct SPACE_ID. 712 * From the grammar/parser, we know the parent is a FIELD definition. 713 */ 714 ArgOp = Op->Asl.Parent; /* Field definition */ 715 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */ 716 Node = ArgOp->Asl.Node; /* OpRegion namespace node */ 717 if (!Node) 718 { 719 break; 720 } 721 722 ArgOp = Node->Op; /* OpRegion definition */ 723 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */ 724 ArgOp = ArgOp->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ 725 726 /* 727 * The Connection() operator is only valid for the following operation 728 * region SpaceIds: GeneralPurposeIo and GenericSerialBus. 729 */ 730 if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && 731 (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) 732 { 733 AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL); 734 } 735 break; 736 737 case PARSEOP_FIELD: 738 /* 739 * Ensure that fields for GeneralPurposeIo and GenericSerialBus 740 * contain at least one Connection() operator 741 */ 742 ArgOp = Op->Asl.Child; /* 1st child is the OpRegion Name */ 743 Node = ArgOp->Asl.Node; /* OpRegion namespace node */ 744 if (!Node) 745 { 746 break; 747 } 748 749 ArgOp = Node->Op; /* OpRegion definition */ 750 ArgOp = ArgOp->Asl.Child; /* First child is the OpRegion Name */ 751 ArgOp = ArgOp->Asl.Next; /* Next peer is the SPACE_ID (what we want) */ 752 753 /* We are only interested in GeneralPurposeIo and GenericSerialBus */ 754 755 if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) && 756 (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS)) 757 { 758 break; 759 } 760 761 ArgOp = Op->Asl.Child; /* 1st child is the OpRegion Name */ 762 ArgOp = ArgOp->Asl.Next; /* AccessType */ 763 ArgOp = ArgOp->Asl.Next; /* LockRule */ 764 ArgOp = ArgOp->Asl.Next; /* UpdateRule */ 765 ArgOp = ArgOp->Asl.Next; /* Start of FieldUnitList */ 766 767 /* Walk the FieldUnitList */ 768 769 while (ArgOp) 770 { 771 if (ArgOp->Asl.ParseOpcode == PARSEOP_CONNECTION) 772 { 773 break; 774 } 775 else if (ArgOp->Asl.ParseOpcode == PARSEOP_NAMESEG) 776 { 777 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgOp, NULL); 778 break; 779 } 780 781 ArgOp = ArgOp->Asl.Next; 782 } 783 break; 784 785 default: 786 787 break; 788 } 789 790 return (AE_OK); 791 } 792 793 794 /******************************************************************************* 795 * 796 * FUNCTION: AnValidateCreateBufferField 797 * 798 * PARAMETERS: Op - A create buffer field operator 799 * 800 * RETURN: None 801 * 802 * DESCRIPTION: Check if a buffer index argument to a create buffer field 803 * operation is beyond the end of the target buffer. 804 * 805 * Validates these AML operators: 806 * 807 * AML_CREATE_FIELD_OP 808 * AML_CREATE_BIT_FIELD_OP 809 * AML_CREATE_BYTE_FIELD_OP 810 * AML_CREATE_WORD_FIELD_OP 811 * AML_CREATE_DWORD_FIELD_OP 812 * AML_CREATE_QWORD_FIELD_OP 813 * 814 * There are two conditions that must be satisfied in order to enable 815 * validation at compile time: 816 * 817 * 1) The length of the target buffer must be an integer constant 818 * 2) The index specified in the create* must be an integer constant 819 * 3) For CreateField, the bit length argument must be non-zero. 820 * 821 ******************************************************************************/ 822 823 static void 824 AnValidateCreateBufferField ( 825 ACPI_PARSE_OBJECT *CreateBufferFieldOp) 826 { 827 ACPI_PARSE_OBJECT *TargetBufferOp; 828 ACPI_PARSE_OBJECT *ArgOp; 829 UINT32 TargetBufferLength; 830 UINT32 LastFieldByteIndex; 831 832 833 /* 834 * 1) Get the length of the target buffer 835 */ 836 ArgOp = CreateBufferFieldOp->Asl.Child; /* Reference to target buffer */ 837 838 /* 839 * If no attached Node, the target buffer may be something like an 840 * ArgX or LocalX and cannot be evaluated at compile time. 841 */ 842 if (!ArgOp->Asl.Node) 843 { 844 return; 845 } 846 847 TargetBufferOp = ArgOp->Asl.Node->Op; 848 TargetBufferOp = TargetBufferOp->Asl.Child; /* Target buffer */ 849 TargetBufferOp = TargetBufferOp->Asl.Next; /* "Buffer" keyword */ 850 if (!TargetBufferOp) 851 { 852 /* Not a statement of the form NAME(XXXX, Buffer.... */ 853 854 return; 855 } 856 857 /* Get the buffer length argument. It must be an integer constant */ 858 859 ArgOp = TargetBufferOp->Asl.Child; 860 if (!AnIsValidBufferConstant (ArgOp)) 861 { 862 return; 863 } 864 865 TargetBufferLength = (UINT32) ArgOp->Asl.Value.Integer; 866 867 /* 868 * 2) Get the value of the buffer index argument. It must be 869 * an integer constant. 870 */ 871 ArgOp = CreateBufferFieldOp->Asl.Child; /* Reference to target buffer */ 872 ArgOp = ArgOp->Asl.Next; /* Buffer Index argument*/ 873 if (!AnIsValidBufferConstant (ArgOp)) 874 { 875 return; 876 } 877 878 LastFieldByteIndex = 879 (UINT32) ArgOp->Asl.Value.Integer; /* Index can be in either bytes or bits */ 880 881 /* 882 * 3) Get the length of the new buffer field, in bytes. Also, 883 * create the final target buffer index for the last byte of the field 884 */ 885 switch (CreateBufferFieldOp->Asl.ParseOpcode) 886 { 887 case PARSEOP_CREATEBITFIELD: /* A one bit field */ 888 889 LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex); 890 break; 891 892 case PARSEOP_CREATEBYTEFIELD: 893 break; 894 895 case PARSEOP_CREATEWORDFIELD: 896 897 LastFieldByteIndex += (sizeof (UINT16) - 1); 898 break; 899 900 case PARSEOP_CREATEDWORDFIELD: 901 902 LastFieldByteIndex += (sizeof (UINT32) - 1); 903 break; 904 905 case PARSEOP_CREATEQWORDFIELD: 906 907 LastFieldByteIndex += (sizeof (UINT64) - 1); 908 break; 909 910 case PARSEOP_CREATEFIELD: /* Multi-bit field */ 911 912 ArgOp = ArgOp->Asl.Next; /* Length argument, in bits */ 913 if (!AnIsValidBufferConstant (ArgOp)) 914 { 915 return; 916 } 917 918 /* The buffer field length is not allowed to be zero */ 919 920 if (ArgOp->Asl.Value.Integer == 0) 921 { 922 AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_LENGTH, ArgOp, NULL); 923 return; 924 } 925 926 LastFieldByteIndex += 927 ((UINT32) ArgOp->Asl.Value.Integer - 1); /* Create final bit index */ 928 929 /* Convert bit index to a byte index */ 930 931 LastFieldByteIndex = ACPI_ROUND_BITS_DOWN_TO_BYTES (LastFieldByteIndex); 932 break; 933 934 default: 935 return; 936 } 937 938 /* 939 * 4) Check for an access (index) beyond the end of the target buffer, 940 * or a zero length target buffer. 941 */ 942 if (!TargetBufferLength || (LastFieldByteIndex >= TargetBufferLength)) 943 { 944 AslError (ASL_WARNING, ASL_MSG_BUFFER_FIELD_OVERFLOW, ArgOp, NULL); 945 } 946 } 947 948 949 /******************************************************************************* 950 * 951 * FUNCTION: AnIsValidBufferConstant 952 * 953 * PARAMETERS: Op - A buffer-related operand 954 * 955 * RETURN: TRUE if operand is valid constant, FALSE otherwise 956 * 957 * DESCRIPTION: Check if the input Op is valid constant that can be used 958 * in compile-time analysis. 959 * 960 ******************************************************************************/ 961 962 static BOOLEAN 963 AnIsValidBufferConstant ( 964 ACPI_PARSE_OBJECT *Op) 965 { 966 if (!Op) 967 { 968 return (FALSE); 969 } 970 971 if ((Op->Asl.ParseOpcode == PARSEOP_INTEGER) || 972 (Op->Asl.ParseOpcode == PARSEOP_ZERO) || 973 (Op->Asl.ParseOpcode == PARSEOP_ONE)) 974 { 975 return (TRUE); 976 } 977 978 return (FALSE); 979 } 980 981 982 /******************************************************************************* 983 * 984 * FUNCTION: AnAnalyzeStoreOperator 985 * 986 * PARAMETERS: Op - Store() operator 987 * 988 * RETURN: None 989 * 990 * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package 991 * objects where there are more restrictions than other data 992 * types. 993 * 994 ******************************************************************************/ 995 996 static void 997 AnAnalyzeStoreOperator ( 998 ACPI_PARSE_OBJECT *Op) 999 { 1000 ACPI_NAMESPACE_NODE *SourceNode; 1001 ACPI_NAMESPACE_NODE *TargetNode; 1002 ACPI_PARSE_OBJECT *SourceOperandOp; 1003 ACPI_PARSE_OBJECT *TargetOperandOp; 1004 UINT32 SourceOperandBtype; 1005 UINT32 TargetOperandBtype; 1006 1007 1008 /* Extract the two operands for STORE */ 1009 1010 SourceOperandOp = Op->Asl.Child; 1011 TargetOperandOp = SourceOperandOp->Asl.Next; 1012 1013 /* 1014 * Ignore these Source operand opcodes, they cannot be typechecked, 1015 * the actual result is unknown here. 1016 */ 1017 switch (SourceOperandOp->Asl.ParseOpcode) 1018 { 1019 /* For these, type of the returned value is unknown at compile time */ 1020 1021 case PARSEOP_DEREFOF: 1022 case PARSEOP_METHODCALL: 1023 case PARSEOP_STORE: 1024 case PARSEOP_COPYOBJECT: 1025 1026 return; 1027 1028 case PARSEOP_INDEX: 1029 case PARSEOP_REFOF: 1030 1031 if (!AslGbl_EnableReferenceTypechecking) 1032 { 1033 return; 1034 } 1035 1036 /* 1037 * These opcodes always return an object reference, and thus 1038 * the result can only be stored to a Local, Arg, or Debug. 1039 */ 1040 if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP) 1041 { 1042 return; 1043 } 1044 1045 if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) || 1046 (TargetOperandOp->Asl.AmlOpcode > AML_ARG6)) 1047 { 1048 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp, 1049 "Source [Reference], Target must be [Local/Arg/Debug]"); 1050 } 1051 return; 1052 1053 default: 1054 break; 1055 } 1056 1057 /* 1058 * Ignore these Target operand opcodes, they cannot be typechecked 1059 */ 1060 switch (TargetOperandOp->Asl.ParseOpcode) 1061 { 1062 case PARSEOP_DEBUG: 1063 case PARSEOP_DEREFOF: 1064 case PARSEOP_REFOF: 1065 case PARSEOP_INDEX: 1066 case PARSEOP_STORE: 1067 1068 return; 1069 1070 default: 1071 break; 1072 } 1073 1074 /* 1075 * Ignore typecheck for External() operands of type "UnknownObj", 1076 * we don't know the actual type (source or target). 1077 */ 1078 SourceNode = SourceOperandOp->Asl.Node; 1079 if (SourceNode && 1080 (SourceNode->Flags & ANOBJ_IS_EXTERNAL) && 1081 (SourceNode->Type == ACPI_TYPE_ANY)) 1082 { 1083 return; 1084 } 1085 1086 TargetNode = TargetOperandOp->Asl.Node; 1087 if (TargetNode && 1088 (TargetNode->Flags & ANOBJ_IS_EXTERNAL) && 1089 (TargetNode->Type == ACPI_TYPE_ANY)) 1090 { 1091 return; 1092 } 1093 1094 /* 1095 * A NULL node with a namepath AML opcode indicates non-existent 1096 * name. Just return, the error message is generated elsewhere. 1097 */ 1098 if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) || 1099 (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP))) 1100 { 1101 return; 1102 } 1103 1104 /* 1105 * Simple check for source same as target via NS node. 1106 * -- Could be expanded to locals and args. 1107 */ 1108 if (SourceNode && TargetNode) 1109 { 1110 if (SourceNode == TargetNode) 1111 { 1112 AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM, 1113 TargetOperandOp, "Source is the same as Target"); 1114 return; 1115 } 1116 } 1117 1118 /* Ignore typecheck if either source or target is a local or arg */ 1119 1120 if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) && 1121 (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6)) 1122 { 1123 return; /* Cannot type a local/arg at compile time */ 1124 } 1125 1126 if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) && 1127 (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6)) 1128 { 1129 return; /* Cannot type a local/arg at compile time */ 1130 } 1131 1132 /* 1133 * Package objects are a special case because they cannot by implicitly 1134 * converted to/from anything. Check for these two illegal cases: 1135 * 1136 * Store (non-package, package) 1137 * Store (package, non-package) 1138 */ 1139 SourceOperandBtype = AnGetBtype (SourceOperandOp); 1140 TargetOperandBtype = AnGetBtype (TargetOperandOp); 1141 1142 /* Check source first for (package, non-package) case */ 1143 1144 if (SourceOperandBtype & ACPI_BTYPE_PACKAGE) 1145 { 1146 /* If Source is PACKAGE-->Target must be PACKAGE */ 1147 1148 if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE)) 1149 { 1150 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp, 1151 "Source is [Package], Target must be a package also"); 1152 } 1153 } 1154 1155 /* Else check target for (non-package, package) case */ 1156 1157 else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE) 1158 { 1159 /* If Target is PACKAGE, Source must be PACKAGE */ 1160 1161 if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE)) 1162 { 1163 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp, 1164 "Target is [Package], Source must be a package also"); 1165 } 1166 } 1167 } 1168