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