1 /******************************************************************************
   2  *
   3  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 #define __EXMISC_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acinterp.h"
  49 #include "amlcode.h"
  50 #include "amlresrc.h"
  51 
  52 
  53 #define _COMPONENT          ACPI_EXECUTER
  54         ACPI_MODULE_NAME    ("exmisc")
  55 
  56 
  57 /*******************************************************************************
  58  *
  59  * FUNCTION:    AcpiExGetObjectReference
  60  *
  61  * PARAMETERS:  ObjDesc             - Create a reference to this object
  62  *              ReturnDesc          - Where to store the reference
  63  *              WalkState           - Current state
  64  *
  65  * RETURN:      Status
  66  *
  67  * DESCRIPTION: Obtain and return a "reference" to the target object
  68  *              Common code for the RefOfOp and the CondRefOfOp.
  69  *
  70  ******************************************************************************/
  71 
  72 ACPI_STATUS
  73 AcpiExGetObjectReference (
  74     ACPI_OPERAND_OBJECT     *ObjDesc,
  75     ACPI_OPERAND_OBJECT     **ReturnDesc,
  76     ACPI_WALK_STATE         *WalkState)
  77 {
  78     ACPI_OPERAND_OBJECT     *ReferenceObj;
  79     ACPI_OPERAND_OBJECT     *ReferencedObj;
  80 
  81 
  82     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
  83 
  84 
  85     *ReturnDesc = NULL;
  86 
  87     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
  88     {
  89     case ACPI_DESC_TYPE_OPERAND:
  90 
  91         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
  92         {
  93             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
  94         }
  95 
  96         /*
  97          * Must be a reference to a Local or Arg
  98          */
  99         switch (ObjDesc->Reference.Class)
 100         {
 101         case ACPI_REFCLASS_LOCAL:
 102         case ACPI_REFCLASS_ARG:
 103         case ACPI_REFCLASS_DEBUG:
 104 
 105             /* The referenced object is the pseudo-node for the local/arg */
 106 
 107             ReferencedObj = ObjDesc->Reference.Object;
 108             break;
 109 
 110         default:
 111 
 112             ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X",
 113                 ObjDesc->Reference.Class));
 114             return_ACPI_STATUS (AE_AML_INTERNAL);
 115         }
 116         break;
 117 
 118     case ACPI_DESC_TYPE_NAMED:
 119         /*
 120          * A named reference that has already been resolved to a Node
 121          */
 122         ReferencedObj = ObjDesc;
 123         break;
 124 
 125     default:
 126 
 127         ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
 128             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
 129         return_ACPI_STATUS (AE_TYPE);
 130     }
 131 
 132 
 133     /* Create a new reference object */
 134 
 135     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
 136     if (!ReferenceObj)
 137     {
 138         return_ACPI_STATUS (AE_NO_MEMORY);
 139     }
 140 
 141     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
 142     ReferenceObj->Reference.Object = ReferencedObj;
 143     *ReturnDesc = ReferenceObj;
 144 
 145     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
 146         "Object %p Type [%s], returning Reference %p\n",
 147         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
 148 
 149     return_ACPI_STATUS (AE_OK);
 150 }
 151 
 152 
 153 /*******************************************************************************
 154  *
 155  * FUNCTION:    AcpiExConcatTemplate
 156  *
 157  * PARAMETERS:  Operand0            - First source object
 158  *              Operand1            - Second source object
 159  *              ActualReturnDesc    - Where to place the return object
 160  *              WalkState           - Current walk state
 161  *
 162  * RETURN:      Status
 163  *
 164  * DESCRIPTION: Concatenate two resource templates
 165  *
 166  ******************************************************************************/
 167 
 168 ACPI_STATUS
 169 AcpiExConcatTemplate (
 170     ACPI_OPERAND_OBJECT     *Operand0,
 171     ACPI_OPERAND_OBJECT     *Operand1,
 172     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
 173     ACPI_WALK_STATE         *WalkState)
 174 {
 175     ACPI_STATUS             Status;
 176     ACPI_OPERAND_OBJECT     *ReturnDesc;
 177     UINT8                   *NewBuf;
 178     UINT8                   *EndTag;
 179     ACPI_SIZE               Length0;
 180     ACPI_SIZE               Length1;
 181     ACPI_SIZE               NewLength;
 182 
 183 
 184     ACPI_FUNCTION_TRACE (ExConcatTemplate);
 185 
 186 
 187     /*
 188      * Find the EndTag descriptor in each resource template.
 189      * Note1: returned pointers point TO the EndTag, not past it.
 190      * Note2: zero-length buffers are allowed; treated like one EndTag
 191      */
 192 
 193     /* Get the length of the first resource template */
 194 
 195     Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
 196     if (ACPI_FAILURE (Status))
 197     {
 198         return_ACPI_STATUS (Status);
 199     }
 200 
 201     Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
 202 
 203     /* Get the length of the second resource template */
 204 
 205     Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
 206     if (ACPI_FAILURE (Status))
 207     {
 208         return_ACPI_STATUS (Status);
 209     }
 210 
 211     Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
 212 
 213     /* Combine both lengths, minimum size will be 2 for EndTag */
 214 
 215     NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
 216 
 217     /* Create a new buffer object for the result (with one EndTag) */
 218 
 219     ReturnDesc = AcpiUtCreateBufferObject (NewLength);
 220     if (!ReturnDesc)
 221     {
 222         return_ACPI_STATUS (AE_NO_MEMORY);
 223     }
 224 
 225     /*
 226      * Copy the templates to the new buffer, 0 first, then 1 follows. One
 227      * EndTag descriptor is copied from Operand1.
 228      */
 229     NewBuf = ReturnDesc->Buffer.Pointer;
 230     ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0);
 231     ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
 232 
 233     /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
 234 
 235     NewBuf[NewLength - 1] = 0;
 236     NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
 237 
 238     /* Return the completed resource template */
 239 
 240     *ActualReturnDesc = ReturnDesc;
 241     return_ACPI_STATUS (AE_OK);
 242 }
 243 
 244 
 245 /*******************************************************************************
 246  *
 247  * FUNCTION:    AcpiExDoConcatenate
 248  *
 249  * PARAMETERS:  Operand0            - First source object
 250  *              Operand1            - Second source object
 251  *              ActualReturnDesc    - Where to place the return object
 252  *              WalkState           - Current walk state
 253  *
 254  * RETURN:      Status
 255  *
 256  * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
 257  *
 258  ******************************************************************************/
 259 
 260 ACPI_STATUS
 261 AcpiExDoConcatenate (
 262     ACPI_OPERAND_OBJECT     *Operand0,
 263     ACPI_OPERAND_OBJECT     *Operand1,
 264     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
 265     ACPI_WALK_STATE         *WalkState)
 266 {
 267     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
 268     ACPI_OPERAND_OBJECT     *ReturnDesc;
 269     char                    *NewBuf;
 270     ACPI_STATUS             Status;
 271 
 272 
 273     ACPI_FUNCTION_TRACE (ExDoConcatenate);
 274 
 275 
 276     /*
 277      * Convert the second operand if necessary. The first operand
 278      * determines the type of the second operand, (See the Data Types
 279      * section of the ACPI specification.)  Both object types are
 280      * guaranteed to be either Integer/String/Buffer by the operand
 281      * resolution mechanism.
 282      */
 283     switch (Operand0->Common.Type)
 284     {
 285     case ACPI_TYPE_INTEGER:
 286 
 287         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
 288         break;
 289 
 290     case ACPI_TYPE_STRING:
 291 
 292         Status = AcpiExConvertToString (Operand1, &LocalOperand1,
 293                     ACPI_IMPLICIT_CONVERT_HEX);
 294         break;
 295 
 296     case ACPI_TYPE_BUFFER:
 297 
 298         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
 299         break;
 300 
 301     default:
 302 
 303         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
 304             Operand0->Common.Type));
 305         Status = AE_AML_INTERNAL;
 306     }
 307 
 308     if (ACPI_FAILURE (Status))
 309     {
 310         goto Cleanup;
 311     }
 312 
 313     /*
 314      * Both operands are now known to be the same object type
 315      * (Both are Integer, String, or Buffer), and we can now perform the
 316      * concatenation.
 317      */
 318 
 319     /*
 320      * There are three cases to handle:
 321      *
 322      * 1) Two Integers concatenated to produce a new Buffer
 323      * 2) Two Strings concatenated to produce a new String
 324      * 3) Two Buffers concatenated to produce a new Buffer
 325      */
 326     switch (Operand0->Common.Type)
 327     {
 328     case ACPI_TYPE_INTEGER:
 329 
 330         /* Result of two Integers is a Buffer */
 331         /* Need enough buffer space for two integers */
 332 
 333         ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE)
 334                             ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
 335         if (!ReturnDesc)
 336         {
 337             Status = AE_NO_MEMORY;
 338             goto Cleanup;
 339         }
 340 
 341         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
 342 
 343         /* Copy the first integer, LSB first */
 344 
 345         ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value,
 346                         AcpiGbl_IntegerByteWidth);
 347 
 348         /* Copy the second integer (LSB first) after the first */
 349 
 350         ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth,
 351                         &LocalOperand1->Integer.Value,
 352                         AcpiGbl_IntegerByteWidth);
 353         break;
 354 
 355     case ACPI_TYPE_STRING:
 356 
 357         /* Result of two Strings is a String */
 358 
 359         ReturnDesc = AcpiUtCreateStringObject (
 360                         ((ACPI_SIZE) Operand0->String.Length +
 361                         LocalOperand1->String.Length));
 362         if (!ReturnDesc)
 363         {
 364             Status = AE_NO_MEMORY;
 365             goto Cleanup;
 366         }
 367 
 368         NewBuf = ReturnDesc->String.Pointer;
 369 
 370         /* Concatenate the strings */
 371 
 372         ACPI_STRCPY (NewBuf, Operand0->String.Pointer);
 373         ACPI_STRCPY (NewBuf + Operand0->String.Length,
 374                         LocalOperand1->String.Pointer);
 375         break;
 376 
 377     case ACPI_TYPE_BUFFER:
 378 
 379         /* Result of two Buffers is a Buffer */
 380 
 381         ReturnDesc = AcpiUtCreateBufferObject (
 382                         ((ACPI_SIZE) Operand0->Buffer.Length +
 383                         LocalOperand1->Buffer.Length));
 384         if (!ReturnDesc)
 385         {
 386             Status = AE_NO_MEMORY;
 387             goto Cleanup;
 388         }
 389 
 390         NewBuf = (char *) ReturnDesc->Buffer.Pointer;
 391 
 392         /* Concatenate the buffers */
 393 
 394         ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer,
 395                         Operand0->Buffer.Length);
 396         ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length,
 397                         LocalOperand1->Buffer.Pointer,
 398                         LocalOperand1->Buffer.Length);
 399         break;
 400 
 401     default:
 402 
 403         /* Invalid object type, should not happen here */
 404 
 405         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
 406             Operand0->Common.Type));
 407         Status =AE_AML_INTERNAL;
 408         goto Cleanup;
 409     }
 410 
 411     *ActualReturnDesc = ReturnDesc;
 412 
 413 Cleanup:
 414     if (LocalOperand1 != Operand1)
 415     {
 416         AcpiUtRemoveReference (LocalOperand1);
 417     }
 418     return_ACPI_STATUS (Status);
 419 }
 420 
 421 
 422 /*******************************************************************************
 423  *
 424  * FUNCTION:    AcpiExDoMathOp
 425  *
 426  * PARAMETERS:  Opcode              - AML opcode
 427  *              Integer0            - Integer operand #0
 428  *              Integer1            - Integer operand #1
 429  *
 430  * RETURN:      Integer result of the operation
 431  *
 432  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
 433  *              math functions here is to prevent a lot of pointer dereferencing
 434  *              to obtain the operands.
 435  *
 436  ******************************************************************************/
 437 
 438 UINT64
 439 AcpiExDoMathOp (
 440     UINT16                  Opcode,
 441     UINT64                  Integer0,
 442     UINT64                  Integer1)
 443 {
 444 
 445     ACPI_FUNCTION_ENTRY ();
 446 
 447 
 448     switch (Opcode)
 449     {
 450     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
 451 
 452         return (Integer0 + Integer1);
 453 
 454     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
 455 
 456         return (Integer0 & Integer1);
 457 
 458     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
 459 
 460         return (~(Integer0 & Integer1));
 461 
 462     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
 463 
 464         return (Integer0 | Integer1);
 465 
 466     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
 467 
 468         return (~(Integer0 | Integer1));
 469 
 470     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
 471 
 472         return (Integer0 ^ Integer1);
 473 
 474     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
 475 
 476         return (Integer0 * Integer1);
 477 
 478     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
 479 
 480         /*
 481          * We need to check if the shiftcount is larger than the integer bit
 482          * width since the behavior of this is not well-defined in the C language.
 483          */
 484         if (Integer1 >= AcpiGbl_IntegerBitWidth)
 485         {
 486             return (0);
 487         }
 488         return (Integer0 << Integer1);
 489 
 490     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
 491 
 492         /*
 493          * We need to check if the shiftcount is larger than the integer bit
 494          * width since the behavior of this is not well-defined in the C language.
 495          */
 496         if (Integer1 >= AcpiGbl_IntegerBitWidth)
 497         {
 498             return (0);
 499         }
 500         return (Integer0 >> Integer1);
 501 
 502     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
 503 
 504         return (Integer0 - Integer1);
 505 
 506     default:
 507 
 508         return (0);
 509     }
 510 }
 511 
 512 
 513 /*******************************************************************************
 514  *
 515  * FUNCTION:    AcpiExDoLogicalNumericOp
 516  *
 517  * PARAMETERS:  Opcode              - AML opcode
 518  *              Integer0            - Integer operand #0
 519  *              Integer1            - Integer operand #1
 520  *              LogicalResult       - TRUE/FALSE result of the operation
 521  *
 522  * RETURN:      Status
 523  *
 524  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
 525  *              operators (LAnd and LOr), both operands must be integers.
 526  *
 527  *              Note: cleanest machine code seems to be produced by the code
 528  *              below, rather than using statements of the form:
 529  *                  Result = (Integer0 && Integer1);
 530  *
 531  ******************************************************************************/
 532 
 533 ACPI_STATUS
 534 AcpiExDoLogicalNumericOp (
 535     UINT16                  Opcode,
 536     UINT64                  Integer0,
 537     UINT64                  Integer1,
 538     BOOLEAN                 *LogicalResult)
 539 {
 540     ACPI_STATUS             Status = AE_OK;
 541     BOOLEAN                 LocalResult = FALSE;
 542 
 543 
 544     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
 545 
 546 
 547     switch (Opcode)
 548     {
 549     case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
 550 
 551         if (Integer0 && Integer1)
 552         {
 553             LocalResult = TRUE;
 554         }
 555         break;
 556 
 557     case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
 558 
 559         if (Integer0 || Integer1)
 560         {
 561             LocalResult = TRUE;
 562         }
 563         break;
 564 
 565     default:
 566 
 567         Status = AE_AML_INTERNAL;
 568         break;
 569     }
 570 
 571     /* Return the logical result and status */
 572 
 573     *LogicalResult = LocalResult;
 574     return_ACPI_STATUS (Status);
 575 }
 576 
 577 
 578 /*******************************************************************************
 579  *
 580  * FUNCTION:    AcpiExDoLogicalOp
 581  *
 582  * PARAMETERS:  Opcode              - AML opcode
 583  *              Operand0            - operand #0
 584  *              Operand1            - operand #1
 585  *              LogicalResult       - TRUE/FALSE result of the operation
 586  *
 587  * RETURN:      Status
 588  *
 589  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
 590  *              functions here is to prevent a lot of pointer dereferencing
 591  *              to obtain the operands and to simplify the generation of the
 592  *              logical value. For the Numeric operators (LAnd and LOr), both
 593  *              operands must be integers. For the other logical operators,
 594  *              operands can be any combination of Integer/String/Buffer. The
 595  *              first operand determines the type to which the second operand
 596  *              will be converted.
 597  *
 598  *              Note: cleanest machine code seems to be produced by the code
 599  *              below, rather than using statements of the form:
 600  *                  Result = (Operand0 == Operand1);
 601  *
 602  ******************************************************************************/
 603 
 604 ACPI_STATUS
 605 AcpiExDoLogicalOp (
 606     UINT16                  Opcode,
 607     ACPI_OPERAND_OBJECT     *Operand0,
 608     ACPI_OPERAND_OBJECT     *Operand1,
 609     BOOLEAN                 *LogicalResult)
 610 {
 611     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
 612     UINT64                  Integer0;
 613     UINT64                  Integer1;
 614     UINT32                  Length0;
 615     UINT32                  Length1;
 616     ACPI_STATUS             Status = AE_OK;
 617     BOOLEAN                 LocalResult = FALSE;
 618     int                     Compare;
 619 
 620 
 621     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
 622 
 623 
 624     /*
 625      * Convert the second operand if necessary. The first operand
 626      * determines the type of the second operand, (See the Data Types
 627      * section of the ACPI 3.0+ specification.)  Both object types are
 628      * guaranteed to be either Integer/String/Buffer by the operand
 629      * resolution mechanism.
 630      */
 631     switch (Operand0->Common.Type)
 632     {
 633     case ACPI_TYPE_INTEGER:
 634 
 635         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
 636         break;
 637 
 638     case ACPI_TYPE_STRING:
 639 
 640         Status = AcpiExConvertToString (Operand1, &LocalOperand1,
 641                     ACPI_IMPLICIT_CONVERT_HEX);
 642         break;
 643 
 644     case ACPI_TYPE_BUFFER:
 645 
 646         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
 647         break;
 648 
 649     default:
 650 
 651         Status = AE_AML_INTERNAL;
 652         break;
 653     }
 654 
 655     if (ACPI_FAILURE (Status))
 656     {
 657         goto Cleanup;
 658     }
 659 
 660     /*
 661      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
 662      */
 663     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
 664     {
 665         /*
 666          * 1) Both operands are of type integer
 667          *    Note: LocalOperand1 may have changed above
 668          */
 669         Integer0 = Operand0->Integer.Value;
 670         Integer1 = LocalOperand1->Integer.Value;
 671 
 672         switch (Opcode)
 673         {
 674         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
 675 
 676             if (Integer0 == Integer1)
 677             {
 678                 LocalResult = TRUE;
 679             }
 680             break;
 681 
 682         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
 683 
 684             if (Integer0 > Integer1)
 685             {
 686                 LocalResult = TRUE;
 687             }
 688             break;
 689 
 690         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
 691 
 692             if (Integer0 < Integer1)
 693             {
 694                 LocalResult = TRUE;
 695             }
 696             break;
 697 
 698         default:
 699 
 700             Status = AE_AML_INTERNAL;
 701             break;
 702         }
 703     }
 704     else
 705     {
 706         /*
 707          * 2) Both operands are Strings or both are Buffers
 708          *    Note: Code below takes advantage of common Buffer/String
 709          *          object fields. LocalOperand1 may have changed above. Use
 710          *          memcmp to handle nulls in buffers.
 711          */
 712         Length0 = Operand0->Buffer.Length;
 713         Length1 = LocalOperand1->Buffer.Length;
 714 
 715         /* Lexicographic compare: compare the data bytes */
 716 
 717         Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer,
 718                     LocalOperand1->Buffer.Pointer,
 719                     (Length0 > Length1) ? Length1 : Length0);
 720 
 721         switch (Opcode)
 722         {
 723         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
 724 
 725             /* Length and all bytes must be equal */
 726 
 727             if ((Length0 == Length1) &&
 728                 (Compare == 0))
 729             {
 730                 /* Length and all bytes match ==> TRUE */
 731 
 732                 LocalResult = TRUE;
 733             }
 734             break;
 735 
 736         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
 737 
 738             if (Compare > 0)
 739             {
 740                 LocalResult = TRUE;
 741                 goto Cleanup;   /* TRUE */
 742             }
 743             if (Compare < 0)
 744             {
 745                 goto Cleanup;   /* FALSE */
 746             }
 747 
 748             /* Bytes match (to shortest length), compare lengths */
 749 
 750             if (Length0 > Length1)
 751             {
 752                 LocalResult = TRUE;
 753             }
 754             break;
 755 
 756         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
 757 
 758             if (Compare > 0)
 759             {
 760                 goto Cleanup;   /* FALSE */
 761             }
 762             if (Compare < 0)
 763             {
 764                 LocalResult = TRUE;
 765                 goto Cleanup;   /* TRUE */
 766             }
 767 
 768             /* Bytes match (to shortest length), compare lengths */
 769 
 770             if (Length0 < Length1)
 771             {
 772                 LocalResult = TRUE;
 773             }
 774             break;
 775 
 776         default:
 777 
 778             Status = AE_AML_INTERNAL;
 779             break;
 780         }
 781     }
 782 
 783 Cleanup:
 784 
 785     /* New object was created if implicit conversion performed - delete */
 786 
 787     if (LocalOperand1 != Operand1)
 788     {
 789         AcpiUtRemoveReference (LocalOperand1);
 790     }
 791 
 792     /* Return the logical result and status */
 793 
 794     *LogicalResult = LocalResult;
 795     return_ACPI_STATUS (Status);
 796 }