1 2 /****************************************************************************** 3 * 4 * Module Name: exoparg1 - AML execution - opcodes with 1 argument 5 * 6 *****************************************************************************/ 7 8 /****************************************************************************** 9 * 10 * 1. Copyright Notice 11 * 12 * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 13 * All rights reserved. 14 * 15 * 2. License 16 * 17 * 2.1. This is your license from Intel Corp. under its intellectual property 18 * rights. You may have additional license terms from the party that provided 19 * you this software, covering your right to use that party's intellectual 20 * property rights. 21 * 22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23 * copy of the source code appearing in this file ("Covered Code") an 24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25 * base code distributed originally by Intel ("Original Intel Code") to copy, 26 * make derivatives, distribute, use and display any portion of the Covered 27 * Code in any form, with the right to sublicense such rights; and 28 * 29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30 * license (with the right to sublicense), under only those claims of Intel 31 * patents that are infringed by the Original Intel Code, to make, use, sell, 32 * offer to sell, and import the Covered Code and derivative works thereof 33 * solely to the minimum extent necessary to exercise the above copyright 34 * license, and in no event shall the patent license extend to any additions 35 * to or modifications of the Original Intel Code. No other license or right 36 * is granted directly or by implication, estoppel or otherwise; 37 * 38 * The above copyright and patent license is granted only if the following 39 * conditions are met: 40 * 41 * 3. Conditions 42 * 43 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44 * Redistribution of source code of any substantial portion of the Covered 45 * Code or modification with rights to further distribute source must include 46 * the above Copyright Notice, the above License, this list of Conditions, 47 * and the following Disclaimer and Export Compliance provision. In addition, 48 * Licensee must cause all Covered Code to which Licensee contributes to 49 * contain a file documenting the changes Licensee made to create that Covered 50 * Code and the date of any change. Licensee must include in that file the 51 * documentation of any changes made by any predecessor Licensee. Licensee 52 * must include a prominent statement that the modification is derived, 53 * directly or indirectly, from Original Intel Code. 54 * 55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56 * Redistribution of source code of any substantial portion of the Covered 57 * Code or modification without rights to further distribute source must 58 * include the following Disclaimer and Export Compliance provision in the 59 * documentation and/or other materials provided with distribution. In 60 * addition, Licensee may not authorize further sublicense of source of any 61 * portion of the Covered Code, and must include terms to the effect that the 62 * license from Licensee to its licensee is limited to the intellectual 63 * property embodied in the software Licensee provides to its licensee, and 64 * not to intellectual property embodied in modifications its licensee may 65 * make. 66 * 67 * 3.3. Redistribution of Executable. Redistribution in executable form of any 68 * substantial portion of the Covered Code or modification must reproduce the 69 * above Copyright Notice, and the following Disclaimer and Export Compliance 70 * provision in the documentation and/or other materials provided with the 71 * distribution. 72 * 73 * 3.4. Intel retains all right, title, and interest in and to the Original 74 * Intel Code. 75 * 76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77 * Intel shall be used in advertising or otherwise to promote the sale, use or 78 * other dealings in products derived from or relating to the Covered Code 79 * without prior written authorization from Intel. 80 * 81 * 4. Disclaimer and Export Compliance 82 * 83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89 * PARTICULAR PURPOSE. 90 * 91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98 * LIMITED REMEDY. 99 * 100 * 4.3. Licensee shall not export, either directly or indirectly, any of this 101 * software or system incorporating such software without first obtaining any 102 * required license or other approval from the U. S. Department of Commerce or 103 * any other agency or department of the United States Government. In the 104 * event Licensee exports any such software from the United States or 105 * re-exports any such software from a foreign destination, Licensee shall 106 * ensure that the distribution and export/re-export of the software is in 107 * compliance with all laws, regulations, orders, or other restrictions of the 108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109 * any of its subsidiaries will export/re-export any technical data, process, 110 * software, or service, directly or indirectly, to any country for which the 111 * United States government or any agency thereof requires an export license, 112 * other governmental approval, or letter of assurance, without first obtaining 113 * such license, approval or letter. 114 * 115 *****************************************************************************/ 116 117 #define __EXOPARG1_C__ 118 119 #include "acpi.h" 120 #include "accommon.h" 121 #include "acparser.h" 122 #include "acdispat.h" 123 #include "acinterp.h" 124 #include "amlcode.h" 125 #include "acnamesp.h" 126 127 128 #define _COMPONENT ACPI_EXECUTER 129 ACPI_MODULE_NAME ("exoparg1") 130 131 132 /*! 133 * Naming convention for AML interpreter execution routines. 134 * 135 * The routines that begin execution of AML opcodes are named with a common 136 * convention based upon the number of arguments, the number of target operands, 137 * and whether or not a value is returned: 138 * 139 * AcpiExOpcode_xA_yT_zR 140 * 141 * Where: 142 * 143 * xA - ARGUMENTS: The number of arguments (input operands) that are 144 * required for this opcode type (0 through 6 args). 145 * yT - TARGETS: The number of targets (output operands) that are required 146 * for this opcode type (0, 1, or 2 targets). 147 * zR - RETURN VALUE: Indicates whether this opcode type returns a value 148 * as the function return (0 or 1). 149 * 150 * The AcpiExOpcode* functions are called via the Dispatcher component with 151 * fully resolved operands. 152 !*/ 153 154 /******************************************************************************* 155 * 156 * FUNCTION: AcpiExOpcode_0A_0T_1R 157 * 158 * PARAMETERS: WalkState - Current state (contains AML opcode) 159 * 160 * RETURN: Status 161 * 162 * DESCRIPTION: Execute operator with no operands, one return value 163 * 164 ******************************************************************************/ 165 166 ACPI_STATUS 167 AcpiExOpcode_0A_0T_1R ( 168 ACPI_WALK_STATE *WalkState) 169 { 170 ACPI_STATUS Status = AE_OK; 171 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 172 173 174 ACPI_FUNCTION_TRACE_STR (ExOpcode_0A_0T_1R, 175 AcpiPsGetOpcodeName (WalkState->Opcode)); 176 177 178 /* Examine the AML opcode */ 179 180 switch (WalkState->Opcode) 181 { 182 case AML_TIMER_OP: /* Timer () */ 183 184 /* Create a return object of type Integer */ 185 186 ReturnDesc = AcpiUtCreateIntegerObject (AcpiOsGetTimer ()); 187 if (!ReturnDesc) 188 { 189 Status = AE_NO_MEMORY; 190 goto Cleanup; 191 } 192 break; 193 194 default: /* Unknown opcode */ 195 196 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 197 WalkState->Opcode)); 198 Status = AE_AML_BAD_OPCODE; 199 break; 200 } 201 202 Cleanup: 203 204 /* Delete return object on error */ 205 206 if ((ACPI_FAILURE (Status)) || WalkState->ResultObj) 207 { 208 AcpiUtRemoveReference (ReturnDesc); 209 WalkState->ResultObj = NULL; 210 } 211 else 212 { 213 /* Save the return value */ 214 215 WalkState->ResultObj = ReturnDesc; 216 } 217 218 return_ACPI_STATUS (Status); 219 } 220 221 222 /******************************************************************************* 223 * 224 * FUNCTION: AcpiExOpcode_1A_0T_0R 225 * 226 * PARAMETERS: WalkState - Current state (contains AML opcode) 227 * 228 * RETURN: Status 229 * 230 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on 231 * object stack 232 * 233 ******************************************************************************/ 234 235 ACPI_STATUS 236 AcpiExOpcode_1A_0T_0R ( 237 ACPI_WALK_STATE *WalkState) 238 { 239 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 240 ACPI_STATUS Status = AE_OK; 241 242 243 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_0R, 244 AcpiPsGetOpcodeName (WalkState->Opcode)); 245 246 247 /* Examine the AML opcode */ 248 249 switch (WalkState->Opcode) 250 { 251 case AML_RELEASE_OP: /* Release (MutexObject) */ 252 253 Status = AcpiExReleaseMutex (Operand[0], WalkState); 254 break; 255 256 257 case AML_RESET_OP: /* Reset (EventObject) */ 258 259 Status = AcpiExSystemResetEvent (Operand[0]); 260 break; 261 262 263 case AML_SIGNAL_OP: /* Signal (EventObject) */ 264 265 Status = AcpiExSystemSignalEvent (Operand[0]); 266 break; 267 268 269 case AML_SLEEP_OP: /* Sleep (MsecTime) */ 270 271 Status = AcpiExSystemDoSuspend (Operand[0]->Integer.Value); 272 break; 273 274 275 case AML_STALL_OP: /* Stall (UsecTime) */ 276 277 Status = AcpiExSystemDoStall ((UINT32) Operand[0]->Integer.Value); 278 break; 279 280 281 case AML_UNLOAD_OP: /* Unload (Handle) */ 282 283 Status = AcpiExUnloadTable (Operand[0]); 284 break; 285 286 287 default: /* Unknown opcode */ 288 289 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 290 WalkState->Opcode)); 291 Status = AE_AML_BAD_OPCODE; 292 break; 293 } 294 295 return_ACPI_STATUS (Status); 296 } 297 298 299 /******************************************************************************* 300 * 301 * FUNCTION: AcpiExOpcode_1A_1T_0R 302 * 303 * PARAMETERS: WalkState - Current state (contains AML opcode) 304 * 305 * RETURN: Status 306 * 307 * DESCRIPTION: Execute opcode with one argument, one target, and no 308 * return value. 309 * 310 ******************************************************************************/ 311 312 ACPI_STATUS 313 AcpiExOpcode_1A_1T_0R ( 314 ACPI_WALK_STATE *WalkState) 315 { 316 ACPI_STATUS Status = AE_OK; 317 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 318 319 320 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_0R, 321 AcpiPsGetOpcodeName (WalkState->Opcode)); 322 323 324 /* Examine the AML opcode */ 325 326 switch (WalkState->Opcode) 327 { 328 case AML_LOAD_OP: 329 330 Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState); 331 break; 332 333 default: /* Unknown opcode */ 334 335 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 336 WalkState->Opcode)); 337 Status = AE_AML_BAD_OPCODE; 338 goto Cleanup; 339 } 340 341 342 Cleanup: 343 344 return_ACPI_STATUS (Status); 345 } 346 347 348 /******************************************************************************* 349 * 350 * FUNCTION: AcpiExOpcode_1A_1T_1R 351 * 352 * PARAMETERS: WalkState - Current state (contains AML opcode) 353 * 354 * RETURN: Status 355 * 356 * DESCRIPTION: Execute opcode with one argument, one target, and a 357 * return value. 358 * 359 ******************************************************************************/ 360 361 ACPI_STATUS 362 AcpiExOpcode_1A_1T_1R ( 363 ACPI_WALK_STATE *WalkState) 364 { 365 ACPI_STATUS Status = AE_OK; 366 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 367 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 368 ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; 369 UINT32 Temp32; 370 UINT32 i; 371 ACPI_INTEGER PowerOfTen; 372 ACPI_INTEGER Digit; 373 374 375 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_1R, 376 AcpiPsGetOpcodeName (WalkState->Opcode)); 377 378 379 /* Examine the AML opcode */ 380 381 switch (WalkState->Opcode) 382 { 383 case AML_BIT_NOT_OP: 384 case AML_FIND_SET_LEFT_BIT_OP: 385 case AML_FIND_SET_RIGHT_BIT_OP: 386 case AML_FROM_BCD_OP: 387 case AML_TO_BCD_OP: 388 case AML_COND_REF_OF_OP: 389 390 /* Create a return object of type Integer for these opcodes */ 391 392 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 393 if (!ReturnDesc) 394 { 395 Status = AE_NO_MEMORY; 396 goto Cleanup; 397 } 398 399 switch (WalkState->Opcode) 400 { 401 case AML_BIT_NOT_OP: /* Not (Operand, Result) */ 402 403 ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value; 404 break; 405 406 407 case AML_FIND_SET_LEFT_BIT_OP: /* FindSetLeftBit (Operand, Result) */ 408 409 ReturnDesc->Integer.Value = Operand[0]->Integer.Value; 410 411 /* 412 * Acpi specification describes Integer type as a little 413 * endian unsigned value, so this boundary condition is valid. 414 */ 415 for (Temp32 = 0; ReturnDesc->Integer.Value && 416 Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) 417 { 418 ReturnDesc->Integer.Value >>= 1; 419 } 420 421 ReturnDesc->Integer.Value = Temp32; 422 break; 423 424 425 case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */ 426 427 ReturnDesc->Integer.Value = Operand[0]->Integer.Value; 428 429 /* 430 * The Acpi specification describes Integer type as a little 431 * endian unsigned value, so this boundary condition is valid. 432 */ 433 for (Temp32 = 0; ReturnDesc->Integer.Value && 434 Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) 435 { 436 ReturnDesc->Integer.Value <<= 1; 437 } 438 439 /* Since the bit position is one-based, subtract from 33 (65) */ 440 441 ReturnDesc->Integer.Value = 442 Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32; 443 break; 444 445 446 case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */ 447 448 /* 449 * The 64-bit ACPI integer can hold 16 4-bit BCD characters 450 * (if table is 32-bit, integer can hold 8 BCD characters) 451 * Convert each 4-bit BCD value 452 */ 453 PowerOfTen = 1; 454 ReturnDesc->Integer.Value = 0; 455 Digit = Operand[0]->Integer.Value; 456 457 /* Convert each BCD digit (each is one nybble wide) */ 458 459 for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) 460 { 461 /* Get the least significant 4-bit BCD digit */ 462 463 Temp32 = ((UINT32) Digit) & 0xF; 464 465 /* Check the range of the digit */ 466 467 if (Temp32 > 9) 468 { 469 ACPI_ERROR ((AE_INFO, 470 "BCD digit too large (not decimal): 0x%X", 471 Temp32)); 472 473 Status = AE_AML_NUMERIC_OVERFLOW; 474 goto Cleanup; 475 } 476 477 /* Sum the digit into the result with the current power of 10 */ 478 479 ReturnDesc->Integer.Value += 480 (((ACPI_INTEGER) Temp32) * PowerOfTen); 481 482 /* Shift to next BCD digit */ 483 484 Digit >>= 4; 485 486 /* Next power of 10 */ 487 488 PowerOfTen *= 10; 489 } 490 break; 491 492 493 case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */ 494 495 ReturnDesc->Integer.Value = 0; 496 Digit = Operand[0]->Integer.Value; 497 498 /* Each BCD digit is one nybble wide */ 499 500 for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) 501 { 502 (void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32); 503 504 /* 505 * Insert the BCD digit that resides in the 506 * remainder from above 507 */ 508 ReturnDesc->Integer.Value |= 509 (((ACPI_INTEGER) Temp32) << ACPI_MUL_4 (i)); 510 } 511 512 /* Overflow if there is any data left in Digit */ 513 514 if (Digit > 0) 515 { 516 ACPI_ERROR ((AE_INFO, 517 "Integer too large to convert to BCD: %8.8X%8.8X", 518 ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value))); 519 Status = AE_AML_NUMERIC_OVERFLOW; 520 goto Cleanup; 521 } 522 break; 523 524 525 case AML_COND_REF_OF_OP: /* CondRefOf (SourceObject, Result) */ 526 527 /* 528 * This op is a little strange because the internal return value is 529 * different than the return value stored in the result descriptor 530 * (There are really two return values) 531 */ 532 if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode) 533 { 534 /* 535 * This means that the object does not exist in the namespace, 536 * return FALSE 537 */ 538 ReturnDesc->Integer.Value = 0; 539 goto Cleanup; 540 } 541 542 /* Get the object reference, store it, and remove our reference */ 543 544 Status = AcpiExGetObjectReference (Operand[0], 545 &ReturnDesc2, WalkState); 546 if (ACPI_FAILURE (Status)) 547 { 548 goto Cleanup; 549 } 550 551 Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState); 552 AcpiUtRemoveReference (ReturnDesc2); 553 554 /* The object exists in the namespace, return TRUE */ 555 556 ReturnDesc->Integer.Value = ACPI_INTEGER_MAX; 557 goto Cleanup; 558 559 560 default: 561 /* No other opcodes get here */ 562 break; 563 } 564 break; 565 566 567 case AML_STORE_OP: /* Store (Source, Target) */ 568 569 /* 570 * A store operand is typically a number, string, buffer or lvalue 571 * Be careful about deleting the source object, 572 * since the object itself may have been stored. 573 */ 574 Status = AcpiExStore (Operand[0], Operand[1], WalkState); 575 if (ACPI_FAILURE (Status)) 576 { 577 return_ACPI_STATUS (Status); 578 } 579 580 /* It is possible that the Store already produced a return object */ 581 582 if (!WalkState->ResultObj) 583 { 584 /* 585 * Normally, we would remove a reference on the Operand[0] 586 * parameter; But since it is being used as the internal return 587 * object (meaning we would normally increment it), the two 588 * cancel out, and we simply don't do anything. 589 */ 590 WalkState->ResultObj = Operand[0]; 591 WalkState->Operands[0] = NULL; /* Prevent deletion */ 592 } 593 return_ACPI_STATUS (Status); 594 595 596 /* 597 * ACPI 2.0 Opcodes 598 */ 599 case AML_COPY_OP: /* Copy (Source, Target) */ 600 601 Status = AcpiUtCopyIobjectToIobject (Operand[0], &ReturnDesc, 602 WalkState); 603 break; 604 605 606 case AML_TO_DECSTRING_OP: /* ToDecimalString (Data, Result) */ 607 608 Status = AcpiExConvertToString (Operand[0], &ReturnDesc, 609 ACPI_EXPLICIT_CONVERT_DECIMAL); 610 if (ReturnDesc == Operand[0]) 611 { 612 /* No conversion performed, add ref to handle return value */ 613 AcpiUtAddReference (ReturnDesc); 614 } 615 break; 616 617 618 case AML_TO_HEXSTRING_OP: /* ToHexString (Data, Result) */ 619 620 Status = AcpiExConvertToString (Operand[0], &ReturnDesc, 621 ACPI_EXPLICIT_CONVERT_HEX); 622 if (ReturnDesc == Operand[0]) 623 { 624 /* No conversion performed, add ref to handle return value */ 625 AcpiUtAddReference (ReturnDesc); 626 } 627 break; 628 629 630 case AML_TO_BUFFER_OP: /* ToBuffer (Data, Result) */ 631 632 Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc); 633 if (ReturnDesc == Operand[0]) 634 { 635 /* No conversion performed, add ref to handle return value */ 636 AcpiUtAddReference (ReturnDesc); 637 } 638 break; 639 640 641 case AML_TO_INTEGER_OP: /* ToInteger (Data, Result) */ 642 643 Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc, 644 ACPI_ANY_BASE); 645 if (ReturnDesc == Operand[0]) 646 { 647 /* No conversion performed, add ref to handle return value */ 648 AcpiUtAddReference (ReturnDesc); 649 } 650 break; 651 652 653 case AML_SHIFT_LEFT_BIT_OP: /* ShiftLeftBit (Source, BitNum) */ 654 case AML_SHIFT_RIGHT_BIT_OP: /* ShiftRightBit (Source, BitNum) */ 655 656 /* These are two obsolete opcodes */ 657 658 ACPI_ERROR ((AE_INFO, 659 "%s is obsolete and not implemented", 660 AcpiPsGetOpcodeName (WalkState->Opcode))); 661 Status = AE_SUPPORT; 662 goto Cleanup; 663 664 665 default: /* Unknown opcode */ 666 667 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 668 WalkState->Opcode)); 669 Status = AE_AML_BAD_OPCODE; 670 goto Cleanup; 671 } 672 673 if (ACPI_SUCCESS (Status)) 674 { 675 /* Store the return value computed above into the target object */ 676 677 Status = AcpiExStore (ReturnDesc, Operand[1], WalkState); 678 } 679 680 681 Cleanup: 682 683 /* Delete return object on error */ 684 685 if (ACPI_FAILURE (Status)) 686 { 687 AcpiUtRemoveReference (ReturnDesc); 688 } 689 690 /* Save return object on success */ 691 692 else if (!WalkState->ResultObj) 693 { 694 WalkState->ResultObj = ReturnDesc; 695 } 696 697 return_ACPI_STATUS (Status); 698 } 699 700 701 /******************************************************************************* 702 * 703 * FUNCTION: AcpiExOpcode_1A_0T_1R 704 * 705 * PARAMETERS: WalkState - Current state (contains AML opcode) 706 * 707 * RETURN: Status 708 * 709 * DESCRIPTION: Execute opcode with one argument, no target, and a return value 710 * 711 ******************************************************************************/ 712 713 ACPI_STATUS 714 AcpiExOpcode_1A_0T_1R ( 715 ACPI_WALK_STATE *WalkState) 716 { 717 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 718 ACPI_OPERAND_OBJECT *TempDesc; 719 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 720 ACPI_STATUS Status = AE_OK; 721 UINT32 Type; 722 ACPI_INTEGER Value; 723 724 725 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R, 726 AcpiPsGetOpcodeName (WalkState->Opcode)); 727 728 729 /* Examine the AML opcode */ 730 731 switch (WalkState->Opcode) 732 { 733 case AML_LNOT_OP: /* LNot (Operand) */ 734 735 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0); 736 if (!ReturnDesc) 737 { 738 Status = AE_NO_MEMORY; 739 goto Cleanup; 740 } 741 742 /* 743 * Set result to ONES (TRUE) if Value == 0. Note: 744 * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above. 745 */ 746 if (!Operand[0]->Integer.Value) 747 { 748 ReturnDesc->Integer.Value = ACPI_INTEGER_MAX; 749 } 750 break; 751 752 753 case AML_DECREMENT_OP: /* Decrement (Operand) */ 754 case AML_INCREMENT_OP: /* Increment (Operand) */ 755 756 /* 757 * Create a new integer. Can't just get the base integer and 758 * increment it because it may be an Arg or Field. 759 */ 760 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 761 if (!ReturnDesc) 762 { 763 Status = AE_NO_MEMORY; 764 goto Cleanup; 765 } 766 767 /* 768 * Since we are expecting a Reference operand, it can be either a 769 * NS Node or an internal object. 770 */ 771 TempDesc = Operand[0]; 772 if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND) 773 { 774 /* Internal reference object - prevent deletion */ 775 776 AcpiUtAddReference (TempDesc); 777 } 778 779 /* 780 * Convert the Reference operand to an Integer (This removes a 781 * reference on the Operand[0] object) 782 * 783 * NOTE: We use LNOT_OP here in order to force resolution of the 784 * reference operand to an actual integer. 785 */ 786 Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState); 787 if (ACPI_FAILURE (Status)) 788 { 789 ACPI_EXCEPTION ((AE_INFO, Status, 790 "While resolving operands for [%s]", 791 AcpiPsGetOpcodeName (WalkState->Opcode))); 792 793 goto Cleanup; 794 } 795 796 /* 797 * TempDesc is now guaranteed to be an Integer object -- 798 * Perform the actual increment or decrement 799 */ 800 if (WalkState->Opcode == AML_INCREMENT_OP) 801 { 802 ReturnDesc->Integer.Value = TempDesc->Integer.Value +1; 803 } 804 else 805 { 806 ReturnDesc->Integer.Value = TempDesc->Integer.Value -1; 807 } 808 809 /* Finished with this Integer object */ 810 811 AcpiUtRemoveReference (TempDesc); 812 813 /* 814 * Store the result back (indirectly) through the original 815 * Reference object 816 */ 817 Status = AcpiExStore (ReturnDesc, Operand[0], WalkState); 818 break; 819 820 821 case AML_TYPE_OP: /* ObjectType (SourceObject) */ 822 823 /* 824 * Note: The operand is not resolved at this point because we want to 825 * get the associated object, not its value. For example, we don't 826 * want to resolve a FieldUnit to its value, we want the actual 827 * FieldUnit object. 828 */ 829 830 /* Get the type of the base object */ 831 832 Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL); 833 if (ACPI_FAILURE (Status)) 834 { 835 goto Cleanup; 836 } 837 838 /* Allocate a descriptor to hold the type. */ 839 840 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type); 841 if (!ReturnDesc) 842 { 843 Status = AE_NO_MEMORY; 844 goto Cleanup; 845 } 846 break; 847 848 849 case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */ 850 851 /* 852 * Note: The operand is not resolved at this point because we want to 853 * get the associated object, not its value. 854 */ 855 856 /* Get the base object */ 857 858 Status = AcpiExResolveMultiple (WalkState, 859 Operand[0], &Type, &TempDesc); 860 if (ACPI_FAILURE (Status)) 861 { 862 goto Cleanup; 863 } 864 865 /* 866 * The type of the base object must be integer, buffer, string, or 867 * package. All others are not supported. 868 * 869 * NOTE: Integer is not specifically supported by the ACPI spec, 870 * but is supported implicitly via implicit operand conversion. 871 * rather than bother with conversion, we just use the byte width 872 * global (4 or 8 bytes). 873 */ 874 switch (Type) 875 { 876 case ACPI_TYPE_INTEGER: 877 Value = AcpiGbl_IntegerByteWidth; 878 break; 879 880 case ACPI_TYPE_STRING: 881 Value = TempDesc->String.Length; 882 break; 883 884 case ACPI_TYPE_BUFFER: 885 886 /* Buffer arguments may not be evaluated at this point */ 887 888 Status = AcpiDsGetBufferArguments (TempDesc); 889 Value = TempDesc->Buffer.Length; 890 break; 891 892 case ACPI_TYPE_PACKAGE: 893 894 /* Package arguments may not be evaluated at this point */ 895 896 Status = AcpiDsGetPackageArguments (TempDesc); 897 Value = TempDesc->Package.Count; 898 break; 899 900 default: 901 ACPI_ERROR ((AE_INFO, 902 "Operand must be Buffer/Integer/String/Package - found type %s", 903 AcpiUtGetTypeName (Type))); 904 Status = AE_AML_OPERAND_TYPE; 905 goto Cleanup; 906 } 907 908 if (ACPI_FAILURE (Status)) 909 { 910 goto Cleanup; 911 } 912 913 /* 914 * Now that we have the size of the object, create a result 915 * object to hold the value 916 */ 917 ReturnDesc = AcpiUtCreateIntegerObject (Value); 918 if (!ReturnDesc) 919 { 920 Status = AE_NO_MEMORY; 921 goto Cleanup; 922 } 923 break; 924 925 926 case AML_REF_OF_OP: /* RefOf (SourceObject) */ 927 928 Status = AcpiExGetObjectReference (Operand[0], &ReturnDesc, WalkState); 929 if (ACPI_FAILURE (Status)) 930 { 931 goto Cleanup; 932 } 933 break; 934 935 936 case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */ 937 938 /* Check for a method local or argument, or standalone String */ 939 940 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) 941 { 942 TempDesc = AcpiNsGetAttachedObject ( 943 (ACPI_NAMESPACE_NODE *) Operand[0]); 944 if (TempDesc && 945 ((TempDesc->Common.Type == ACPI_TYPE_STRING) || 946 (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE))) 947 { 948 Operand[0] = TempDesc; 949 AcpiUtAddReference (TempDesc); 950 } 951 else 952 { 953 Status = AE_AML_OPERAND_TYPE; 954 goto Cleanup; 955 } 956 } 957 else 958 { 959 switch ((Operand[0])->Common.Type) 960 { 961 case ACPI_TYPE_LOCAL_REFERENCE: 962 /* 963 * This is a DerefOf (LocalX | ArgX) 964 * 965 * Must resolve/dereference the local/arg reference first 966 */ 967 switch (Operand[0]->Reference.Class) 968 { 969 case ACPI_REFCLASS_LOCAL: 970 case ACPI_REFCLASS_ARG: 971 972 /* Set Operand[0] to the value of the local/arg */ 973 974 Status = AcpiDsMethodDataGetValue ( 975 Operand[0]->Reference.Class, 976 Operand[0]->Reference.Value, 977 WalkState, &TempDesc); 978 if (ACPI_FAILURE (Status)) 979 { 980 goto Cleanup; 981 } 982 983 /* 984 * Delete our reference to the input object and 985 * point to the object just retrieved 986 */ 987 AcpiUtRemoveReference (Operand[0]); 988 Operand[0] = TempDesc; 989 break; 990 991 case ACPI_REFCLASS_REFOF: 992 993 /* Get the object to which the reference refers */ 994 995 TempDesc = Operand[0]->Reference.Object; 996 AcpiUtRemoveReference (Operand[0]); 997 Operand[0] = TempDesc; 998 break; 999 1000 default: 1001 1002 /* Must be an Index op - handled below */ 1003 break; 1004 } 1005 break; 1006 1007 case ACPI_TYPE_STRING: 1008 break; 1009 1010 default: 1011 Status = AE_AML_OPERAND_TYPE; 1012 goto Cleanup; 1013 } 1014 } 1015 1016 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED) 1017 { 1018 if ((Operand[0])->Common.Type == ACPI_TYPE_STRING) 1019 { 1020 /* 1021 * This is a DerefOf (String). The string is a reference 1022 * to a named ACPI object. 1023 * 1024 * 1) Find the owning Node 1025 * 2) Dereference the node to an actual object. Could be a 1026 * Field, so we need to resolve the node to a value. 1027 */ 1028 Status = AcpiNsGetNode (WalkState->ScopeInfo->Scope.Node, 1029 Operand[0]->String.Pointer, 1030 ACPI_NS_SEARCH_PARENT, 1031 ACPI_CAST_INDIRECT_PTR ( 1032 ACPI_NAMESPACE_NODE, &ReturnDesc)); 1033 if (ACPI_FAILURE (Status)) 1034 { 1035 goto Cleanup; 1036 } 1037 1038 Status = AcpiExResolveNodeToValue ( 1039 ACPI_CAST_INDIRECT_PTR ( 1040 ACPI_NAMESPACE_NODE, &ReturnDesc), 1041 WalkState); 1042 goto Cleanup; 1043 } 1044 } 1045 1046 /* Operand[0] may have changed from the code above */ 1047 1048 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) 1049 { 1050 /* 1051 * This is a DerefOf (ObjectReference) 1052 * Get the actual object from the Node (This is the dereference). 1053 * This case may only happen when a LocalX or ArgX is 1054 * dereferenced above. 1055 */ 1056 ReturnDesc = AcpiNsGetAttachedObject ( 1057 (ACPI_NAMESPACE_NODE *) Operand[0]); 1058 AcpiUtAddReference (ReturnDesc); 1059 } 1060 else 1061 { 1062 /* 1063 * This must be a reference object produced by either the 1064 * Index() or RefOf() operator 1065 */ 1066 switch (Operand[0]->Reference.Class) 1067 { 1068 case ACPI_REFCLASS_INDEX: 1069 1070 /* 1071 * The target type for the Index operator must be 1072 * either a Buffer or a Package 1073 */ 1074 switch (Operand[0]->Reference.TargetType) 1075 { 1076 case ACPI_TYPE_BUFFER_FIELD: 1077 1078 TempDesc = Operand[0]->Reference.Object; 1079 1080 /* 1081 * Create a new object that contains one element of the 1082 * buffer -- the element pointed to by the index. 1083 * 1084 * NOTE: index into a buffer is NOT a pointer to a 1085 * sub-buffer of the main buffer, it is only a pointer to a 1086 * single element (byte) of the buffer! 1087 * 1088 * Since we are returning the value of the buffer at the 1089 * indexed location, we don't need to add an additional 1090 * reference to the buffer itself. 1091 */ 1092 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 1093 TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]); 1094 if (!ReturnDesc) 1095 { 1096 Status = AE_NO_MEMORY; 1097 goto Cleanup; 1098 } 1099 break; 1100 1101 1102 case ACPI_TYPE_PACKAGE: 1103 1104 /* 1105 * Return the referenced element of the package. We must 1106 * add another reference to the referenced object, however. 1107 */ 1108 ReturnDesc = *(Operand[0]->Reference.Where); 1109 if (ReturnDesc) 1110 { 1111 AcpiUtAddReference (ReturnDesc); 1112 } 1113 break; 1114 1115 1116 default: 1117 1118 ACPI_ERROR ((AE_INFO, 1119 "Unknown Index TargetType %X in reference object %p", 1120 Operand[0]->Reference.TargetType, Operand[0])); 1121 Status = AE_AML_OPERAND_TYPE; 1122 goto Cleanup; 1123 } 1124 break; 1125 1126 1127 case ACPI_REFCLASS_REFOF: 1128 1129 ReturnDesc = Operand[0]->Reference.Object; 1130 1131 if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) == 1132 ACPI_DESC_TYPE_NAMED) 1133 { 1134 ReturnDesc = AcpiNsGetAttachedObject ( 1135 (ACPI_NAMESPACE_NODE *) ReturnDesc); 1136 } 1137 1138 /* Add another reference to the object! */ 1139 1140 AcpiUtAddReference (ReturnDesc); 1141 break; 1142 1143 1144 default: 1145 ACPI_ERROR ((AE_INFO, 1146 "Unknown class in reference(%p) - %2.2X", 1147 Operand[0], Operand[0]->Reference.Class)); 1148 1149 Status = AE_TYPE; 1150 goto Cleanup; 1151 } 1152 } 1153 break; 1154 1155 1156 default: 1157 1158 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 1159 WalkState->Opcode)); 1160 Status = AE_AML_BAD_OPCODE; 1161 goto Cleanup; 1162 } 1163 1164 1165 Cleanup: 1166 1167 /* Delete return object on error */ 1168 1169 if (ACPI_FAILURE (Status)) 1170 { 1171 AcpiUtRemoveReference (ReturnDesc); 1172 } 1173 1174 /* Save return object on success */ 1175 1176 else 1177 { 1178 WalkState->ResultObj = ReturnDesc; 1179 } 1180 1181 return_ACPI_STATUS (Status); 1182 } 1183 1184