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 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 187 if (!ReturnDesc) 188 { 189 Status = AE_NO_MEMORY; 190 goto Cleanup; 191 } 192 ReturnDesc->Integer.Value = AcpiOsGetTimer (); 193 break; 194 195 default: /* Unknown opcode */ 196 197 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 198 WalkState->Opcode)); 199 Status = AE_AML_BAD_OPCODE; 200 break; 201 } 202 203 Cleanup: 204 205 /* Delete return object on error */ 206 207 if ((ACPI_FAILURE (Status)) || WalkState->ResultObj) 208 { 209 AcpiUtRemoveReference (ReturnDesc); 210 WalkState->ResultObj = NULL; 211 } 212 else 213 { 214 /* Save the return value */ 215 216 WalkState->ResultObj = ReturnDesc; 217 } 218 219 return_ACPI_STATUS (Status); 220 } 221 222 223 /******************************************************************************* 224 * 225 * FUNCTION: AcpiExOpcode_1A_0T_0R 226 * 227 * PARAMETERS: WalkState - Current state (contains AML opcode) 228 * 229 * RETURN: Status 230 * 231 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on 232 * object stack 233 * 234 ******************************************************************************/ 235 236 ACPI_STATUS 237 AcpiExOpcode_1A_0T_0R ( 238 ACPI_WALK_STATE *WalkState) 239 { 240 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 241 ACPI_STATUS Status = AE_OK; 242 243 244 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_0R, 245 AcpiPsGetOpcodeName (WalkState->Opcode)); 246 247 248 /* Examine the AML opcode */ 249 250 switch (WalkState->Opcode) 251 { 252 case AML_RELEASE_OP: /* Release (MutexObject) */ 253 254 Status = AcpiExReleaseMutex (Operand[0], WalkState); 255 break; 256 257 258 case AML_RESET_OP: /* Reset (EventObject) */ 259 260 Status = AcpiExSystemResetEvent (Operand[0]); 261 break; 262 263 264 case AML_SIGNAL_OP: /* Signal (EventObject) */ 265 266 Status = AcpiExSystemSignalEvent (Operand[0]); 267 break; 268 269 270 case AML_SLEEP_OP: /* Sleep (MsecTime) */ 271 272 Status = AcpiExSystemDoSuspend (Operand[0]->Integer.Value); 273 break; 274 275 276 case AML_STALL_OP: /* Stall (UsecTime) */ 277 278 Status = AcpiExSystemDoStall ((UINT32) Operand[0]->Integer.Value); 279 break; 280 281 282 case AML_UNLOAD_OP: /* Unload (Handle) */ 283 284 Status = AcpiExUnloadTable (Operand[0]); 285 break; 286 287 288 default: /* Unknown opcode */ 289 290 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 291 WalkState->Opcode)); 292 Status = AE_AML_BAD_OPCODE; 293 break; 294 } 295 296 return_ACPI_STATUS (Status); 297 } 298 299 300 /******************************************************************************* 301 * 302 * FUNCTION: AcpiExOpcode_1A_1T_0R 303 * 304 * PARAMETERS: WalkState - Current state (contains AML opcode) 305 * 306 * RETURN: Status 307 * 308 * DESCRIPTION: Execute opcode with one argument, one target, and no 309 * return value. 310 * 311 ******************************************************************************/ 312 313 ACPI_STATUS 314 AcpiExOpcode_1A_1T_0R ( 315 ACPI_WALK_STATE *WalkState) 316 { 317 ACPI_STATUS Status = AE_OK; 318 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 319 320 321 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_0R, 322 AcpiPsGetOpcodeName (WalkState->Opcode)); 323 324 325 /* Examine the AML opcode */ 326 327 switch (WalkState->Opcode) 328 { 329 case AML_LOAD_OP: 330 331 Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState); 332 break; 333 334 default: /* Unknown opcode */ 335 336 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 337 WalkState->Opcode)); 338 Status = AE_AML_BAD_OPCODE; 339 goto Cleanup; 340 } 341 342 343 Cleanup: 344 345 return_ACPI_STATUS (Status); 346 } 347 348 349 /******************************************************************************* 350 * 351 * FUNCTION: AcpiExOpcode_1A_1T_1R 352 * 353 * PARAMETERS: WalkState - Current state (contains AML opcode) 354 * 355 * RETURN: Status 356 * 357 * DESCRIPTION: Execute opcode with one argument, one target, and a 358 * return value. 359 * 360 ******************************************************************************/ 361 362 ACPI_STATUS 363 AcpiExOpcode_1A_1T_1R ( 364 ACPI_WALK_STATE *WalkState) 365 { 366 ACPI_STATUS Status = AE_OK; 367 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 368 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 369 ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; 370 UINT32 Temp32; 371 UINT32 i; 372 ACPI_INTEGER PowerOfTen; 373 ACPI_INTEGER Digit; 374 375 376 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_1R, 377 AcpiPsGetOpcodeName (WalkState->Opcode)); 378 379 380 /* Examine the AML opcode */ 381 382 switch (WalkState->Opcode) 383 { 384 case AML_BIT_NOT_OP: 385 case AML_FIND_SET_LEFT_BIT_OP: 386 case AML_FIND_SET_RIGHT_BIT_OP: 387 case AML_FROM_BCD_OP: 388 case AML_TO_BCD_OP: 389 case AML_COND_REF_OF_OP: 390 391 /* Create a return object of type Integer for these opcodes */ 392 393 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 394 if (!ReturnDesc) 395 { 396 Status = AE_NO_MEMORY; 397 goto Cleanup; 398 } 399 400 switch (WalkState->Opcode) 401 { 402 case AML_BIT_NOT_OP: /* Not (Operand, Result) */ 403 404 ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value; 405 break; 406 407 408 case AML_FIND_SET_LEFT_BIT_OP: /* FindSetLeftBit (Operand, Result) */ 409 410 ReturnDesc->Integer.Value = Operand[0]->Integer.Value; 411 412 /* 413 * Acpi specification describes Integer type as a little 414 * endian unsigned value, so this boundary condition is valid. 415 */ 416 for (Temp32 = 0; ReturnDesc->Integer.Value && 417 Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) 418 { 419 ReturnDesc->Integer.Value >>= 1; 420 } 421 422 ReturnDesc->Integer.Value = Temp32; 423 break; 424 425 426 case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */ 427 428 ReturnDesc->Integer.Value = Operand[0]->Integer.Value; 429 430 /* 431 * The Acpi specification describes Integer type as a little 432 * endian unsigned value, so this boundary condition is valid. 433 */ 434 for (Temp32 = 0; ReturnDesc->Integer.Value && 435 Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) 436 { 437 ReturnDesc->Integer.Value <<= 1; 438 } 439 440 /* Since the bit position is one-based, subtract from 33 (65) */ 441 442 ReturnDesc->Integer.Value = 443 Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32; 444 break; 445 446 447 case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */ 448 449 /* 450 * The 64-bit ACPI integer can hold 16 4-bit BCD characters 451 * (if table is 32-bit, integer can hold 8 BCD characters) 452 * Convert each 4-bit BCD value 453 */ 454 PowerOfTen = 1; 455 ReturnDesc->Integer.Value = 0; 456 Digit = Operand[0]->Integer.Value; 457 458 /* Convert each BCD digit (each is one nybble wide) */ 459 460 for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) 461 { 462 /* Get the least significant 4-bit BCD digit */ 463 464 Temp32 = ((UINT32) Digit) & 0xF; 465 466 /* Check the range of the digit */ 467 468 if (Temp32 > 9) 469 { 470 ACPI_ERROR ((AE_INFO, 471 "BCD digit too large (not decimal): 0x%X", 472 Temp32)); 473 474 Status = AE_AML_NUMERIC_OVERFLOW; 475 goto Cleanup; 476 } 477 478 /* Sum the digit into the result with the current power of 10 */ 479 480 ReturnDesc->Integer.Value += 481 (((ACPI_INTEGER) Temp32) * PowerOfTen); 482 483 /* Shift to next BCD digit */ 484 485 Digit >>= 4; 486 487 /* Next power of 10 */ 488 489 PowerOfTen *= 10; 490 } 491 break; 492 493 494 case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */ 495 496 ReturnDesc->Integer.Value = 0; 497 Digit = Operand[0]->Integer.Value; 498 499 /* Each BCD digit is one nybble wide */ 500 501 for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) 502 { 503 (void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32); 504 505 /* 506 * Insert the BCD digit that resides in the 507 * remainder from above 508 */ 509 ReturnDesc->Integer.Value |= 510 (((ACPI_INTEGER) Temp32) << ACPI_MUL_4 (i)); 511 } 512 513 /* Overflow if there is any data left in Digit */ 514 515 if (Digit > 0) 516 { 517 ACPI_ERROR ((AE_INFO, 518 "Integer too large to convert to BCD: %8.8X%8.8X", 519 ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value))); 520 Status = AE_AML_NUMERIC_OVERFLOW; 521 goto Cleanup; 522 } 523 break; 524 525 526 case AML_COND_REF_OF_OP: /* CondRefOf (SourceObject, Result) */ 527 528 /* 529 * This op is a little strange because the internal return value is 530 * different than the return value stored in the result descriptor 531 * (There are really two return values) 532 */ 533 if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode) 534 { 535 /* 536 * This means that the object does not exist in the namespace, 537 * return FALSE 538 */ 539 ReturnDesc->Integer.Value = 0; 540 goto Cleanup; 541 } 542 543 /* Get the object reference, store it, and remove our reference */ 544 545 Status = AcpiExGetObjectReference (Operand[0], 546 &ReturnDesc2, WalkState); 547 if (ACPI_FAILURE (Status)) 548 { 549 goto Cleanup; 550 } 551 552 Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState); 553 AcpiUtRemoveReference (ReturnDesc2); 554 555 /* The object exists in the namespace, return TRUE */ 556 557 ReturnDesc->Integer.Value = ACPI_INTEGER_MAX; 558 goto Cleanup; 559 560 561 default: 562 /* No other opcodes get here */ 563 break; 564 } 565 break; 566 567 568 case AML_STORE_OP: /* Store (Source, Target) */ 569 570 /* 571 * A store operand is typically a number, string, buffer or lvalue 572 * Be careful about deleting the source object, 573 * since the object itself may have been stored. 574 */ 575 Status = AcpiExStore (Operand[0], Operand[1], WalkState); 576 if (ACPI_FAILURE (Status)) 577 { 578 return_ACPI_STATUS (Status); 579 } 580 581 /* It is possible that the Store already produced a return object */ 582 583 if (!WalkState->ResultObj) 584 { 585 /* 586 * Normally, we would remove a reference on the Operand[0] 587 * parameter; But since it is being used as the internal return 588 * object (meaning we would normally increment it), the two 589 * cancel out, and we simply don't do anything. 590 */ 591 WalkState->ResultObj = Operand[0]; 592 WalkState->Operands[0] = NULL; /* Prevent deletion */ 593 } 594 return_ACPI_STATUS (Status); 595 596 597 /* 598 * ACPI 2.0 Opcodes 599 */ 600 case AML_COPY_OP: /* Copy (Source, Target) */ 601 602 Status = AcpiUtCopyIobjectToIobject (Operand[0], &ReturnDesc, 603 WalkState); 604 break; 605 606 607 case AML_TO_DECSTRING_OP: /* ToDecimalString (Data, Result) */ 608 609 Status = AcpiExConvertToString (Operand[0], &ReturnDesc, 610 ACPI_EXPLICIT_CONVERT_DECIMAL); 611 if (ReturnDesc == Operand[0]) 612 { 613 /* No conversion performed, add ref to handle return value */ 614 AcpiUtAddReference (ReturnDesc); 615 } 616 break; 617 618 619 case AML_TO_HEXSTRING_OP: /* ToHexString (Data, Result) */ 620 621 Status = AcpiExConvertToString (Operand[0], &ReturnDesc, 622 ACPI_EXPLICIT_CONVERT_HEX); 623 if (ReturnDesc == Operand[0]) 624 { 625 /* No conversion performed, add ref to handle return value */ 626 AcpiUtAddReference (ReturnDesc); 627 } 628 break; 629 630 631 case AML_TO_BUFFER_OP: /* ToBuffer (Data, Result) */ 632 633 Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc); 634 if (ReturnDesc == Operand[0]) 635 { 636 /* No conversion performed, add ref to handle return value */ 637 AcpiUtAddReference (ReturnDesc); 638 } 639 break; 640 641 642 case AML_TO_INTEGER_OP: /* ToInteger (Data, Result) */ 643 644 Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc, 645 ACPI_ANY_BASE); 646 if (ReturnDesc == Operand[0]) 647 { 648 /* No conversion performed, add ref to handle return value */ 649 AcpiUtAddReference (ReturnDesc); 650 } 651 break; 652 653 654 case AML_SHIFT_LEFT_BIT_OP: /* ShiftLeftBit (Source, BitNum) */ 655 case AML_SHIFT_RIGHT_BIT_OP: /* ShiftRightBit (Source, BitNum) */ 656 657 /* These are two obsolete opcodes */ 658 659 ACPI_ERROR ((AE_INFO, 660 "%s is obsolete and not implemented", 661 AcpiPsGetOpcodeName (WalkState->Opcode))); 662 Status = AE_SUPPORT; 663 goto Cleanup; 664 665 666 default: /* Unknown opcode */ 667 668 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 669 WalkState->Opcode)); 670 Status = AE_AML_BAD_OPCODE; 671 goto Cleanup; 672 } 673 674 if (ACPI_SUCCESS (Status)) 675 { 676 /* Store the return value computed above into the target object */ 677 678 Status = AcpiExStore (ReturnDesc, Operand[1], WalkState); 679 } 680 681 682 Cleanup: 683 684 /* Delete return object on error */ 685 686 if (ACPI_FAILURE (Status)) 687 { 688 AcpiUtRemoveReference (ReturnDesc); 689 } 690 691 /* Save return object on success */ 692 693 else if (!WalkState->ResultObj) 694 { 695 WalkState->ResultObj = ReturnDesc; 696 } 697 698 return_ACPI_STATUS (Status); 699 } 700 701 702 /******************************************************************************* 703 * 704 * FUNCTION: AcpiExOpcode_1A_0T_1R 705 * 706 * PARAMETERS: WalkState - Current state (contains AML opcode) 707 * 708 * RETURN: Status 709 * 710 * DESCRIPTION: Execute opcode with one argument, no target, and a return value 711 * 712 ******************************************************************************/ 713 714 ACPI_STATUS 715 AcpiExOpcode_1A_0T_1R ( 716 ACPI_WALK_STATE *WalkState) 717 { 718 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 719 ACPI_OPERAND_OBJECT *TempDesc; 720 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 721 ACPI_STATUS Status = AE_OK; 722 UINT32 Type; 723 ACPI_INTEGER Value; 724 725 726 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R, 727 AcpiPsGetOpcodeName (WalkState->Opcode)); 728 729 730 /* Examine the AML opcode */ 731 732 switch (WalkState->Opcode) 733 { 734 case AML_LNOT_OP: /* LNot (Operand) */ 735 736 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 737 if (!ReturnDesc) 738 { 739 Status = AE_NO_MEMORY; 740 goto Cleanup; 741 } 742 743 /* 744 * Set result to ONES (TRUE) if Value == 0. Note: 745 * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above. 746 */ 747 if (!Operand[0]->Integer.Value) 748 { 749 ReturnDesc->Integer.Value = ACPI_INTEGER_MAX; 750 } 751 break; 752 753 754 case AML_DECREMENT_OP: /* Decrement (Operand) */ 755 case AML_INCREMENT_OP: /* Increment (Operand) */ 756 757 /* 758 * Create a new integer. Can't just get the base integer and 759 * increment it because it may be an Arg or Field. 760 */ 761 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 762 if (!ReturnDesc) 763 { 764 Status = AE_NO_MEMORY; 765 goto Cleanup; 766 } 767 768 /* 769 * Since we are expecting a Reference operand, it can be either a 770 * NS Node or an internal object. 771 */ 772 TempDesc = Operand[0]; 773 if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND) 774 { 775 /* Internal reference object - prevent deletion */ 776 777 AcpiUtAddReference (TempDesc); 778 } 779 780 /* 781 * Convert the Reference operand to an Integer (This removes a 782 * reference on the Operand[0] object) 783 * 784 * NOTE: We use LNOT_OP here in order to force resolution of the 785 * reference operand to an actual integer. 786 */ 787 Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState); 788 if (ACPI_FAILURE (Status)) 789 { 790 ACPI_EXCEPTION ((AE_INFO, Status, 791 "While resolving operands for [%s]", 792 AcpiPsGetOpcodeName (WalkState->Opcode))); 793 794 goto Cleanup; 795 } 796 797 /* 798 * TempDesc is now guaranteed to be an Integer object -- 799 * Perform the actual increment or decrement 800 */ 801 if (WalkState->Opcode == AML_INCREMENT_OP) 802 { 803 ReturnDesc->Integer.Value = TempDesc->Integer.Value +1; 804 } 805 else 806 { 807 ReturnDesc->Integer.Value = TempDesc->Integer.Value -1; 808 } 809 810 /* Finished with this Integer object */ 811 812 AcpiUtRemoveReference (TempDesc); 813 814 /* 815 * Store the result back (indirectly) through the original 816 * Reference object 817 */ 818 Status = AcpiExStore (ReturnDesc, Operand[0], WalkState); 819 break; 820 821 822 case AML_TYPE_OP: /* ObjectType (SourceObject) */ 823 824 /* 825 * Note: The operand is not resolved at this point because we want to 826 * get the associated object, not its value. For example, we don't 827 * want to resolve a FieldUnit to its value, we want the actual 828 * FieldUnit object. 829 */ 830 831 /* Get the type of the base object */ 832 833 Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL); 834 if (ACPI_FAILURE (Status)) 835 { 836 goto Cleanup; 837 } 838 839 /* Allocate a descriptor to hold the type. */ 840 841 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 842 if (!ReturnDesc) 843 { 844 Status = AE_NO_MEMORY; 845 goto Cleanup; 846 } 847 848 ReturnDesc->Integer.Value = Type; 849 break; 850 851 852 case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */ 853 854 /* 855 * Note: The operand is not resolved at this point because we want to 856 * get the associated object, not its value. 857 */ 858 859 /* Get the base object */ 860 861 Status = AcpiExResolveMultiple (WalkState, 862 Operand[0], &Type, &TempDesc); 863 if (ACPI_FAILURE (Status)) 864 { 865 goto Cleanup; 866 } 867 868 /* 869 * The type of the base object must be integer, buffer, string, or 870 * package. All others are not supported. 871 * 872 * NOTE: Integer is not specifically supported by the ACPI spec, 873 * but is supported implicitly via implicit operand conversion. 874 * rather than bother with conversion, we just use the byte width 875 * global (4 or 8 bytes). 876 */ 877 switch (Type) 878 { 879 case ACPI_TYPE_INTEGER: 880 Value = AcpiGbl_IntegerByteWidth; 881 break; 882 883 case ACPI_TYPE_STRING: 884 Value = TempDesc->String.Length; 885 break; 886 887 case ACPI_TYPE_BUFFER: 888 889 /* Buffer arguments may not be evaluated at this point */ 890 891 Status = AcpiDsGetBufferArguments (TempDesc); 892 Value = TempDesc->Buffer.Length; 893 break; 894 895 case ACPI_TYPE_PACKAGE: 896 897 /* Package arguments may not be evaluated at this point */ 898 899 Status = AcpiDsGetPackageArguments (TempDesc); 900 Value = TempDesc->Package.Count; 901 break; 902 903 default: 904 ACPI_ERROR ((AE_INFO, 905 "Operand must be Buffer/Integer/String/Package - found type %s", 906 AcpiUtGetTypeName (Type))); 907 Status = AE_AML_OPERAND_TYPE; 908 goto Cleanup; 909 } 910 911 if (ACPI_FAILURE (Status)) 912 { 913 goto Cleanup; 914 } 915 916 /* 917 * Now that we have the size of the object, create a result 918 * object to hold the value 919 */ 920 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 921 if (!ReturnDesc) 922 { 923 Status = AE_NO_MEMORY; 924 goto Cleanup; 925 } 926 927 ReturnDesc->Integer.Value = Value; 928 break; 929 930 931 case AML_REF_OF_OP: /* RefOf (SourceObject) */ 932 933 Status = AcpiExGetObjectReference (Operand[0], &ReturnDesc, WalkState); 934 if (ACPI_FAILURE (Status)) 935 { 936 goto Cleanup; 937 } 938 break; 939 940 941 case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */ 942 943 /* Check for a method local or argument, or standalone String */ 944 945 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) 946 { 947 TempDesc = AcpiNsGetAttachedObject ( 948 (ACPI_NAMESPACE_NODE *) Operand[0]); 949 if (TempDesc && 950 ((TempDesc->Common.Type == ACPI_TYPE_STRING) || 951 (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE))) 952 { 953 Operand[0] = TempDesc; 954 AcpiUtAddReference (TempDesc); 955 } 956 else 957 { 958 Status = AE_AML_OPERAND_TYPE; 959 goto Cleanup; 960 } 961 } 962 else 963 { 964 switch ((Operand[0])->Common.Type) 965 { 966 case ACPI_TYPE_LOCAL_REFERENCE: 967 /* 968 * This is a DerefOf (LocalX | ArgX) 969 * 970 * Must resolve/dereference the local/arg reference first 971 */ 972 switch (Operand[0]->Reference.Class) 973 { 974 case ACPI_REFCLASS_LOCAL: 975 case ACPI_REFCLASS_ARG: 976 977 /* Set Operand[0] to the value of the local/arg */ 978 979 Status = AcpiDsMethodDataGetValue ( 980 Operand[0]->Reference.Class, 981 Operand[0]->Reference.Value, 982 WalkState, &TempDesc); 983 if (ACPI_FAILURE (Status)) 984 { 985 goto Cleanup; 986 } 987 988 /* 989 * Delete our reference to the input object and 990 * point to the object just retrieved 991 */ 992 AcpiUtRemoveReference (Operand[0]); 993 Operand[0] = TempDesc; 994 break; 995 996 case ACPI_REFCLASS_REFOF: 997 998 /* Get the object to which the reference refers */ 999 1000 TempDesc = Operand[0]->Reference.Object; 1001 AcpiUtRemoveReference (Operand[0]); 1002 Operand[0] = TempDesc; 1003 break; 1004 1005 default: 1006 1007 /* Must be an Index op - handled below */ 1008 break; 1009 } 1010 break; 1011 1012 case ACPI_TYPE_STRING: 1013 break; 1014 1015 default: 1016 Status = AE_AML_OPERAND_TYPE; 1017 goto Cleanup; 1018 } 1019 } 1020 1021 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED) 1022 { 1023 if ((Operand[0])->Common.Type == ACPI_TYPE_STRING) 1024 { 1025 /* 1026 * This is a DerefOf (String). The string is a reference 1027 * to a named ACPI object. 1028 * 1029 * 1) Find the owning Node 1030 * 2) Dereference the node to an actual object. Could be a 1031 * Field, so we need to resolve the node to a value. 1032 */ 1033 Status = AcpiNsGetNode (WalkState->ScopeInfo->Scope.Node, 1034 Operand[0]->String.Pointer, 1035 ACPI_NS_SEARCH_PARENT, 1036 ACPI_CAST_INDIRECT_PTR ( 1037 ACPI_NAMESPACE_NODE, &ReturnDesc)); 1038 if (ACPI_FAILURE (Status)) 1039 { 1040 goto Cleanup; 1041 } 1042 1043 Status = AcpiExResolveNodeToValue ( 1044 ACPI_CAST_INDIRECT_PTR ( 1045 ACPI_NAMESPACE_NODE, &ReturnDesc), 1046 WalkState); 1047 goto Cleanup; 1048 } 1049 } 1050 1051 /* Operand[0] may have changed from the code above */ 1052 1053 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) 1054 { 1055 /* 1056 * This is a DerefOf (ObjectReference) 1057 * Get the actual object from the Node (This is the dereference). 1058 * This case may only happen when a LocalX or ArgX is 1059 * dereferenced above. 1060 */ 1061 ReturnDesc = AcpiNsGetAttachedObject ( 1062 (ACPI_NAMESPACE_NODE *) Operand[0]); 1063 AcpiUtAddReference (ReturnDesc); 1064 } 1065 else 1066 { 1067 /* 1068 * This must be a reference object produced by either the 1069 * Index() or RefOf() operator 1070 */ 1071 switch (Operand[0]->Reference.Class) 1072 { 1073 case ACPI_REFCLASS_INDEX: 1074 1075 /* 1076 * The target type for the Index operator must be 1077 * either a Buffer or a Package 1078 */ 1079 switch (Operand[0]->Reference.TargetType) 1080 { 1081 case ACPI_TYPE_BUFFER_FIELD: 1082 1083 TempDesc = Operand[0]->Reference.Object; 1084 1085 /* 1086 * Create a new object that contains one element of the 1087 * buffer -- the element pointed to by the index. 1088 * 1089 * NOTE: index into a buffer is NOT a pointer to a 1090 * sub-buffer of the main buffer, it is only a pointer to a 1091 * single element (byte) of the buffer! 1092 */ 1093 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 1094 if (!ReturnDesc) 1095 { 1096 Status = AE_NO_MEMORY; 1097 goto Cleanup; 1098 } 1099 1100 /* 1101 * Since we are returning the value of the buffer at the 1102 * indexed location, we don't need to add an additional 1103 * reference to the buffer itself. 1104 */ 1105 ReturnDesc->Integer.Value = 1106 TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]; 1107 break; 1108 1109 1110 case ACPI_TYPE_PACKAGE: 1111 1112 /* 1113 * Return the referenced element of the package. We must 1114 * add another reference to the referenced object, however. 1115 */ 1116 ReturnDesc = *(Operand[0]->Reference.Where); 1117 if (ReturnDesc) 1118 { 1119 AcpiUtAddReference (ReturnDesc); 1120 } 1121 break; 1122 1123 1124 default: 1125 1126 ACPI_ERROR ((AE_INFO, 1127 "Unknown Index TargetType %X in reference object %p", 1128 Operand[0]->Reference.TargetType, Operand[0])); 1129 Status = AE_AML_OPERAND_TYPE; 1130 goto Cleanup; 1131 } 1132 break; 1133 1134 1135 case ACPI_REFCLASS_REFOF: 1136 1137 ReturnDesc = Operand[0]->Reference.Object; 1138 1139 if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) == 1140 ACPI_DESC_TYPE_NAMED) 1141 { 1142 ReturnDesc = AcpiNsGetAttachedObject ( 1143 (ACPI_NAMESPACE_NODE *) ReturnDesc); 1144 } 1145 1146 /* Add another reference to the object! */ 1147 1148 AcpiUtAddReference (ReturnDesc); 1149 break; 1150 1151 1152 default: 1153 ACPI_ERROR ((AE_INFO, 1154 "Unknown class in reference(%p) - %2.2X", 1155 Operand[0], Operand[0]->Reference.Class)); 1156 1157 Status = AE_TYPE; 1158 goto Cleanup; 1159 } 1160 } 1161 break; 1162 1163 1164 default: 1165 1166 ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", 1167 WalkState->Opcode)); 1168 Status = AE_AML_BAD_OPCODE; 1169 goto Cleanup; 1170 } 1171 1172 1173 Cleanup: 1174 1175 /* Delete return object on error */ 1176 1177 if (ACPI_FAILURE (Status)) 1178 { 1179 AcpiUtRemoveReference (ReturnDesc); 1180 } 1181 1182 /* Save return object on success */ 1183 1184 else 1185 { 1186 WalkState->ResultObj = ReturnDesc; 1187 } 1188 1189 return_ACPI_STATUS (Status); 1190 } 1191 1192