1 2 /****************************************************************************** 3 * 4 * Module Name: exoparg1 - AML execution - opcodes with 1 argument 5 * $Revision: 167 $ 6 * 7 *****************************************************************************/ 8 9 /****************************************************************************** 10 * 11 * 1. Copyright Notice 12 * 13 * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp. 14 * All rights reserved. 15 * 16 * 2. License 17 * 18 * 2.1. This is your license from Intel Corp. under its intellectual property 19 * rights. You may have additional license terms from the party that provided 20 * you this software, covering your right to use that party's intellectual 21 * property rights. 22 * 23 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 24 * copy of the source code appearing in this file ("Covered Code") an 25 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 26 * base code distributed originally by Intel ("Original Intel Code") to copy, 27 * make derivatives, distribute, use and display any portion of the Covered 28 * Code in any form, with the right to sublicense such rights; and 29 * 30 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 31 * license (with the right to sublicense), under only those claims of Intel 32 * patents that are infringed by the Original Intel Code, to make, use, sell, 33 * offer to sell, and import the Covered Code and derivative works thereof 34 * solely to the minimum extent necessary to exercise the above copyright 35 * license, and in no event shall the patent license extend to any additions 36 * to or modifications of the Original Intel Code. No other license or right 37 * is granted directly or by implication, estoppel or otherwise; 38 * 39 * The above copyright and patent license is granted only if the following 40 * conditions are met: 41 * 42 * 3. Conditions 43 * 44 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 45 * Redistribution of source code of any substantial portion of the Covered 46 * Code or modification with rights to further distribute source must include 47 * the above Copyright Notice, the above License, this list of Conditions, 48 * and the following Disclaimer and Export Compliance provision. In addition, 49 * Licensee must cause all Covered Code to which Licensee contributes to 50 * contain a file documenting the changes Licensee made to create that Covered 51 * Code and the date of any change. Licensee must include in that file the 52 * documentation of any changes made by any predecessor Licensee. Licensee 53 * must include a prominent statement that the modification is derived, 54 * directly or indirectly, from Original Intel Code. 55 * 56 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 57 * Redistribution of source code of any substantial portion of the Covered 58 * Code or modification without rights to further distribute source must 59 * include the following Disclaimer and Export Compliance provision in the 60 * documentation and/or other materials provided with distribution. In 61 * addition, Licensee may not authorize further sublicense of source of any 62 * portion of the Covered Code, and must include terms to the effect that the 63 * license from Licensee to its licensee is limited to the intellectual 64 * property embodied in the software Licensee provides to its licensee, and 65 * not to intellectual property embodied in modifications its licensee may 66 * make. 67 * 68 * 3.3. Redistribution of Executable. Redistribution in executable form of any 69 * substantial portion of the Covered Code or modification must reproduce the 70 * above Copyright Notice, and the following Disclaimer and Export Compliance 71 * provision in the documentation and/or other materials provided with the 72 * distribution. 73 * 74 * 3.4. Intel retains all right, title, and interest in and to the Original 75 * Intel Code. 76 * 77 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 78 * Intel shall be used in advertising or otherwise to promote the sale, use or 79 * other dealings in products derived from or relating to the Covered Code 80 * without prior written authorization from Intel. 81 * 82 * 4. Disclaimer and Export Compliance 83 * 84 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 85 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 86 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 87 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 88 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 89 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 90 * PARTICULAR PURPOSE. 91 * 92 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 93 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 94 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 95 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 96 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 97 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 98 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 99 * LIMITED REMEDY. 100 * 101 * 4.3. Licensee shall not export, either directly or indirectly, any of this 102 * software or system incorporating such software without first obtaining any 103 * required license or other approval from the U. S. Department of Commerce or 104 * any other agency or department of the United States Government. In the 105 * event Licensee exports any such software from the United States or 106 * re-exports any such software from a foreign destination, Licensee shall 107 * ensure that the distribution and export/re-export of the software is in 108 * compliance with all laws, regulations, orders, or other restrictions of the 109 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 110 * any of its subsidiaries will export/re-export any technical data, process, 111 * software, or service, directly or indirectly, to any country for which the 112 * United States government or any agency thereof requires an export license, 113 * other governmental approval, or letter of assurance, without first obtaining 114 * such license, approval or letter. 115 * 116 *****************************************************************************/ 117 118 #define __EXOPARG1_C__ 119 120 #include "acpi.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 193 ReturnDesc->Integer.Value = AcpiOsGetTimer (); 194 break; 195 196 default: /* Unknown opcode */ 197 198 ACPI_REPORT_ERROR (("AcpiExOpcode_0A_0T_1R: Unknown opcode %X\n", 199 WalkState->Opcode)); 200 Status = AE_AML_BAD_OPCODE; 201 break; 202 } 203 204 Cleanup: 205 206 if (!WalkState->ResultObj) 207 { 208 WalkState->ResultObj = ReturnDesc; 209 } 210 211 /* Delete return object on error */ 212 213 if (ACPI_FAILURE (Status)) 214 { 215 AcpiUtRemoveReference (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_REPORT_ERROR (("AcpiExOpcode_1A_0T_0R: Unknown opcode %X\n", 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_REPORT_ERROR (("AcpiExOpcode_1A_1T_0R: Unknown opcode %X\n", 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 = Temp32 == 0 ? 0 : 442 (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_DEBUG_PRINT ((ACPI_DB_ERROR, 470 "BCD digit too large (not decimal): 0x%X\n", 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 += (((ACPI_INTEGER) Temp32) * 480 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 |= (((ACPI_INTEGER) Temp32) << 509 ACPI_MUL_4 (i)); 510 } 511 512 /* Overflow if there is any data left in Digit */ 513 514 if (Digit > 0) 515 { 516 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 517 "Integer too large to convert to BCD: %8.8X%8.8X\n", 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_DEBUG_PRINT ((ACPI_DB_ERROR, 659 "%s is obsolete and not implemented\n", 660 AcpiPsGetOpcodeName (WalkState->Opcode))); 661 Status = AE_SUPPORT; 662 goto Cleanup; 663 664 665 default: /* Unknown opcode */ 666 667 ACPI_REPORT_ERROR (("AcpiExOpcode_1A_1T_1R: Unknown opcode %X\n", 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 if (!WalkState->ResultObj) 684 { 685 WalkState->ResultObj = ReturnDesc; 686 } 687 688 /* Delete return object on error */ 689 690 if (ACPI_FAILURE (Status)) 691 { 692 AcpiUtRemoveReference (ReturnDesc); 693 } 694 695 return_ACPI_STATUS (Status); 696 } 697 698 699 /******************************************************************************* 700 * 701 * FUNCTION: AcpiExOpcode_1A_0T_1R 702 * 703 * PARAMETERS: WalkState - Current state (contains AML opcode) 704 * 705 * RETURN: Status 706 * 707 * DESCRIPTION: Execute opcode with one argument, no target, and a return value 708 * 709 ******************************************************************************/ 710 711 ACPI_STATUS 712 AcpiExOpcode_1A_0T_1R ( 713 ACPI_WALK_STATE *WalkState) 714 { 715 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 716 ACPI_OPERAND_OBJECT *TempDesc; 717 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 718 ACPI_STATUS Status = AE_OK; 719 UINT32 Type; 720 ACPI_INTEGER Value; 721 722 723 ACPI_FUNCTION_TRACE_STR ("ExOpcode_1A_0T_1R", 724 AcpiPsGetOpcodeName (WalkState->Opcode)); 725 726 727 /* Examine the AML opcode */ 728 729 switch (WalkState->Opcode) 730 { 731 case AML_LNOT_OP: /* LNot (Operand) */ 732 733 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 734 if (!ReturnDesc) 735 { 736 Status = AE_NO_MEMORY; 737 goto Cleanup; 738 } 739 740 /* 741 * Set result to ONES (TRUE) if Value == 0. Note: 742 * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above. 743 */ 744 if (!Operand[0]->Integer.Value) 745 { 746 ReturnDesc->Integer.Value = ACPI_INTEGER_MAX; 747 } 748 break; 749 750 751 case AML_DECREMENT_OP: /* Decrement (Operand) */ 752 case AML_INCREMENT_OP: /* Increment (Operand) */ 753 754 /* 755 * Create a new integer. Can't just get the base integer and 756 * increment it because it may be an Arg or Field. 757 */ 758 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 759 if (!ReturnDesc) 760 { 761 Status = AE_NO_MEMORY; 762 goto Cleanup; 763 } 764 765 /* 766 * Since we are expecting a Reference operand, it can be either a 767 * NS Node or an internal object. 768 */ 769 TempDesc = Operand[0]; 770 if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND) 771 { 772 /* Internal reference object - prevent deletion */ 773 774 AcpiUtAddReference (TempDesc); 775 } 776 777 /* 778 * Convert the Reference operand to an Integer (This removes a 779 * reference on the Operand[0] object) 780 * 781 * NOTE: We use LNOT_OP here in order to force resolution of the 782 * reference operand to an actual integer. 783 */ 784 Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState); 785 if (ACPI_FAILURE (Status)) 786 { 787 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s: bad operand(s) %s\n", 788 AcpiPsGetOpcodeName (WalkState->Opcode), 789 AcpiFormatException(Status))); 790 791 goto Cleanup; 792 } 793 794 /* 795 * TempDesc is now guaranteed to be an Integer object -- 796 * Perform the actual increment or decrement 797 */ 798 if (WalkState->Opcode == AML_INCREMENT_OP) 799 { 800 ReturnDesc->Integer.Value = TempDesc->Integer.Value +1; 801 } 802 else 803 { 804 ReturnDesc->Integer.Value = TempDesc->Integer.Value -1; 805 } 806 807 /* Finished with this Integer object */ 808 809 AcpiUtRemoveReference (TempDesc); 810 811 /* 812 * Store the result back (indirectly) through the original 813 * Reference object 814 */ 815 Status = AcpiExStore (ReturnDesc, Operand[0], WalkState); 816 break; 817 818 819 case AML_TYPE_OP: /* ObjectType (SourceObject) */ 820 821 /* 822 * Note: The operand is not resolved at this point because we want to 823 * get the associated object, not its value. For example, we don't 824 * want to resolve a FieldUnit to its value, we want the actual 825 * FieldUnit object. 826 */ 827 828 /* Get the type of the base object */ 829 830 Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL); 831 if (ACPI_FAILURE (Status)) 832 { 833 goto Cleanup; 834 } 835 /* Allocate a descriptor to hold the type. */ 836 837 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 838 if (!ReturnDesc) 839 { 840 Status = AE_NO_MEMORY; 841 goto Cleanup; 842 } 843 844 ReturnDesc->Integer.Value = Type; 845 break; 846 847 848 case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */ 849 850 /* 851 * Note: The operand is not resolved at this point because we want to 852 * get the associated object, not its value. 853 */ 854 855 /* Get the base object */ 856 857 Status = AcpiExResolveMultiple (WalkState, 858 Operand[0], &Type, &TempDesc); 859 if (ACPI_FAILURE (Status)) 860 { 861 goto Cleanup; 862 } 863 864 /* 865 * The type of the base object must be integer, buffer, string, or 866 * package. All others are not supported. 867 * 868 * NOTE: Integer is not specifically supported by the ACPI spec, 869 * but is supported implicitly via implicit operand conversion. 870 * rather than bother with conversion, we just use the byte width 871 * global (4 or 8 bytes). 872 */ 873 switch (Type) 874 { 875 case ACPI_TYPE_INTEGER: 876 Value = AcpiGbl_IntegerByteWidth; 877 break; 878 879 case ACPI_TYPE_BUFFER: 880 Value = TempDesc->Buffer.Length; 881 break; 882 883 case ACPI_TYPE_STRING: 884 Value = TempDesc->String.Length; 885 break; 886 887 case ACPI_TYPE_PACKAGE: 888 Value = TempDesc->Package.Count; 889 break; 890 891 default: 892 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 893 "SizeOf - Operand is not Buf/Int/Str/Pkg - found type %s\n", 894 AcpiUtGetTypeName (Type))); 895 Status = AE_AML_OPERAND_TYPE; 896 goto Cleanup; 897 } 898 899 /* 900 * Now that we have the size of the object, create a result 901 * object to hold the value 902 */ 903 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 904 if (!ReturnDesc) 905 { 906 Status = AE_NO_MEMORY; 907 goto Cleanup; 908 } 909 910 ReturnDesc->Integer.Value = Value; 911 break; 912 913 914 case AML_REF_OF_OP: /* RefOf (SourceObject) */ 915 916 Status = AcpiExGetObjectReference (Operand[0], &ReturnDesc, WalkState); 917 if (ACPI_FAILURE (Status)) 918 { 919 goto Cleanup; 920 } 921 break; 922 923 924 case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */ 925 926 /* Check for a method local or argument, or standalone String */ 927 928 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED) 929 { 930 switch (ACPI_GET_OBJECT_TYPE (Operand[0])) 931 { 932 case ACPI_TYPE_LOCAL_REFERENCE: 933 /* 934 * This is a DerefOf (LocalX | ArgX) 935 * 936 * Must resolve/dereference the local/arg reference first 937 */ 938 switch (Operand[0]->Reference.Opcode) 939 { 940 case AML_LOCAL_OP: 941 case AML_ARG_OP: 942 943 /* Set Operand[0] to the value of the local/arg */ 944 945 Status = AcpiDsMethodDataGetValue ( 946 Operand[0]->Reference.Opcode, 947 Operand[0]->Reference.Offset, 948 WalkState, &TempDesc); 949 if (ACPI_FAILURE (Status)) 950 { 951 goto Cleanup; 952 } 953 954 /* 955 * Delete our reference to the input object and 956 * point to the object just retrieved 957 */ 958 AcpiUtRemoveReference (Operand[0]); 959 Operand[0] = TempDesc; 960 break; 961 962 case AML_REF_OF_OP: 963 964 /* Get the object to which the reference refers */ 965 966 TempDesc = Operand[0]->Reference.Object; 967 AcpiUtRemoveReference (Operand[0]); 968 Operand[0] = TempDesc; 969 break; 970 971 default: 972 973 /* Must be an Index op - handled below */ 974 break; 975 } 976 break; 977 978 979 case ACPI_TYPE_STRING: 980 981 /* 982 * This is a DerefOf (String). The string is a reference 983 * to a named ACPI object. 984 * 985 * 1) Find the owning Node 986 * 2) Dereference the node to an actual object. Could be a 987 * Field, so we need to resolve the node to a value. 988 */ 989 Status = AcpiNsGetNodeByPath (Operand[0]->String.Pointer, 990 WalkState->ScopeInfo->Scope.Node, 991 ACPI_NS_SEARCH_PARENT, 992 ACPI_CAST_INDIRECT_PTR ( 993 ACPI_NAMESPACE_NODE, &ReturnDesc)); 994 if (ACPI_FAILURE (Status)) 995 { 996 goto Cleanup; 997 } 998 999 Status = AcpiExResolveNodeToValue ( 1000 ACPI_CAST_INDIRECT_PTR ( 1001 ACPI_NAMESPACE_NODE, &ReturnDesc), 1002 WalkState); 1003 goto Cleanup; 1004 1005 1006 default: 1007 1008 Status = AE_AML_OPERAND_TYPE; 1009 goto Cleanup; 1010 } 1011 } 1012 1013 /* Operand[0] may have changed from the code above */ 1014 1015 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) 1016 { 1017 /* 1018 * This is a DerefOf (ObjectReference) 1019 * Get the actual object from the Node (This is the dereference). 1020 * This case may only happen when a LocalX or ArgX is 1021 * dereferenced above. 1022 */ 1023 ReturnDesc = AcpiNsGetAttachedObject ( 1024 (ACPI_NAMESPACE_NODE *) Operand[0]); 1025 } 1026 else 1027 { 1028 /* 1029 * This must be a reference object produced by either the 1030 * Index() or RefOf() operator 1031 */ 1032 switch (Operand[0]->Reference.Opcode) 1033 { 1034 case AML_INDEX_OP: 1035 1036 /* 1037 * The target type for the Index operator must be 1038 * either a Buffer or a Package 1039 */ 1040 switch (Operand[0]->Reference.TargetType) 1041 { 1042 case ACPI_TYPE_BUFFER_FIELD: 1043 1044 TempDesc = Operand[0]->Reference.Object; 1045 1046 /* 1047 * Create a new object that contains one element of the 1048 * buffer -- the element pointed to by the index. 1049 * 1050 * NOTE: index into a buffer is NOT a pointer to a 1051 * sub-buffer of the main buffer, it is only a pointer to a 1052 * single element (byte) of the buffer! 1053 */ 1054 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 1055 if (!ReturnDesc) 1056 { 1057 Status = AE_NO_MEMORY; 1058 goto Cleanup; 1059 } 1060 1061 /* 1062 * Since we are returning the value of the buffer at the 1063 * indexed location, we don't need to add an additional 1064 * reference to the buffer itself. 1065 */ 1066 ReturnDesc->Integer.Value = 1067 TempDesc->Buffer.Pointer[Operand[0]->Reference.Offset]; 1068 break; 1069 1070 1071 case ACPI_TYPE_PACKAGE: 1072 1073 /* 1074 * Return the referenced element of the package. We must 1075 * add another reference to the referenced object, however. 1076 */ 1077 ReturnDesc = *(Operand[0]->Reference.Where); 1078 if (!ReturnDesc) 1079 { 1080 /* 1081 * We can't return a NULL dereferenced value. This is 1082 * an uninitialized package element and is thus a 1083 * severe error. 1084 */ 1085 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 1086 "NULL package element obj %p\n", 1087 Operand[0])); 1088 Status = AE_AML_UNINITIALIZED_ELEMENT; 1089 goto Cleanup; 1090 } 1091 1092 AcpiUtAddReference (ReturnDesc); 1093 break; 1094 1095 1096 default: 1097 1098 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 1099 "Unknown Index TargetType %X in obj %p\n", 1100 Operand[0]->Reference.TargetType, Operand[0])); 1101 Status = AE_AML_OPERAND_TYPE; 1102 goto Cleanup; 1103 } 1104 break; 1105 1106 1107 case AML_REF_OF_OP: 1108 1109 ReturnDesc = Operand[0]->Reference.Object; 1110 1111 if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) == 1112 ACPI_DESC_TYPE_NAMED) 1113 { 1114 1115 ReturnDesc = AcpiNsGetAttachedObject ( 1116 (ACPI_NAMESPACE_NODE *) ReturnDesc); 1117 } 1118 1119 /* Add another reference to the object! */ 1120 1121 AcpiUtAddReference (ReturnDesc); 1122 break; 1123 1124 1125 default: 1126 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 1127 "Unknown opcode in ref(%p) - %X\n", 1128 Operand[0], Operand[0]->Reference.Opcode)); 1129 1130 Status = AE_TYPE; 1131 goto Cleanup; 1132 } 1133 } 1134 break; 1135 1136 1137 default: 1138 1139 ACPI_REPORT_ERROR (("AcpiExOpcode_1A_0T_1R: Unknown opcode %X\n", 1140 WalkState->Opcode)); 1141 Status = AE_AML_BAD_OPCODE; 1142 goto Cleanup; 1143 } 1144 1145 1146 Cleanup: 1147 1148 /* Delete return object on error */ 1149 1150 if (ACPI_FAILURE (Status)) 1151 { 1152 AcpiUtRemoveReference (ReturnDesc); 1153 } 1154 1155 WalkState->ResultObj = ReturnDesc; 1156 return_ACPI_STATUS (Status); 1157 } 1158 1159