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