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