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