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