1 /****************************************************************************** 2 * 3 * Module Name: aslfold - Constant folding 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 #include "aslcompiler.h" 45 #include "aslcompiler.y.h" 46 #include "amlcode.h" 47 48 #include "acdispat.h" 49 #include "acparser.h" 50 51 #define _COMPONENT ACPI_COMPILER 52 ACPI_MODULE_NAME ("aslfold") 53 54 /* Local prototypes */ 55 56 static ACPI_STATUS 57 OpcAmlEvaluationWalk1 ( 58 ACPI_PARSE_OBJECT *Op, 59 UINT32 Level, 60 void *Context); 61 62 static ACPI_STATUS 63 OpcAmlEvaluationWalk2 ( 64 ACPI_PARSE_OBJECT *Op, 65 UINT32 Level, 66 void *Context); 67 68 static ACPI_STATUS 69 OpcAmlCheckForConstant ( 70 ACPI_PARSE_OBJECT *Op, 71 UINT32 Level, 72 void *Context); 73 74 static void 75 OpcUpdateIntegerNode ( 76 ACPI_PARSE_OBJECT *Op, 77 UINT64 Value); 78 79 static ACPI_STATUS 80 TrTransformToStoreOp ( 81 ACPI_PARSE_OBJECT *Op, 82 ACPI_WALK_STATE *WalkState); 83 84 static ACPI_STATUS 85 TrSimpleConstantReduction ( 86 ACPI_PARSE_OBJECT *Op, 87 ACPI_WALK_STATE *WalkState); 88 89 static void 90 TrInstallReducedConstant ( 91 ACPI_PARSE_OBJECT *Op, 92 ACPI_OPERAND_OBJECT *ObjDesc); 93 94 95 /******************************************************************************* 96 * 97 * FUNCTION: OpcAmlConstantWalk 98 * 99 * PARAMETERS: ASL_WALK_CALLBACK 100 * 101 * RETURN: Status 102 * 103 * DESCRIPTION: Reduce an Op and its subtree to a constant if possible. 104 * 105 ******************************************************************************/ 106 107 ACPI_STATUS 108 OpcAmlConstantWalk ( 109 ACPI_PARSE_OBJECT *Op, 110 UINT32 Level, 111 void *Context) 112 { 113 ACPI_WALK_STATE *WalkState; 114 ACPI_STATUS Status = AE_OK; 115 116 117 if (Op->Asl.CompileFlags == 0) 118 { 119 return (AE_OK); 120 } 121 122 /* 123 * Only interested in subtrees that could possibly contain 124 * expressions that can be evaluated at this time 125 */ 126 if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) || 127 (Op->Asl.CompileFlags & NODE_IS_TARGET)) 128 { 129 return (AE_OK); 130 } 131 132 /* Create a new walk state */ 133 134 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 135 if (!WalkState) 136 { 137 return (AE_NO_MEMORY); 138 } 139 140 WalkState->NextOp = NULL; 141 WalkState->Params = NULL; 142 143 /* 144 * Examine the entire subtree -- all nodes must be constants 145 * or type 3/4/5 opcodes 146 */ 147 Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD, 148 OpcAmlCheckForConstant, NULL, WalkState); 149 150 /* 151 * Did we find an entire subtree that contains all constants 152 * and type 3/4/5 opcodes? 153 */ 154 switch (Status) 155 { 156 case AE_OK: 157 158 /* Simple case, like Add(3,4) -> 7 */ 159 160 Status = TrSimpleConstantReduction (Op, WalkState); 161 break; 162 163 case AE_CTRL_RETURN_VALUE: 164 165 /* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */ 166 167 Status = TrTransformToStoreOp (Op, WalkState); 168 break; 169 170 case AE_TYPE: 171 172 AcpiDsDeleteWalkState (WalkState); 173 return (AE_OK); 174 175 default: 176 AcpiDsDeleteWalkState (WalkState); 177 break; 178 } 179 180 if (ACPI_FAILURE (Status)) 181 { 182 DbgPrint (ASL_PARSE_OUTPUT, "Cannot resolve, %s\n", 183 AcpiFormatException (Status)); 184 185 /* We could not resolve the subtree for some reason */ 186 187 AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op, 188 (char *) AcpiFormatException (Status)); 189 190 /* Set the subtree value to ZERO anyway. Eliminates further errors */ 191 192 OpcUpdateIntegerNode (Op, 0); 193 } 194 195 /* Abort the walk of this subtree, we are done with it */ 196 197 return (AE_CTRL_DEPTH); 198 } 199 200 201 /******************************************************************************* 202 * 203 * FUNCTION: OpcAmlCheckForConstant 204 * 205 * PARAMETERS: ASL_WALK_CALLBACK 206 * 207 * RETURN: Status 208 * 209 * DESCRIPTION: Check one Op for a reducible type 3/4/5 AML opcode. 210 * This is performed via a downward walk of the parse subtree. 211 * 212 ******************************************************************************/ 213 214 static ACPI_STATUS 215 OpcAmlCheckForConstant ( 216 ACPI_PARSE_OBJECT *Op, 217 UINT32 Level, 218 void *Context) 219 { 220 ACPI_WALK_STATE *WalkState = Context; 221 ACPI_STATUS Status = AE_OK; 222 ACPI_PARSE_OBJECT *NextOp; 223 const ACPI_OPCODE_INFO *OpInfo; 224 225 226 WalkState->Op = Op; 227 WalkState->Opcode = Op->Common.AmlOpcode; 228 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 229 230 DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ", 231 Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName); 232 233 /* 234 * These opcodes do not appear in the OpcodeInfo table, but 235 * they represent constants, so abort the constant walk now. 236 */ 237 if ((WalkState->Opcode == AML_RAW_DATA_BYTE) || 238 (WalkState->Opcode == AML_RAW_DATA_WORD) || 239 (WalkState->Opcode == AML_RAW_DATA_DWORD) || 240 (WalkState->Opcode == AML_RAW_DATA_QWORD)) 241 { 242 DbgPrint (ASL_PARSE_OUTPUT, "RAW DATA"); 243 Status = AE_TYPE; 244 goto CleanupAndExit; 245 } 246 247 /* 248 * Search upwards for a possible Name() operator. This is done 249 * because a type 3/4/5 opcode within a Name() expression 250 * MUST be reduced to a simple constant. 251 */ 252 NextOp = Op->Asl.Parent; 253 while (NextOp) 254 { 255 /* Finished if we find a Name() opcode */ 256 257 if (NextOp->Asl.AmlOpcode == AML_NAME_OP) 258 { 259 break; 260 } 261 262 /* 263 * Any "deferred" opcodes contain one or more TermArg parameters, 264 * and thus are not required to be folded to constants at compile 265 * time. This affects things like Buffer() and Package() objects. 266 * We just ignore them here. However, any sub-expressions can and 267 * will still be typechecked. Note: These are called the 268 * "deferred" opcodes in the AML interpreter. 269 */ 270 OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode); 271 if (OpInfo->Flags & AML_DEFER) 272 { 273 NextOp = NULL; 274 break; 275 } 276 277 NextOp = NextOp->Asl.Parent; 278 } 279 280 /* Type 3/4/5 opcodes have the AML_CONSTANT flag set */ 281 282 if (!(WalkState->OpInfo->Flags & AML_CONSTANT)) 283 { 284 /* 285 * From the ACPI specification: 286 * 287 * "The Type 3/4/5 opcodes return a value and can be used in an 288 * expression that evaluates to a constant. These opcodes may be 289 * evaluated at ASL compile-time. To ensure that these opcodes 290 * will evaluate to a constant, the following rules apply: The 291 * term cannot have a destination (target) operand, and must have 292 * either a Type3Opcode, Type4Opcode, Type5Opcode, ConstExprTerm, 293 * Integer, BufferTerm, Package, or String for all arguments." 294 */ 295 296 /* 297 * The value (second) operand for the Name() operator MUST 298 * reduce to a single constant, as per the ACPI specification 299 * (the operand is a DataObject). This also implies that there 300 * can be no target operand. Name() is the only ASL operator 301 * with a "DataObject" as an operand and is thus special- 302 * cased here. 303 */ 304 if (NextOp) /* Inspect a Name() operator */ 305 { 306 /* Error if there is a target operand */ 307 308 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 309 { 310 AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op, NULL); 311 Status = AE_TYPE; 312 } 313 314 /* Error if expression cannot be reduced (folded) */ 315 316 if (!(NextOp->Asl.CompileFlags & NODE_COULD_NOT_REDUCE)) 317 { 318 /* Ensure only one error message per statement */ 319 320 NextOp->Asl.CompileFlags |= NODE_COULD_NOT_REDUCE; 321 DbgPrint (ASL_PARSE_OUTPUT, 322 "**** Could not reduce operands for NAME opcode ****\n"); 323 324 AslError (ASL_ERROR, ASL_MSG_CONSTANT_REQUIRED, Op, 325 "Constant is required for Name operator"); 326 Status = AE_TYPE; 327 } 328 } 329 330 if (ACPI_FAILURE (Status)) 331 { 332 goto CleanupAndExit; 333 } 334 335 /* This is not a 3/4/5 opcode, but maybe can convert to STORE */ 336 337 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 338 { 339 DbgPrint (ASL_PARSE_OUTPUT, 340 "**** Valid Target, transform to Store ****\n"); 341 return (AE_CTRL_RETURN_VALUE); 342 } 343 344 /* Expression cannot be reduced */ 345 346 DbgPrint (ASL_PARSE_OUTPUT, 347 "**** Not a Type 3/4/5 opcode or cannot reduce/fold (%s) ****\n", 348 Op->Asl.ParseOpName); 349 350 Status = AE_TYPE; 351 goto CleanupAndExit; 352 } 353 354 /* 355 * TBD: Ignore buffer constants for now. The problem is that these 356 * constants have been transformed into RAW_DATA at this point, from 357 * the parse tree transform process which currently happens before 358 * the constant folding process. We may need to defer this transform 359 * for buffer until after the constant folding. 360 */ 361 if (WalkState->Opcode == AML_BUFFER_OP) 362 { 363 DbgPrint (ASL_PARSE_OUTPUT, 364 "\nBuffer constant reduction is not supported yet\n"); 365 366 if (NextOp) /* Found a Name() operator, error */ 367 { 368 AslError (ASL_ERROR, ASL_MSG_UNSUPPORTED, Op, 369 "Buffer expression cannot be reduced"); 370 } 371 372 Status = AE_TYPE; 373 goto CleanupAndExit; 374 } 375 376 377 /* Debug output */ 378 379 DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345"); 380 381 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 382 { 383 if (Op->Asl.ParseOpcode == PARSEOP_ZERO) 384 { 385 DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " NULL TARGET"); 386 } 387 else 388 { 389 DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " VALID TARGET"); 390 } 391 } 392 393 if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG) 394 { 395 DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " TERMARG"); 396 } 397 398 CleanupAndExit: 399 400 /* Dump the node compile flags also */ 401 402 TrPrintNodeCompileFlags (Op->Asl.CompileFlags); 403 DbgPrint (ASL_PARSE_OUTPUT, "\n"); 404 return (Status); 405 } 406 407 408 /******************************************************************************* 409 * 410 * FUNCTION: TrSimpleConstantReduction 411 * 412 * PARAMETERS: Op - Parent operator to be transformed 413 * WalkState - Current walk state 414 * 415 * RETURN: Status 416 * 417 * DESCRIPTION: Reduce an entire AML operation to a single constant. The 418 * operation must not have a target operand. 419 * 420 * Add (32,64) --> 96 421 * 422 ******************************************************************************/ 423 424 static ACPI_STATUS 425 TrSimpleConstantReduction ( 426 ACPI_PARSE_OBJECT *Op, 427 ACPI_WALK_STATE *WalkState) 428 { 429 ACPI_PARSE_OBJECT *RootOp; 430 ACPI_PARSE_OBJECT *OriginalParentOp; 431 ACPI_OPERAND_OBJECT *ObjDesc; 432 ACPI_STATUS Status; 433 434 435 DbgPrint (ASL_PARSE_OUTPUT, 436 "Simple subtree constant reduction, operator to constant\n"); 437 438 /* Allocate a new temporary root for this subtree */ 439 440 RootOp = TrAllocateNode (PARSEOP_INTEGER); 441 if (!RootOp) 442 { 443 return (AE_NO_MEMORY); 444 } 445 446 RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP; 447 448 OriginalParentOp = Op->Common.Parent; 449 Op->Common.Parent = RootOp; 450 451 /* Hand off the subtree to the AML interpreter */ 452 453 WalkState->CallerReturnDesc = &ObjDesc; 454 455 Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE, 456 OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState); 457 458 /* Restore original parse tree */ 459 460 Op->Common.Parent = OriginalParentOp; 461 462 if (ACPI_FAILURE (Status)) 463 { 464 DbgPrint (ASL_PARSE_OUTPUT, 465 "Constant Subtree evaluation(1), %s\n", 466 AcpiFormatException (Status)); 467 return (Status); 468 } 469 470 /* Get the final result */ 471 472 Status = AcpiDsResultPop (&ObjDesc, WalkState); 473 if (ACPI_FAILURE (Status)) 474 { 475 DbgPrint (ASL_PARSE_OUTPUT, 476 "Constant Subtree evaluation(2), %s\n", 477 AcpiFormatException (Status)); 478 return (Status); 479 } 480 481 /* Disconnect any existing children, install new constant */ 482 483 Op->Asl.Child = NULL; 484 TrInstallReducedConstant (Op, ObjDesc); 485 486 UtSetParseOpName (Op); 487 return (AE_OK); 488 } 489 490 491 /******************************************************************************* 492 * 493 * FUNCTION: TrTransformToStoreOp 494 * 495 * PARAMETERS: Op - Parent operator to be transformed 496 * WalkState - Current walk state 497 * 498 * RETURN: Status 499 * 500 * DESCRIPTION: Transforms a single AML operation with a constant and target 501 * to a simple store operation: 502 * 503 * Add (32,64,DATA) --> Store (96,DATA) 504 * 505 ******************************************************************************/ 506 507 static ACPI_STATUS 508 TrTransformToStoreOp ( 509 ACPI_PARSE_OBJECT *Op, 510 ACPI_WALK_STATE *WalkState) 511 { 512 ACPI_PARSE_OBJECT *OriginalTarget; 513 ACPI_PARSE_OBJECT *NewTarget; 514 ACPI_PARSE_OBJECT *Child1; 515 ACPI_PARSE_OBJECT *Child2; 516 ACPI_OPERAND_OBJECT *ObjDesc; 517 ACPI_PARSE_OBJECT *NewParent; 518 ACPI_PARSE_OBJECT *OriginalParent; 519 ACPI_STATUS Status; 520 521 522 DbgPrint (ASL_PARSE_OUTPUT, 523 "Reduction/Transform to StoreOp: Store(Constant, Target)\n"); 524 525 /* Extract the operands */ 526 527 Child1 = Op->Asl.Child; 528 Child2 = Child1->Asl.Next; 529 530 /* 531 * Special case for DIVIDE -- it has two targets. The first 532 * is for the remainder and if present, we will not attempt 533 * to reduce the expression. 534 */ 535 if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE) 536 { 537 Child2 = Child2->Asl.Next; 538 if (Child2->Asl.ParseOpcode != PARSEOP_ZERO) 539 { 540 DbgPrint (ASL_PARSE_OUTPUT, 541 "Cannot reduce DIVIDE - has two targets\n\n"); 542 return (AE_OK); 543 } 544 } 545 546 /* 547 * Create a NULL (zero) target so that we can use the 548 * interpreter to evaluate the expression. 549 */ 550 NewTarget = TrCreateNullTarget (); 551 NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP; 552 553 /* Handle one-operand cases (NOT, TOBCD, etc.) */ 554 555 if (!Child2->Asl.Next) 556 { 557 Child2 = Child1; 558 } 559 560 /* Link in new NULL target as the last operand */ 561 562 OriginalTarget = Child2->Asl.Next; 563 Child2->Asl.Next = NewTarget; 564 NewTarget->Asl.Parent = OriginalTarget->Asl.Parent; 565 566 NewParent = TrAllocateNode (PARSEOP_INTEGER); 567 NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP; 568 569 OriginalParent = Op->Common.Parent; 570 Op->Common.Parent = NewParent; 571 572 /* Hand off the subtree to the AML interpreter */ 573 574 WalkState->CallerReturnDesc = &ObjDesc; 575 576 Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE, 577 OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState); 578 if (ACPI_FAILURE (Status)) 579 { 580 DbgPrint (ASL_PARSE_OUTPUT, 581 "Constant Subtree evaluation(3), %s\n", 582 AcpiFormatException (Status)); 583 goto EvalError; 584 } 585 586 /* Get the final result */ 587 588 Status = AcpiDsResultPop (&ObjDesc, WalkState); 589 if (ACPI_FAILURE (Status)) 590 { 591 DbgPrint (ASL_PARSE_OUTPUT, 592 "Constant Subtree evaluation(4), %s\n", 593 AcpiFormatException (Status)); 594 goto EvalError; 595 } 596 597 /* Truncate any subtree expressions, they have been evaluated */ 598 599 Child1->Asl.Child = NULL; 600 601 /* Folded constant is in ObjDesc, store into Child1 */ 602 603 TrInstallReducedConstant (Child1, ObjDesc); 604 605 /* Convert operator to STORE */ 606 607 Op->Asl.ParseOpcode = PARSEOP_STORE; 608 Op->Asl.AmlOpcode = AML_STORE_OP; 609 UtSetParseOpName (Op); 610 Op->Common.Parent = OriginalParent; 611 612 /* First child is the folded constant */ 613 614 /* Second child will be the target */ 615 616 Child1->Asl.Next = OriginalTarget; 617 return (AE_OK); 618 619 620 EvalError: 621 622 /* Restore original links */ 623 624 Op->Common.Parent = OriginalParent; 625 Child2->Asl.Next = OriginalTarget; 626 return (Status); 627 } 628 629 630 /******************************************************************************* 631 * 632 * FUNCTION: TrInstallReducedConstant 633 * 634 * PARAMETERS: Op - Parent operator to be transformed 635 * ObjDesc - Reduced constant to be installed 636 * 637 * RETURN: None 638 * 639 * DESCRIPTION: Transform the original operator to a simple constant. 640 * Handles Integers, Strings, and Buffers. 641 * 642 ******************************************************************************/ 643 644 static void 645 TrInstallReducedConstant ( 646 ACPI_PARSE_OBJECT *Op, 647 ACPI_OPERAND_OBJECT *ObjDesc) 648 { 649 ACPI_PARSE_OBJECT *LengthOp; 650 ACPI_PARSE_OBJECT *DataOp; 651 652 653 TotalFolds++; 654 AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op, 655 Op->Asl.ParseOpName); 656 657 /* 658 * Because we know we executed type 3/4/5 opcodes above, we know that 659 * the result must be either an Integer, String, or Buffer. 660 */ 661 switch (ObjDesc->Common.Type) 662 { 663 case ACPI_TYPE_INTEGER: 664 665 OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value); 666 667 DbgPrint (ASL_PARSE_OUTPUT, 668 "Constant expression reduced to (%s) %8.8X%8.8X\n\n", 669 Op->Asl.ParseOpName, 670 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer)); 671 break; 672 673 case ACPI_TYPE_STRING: 674 675 Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; 676 Op->Common.AmlOpcode = AML_STRING_OP; 677 Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1; 678 Op->Common.Value.String = ObjDesc->String.Pointer; 679 680 DbgPrint (ASL_PARSE_OUTPUT, 681 "Constant expression reduced to (STRING) %s\n\n", 682 Op->Common.Value.String); 683 break; 684 685 case ACPI_TYPE_BUFFER: 686 /* 687 * Create a new parse subtree of the form: 688 * 689 * BUFFER (Buffer AML opcode) 690 * INTEGER (Buffer length in bytes) 691 * RAW_DATA (Buffer byte data) 692 */ 693 Op->Asl.ParseOpcode = PARSEOP_BUFFER; 694 Op->Common.AmlOpcode = AML_BUFFER_OP; 695 Op->Asl.CompileFlags = NODE_AML_PACKAGE; 696 UtSetParseOpName (Op); 697 698 /* Child node is the buffer length */ 699 700 LengthOp = TrAllocateNode (PARSEOP_INTEGER); 701 702 LengthOp->Asl.AmlOpcode = AML_DWORD_OP; 703 LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length; 704 LengthOp->Asl.Parent = Op; 705 (void) OpcSetOptimalIntegerSize (LengthOp); 706 707 Op->Asl.Child = LengthOp; 708 709 /* Next child is the raw buffer data */ 710 711 DataOp = TrAllocateNode (PARSEOP_RAW_DATA); 712 DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; 713 DataOp->Asl.AmlLength = ObjDesc->Buffer.Length; 714 DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer; 715 DataOp->Asl.Parent = Op; 716 717 LengthOp->Asl.Next = DataOp; 718 719 DbgPrint (ASL_PARSE_OUTPUT, 720 "Constant expression reduced to (BUFFER) length %X\n\n", 721 ObjDesc->Buffer.Length); 722 break; 723 724 default: 725 break; 726 } 727 } 728 729 730 /******************************************************************************* 731 * 732 * FUNCTION: OpcUpdateIntegerNode 733 * 734 * PARAMETERS: Op - Current parse object 735 * Value - Value for the integer op 736 * 737 * RETURN: None 738 * 739 * DESCRIPTION: Update node to the correct Integer type and value 740 * 741 ******************************************************************************/ 742 743 static void 744 OpcUpdateIntegerNode ( 745 ACPI_PARSE_OBJECT *Op, 746 UINT64 Value) 747 { 748 749 Op->Common.Value.Integer = Value; 750 751 /* 752 * The AmlLength is used by the parser to indicate a constant, 753 * (if non-zero). Length is either (1/2/4/8) 754 */ 755 switch (Op->Asl.AmlLength) 756 { 757 case 1: 758 759 TrUpdateNode (PARSEOP_BYTECONST, Op); 760 Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE; 761 break; 762 763 case 2: 764 765 TrUpdateNode (PARSEOP_WORDCONST, Op); 766 Op->Asl.AmlOpcode = AML_RAW_DATA_WORD; 767 break; 768 769 case 4: 770 771 TrUpdateNode (PARSEOP_DWORDCONST, Op); 772 Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD; 773 break; 774 775 case 8: 776 777 TrUpdateNode (PARSEOP_QWORDCONST, Op); 778 Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD; 779 break; 780 781 case 0: 782 default: 783 784 OpcSetOptimalIntegerSize (Op); 785 TrUpdateNode (PARSEOP_INTEGER, Op); 786 break; 787 } 788 789 Op->Asl.AmlLength = 0; 790 } 791 792 793 /******************************************************************************* 794 * 795 * FUNCTION: OpcAmlEvaluationWalk1 796 * 797 * PARAMETERS: ASL_WALK_CALLBACK 798 * 799 * RETURN: Status 800 * 801 * DESCRIPTION: Descending callback for AML execution of constant subtrees 802 * 803 ******************************************************************************/ 804 805 static ACPI_STATUS 806 OpcAmlEvaluationWalk1 ( 807 ACPI_PARSE_OBJECT *Op, 808 UINT32 Level, 809 void *Context) 810 { 811 ACPI_WALK_STATE *WalkState = Context; 812 ACPI_STATUS Status; 813 ACPI_PARSE_OBJECT *OutOp; 814 815 816 WalkState->Op = Op; 817 WalkState->Opcode = Op->Common.AmlOpcode; 818 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 819 820 /* Copy child pointer to Arg for compatibility with Interpreter */ 821 822 if (Op->Asl.Child) 823 { 824 Op->Common.Value.Arg = Op->Asl.Child; 825 } 826 827 /* Call AML dispatcher */ 828 829 Status = AcpiDsExecBeginOp (WalkState, &OutOp); 830 if (ACPI_FAILURE (Status)) 831 { 832 DbgPrint (ASL_PARSE_OUTPUT, 833 "%s Constant interpretation failed (1) - %s\n", 834 Op->Asl.ParseOpName, AcpiFormatException (Status)); 835 } 836 837 return (Status); 838 } 839 840 841 /******************************************************************************* 842 * 843 * FUNCTION: OpcAmlEvaluationWalk2 844 * 845 * PARAMETERS: ASL_WALK_CALLBACK 846 * 847 * RETURN: Status 848 * 849 * DESCRIPTION: Ascending callback for AML execution of constant subtrees 850 * 851 ******************************************************************************/ 852 853 static ACPI_STATUS 854 OpcAmlEvaluationWalk2 ( 855 ACPI_PARSE_OBJECT *Op, 856 UINT32 Level, 857 void *Context) 858 { 859 ACPI_WALK_STATE *WalkState = Context; 860 ACPI_STATUS Status; 861 862 863 WalkState->Op = Op; 864 WalkState->Opcode = Op->Common.AmlOpcode; 865 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 866 867 /* Copy child pointer to Arg for compatibility with Interpreter */ 868 869 if (Op->Asl.Child) 870 { 871 Op->Common.Value.Arg = Op->Asl.Child; 872 } 873 874 /* Call AML dispatcher */ 875 876 Status = AcpiDsExecEndOp (WalkState); 877 if (ACPI_FAILURE (Status)) 878 { 879 DbgPrint (ASL_PARSE_OUTPUT, 880 "%s: Constant interpretation failed (2) - %s\n", 881 Op->Asl.ParseOpName, AcpiFormatException (Status)); 882 } 883 884 return (Status); 885 } 886