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