Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.13 1031 lines 28 kB view raw
1 2/****************************************************************************** 3 * 4 * Module Name: exoparg1 - AML execution - opcodes with 1 argument 5 * 6 *****************************************************************************/ 7 8/* 9 * Copyright (C) 2000 - 2005, R. Byron Moore 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 46#include <acpi/acpi.h> 47#include <acpi/acparser.h> 48#include <acpi/acdispat.h> 49#include <acpi/acinterp.h> 50#include <acpi/amlcode.h> 51#include <acpi/acnamesp.h> 52 53 54#define _COMPONENT ACPI_EXECUTER 55 ACPI_MODULE_NAME ("exoparg1") 56 57 58/*! 59 * Naming convention for AML interpreter execution routines. 60 * 61 * The routines that begin execution of AML opcodes are named with a common 62 * convention based upon the number of arguments, the number of target operands, 63 * and whether or not a value is returned: 64 * 65 * AcpiExOpcode_xA_yT_zR 66 * 67 * Where: 68 * 69 * xA - ARGUMENTS: The number of arguments (input operands) that are 70 * required for this opcode type (0 through 6 args). 71 * yT - TARGETS: The number of targets (output operands) that are required 72 * for this opcode type (0, 1, or 2 targets). 73 * zR - RETURN VALUE: Indicates whether this opcode type returns a value 74 * as the function return (0 or 1). 75 * 76 * The AcpiExOpcode* functions are called via the Dispatcher component with 77 * fully resolved operands. 78!*/ 79 80/******************************************************************************* 81 * 82 * FUNCTION: acpi_ex_opcode_0A_0T_1R 83 * 84 * PARAMETERS: walk_state - Current state (contains AML opcode) 85 * 86 * RETURN: Status 87 * 88 * DESCRIPTION: Execute operator with no operands, one return value 89 * 90 ******************************************************************************/ 91 92acpi_status 93acpi_ex_opcode_0A_0T_1R ( 94 struct acpi_walk_state *walk_state) 95{ 96 acpi_status status = AE_OK; 97 union acpi_operand_object *return_desc = NULL; 98 99 100 ACPI_FUNCTION_TRACE_STR ("ex_opcode_0A_0T_1R", 101 acpi_ps_get_opcode_name (walk_state->opcode)); 102 103 104 /* Examine the AML opcode */ 105 106 switch (walk_state->opcode) { 107 case AML_TIMER_OP: /* Timer () */ 108 109 /* Create a return object of type Integer */ 110 111 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 112 if (!return_desc) { 113 status = AE_NO_MEMORY; 114 goto cleanup; 115 } 116 117 return_desc->integer.value = acpi_os_get_timer (); 118 break; 119 120 default: /* Unknown opcode */ 121 122 ACPI_REPORT_ERROR (("acpi_ex_opcode_0A_0T_1R: Unknown opcode %X\n", 123 walk_state->opcode)); 124 status = AE_AML_BAD_OPCODE; 125 break; 126 } 127 128cleanup: 129 130 if (!walk_state->result_obj) { 131 walk_state->result_obj = return_desc; 132 } 133 134 /* Delete return object on error */ 135 136 if (ACPI_FAILURE (status)) { 137 acpi_ut_remove_reference (return_desc); 138 } 139 140 return_ACPI_STATUS (status); 141} 142 143 144/******************************************************************************* 145 * 146 * FUNCTION: acpi_ex_opcode_1A_0T_0R 147 * 148 * PARAMETERS: walk_state - Current state (contains AML opcode) 149 * 150 * RETURN: Status 151 * 152 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on 153 * object stack 154 * 155 ******************************************************************************/ 156 157acpi_status 158acpi_ex_opcode_1A_0T_0R ( 159 struct acpi_walk_state *walk_state) 160{ 161 union acpi_operand_object **operand = &walk_state->operands[0]; 162 acpi_status status = AE_OK; 163 164 165 ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_0R", 166 acpi_ps_get_opcode_name (walk_state->opcode)); 167 168 169 /* Examine the AML opcode */ 170 171 switch (walk_state->opcode) { 172 case AML_RELEASE_OP: /* Release (mutex_object) */ 173 174 status = acpi_ex_release_mutex (operand[0], walk_state); 175 break; 176 177 178 case AML_RESET_OP: /* Reset (event_object) */ 179 180 status = acpi_ex_system_reset_event (operand[0]); 181 break; 182 183 184 case AML_SIGNAL_OP: /* Signal (event_object) */ 185 186 status = acpi_ex_system_signal_event (operand[0]); 187 break; 188 189 190 case AML_SLEEP_OP: /* Sleep (msec_time) */ 191 192 status = acpi_ex_system_do_suspend (operand[0]->integer.value); 193 break; 194 195 196 case AML_STALL_OP: /* Stall (usec_time) */ 197 198 status = acpi_ex_system_do_stall ((u32) operand[0]->integer.value); 199 break; 200 201 202 case AML_UNLOAD_OP: /* Unload (Handle) */ 203 204 status = acpi_ex_unload_table (operand[0]); 205 break; 206 207 208 default: /* Unknown opcode */ 209 210 ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_0R: Unknown opcode %X\n", 211 walk_state->opcode)); 212 status = AE_AML_BAD_OPCODE; 213 break; 214 } 215 216 return_ACPI_STATUS (status); 217} 218 219 220/******************************************************************************* 221 * 222 * FUNCTION: acpi_ex_opcode_1A_1T_0R 223 * 224 * PARAMETERS: walk_state - 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 233acpi_status 234acpi_ex_opcode_1A_1T_0R ( 235 struct acpi_walk_state *walk_state) 236{ 237 acpi_status status = AE_OK; 238 union acpi_operand_object **operand = &walk_state->operands[0]; 239 240 241 ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_0R", 242 acpi_ps_get_opcode_name (walk_state->opcode)); 243 244 245 /* Examine the AML opcode */ 246 247 switch (walk_state->opcode) { 248 case AML_LOAD_OP: 249 250 status = acpi_ex_load_op (operand[0], operand[1], walk_state); 251 break; 252 253 default: /* Unknown opcode */ 254 255 ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_0R: Unknown opcode %X\n", 256 walk_state->opcode)); 257 status = AE_AML_BAD_OPCODE; 258 goto cleanup; 259 } 260 261 262cleanup: 263 264 return_ACPI_STATUS (status); 265} 266 267 268/******************************************************************************* 269 * 270 * FUNCTION: acpi_ex_opcode_1A_1T_1R 271 * 272 * PARAMETERS: walk_state - Current state (contains AML opcode) 273 * 274 * RETURN: Status 275 * 276 * DESCRIPTION: Execute opcode with one argument, one target, and a 277 * return value. 278 * 279 ******************************************************************************/ 280 281acpi_status 282acpi_ex_opcode_1A_1T_1R ( 283 struct acpi_walk_state *walk_state) 284{ 285 acpi_status status = AE_OK; 286 union acpi_operand_object **operand = &walk_state->operands[0]; 287 union acpi_operand_object *return_desc = NULL; 288 union acpi_operand_object *return_desc2 = NULL; 289 u32 temp32; 290 u32 i; 291 acpi_integer power_of_ten; 292 acpi_integer digit; 293 294 295 ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_1T_1R", 296 acpi_ps_get_opcode_name (walk_state->opcode)); 297 298 299 /* Examine the AML opcode */ 300 301 switch (walk_state->opcode) { 302 case AML_BIT_NOT_OP: 303 case AML_FIND_SET_LEFT_BIT_OP: 304 case AML_FIND_SET_RIGHT_BIT_OP: 305 case AML_FROM_BCD_OP: 306 case AML_TO_BCD_OP: 307 case AML_COND_REF_OF_OP: 308 309 /* Create a return object of type Integer for these opcodes */ 310 311 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 312 if (!return_desc) { 313 status = AE_NO_MEMORY; 314 goto cleanup; 315 } 316 317 switch (walk_state->opcode) { 318 case AML_BIT_NOT_OP: /* Not (Operand, Result) */ 319 320 return_desc->integer.value = ~operand[0]->integer.value; 321 break; 322 323 324 case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */ 325 326 return_desc->integer.value = operand[0]->integer.value; 327 328 /* 329 * Acpi specification describes Integer type as a little 330 * endian unsigned value, so this boundary condition is valid. 331 */ 332 for (temp32 = 0; return_desc->integer.value && 333 temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { 334 return_desc->integer.value >>= 1; 335 } 336 337 return_desc->integer.value = temp32; 338 break; 339 340 341 case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */ 342 343 return_desc->integer.value = operand[0]->integer.value; 344 345 /* 346 * The Acpi specification describes Integer type as a little 347 * endian unsigned value, so this boundary condition is valid. 348 */ 349 for (temp32 = 0; return_desc->integer.value && 350 temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) { 351 return_desc->integer.value <<= 1; 352 } 353 354 /* Since the bit position is one-based, subtract from 33 (65) */ 355 356 return_desc->integer.value = temp32 == 0 ? 0 : 357 (ACPI_INTEGER_BIT_SIZE + 1) - temp32; 358 break; 359 360 361 case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */ 362 363 /* 364 * The 64-bit ACPI integer can hold 16 4-bit BCD characters 365 * (if table is 32-bit, integer can hold 8 BCD characters) 366 * Convert each 4-bit BCD value 367 */ 368 power_of_ten = 1; 369 return_desc->integer.value = 0; 370 digit = operand[0]->integer.value; 371 372 /* Convert each BCD digit (each is one nybble wide) */ 373 374 for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { 375 /* Get the least significant 4-bit BCD digit */ 376 377 temp32 = ((u32) digit) & 0xF; 378 379 /* Check the range of the digit */ 380 381 if (temp32 > 9) { 382 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 383 "BCD digit too large (not decimal): 0x%X\n", 384 temp32)); 385 386 status = AE_AML_NUMERIC_OVERFLOW; 387 goto cleanup; 388 } 389 390 /* Sum the digit into the result with the current power of 10 */ 391 392 return_desc->integer.value += (((acpi_integer) temp32) * 393 power_of_ten); 394 395 /* Shift to next BCD digit */ 396 397 digit >>= 4; 398 399 /* Next power of 10 */ 400 401 power_of_ten *= 10; 402 } 403 break; 404 405 406 case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */ 407 408 return_desc->integer.value = 0; 409 digit = operand[0]->integer.value; 410 411 /* Each BCD digit is one nybble wide */ 412 413 for (i = 0; (i < acpi_gbl_integer_nybble_width) && (digit > 0); i++) { 414 (void) acpi_ut_short_divide (digit, 10, &digit, &temp32); 415 416 /* 417 * Insert the BCD digit that resides in the 418 * remainder from above 419 */ 420 return_desc->integer.value |= (((acpi_integer) temp32) << 421 ACPI_MUL_4 (i)); 422 } 423 424 /* Overflow if there is any data left in Digit */ 425 426 if (digit > 0) { 427 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 428 "Integer too large to convert to BCD: %8.8X%8.8X\n", 429 ACPI_FORMAT_UINT64 (operand[0]->integer.value))); 430 status = AE_AML_NUMERIC_OVERFLOW; 431 goto cleanup; 432 } 433 break; 434 435 436 case AML_COND_REF_OF_OP: /* cond_ref_of (source_object, Result) */ 437 438 /* 439 * This op is a little strange because the internal return value is 440 * different than the return value stored in the result descriptor 441 * (There are really two return values) 442 */ 443 if ((struct acpi_namespace_node *) operand[0] == acpi_gbl_root_node) { 444 /* 445 * This means that the object does not exist in the namespace, 446 * return FALSE 447 */ 448 return_desc->integer.value = 0; 449 goto cleanup; 450 } 451 452 /* Get the object reference, store it, and remove our reference */ 453 454 status = acpi_ex_get_object_reference (operand[0], 455 &return_desc2, walk_state); 456 if (ACPI_FAILURE (status)) { 457 goto cleanup; 458 } 459 460 status = acpi_ex_store (return_desc2, operand[1], walk_state); 461 acpi_ut_remove_reference (return_desc2); 462 463 /* The object exists in the namespace, return TRUE */ 464 465 return_desc->integer.value = ACPI_INTEGER_MAX; 466 goto cleanup; 467 468 469 default: 470 /* No other opcodes get here */ 471 break; 472 } 473 break; 474 475 476 case AML_STORE_OP: /* Store (Source, Target) */ 477 478 /* 479 * A store operand is typically a number, string, buffer or lvalue 480 * Be careful about deleting the source object, 481 * since the object itself may have been stored. 482 */ 483 status = acpi_ex_store (operand[0], operand[1], walk_state); 484 if (ACPI_FAILURE (status)) { 485 return_ACPI_STATUS (status); 486 } 487 488 /* It is possible that the Store already produced a return object */ 489 490 if (!walk_state->result_obj) { 491 /* 492 * Normally, we would remove a reference on the Operand[0] 493 * parameter; But since it is being used as the internal return 494 * object (meaning we would normally increment it), the two 495 * cancel out, and we simply don't do anything. 496 */ 497 walk_state->result_obj = operand[0]; 498 walk_state->operands[0] = NULL; /* Prevent deletion */ 499 } 500 return_ACPI_STATUS (status); 501 502 503 /* 504 * ACPI 2.0 Opcodes 505 */ 506 case AML_COPY_OP: /* Copy (Source, Target) */ 507 508 status = acpi_ut_copy_iobject_to_iobject (operand[0], &return_desc, 509 walk_state); 510 break; 511 512 513 case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */ 514 515 status = acpi_ex_convert_to_string (operand[0], &return_desc, 516 ACPI_EXPLICIT_CONVERT_DECIMAL); 517 if (return_desc == operand[0]) { 518 /* No conversion performed, add ref to handle return value */ 519 acpi_ut_add_reference (return_desc); 520 } 521 break; 522 523 524 case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */ 525 526 status = acpi_ex_convert_to_string (operand[0], &return_desc, 527 ACPI_EXPLICIT_CONVERT_HEX); 528 if (return_desc == operand[0]) { 529 /* No conversion performed, add ref to handle return value */ 530 acpi_ut_add_reference (return_desc); 531 } 532 break; 533 534 535 case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */ 536 537 status = acpi_ex_convert_to_buffer (operand[0], &return_desc); 538 if (return_desc == operand[0]) { 539 /* No conversion performed, add ref to handle return value */ 540 acpi_ut_add_reference (return_desc); 541 } 542 break; 543 544 545 case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */ 546 547 status = acpi_ex_convert_to_integer (operand[0], &return_desc, 548 ACPI_ANY_BASE); 549 if (return_desc == operand[0]) { 550 /* No conversion performed, add ref to handle return value */ 551 acpi_ut_add_reference (return_desc); 552 } 553 break; 554 555 556 case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */ 557 case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */ 558 559 /* These are two obsolete opcodes */ 560 561 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 562 "%s is obsolete and not implemented\n", 563 acpi_ps_get_opcode_name (walk_state->opcode))); 564 status = AE_SUPPORT; 565 goto cleanup; 566 567 568 default: /* Unknown opcode */ 569 570 ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_1T_1R: Unknown opcode %X\n", 571 walk_state->opcode)); 572 status = AE_AML_BAD_OPCODE; 573 goto cleanup; 574 } 575 576 if (ACPI_SUCCESS (status)) { 577 /* Store the return value computed above into the target object */ 578 579 status = acpi_ex_store (return_desc, operand[1], walk_state); 580 } 581 582 583cleanup: 584 585 if (!walk_state->result_obj) { 586 walk_state->result_obj = return_desc; 587 } 588 589 /* Delete return object on error */ 590 591 if (ACPI_FAILURE (status)) { 592 acpi_ut_remove_reference (return_desc); 593 } 594 595 return_ACPI_STATUS (status); 596} 597 598 599/******************************************************************************* 600 * 601 * FUNCTION: acpi_ex_opcode_1A_0T_1R 602 * 603 * PARAMETERS: walk_state - Current state (contains AML opcode) 604 * 605 * RETURN: Status 606 * 607 * DESCRIPTION: Execute opcode with one argument, no target, and a return value 608 * 609 ******************************************************************************/ 610 611acpi_status 612acpi_ex_opcode_1A_0T_1R ( 613 struct acpi_walk_state *walk_state) 614{ 615 union acpi_operand_object **operand = &walk_state->operands[0]; 616 union acpi_operand_object *temp_desc; 617 union acpi_operand_object *return_desc = NULL; 618 acpi_status status = AE_OK; 619 u32 type; 620 acpi_integer value; 621 622 623 ACPI_FUNCTION_TRACE_STR ("ex_opcode_1A_0T_1R", 624 acpi_ps_get_opcode_name (walk_state->opcode)); 625 626 627 /* Examine the AML opcode */ 628 629 switch (walk_state->opcode) { 630 case AML_LNOT_OP: /* LNot (Operand) */ 631 632 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 633 if (!return_desc) { 634 status = AE_NO_MEMORY; 635 goto cleanup; 636 } 637 638 /* 639 * Set result to ONES (TRUE) if Value == 0. Note: 640 * return_desc->Integer.Value is initially == 0 (FALSE) from above. 641 */ 642 if (!operand[0]->integer.value) { 643 return_desc->integer.value = ACPI_INTEGER_MAX; 644 } 645 break; 646 647 648 case AML_DECREMENT_OP: /* Decrement (Operand) */ 649 case AML_INCREMENT_OP: /* Increment (Operand) */ 650 651 /* 652 * Create a new integer. Can't just get the base integer and 653 * increment it because it may be an Arg or Field. 654 */ 655 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 656 if (!return_desc) { 657 status = AE_NO_MEMORY; 658 goto cleanup; 659 } 660 661 /* 662 * Since we are expecting a Reference operand, it can be either a 663 * NS Node or an internal object. 664 */ 665 temp_desc = operand[0]; 666 if (ACPI_GET_DESCRIPTOR_TYPE (temp_desc) == ACPI_DESC_TYPE_OPERAND) { 667 /* Internal reference object - prevent deletion */ 668 669 acpi_ut_add_reference (temp_desc); 670 } 671 672 /* 673 * Convert the Reference operand to an Integer (This removes a 674 * reference on the Operand[0] object) 675 * 676 * NOTE: We use LNOT_OP here in order to force resolution of the 677 * reference operand to an actual integer. 678 */ 679 status = acpi_ex_resolve_operands (AML_LNOT_OP, &temp_desc, walk_state); 680 if (ACPI_FAILURE (status)) { 681 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s: bad operand(s) %s\n", 682 acpi_ps_get_opcode_name (walk_state->opcode), 683 acpi_format_exception(status))); 684 685 goto cleanup; 686 } 687 688 /* 689 * temp_desc is now guaranteed to be an Integer object -- 690 * Perform the actual increment or decrement 691 */ 692 if (walk_state->opcode == AML_INCREMENT_OP) { 693 return_desc->integer.value = temp_desc->integer.value +1; 694 } 695 else { 696 return_desc->integer.value = temp_desc->integer.value -1; 697 } 698 699 /* Finished with this Integer object */ 700 701 acpi_ut_remove_reference (temp_desc); 702 703 /* 704 * Store the result back (indirectly) through the original 705 * Reference object 706 */ 707 status = acpi_ex_store (return_desc, operand[0], walk_state); 708 break; 709 710 711 case AML_TYPE_OP: /* object_type (source_object) */ 712 713 /* 714 * Note: The operand is not resolved at this point because we want to 715 * get the associated object, not its value. For example, we don't 716 * want to resolve a field_unit to its value, we want the actual 717 * field_unit object. 718 */ 719 720 /* Get the type of the base object */ 721 722 status = acpi_ex_resolve_multiple (walk_state, operand[0], &type, NULL); 723 if (ACPI_FAILURE (status)) { 724 goto cleanup; 725 } 726 /* Allocate a descriptor to hold the type. */ 727 728 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 729 if (!return_desc) { 730 status = AE_NO_MEMORY; 731 goto cleanup; 732 } 733 734 return_desc->integer.value = type; 735 break; 736 737 738 case AML_SIZE_OF_OP: /* size_of (source_object) */ 739 740 /* 741 * Note: The operand is not resolved at this point because we want to 742 * get the associated object, not its value. 743 */ 744 745 /* Get the base object */ 746 747 status = acpi_ex_resolve_multiple (walk_state, 748 operand[0], &type, &temp_desc); 749 if (ACPI_FAILURE (status)) { 750 goto cleanup; 751 } 752 753 /* 754 * The type of the base object must be integer, buffer, string, or 755 * package. All others are not supported. 756 * 757 * NOTE: Integer is not specifically supported by the ACPI spec, 758 * but is supported implicitly via implicit operand conversion. 759 * rather than bother with conversion, we just use the byte width 760 * global (4 or 8 bytes). 761 */ 762 switch (type) { 763 case ACPI_TYPE_INTEGER: 764 value = acpi_gbl_integer_byte_width; 765 break; 766 767 case ACPI_TYPE_BUFFER: 768 value = temp_desc->buffer.length; 769 break; 770 771 case ACPI_TYPE_STRING: 772 value = temp_desc->string.length; 773 break; 774 775 case ACPI_TYPE_PACKAGE: 776 value = temp_desc->package.count; 777 break; 778 779 default: 780 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 781 "size_of - Operand is not Buf/Int/Str/Pkg - found type %s\n", 782 acpi_ut_get_type_name (type))); 783 status = AE_AML_OPERAND_TYPE; 784 goto cleanup; 785 } 786 787 /* 788 * Now that we have the size of the object, create a result 789 * object to hold the value 790 */ 791 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 792 if (!return_desc) { 793 status = AE_NO_MEMORY; 794 goto cleanup; 795 } 796 797 return_desc->integer.value = value; 798 break; 799 800 801 case AML_REF_OF_OP: /* ref_of (source_object) */ 802 803 status = acpi_ex_get_object_reference (operand[0], &return_desc, walk_state); 804 if (ACPI_FAILURE (status)) { 805 goto cleanup; 806 } 807 break; 808 809 810 case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */ 811 812 /* Check for a method local or argument, or standalone String */ 813 814 if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) != ACPI_DESC_TYPE_NAMED) { 815 switch (ACPI_GET_OBJECT_TYPE (operand[0])) { 816 case ACPI_TYPE_LOCAL_REFERENCE: 817 /* 818 * This is a deref_of (local_x | arg_x) 819 * 820 * Must resolve/dereference the local/arg reference first 821 */ 822 switch (operand[0]->reference.opcode) { 823 case AML_LOCAL_OP: 824 case AML_ARG_OP: 825 826 /* Set Operand[0] to the value of the local/arg */ 827 828 status = acpi_ds_method_data_get_value ( 829 operand[0]->reference.opcode, 830 operand[0]->reference.offset, 831 walk_state, &temp_desc); 832 if (ACPI_FAILURE (status)) { 833 goto cleanup; 834 } 835 836 /* 837 * Delete our reference to the input object and 838 * point to the object just retrieved 839 */ 840 acpi_ut_remove_reference (operand[0]); 841 operand[0] = temp_desc; 842 break; 843 844 case AML_REF_OF_OP: 845 846 /* Get the object to which the reference refers */ 847 848 temp_desc = operand[0]->reference.object; 849 acpi_ut_remove_reference (operand[0]); 850 operand[0] = temp_desc; 851 break; 852 853 default: 854 855 /* Must be an Index op - handled below */ 856 break; 857 } 858 break; 859 860 861 case ACPI_TYPE_STRING: 862 863 /* 864 * This is a deref_of (String). The string is a reference 865 * to a named ACPI object. 866 * 867 * 1) Find the owning Node 868 * 2) Dereference the node to an actual object. Could be a 869 * Field, so we need to resolve the node to a value. 870 */ 871 status = acpi_ns_get_node_by_path (operand[0]->string.pointer, 872 walk_state->scope_info->scope.node, 873 ACPI_NS_SEARCH_PARENT, 874 ACPI_CAST_INDIRECT_PTR ( 875 struct acpi_namespace_node, &return_desc)); 876 if (ACPI_FAILURE (status)) { 877 goto cleanup; 878 } 879 880 status = acpi_ex_resolve_node_to_value ( 881 ACPI_CAST_INDIRECT_PTR ( 882 struct acpi_namespace_node, &return_desc), 883 walk_state); 884 goto cleanup; 885 886 887 default: 888 889 status = AE_AML_OPERAND_TYPE; 890 goto cleanup; 891 } 892 } 893 894 /* Operand[0] may have changed from the code above */ 895 896 if (ACPI_GET_DESCRIPTOR_TYPE (operand[0]) == ACPI_DESC_TYPE_NAMED) { 897 /* 898 * This is a deref_of (object_reference) 899 * Get the actual object from the Node (This is the dereference). 900 * This case may only happen when a local_x or arg_x is 901 * dereferenced above. 902 */ 903 return_desc = acpi_ns_get_attached_object ( 904 (struct acpi_namespace_node *) operand[0]); 905 } 906 else { 907 /* 908 * This must be a reference object produced by either the 909 * Index() or ref_of() operator 910 */ 911 switch (operand[0]->reference.opcode) { 912 case AML_INDEX_OP: 913 914 /* 915 * The target type for the Index operator must be 916 * either a Buffer or a Package 917 */ 918 switch (operand[0]->reference.target_type) { 919 case ACPI_TYPE_BUFFER_FIELD: 920 921 temp_desc = operand[0]->reference.object; 922 923 /* 924 * Create a new object that contains one element of the 925 * buffer -- the element pointed to by the index. 926 * 927 * NOTE: index into a buffer is NOT a pointer to a 928 * sub-buffer of the main buffer, it is only a pointer to a 929 * single element (byte) of the buffer! 930 */ 931 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER); 932 if (!return_desc) { 933 status = AE_NO_MEMORY; 934 goto cleanup; 935 } 936 937 /* 938 * Since we are returning the value of the buffer at the 939 * indexed location, we don't need to add an additional 940 * reference to the buffer itself. 941 */ 942 return_desc->integer.value = 943 temp_desc->buffer.pointer[operand[0]->reference.offset]; 944 break; 945 946 947 case ACPI_TYPE_PACKAGE: 948 949 /* 950 * Return the referenced element of the package. We must 951 * add another reference to the referenced object, however. 952 */ 953 return_desc = *(operand[0]->reference.where); 954 if (!return_desc) { 955 /* 956 * We can't return a NULL dereferenced value. This is 957 * an uninitialized package element and is thus a 958 * severe error. 959 */ 960 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 961 "NULL package element obj %p\n", 962 operand[0])); 963 status = AE_AML_UNINITIALIZED_ELEMENT; 964 goto cleanup; 965 } 966 967 acpi_ut_add_reference (return_desc); 968 break; 969 970 971 default: 972 973 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 974 "Unknown Index target_type %X in obj %p\n", 975 operand[0]->reference.target_type, operand[0])); 976 status = AE_AML_OPERAND_TYPE; 977 goto cleanup; 978 } 979 break; 980 981 982 case AML_REF_OF_OP: 983 984 return_desc = operand[0]->reference.object; 985 986 if (ACPI_GET_DESCRIPTOR_TYPE (return_desc) == 987 ACPI_DESC_TYPE_NAMED) { 988 989 return_desc = acpi_ns_get_attached_object ( 990 (struct acpi_namespace_node *) return_desc); 991 } 992 993 /* Add another reference to the object! */ 994 995 acpi_ut_add_reference (return_desc); 996 break; 997 998 999 default: 1000 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 1001 "Unknown opcode in ref(%p) - %X\n", 1002 operand[0], operand[0]->reference.opcode)); 1003 1004 status = AE_TYPE; 1005 goto cleanup; 1006 } 1007 } 1008 break; 1009 1010 1011 default: 1012 1013 ACPI_REPORT_ERROR (("acpi_ex_opcode_1A_0T_1R: Unknown opcode %X\n", 1014 walk_state->opcode)); 1015 status = AE_AML_BAD_OPCODE; 1016 goto cleanup; 1017 } 1018 1019 1020cleanup: 1021 1022 /* Delete return object on error */ 1023 1024 if (ACPI_FAILURE (status)) { 1025 acpi_ut_remove_reference (return_desc); 1026 } 1027 1028 walk_state->result_obj = return_desc; 1029 return_ACPI_STATUS (status); 1030} 1031