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