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