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