Home | History | Annotate | Line # | Download | only in executer
exmisc.c revision 1.1.1.2
      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 
    801