Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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