1087 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: exoparg1 - AML execution - opcodes with 1 argument5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acparser.h"13#include "acdispat.h"14#include "acinterp.h"15#include "amlcode.h"16#include "acnamesp.h"17 18#define _COMPONENT ACPI_EXECUTER19ACPI_MODULE_NAME("exoparg1")20 21/*!22 * Naming convention for AML interpreter execution routines.23 *24 * The routines that begin execution of AML opcodes are named with a common25 * convention based upon the number of arguments, the number of target operands,26 * and whether or not a value is returned:27 *28 * AcpiExOpcode_xA_yT_zR29 *30 * Where:31 *32 * xA - ARGUMENTS: The number of arguments (input operands) that are33 * required for this opcode type (0 through 6 args).34 * yT - TARGETS: The number of targets (output operands) that are required35 * for this opcode type (0, 1, or 2 targets).36 * zR - RETURN VALUE: Indicates whether this opcode type returns a value37 * as the function return (0 or 1).38 *39 * The AcpiExOpcode* functions are called via the Dispatcher component with40 * fully resolved operands.41!*/42/*******************************************************************************43 *44 * FUNCTION: acpi_ex_opcode_0A_0T_1R45 *46 * PARAMETERS: walk_state - Current state (contains AML opcode)47 *48 * RETURN: Status49 *50 * DESCRIPTION: Execute operator with no operands, one return value51 *52 ******************************************************************************/53acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)54{55 acpi_status status = AE_OK;56 union acpi_operand_object *return_desc = NULL;57 58 ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R,59 acpi_ps_get_opcode_name(walk_state->opcode));60 61 /* Examine the AML opcode */62 63 switch (walk_state->opcode) {64 case AML_TIMER_OP: /* Timer () */65 66 /* Create a return object of type Integer */67 68 return_desc =69 acpi_ut_create_integer_object(acpi_os_get_timer());70 if (!return_desc) {71 status = AE_NO_MEMORY;72 goto cleanup;73 }74 break;75 76 default: /* Unknown opcode */77 78 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",79 walk_state->opcode));80 status = AE_AML_BAD_OPCODE;81 break;82 }83 84cleanup:85 86 /* Delete return object on error */87 88 if ((ACPI_FAILURE(status)) || walk_state->result_obj) {89 acpi_ut_remove_reference(return_desc);90 walk_state->result_obj = NULL;91 } else {92 /* Save the return value */93 94 walk_state->result_obj = return_desc;95 }96 97 return_ACPI_STATUS(status);98}99 100/*******************************************************************************101 *102 * FUNCTION: acpi_ex_opcode_1A_0T_0R103 *104 * PARAMETERS: walk_state - Current state (contains AML opcode)105 *106 * RETURN: Status107 *108 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on109 * object stack110 *111 ******************************************************************************/112 113acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state)114{115 union acpi_operand_object **operand = &walk_state->operands[0];116 acpi_status status = AE_OK;117 118 ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R,119 acpi_ps_get_opcode_name(walk_state->opcode));120 121 /* Examine the AML opcode */122 123 switch (walk_state->opcode) {124 case AML_RELEASE_OP: /* Release (mutex_object) */125 126 status = acpi_ex_release_mutex(operand[0], walk_state);127 break;128 129 case AML_RESET_OP: /* Reset (event_object) */130 131 status = acpi_ex_system_reset_event(operand[0]);132 break;133 134 case AML_SIGNAL_OP: /* Signal (event_object) */135 136 status = acpi_ex_system_signal_event(operand[0]);137 break;138 139 case AML_SLEEP_OP: /* Sleep (msec_time) */140 141 status = acpi_ex_system_do_sleep(operand[0]->integer.value);142 break;143 144 case AML_STALL_OP: /* Stall (usec_time) */145 146 status =147 acpi_ex_system_do_stall((u32) operand[0]->integer.value);148 break;149 150 case AML_UNLOAD_OP: /* Unload (Handle) */151 152 status = acpi_ex_unload_table(operand[0]);153 break;154 155 default: /* Unknown opcode */156 157 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",158 walk_state->opcode));159 status = AE_AML_BAD_OPCODE;160 break;161 }162 163 return_ACPI_STATUS(status);164}165 166#ifdef _OBSOLETE_CODE /* Was originally used for Load() operator */167/*******************************************************************************168 *169 * FUNCTION: acpi_ex_opcode_1A_1T_0R170 *171 * PARAMETERS: walk_state - Current state (contains AML opcode)172 *173 * RETURN: Status174 *175 * DESCRIPTION: Execute opcode with one argument, one target, and no176 * return value.177 *178 ******************************************************************************/179 180acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)181{182 acpi_status status = AE_OK;183 union acpi_operand_object **operand = &walk_state->operands[0];184 185 ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R,186 acpi_ps_get_opcode_name(walk_state->opcode));187 188 /* Examine the AML opcode */189 190 switch (walk_state->opcode) {191#ifdef _OBSOLETE_CODE192 case AML_LOAD_OP:193 194 status = acpi_ex_load_op(operand[0], operand[1], walk_state);195 break;196#endif197 198 default: /* Unknown opcode */199 200 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",201 walk_state->opcode));202 status = AE_AML_BAD_OPCODE;203 goto cleanup;204 }205 206cleanup:207 208 return_ACPI_STATUS(status);209}210#endif211 212/*******************************************************************************213 *214 * FUNCTION: acpi_ex_opcode_1A_1T_1R215 *216 * PARAMETERS: walk_state - Current state (contains AML opcode)217 *218 * RETURN: Status219 *220 * DESCRIPTION: Execute opcode with one argument, one target, and a221 * return value.222 * January 2022: Added Load operator, with new ACPI 6.4223 * semantics.224 *225 ******************************************************************************/226 227acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)228{229 acpi_status status = AE_OK;230 union acpi_operand_object **operand = &walk_state->operands[0];231 union acpi_operand_object *return_desc = NULL;232 union acpi_operand_object *return_desc2 = NULL;233 u32 temp32;234 u32 i;235 u64 power_of_ten;236 u64 digit;237 238 ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R,239 acpi_ps_get_opcode_name(walk_state->opcode));240 241 /* Examine the AML opcode */242 243 switch (walk_state->opcode) {244 case AML_BIT_NOT_OP:245 case AML_FIND_SET_LEFT_BIT_OP:246 case AML_FIND_SET_RIGHT_BIT_OP:247 case AML_FROM_BCD_OP:248 case AML_LOAD_OP:249 case AML_TO_BCD_OP:250 case AML_CONDITIONAL_REF_OF_OP:251 252 /* Create a return object of type Integer for these opcodes */253 254 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);255 if (!return_desc) {256 status = AE_NO_MEMORY;257 goto cleanup;258 }259 260 switch (walk_state->opcode) {261 case AML_BIT_NOT_OP: /* Not (Operand, Result) */262 263 return_desc->integer.value = ~operand[0]->integer.value;264 break;265 266 case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */267 268 return_desc->integer.value = operand[0]->integer.value;269 270 /*271 * Acpi specification describes Integer type as a little272 * endian unsigned value, so this boundary condition is valid.273 */274 for (temp32 = 0; return_desc->integer.value &&275 temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {276 return_desc->integer.value >>= 1;277 }278 279 return_desc->integer.value = temp32;280 break;281 282 case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */283 284 return_desc->integer.value = operand[0]->integer.value;285 286 /*287 * The Acpi specification describes Integer type as a little288 * endian unsigned value, so this boundary condition is valid.289 */290 for (temp32 = 0; return_desc->integer.value &&291 temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {292 return_desc->integer.value <<= 1;293 }294 295 /* Since the bit position is one-based, subtract from 33 (65) */296 297 return_desc->integer.value =298 temp32 ==299 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32;300 break;301 302 case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */303 /*304 * The 64-bit ACPI integer can hold 16 4-bit BCD characters305 * (if table is 32-bit, integer can hold 8 BCD characters)306 * Convert each 4-bit BCD value307 */308 power_of_ten = 1;309 return_desc->integer.value = 0;310 digit = operand[0]->integer.value;311 312 /* Convert each BCD digit (each is one nybble wide) */313 314 for (i = 0;315 (i < acpi_gbl_integer_nybble_width) && (digit > 0);316 i++) {317 318 /* Get the least significant 4-bit BCD digit */319 320 temp32 = ((u32) digit) & 0xF;321 322 /* Check the range of the digit */323 324 if (temp32 > 9) {325 ACPI_ERROR((AE_INFO,326 "BCD digit too large (not decimal): 0x%X",327 temp32));328 329 status = AE_AML_NUMERIC_OVERFLOW;330 goto cleanup;331 }332 333 /* Sum the digit into the result with the current power of 10 */334 335 return_desc->integer.value +=336 (((u64) temp32) * power_of_ten);337 338 /* Shift to next BCD digit */339 340 digit >>= 4;341 342 /* Next power of 10 */343 344 power_of_ten *= 10;345 }346 break;347 348 case AML_LOAD_OP: /* Result1 = Load (Operand[0], Result1) */349 350 return_desc->integer.value = 0;351 status =352 acpi_ex_load_op(operand[0], return_desc,353 walk_state);354 if (ACPI_SUCCESS(status)) {355 356 /* Return -1 (non-zero) indicates success */357 358 return_desc->integer.value = 0xFFFFFFFFFFFFFFFF;359 }360 break;361 362 case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */363 364 return_desc->integer.value = 0;365 digit = operand[0]->integer.value;366 367 /* Each BCD digit is one nybble wide */368 369 for (i = 0;370 (i < acpi_gbl_integer_nybble_width) && (digit > 0);371 i++) {372 (void)acpi_ut_short_divide(digit, 10, &digit,373 &temp32);374 375 /*376 * Insert the BCD digit that resides in the377 * remainder from above378 */379 return_desc->integer.value |=380 (((u64) temp32) << ACPI_MUL_4(i));381 }382 383 /* Overflow if there is any data left in Digit */384 385 if (digit > 0) {386 ACPI_ERROR((AE_INFO,387 "Integer too large to convert to BCD: 0x%8.8X%8.8X",388 ACPI_FORMAT_UINT64(operand[0]->389 integer.value)));390 status = AE_AML_NUMERIC_OVERFLOW;391 goto cleanup;392 }393 break;394 395 case AML_CONDITIONAL_REF_OF_OP: /* cond_ref_of (source_object, Result) */396 /*397 * This op is a little strange because the internal return value is398 * different than the return value stored in the result descriptor399 * (There are really two return values)400 */401 if ((struct acpi_namespace_node *)operand[0] ==402 acpi_gbl_root_node) {403 /*404 * This means that the object does not exist in the namespace,405 * return FALSE406 */407 return_desc->integer.value = 0;408 goto cleanup;409 }410 411 /* Get the object reference, store it, and remove our reference */412 413 status = acpi_ex_get_object_reference(operand[0],414 &return_desc2,415 walk_state);416 if (ACPI_FAILURE(status)) {417 goto cleanup;418 }419 420 status =421 acpi_ex_store(return_desc2, operand[1], walk_state);422 acpi_ut_remove_reference(return_desc2);423 424 /* The object exists in the namespace, return TRUE */425 426 return_desc->integer.value = ACPI_UINT64_MAX;427 goto cleanup;428 429 default:430 431 /* No other opcodes get here */432 433 break;434 }435 break;436 437 case AML_STORE_OP: /* Store (Source, Target) */438 /*439 * A store operand is typically a number, string, buffer or lvalue440 * Be careful about deleting the source object,441 * since the object itself may have been stored.442 */443 status = acpi_ex_store(operand[0], operand[1], walk_state);444 if (ACPI_FAILURE(status)) {445 return_ACPI_STATUS(status);446 }447 448 /* It is possible that the Store already produced a return object */449 450 if (!walk_state->result_obj) {451 /*452 * Normally, we would remove a reference on the Operand[0]453 * parameter; But since it is being used as the internal return454 * object (meaning we would normally increment it), the two455 * cancel out, and we simply don't do anything.456 */457 walk_state->result_obj = operand[0];458 walk_state->operands[0] = NULL; /* Prevent deletion */459 }460 return_ACPI_STATUS(status);461 462 /*463 * ACPI 2.0 Opcodes464 */465 case AML_COPY_OBJECT_OP: /* copy_object (Source, Target) */466 467 status =468 acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc,469 walk_state);470 break;471 472 case AML_TO_DECIMAL_STRING_OP: /* to_decimal_string (Data, Result) */473 474 status =475 acpi_ex_convert_to_string(operand[0], &return_desc,476 ACPI_EXPLICIT_CONVERT_DECIMAL);477 if (return_desc == operand[0]) {478 479 /* No conversion performed, add ref to handle return value */480 481 acpi_ut_add_reference(return_desc);482 }483 break;484 485 case AML_TO_HEX_STRING_OP: /* to_hex_string (Data, Result) */486 487 status =488 acpi_ex_convert_to_string(operand[0], &return_desc,489 ACPI_EXPLICIT_CONVERT_HEX);490 if (return_desc == operand[0]) {491 492 /* No conversion performed, add ref to handle return value */493 494 acpi_ut_add_reference(return_desc);495 }496 break;497 498 case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */499 500 status = acpi_ex_convert_to_buffer(operand[0], &return_desc);501 if (return_desc == operand[0]) {502 503 /* No conversion performed, add ref to handle return value */504 505 acpi_ut_add_reference(return_desc);506 }507 break;508 509 case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */510 511 /* Perform "explicit" conversion */512 513 status =514 acpi_ex_convert_to_integer(operand[0], &return_desc, 0);515 if (return_desc == operand[0]) {516 517 /* No conversion performed, add ref to handle return value */518 519 acpi_ut_add_reference(return_desc);520 }521 break;522 523 case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */524 case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */525 526 /* These are two obsolete opcodes */527 528 ACPI_ERROR((AE_INFO,529 "%s is obsolete and not implemented",530 acpi_ps_get_opcode_name(walk_state->opcode)));531 status = AE_SUPPORT;532 goto cleanup;533 534 default: /* Unknown opcode */535 536 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",537 walk_state->opcode));538 status = AE_AML_BAD_OPCODE;539 goto cleanup;540 }541 542 if (ACPI_SUCCESS(status)) {543 544 /* Store the return value computed above into the target object */545 546 status = acpi_ex_store(return_desc, operand[1], walk_state);547 }548 549cleanup:550 551 /* Delete return object on error */552 553 if (ACPI_FAILURE(status)) {554 acpi_ut_remove_reference(return_desc);555 }556 557 /* Save return object on success */558 559 else if (!walk_state->result_obj) {560 walk_state->result_obj = return_desc;561 }562 563 return_ACPI_STATUS(status);564}565 566/*******************************************************************************567 *568 * FUNCTION: acpi_ex_opcode_1A_0T_1R569 *570 * PARAMETERS: walk_state - Current state (contains AML opcode)571 *572 * RETURN: Status573 *574 * DESCRIPTION: Execute opcode with one argument, no target, and a return value575 *576 ******************************************************************************/577 578acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)579{580 union acpi_operand_object **operand = &walk_state->operands[0];581 union acpi_operand_object *temp_desc;582 union acpi_operand_object *return_desc = NULL;583 acpi_status status = AE_OK;584 u32 type;585 u64 value;586 587 ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R,588 acpi_ps_get_opcode_name(walk_state->opcode));589 590 /* Examine the AML opcode */591 592 switch (walk_state->opcode) {593 case AML_LOGICAL_NOT_OP: /* LNot (Operand) */594 595 return_desc = acpi_ut_create_integer_object((u64) 0);596 if (!return_desc) {597 status = AE_NO_MEMORY;598 goto cleanup;599 }600 601 /*602 * Set result to ONES (TRUE) if Value == 0. Note:603 * return_desc->Integer.Value is initially == 0 (FALSE) from above.604 */605 if (!operand[0]->integer.value) {606 return_desc->integer.value = ACPI_UINT64_MAX;607 }608 break;609 610 case AML_DECREMENT_OP: /* Decrement (Operand) */611 case AML_INCREMENT_OP: /* Increment (Operand) */612 /*613 * Create a new integer. Can't just get the base integer and614 * increment it because it may be an Arg or Field.615 */616 return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);617 if (!return_desc) {618 status = AE_NO_MEMORY;619 goto cleanup;620 }621 622 /*623 * Since we are expecting a Reference operand, it can be either a624 * NS Node or an internal object.625 */626 temp_desc = operand[0];627 if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==628 ACPI_DESC_TYPE_OPERAND) {629 630 /* Internal reference object - prevent deletion */631 632 acpi_ut_add_reference(temp_desc);633 }634 635 /*636 * Convert the Reference operand to an Integer (This removes a637 * reference on the Operand[0] object)638 *639 * NOTE: We use LNOT_OP here in order to force resolution of the640 * reference operand to an actual integer.641 */642 status = acpi_ex_resolve_operands(AML_LOGICAL_NOT_OP,643 &temp_desc, walk_state);644 if (ACPI_FAILURE(status)) {645 ACPI_EXCEPTION((AE_INFO, status,646 "While resolving operands for [%s]",647 acpi_ps_get_opcode_name(walk_state->648 opcode)));649 650 goto cleanup;651 }652 653 /*654 * temp_desc is now guaranteed to be an Integer object --655 * Perform the actual increment or decrement656 */657 if (walk_state->opcode == AML_INCREMENT_OP) {658 return_desc->integer.value =659 temp_desc->integer.value + 1;660 } else {661 return_desc->integer.value =662 temp_desc->integer.value - 1;663 }664 665 /* Finished with this Integer object */666 667 acpi_ut_remove_reference(temp_desc);668 669 /*670 * Store the result back (indirectly) through the original671 * Reference object672 */673 status = acpi_ex_store(return_desc, operand[0], walk_state);674 break;675 676 case AML_OBJECT_TYPE_OP: /* object_type (source_object) */677 /*678 * Note: The operand is not resolved at this point because we want to679 * get the associated object, not its value. For example, we don't680 * want to resolve a field_unit to its value, we want the actual681 * field_unit object.682 */683 684 /* Get the type of the base object */685 686 status =687 acpi_ex_resolve_multiple(walk_state, operand[0], &type,688 NULL);689 if (ACPI_FAILURE(status)) {690 goto cleanup;691 }692 693 /* Allocate a descriptor to hold the type. */694 695 return_desc = acpi_ut_create_integer_object((u64) type);696 if (!return_desc) {697 status = AE_NO_MEMORY;698 goto cleanup;699 }700 break;701 702 case AML_SIZE_OF_OP: /* size_of (source_object) */703 /*704 * Note: The operand is not resolved at this point because we want to705 * get the associated object, not its value.706 */707 708 /* Get the base object */709 710 status =711 acpi_ex_resolve_multiple(walk_state, operand[0], &type,712 &temp_desc);713 if (ACPI_FAILURE(status)) {714 goto cleanup;715 }716 717 /*718 * The type of the base object must be integer, buffer, string, or719 * package. All others are not supported.720 *721 * NOTE: Integer is not specifically supported by the ACPI spec,722 * but is supported implicitly via implicit operand conversion.723 * rather than bother with conversion, we just use the byte width724 * global (4 or 8 bytes).725 */726 switch (type) {727 case ACPI_TYPE_INTEGER:728 729 value = acpi_gbl_integer_byte_width;730 break;731 732 case ACPI_TYPE_STRING:733 734 value = temp_desc->string.length;735 break;736 737 case ACPI_TYPE_BUFFER:738 739 /* Buffer arguments may not be evaluated at this point */740 741 status = acpi_ds_get_buffer_arguments(temp_desc);742 value = temp_desc->buffer.length;743 break;744 745 case ACPI_TYPE_PACKAGE:746 747 /* Package arguments may not be evaluated at this point */748 749 status = acpi_ds_get_package_arguments(temp_desc);750 value = temp_desc->package.count;751 break;752 753 default:754 755 ACPI_ERROR((AE_INFO,756 "Operand must be Buffer/Integer/String/Package"757 " - found type %s",758 acpi_ut_get_type_name(type)));759 760 status = AE_AML_OPERAND_TYPE;761 goto cleanup;762 }763 764 if (ACPI_FAILURE(status)) {765 goto cleanup;766 }767 768 /*769 * Now that we have the size of the object, create a result770 * object to hold the value771 */772 return_desc = acpi_ut_create_integer_object(value);773 if (!return_desc) {774 status = AE_NO_MEMORY;775 goto cleanup;776 }777 break;778 779 case AML_REF_OF_OP: /* ref_of (source_object) */780 781 status =782 acpi_ex_get_object_reference(operand[0], &return_desc,783 walk_state);784 if (ACPI_FAILURE(status)) {785 goto cleanup;786 }787 break;788 789 case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */790 791 /* Check for a method local or argument, or standalone String */792 793 if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==794 ACPI_DESC_TYPE_NAMED) {795 temp_desc =796 acpi_ns_get_attached_object((struct797 acpi_namespace_node *)798 operand[0]);799 if (temp_desc800 && ((temp_desc->common.type == ACPI_TYPE_STRING)801 || (temp_desc->common.type ==802 ACPI_TYPE_LOCAL_REFERENCE))) {803 operand[0] = temp_desc;804 acpi_ut_add_reference(temp_desc);805 } else {806 status = AE_AML_OPERAND_TYPE;807 goto cleanup;808 }809 } else {810 switch ((operand[0])->common.type) {811 case ACPI_TYPE_LOCAL_REFERENCE:812 /*813 * This is a deref_of (local_x | arg_x)814 *815 * Must resolve/dereference the local/arg reference first816 */817 switch (operand[0]->reference.class) {818 case ACPI_REFCLASS_LOCAL:819 case ACPI_REFCLASS_ARG:820 821 /* Set Operand[0] to the value of the local/arg */822 823 status =824 acpi_ds_method_data_get_value825 (operand[0]->reference.class,826 operand[0]->reference.value,827 walk_state, &temp_desc);828 if (ACPI_FAILURE(status)) {829 goto cleanup;830 }831 832 /*833 * Delete our reference to the input object and834 * point to the object just retrieved835 */836 acpi_ut_remove_reference(operand[0]);837 operand[0] = temp_desc;838 break;839 840 case ACPI_REFCLASS_REFOF:841 842 /* Get the object to which the reference refers */843 844 temp_desc =845 operand[0]->reference.object;846 acpi_ut_remove_reference(operand[0]);847 operand[0] = temp_desc;848 break;849 850 default:851 852 /* Must be an Index op - handled below */853 break;854 }855 break;856 857 case ACPI_TYPE_STRING:858 859 break;860 861 default:862 863 status = AE_AML_OPERAND_TYPE;864 goto cleanup;865 }866 }867 868 if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=869 ACPI_DESC_TYPE_NAMED) {870 if ((operand[0])->common.type == ACPI_TYPE_STRING) {871 /*872 * This is a deref_of (String). The string is a reference873 * to a named ACPI object.874 *875 * 1) Find the owning Node876 * 2) Dereference the node to an actual object. Could be a877 * Field, so we need to resolve the node to a value.878 */879 status =880 acpi_ns_get_node_unlocked(walk_state->881 scope_info->scope.882 node,883 operand[0]->884 string.pointer,885 ACPI_NS_SEARCH_PARENT,886 ACPI_CAST_INDIRECT_PTR887 (struct888 acpi_namespace_node,889 &return_desc));890 if (ACPI_FAILURE(status)) {891 goto cleanup;892 }893 894 status =895 acpi_ex_resolve_node_to_value896 (ACPI_CAST_INDIRECT_PTR897 (struct acpi_namespace_node, &return_desc),898 walk_state);899 goto cleanup;900 }901 }902 903 /* Operand[0] may have changed from the code above */904 905 if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==906 ACPI_DESC_TYPE_NAMED) {907 /*908 * This is a deref_of (object_reference)909 * Get the actual object from the Node (This is the dereference).910 * This case may only happen when a local_x or arg_x is911 * dereferenced above, or for references to device and912 * thermal objects.913 */914 switch (((struct acpi_namespace_node *)operand[0])->915 type) {916 case ACPI_TYPE_DEVICE:917 case ACPI_TYPE_THERMAL:918 919 /* These types have no node subobject, return the NS node */920 921 return_desc = operand[0];922 break;923 924 default:925 /* For most types, get the object attached to the node */926 927 return_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)operand[0]);928 acpi_ut_add_reference(return_desc);929 break;930 }931 } else {932 /*933 * This must be a reference object produced by either the934 * Index() or ref_of() operator935 */936 switch (operand[0]->reference.class) {937 case ACPI_REFCLASS_INDEX:938 /*939 * The target type for the Index operator must be940 * either a Buffer or a Package941 */942 switch (operand[0]->reference.target_type) {943 case ACPI_TYPE_BUFFER_FIELD:944 945 temp_desc =946 operand[0]->reference.object;947 948 /*949 * Create a new object that contains one element of the950 * buffer -- the element pointed to by the index.951 *952 * NOTE: index into a buffer is NOT a pointer to a953 * sub-buffer of the main buffer, it is only a pointer to a954 * single element (byte) of the buffer!955 *956 * Since we are returning the value of the buffer at the957 * indexed location, we don't need to add an additional958 * reference to the buffer itself.959 */960 return_desc =961 acpi_ut_create_integer_object((u64)962 temp_desc->buffer.pointer[operand[0]->reference.value]);963 if (!return_desc) {964 status = AE_NO_MEMORY;965 goto cleanup;966 }967 break;968 969 case ACPI_TYPE_PACKAGE:970 /*971 * Return the referenced element of the package. We must972 * add another reference to the referenced object, however.973 */974 return_desc =975 *(operand[0]->reference.where);976 if (!return_desc) {977 /*978 * Element is NULL, do not allow the dereference.979 * This provides compatibility with other ACPI980 * implementations.981 */982 return_ACPI_STATUS983 (AE_AML_UNINITIALIZED_ELEMENT);984 }985 986 acpi_ut_add_reference(return_desc);987 break;988 989 default:990 991 ACPI_ERROR((AE_INFO,992 "Unknown Index TargetType 0x%X in reference object %p",993 operand[0]->reference.994 target_type, operand[0]));995 996 status = AE_AML_OPERAND_TYPE;997 goto cleanup;998 }999 break;1000 1001 case ACPI_REFCLASS_REFOF:1002 1003 return_desc = operand[0]->reference.object;1004 1005 if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==1006 ACPI_DESC_TYPE_NAMED) {1007 return_desc =1008 acpi_ns_get_attached_object((struct1009 acpi_namespace_node1010 *)1011 return_desc);1012 if (!return_desc) {1013 break;1014 }1015 1016 /*1017 * June 2013:1018 * buffer_fields/field_units require additional resolution1019 */1020 switch (return_desc->common.type) {1021 case ACPI_TYPE_BUFFER_FIELD:1022 case ACPI_TYPE_LOCAL_REGION_FIELD:1023 case ACPI_TYPE_LOCAL_BANK_FIELD:1024 case ACPI_TYPE_LOCAL_INDEX_FIELD:1025 1026 status =1027 acpi_ex_read_data_from_field1028 (walk_state, return_desc,1029 &temp_desc);1030 if (ACPI_FAILURE(status)) {1031 return_ACPI_STATUS1032 (status);1033 }1034 1035 return_desc = temp_desc;1036 break;1037 1038 default:1039 1040 /* Add another reference to the object */1041 1042 acpi_ut_add_reference1043 (return_desc);1044 break;1045 }1046 }1047 break;1048 1049 default:1050 1051 ACPI_ERROR((AE_INFO,1052 "Unknown class in reference(%p) - 0x%2.2X",1053 operand[0],1054 operand[0]->reference.class));1055 1056 status = AE_TYPE;1057 goto cleanup;1058 }1059 }1060 break;1061 1062 default:1063 1064 ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",1065 walk_state->opcode));1066 1067 status = AE_AML_BAD_OPCODE;1068 goto cleanup;1069 }1070 1071cleanup:1072 1073 /* Delete return object on error */1074 1075 if (ACPI_FAILURE(status)) {1076 acpi_ut_remove_reference(return_desc);1077 }1078 1079 /* Save return object on success */1080 1081 else {1082 walk_state->result_obj = return_desc;1083 }1084 1085 return_ACPI_STATUS(status);1086}1087