Home | History | Annotate | Line # | Download | only in executer
exmisc.c revision 1.1.1.9
      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 
     49 
     50 #define _COMPONENT          ACPI_EXECUTER
     51         ACPI_MODULE_NAME    ("exmisc")
     52 
     53 
     54 /*******************************************************************************
     55  *
     56  * FUNCTION:    AcpiExGetObjectReference
     57  *
     58  * PARAMETERS:  ObjDesc             - Create a reference to this object
     59  *              ReturnDesc          - Where to store the reference
     60  *              WalkState           - Current state
     61  *
     62  * RETURN:      Status
     63  *
     64  * DESCRIPTION: Obtain and return a "reference" to the target object
     65  *              Common code for the RefOfOp and the CondRefOfOp.
     66  *
     67  ******************************************************************************/
     68 
     69 ACPI_STATUS
     70 AcpiExGetObjectReference (
     71     ACPI_OPERAND_OBJECT     *ObjDesc,
     72     ACPI_OPERAND_OBJECT     **ReturnDesc,
     73     ACPI_WALK_STATE         *WalkState)
     74 {
     75     ACPI_OPERAND_OBJECT     *ReferenceObj;
     76     ACPI_OPERAND_OBJECT     *ReferencedObj;
     77 
     78 
     79     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
     80 
     81 
     82     *ReturnDesc = NULL;
     83 
     84     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
     85     {
     86     case ACPI_DESC_TYPE_OPERAND:
     87 
     88         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
     89         {
     90             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
     91         }
     92 
     93         /*
     94          * Must be a reference to a Local or Arg
     95          */
     96         switch (ObjDesc->Reference.Class)
     97         {
     98         case ACPI_REFCLASS_LOCAL:
     99         case ACPI_REFCLASS_ARG:
    100         case ACPI_REFCLASS_DEBUG:
    101 
    102             /* The referenced object is the pseudo-node for the local/arg */
    103 
    104             ReferencedObj = ObjDesc->Reference.Object;
    105             break;
    106 
    107         default:
    108 
    109             ACPI_ERROR ((AE_INFO, "Invalid Reference Class 0x%2.2X",
    110                 ObjDesc->Reference.Class));
    111             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
    112         }
    113         break;
    114 
    115     case ACPI_DESC_TYPE_NAMED:
    116         /*
    117          * A named reference that has already been resolved to a Node
    118          */
    119         ReferencedObj = ObjDesc;
    120         break;
    121 
    122     default:
    123 
    124         ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
    125             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
    126         return_ACPI_STATUS (AE_TYPE);
    127     }
    128 
    129 
    130     /* Create a new reference object */
    131 
    132     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
    133     if (!ReferenceObj)
    134     {
    135         return_ACPI_STATUS (AE_NO_MEMORY);
    136     }
    137 
    138     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
    139     ReferenceObj->Reference.Object = ReferencedObj;
    140     *ReturnDesc = ReferenceObj;
    141 
    142     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    143         "Object %p Type [%s], returning Reference %p\n",
    144         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
    145 
    146     return_ACPI_STATUS (AE_OK);
    147 }
    148 
    149 
    150 /*******************************************************************************
    151  *
    152  * FUNCTION:    AcpiExDoMathOp
    153  *
    154  * PARAMETERS:  Opcode              - AML opcode
    155  *              Integer0            - Integer operand #0
    156  *              Integer1            - Integer operand #1
    157  *
    158  * RETURN:      Integer result of the operation
    159  *
    160  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
    161  *              math functions here is to prevent a lot of pointer dereferencing
    162  *              to obtain the operands.
    163  *
    164  ******************************************************************************/
    165 
    166 UINT64
    167 AcpiExDoMathOp (
    168     UINT16                  Opcode,
    169     UINT64                  Integer0,
    170     UINT64                  Integer1)
    171 {
    172 
    173     ACPI_FUNCTION_ENTRY ();
    174 
    175 
    176     switch (Opcode)
    177     {
    178     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
    179 
    180         return (Integer0 + Integer1);
    181 
    182     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
    183 
    184         return (Integer0 & Integer1);
    185 
    186     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
    187 
    188         return (~(Integer0 & Integer1));
    189 
    190     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
    191 
    192         return (Integer0 | Integer1);
    193 
    194     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
    195 
    196         return (~(Integer0 | Integer1));
    197 
    198     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
    199 
    200         return (Integer0 ^ Integer1);
    201 
    202     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
    203 
    204         return (Integer0 * Integer1);
    205 
    206     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
    207 
    208         /*
    209          * We need to check if the shiftcount is larger than the integer bit
    210          * width since the behavior of this is not well-defined in the C language.
    211          */
    212         if (Integer1 >= AcpiGbl_IntegerBitWidth)
    213         {
    214             return (0);
    215         }
    216         return (Integer0 << Integer1);
    217 
    218     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
    219 
    220         /*
    221          * We need to check if the shiftcount is larger than the integer bit
    222          * width since the behavior of this is not well-defined in the C language.
    223          */
    224         if (Integer1 >= AcpiGbl_IntegerBitWidth)
    225         {
    226             return (0);
    227         }
    228         return (Integer0 >> Integer1);
    229 
    230     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
    231 
    232         return (Integer0 - Integer1);
    233 
    234     default:
    235 
    236         return (0);
    237     }
    238 }
    239 
    240 
    241 /*******************************************************************************
    242  *
    243  * FUNCTION:    AcpiExDoLogicalNumericOp
    244  *
    245  * PARAMETERS:  Opcode              - AML opcode
    246  *              Integer0            - Integer operand #0
    247  *              Integer1            - Integer operand #1
    248  *              LogicalResult       - TRUE/FALSE result of the operation
    249  *
    250  * RETURN:      Status
    251  *
    252  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
    253  *              operators (LAnd and LOr), both operands must be integers.
    254  *
    255  *              Note: cleanest machine code seems to be produced by the code
    256  *              below, rather than using statements of the form:
    257  *                  Result = (Integer0 && Integer1);
    258  *
    259  ******************************************************************************/
    260 
    261 ACPI_STATUS
    262 AcpiExDoLogicalNumericOp (
    263     UINT16                  Opcode,
    264     UINT64                  Integer0,
    265     UINT64                  Integer1,
    266     BOOLEAN                 *LogicalResult)
    267 {
    268     ACPI_STATUS             Status = AE_OK;
    269     BOOLEAN                 LocalResult = FALSE;
    270 
    271 
    272     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
    273 
    274 
    275     switch (Opcode)
    276     {
    277     case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
    278 
    279         if (Integer0 && Integer1)
    280         {
    281             LocalResult = TRUE;
    282         }
    283         break;
    284 
    285     case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
    286 
    287         if (Integer0 || Integer1)
    288         {
    289             LocalResult = TRUE;
    290         }
    291         break;
    292 
    293     default:
    294 
    295         Status = AE_AML_INTERNAL;
    296         break;
    297     }
    298 
    299     /* Return the logical result and status */
    300 
    301     *LogicalResult = LocalResult;
    302     return_ACPI_STATUS (Status);
    303 }
    304 
    305 
    306 /*******************************************************************************
    307  *
    308  * FUNCTION:    AcpiExDoLogicalOp
    309  *
    310  * PARAMETERS:  Opcode              - AML opcode
    311  *              Operand0            - operand #0
    312  *              Operand1            - operand #1
    313  *              LogicalResult       - TRUE/FALSE result of the operation
    314  *
    315  * RETURN:      Status
    316  *
    317  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
    318  *              functions here is to prevent a lot of pointer dereferencing
    319  *              to obtain the operands and to simplify the generation of the
    320  *              logical value. For the Numeric operators (LAnd and LOr), both
    321  *              operands must be integers. For the other logical operators,
    322  *              operands can be any combination of Integer/String/Buffer. The
    323  *              first operand determines the type to which the second operand
    324  *              will be converted.
    325  *
    326  *              Note: cleanest machine code seems to be produced by the code
    327  *              below, rather than using statements of the form:
    328  *                  Result = (Operand0 == Operand1);
    329  *
    330  ******************************************************************************/
    331 
    332 ACPI_STATUS
    333 AcpiExDoLogicalOp (
    334     UINT16                  Opcode,
    335     ACPI_OPERAND_OBJECT     *Operand0,
    336     ACPI_OPERAND_OBJECT     *Operand1,
    337     BOOLEAN                 *LogicalResult)
    338 {
    339     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
    340     UINT64                  Integer0;
    341     UINT64                  Integer1;
    342     UINT32                  Length0;
    343     UINT32                  Length1;
    344     ACPI_STATUS             Status = AE_OK;
    345     BOOLEAN                 LocalResult = FALSE;
    346     int                     Compare;
    347 
    348 
    349     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
    350 
    351 
    352     /*
    353      * Convert the second operand if necessary. The first operand
    354      * determines the type of the second operand, (See the Data Types
    355      * section of the ACPI 3.0+ specification.)  Both object types are
    356      * guaranteed to be either Integer/String/Buffer by the operand
    357      * resolution mechanism.
    358      */
    359     switch (Operand0->Common.Type)
    360     {
    361     case ACPI_TYPE_INTEGER:
    362 
    363         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1,
    364             ACPI_STRTOUL_BASE16);
    365         break;
    366 
    367     case ACPI_TYPE_STRING:
    368 
    369         Status = AcpiExConvertToString (
    370             Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
    371         break;
    372 
    373     case ACPI_TYPE_BUFFER:
    374 
    375         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
    376         break;
    377 
    378     default:
    379 
    380         Status = AE_AML_INTERNAL;
    381         break;
    382     }
    383 
    384     if (ACPI_FAILURE (Status))
    385     {
    386         goto Cleanup;
    387     }
    388 
    389     /*
    390      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
    391      */
    392     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
    393     {
    394         /*
    395          * 1) Both operands are of type integer
    396          *    Note: LocalOperand1 may have changed above
    397          */
    398         Integer0 = Operand0->Integer.Value;
    399         Integer1 = LocalOperand1->Integer.Value;
    400 
    401         switch (Opcode)
    402         {
    403         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
    404 
    405             if (Integer0 == Integer1)
    406             {
    407                 LocalResult = TRUE;
    408             }
    409             break;
    410 
    411         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
    412 
    413             if (Integer0 > Integer1)
    414             {
    415                 LocalResult = TRUE;
    416             }
    417             break;
    418 
    419         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
    420 
    421             if (Integer0 < Integer1)
    422             {
    423                 LocalResult = TRUE;
    424             }
    425             break;
    426 
    427         default:
    428 
    429             Status = AE_AML_INTERNAL;
    430             break;
    431         }
    432     }
    433     else
    434     {
    435         /*
    436          * 2) Both operands are Strings or both are Buffers
    437          *    Note: Code below takes advantage of common Buffer/String
    438          *          object fields. LocalOperand1 may have changed above. Use
    439          *          memcmp to handle nulls in buffers.
    440          */
    441         Length0 = Operand0->Buffer.Length;
    442         Length1 = LocalOperand1->Buffer.Length;
    443 
    444         /* Lexicographic compare: compare the data bytes */
    445 
    446         Compare = memcmp (Operand0->Buffer.Pointer,
    447             LocalOperand1->Buffer.Pointer,
    448             (Length0 > Length1) ? Length1 : Length0);
    449 
    450         switch (Opcode)
    451         {
    452         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
    453 
    454             /* Length and all bytes must be equal */
    455 
    456             if ((Length0 == Length1) &&
    457                 (Compare == 0))
    458             {
    459                 /* Length and all bytes match ==> TRUE */
    460 
    461                 LocalResult = TRUE;
    462             }
    463             break;
    464 
    465         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
    466 
    467             if (Compare > 0)
    468             {
    469                 LocalResult = TRUE;
    470                 goto Cleanup;   /* TRUE */
    471             }
    472             if (Compare < 0)
    473             {
    474                 goto Cleanup;   /* FALSE */
    475             }
    476 
    477             /* Bytes match (to shortest length), compare lengths */
    478 
    479             if (Length0 > Length1)
    480             {
    481                 LocalResult = TRUE;
    482             }
    483             break;
    484 
    485         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
    486 
    487             if (Compare > 0)
    488             {
    489                 goto Cleanup;   /* FALSE */
    490             }
    491             if (Compare < 0)
    492             {
    493                 LocalResult = TRUE;
    494                 goto Cleanup;   /* TRUE */
    495             }
    496 
    497             /* Bytes match (to shortest length), compare lengths */
    498 
    499             if (Length0 < Length1)
    500             {
    501                 LocalResult = TRUE;
    502             }
    503             break;
    504 
    505         default:
    506 
    507             Status = AE_AML_INTERNAL;
    508             break;
    509         }
    510     }
    511 
    512 Cleanup:
    513 
    514     /* New object was created if implicit conversion performed - delete */
    515 
    516     if (LocalOperand1 != Operand1)
    517     {
    518         AcpiUtRemoveReference (LocalOperand1);
    519     }
    520 
    521     /* Return the logical result and status */
    522 
    523     *LogicalResult = LocalResult;
    524     return_ACPI_STATUS (Status);
    525 }
    526