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