Home | History | Annotate | Line # | Download | only in executer
exconcat.c revision 1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: exconcat - Concatenate-type AML operators
      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 "amlresrc.h"
     48 
     49 
     50 #define _COMPONENT          ACPI_EXECUTER
     51         ACPI_MODULE_NAME    ("exconcat")
     52 
     53 /* Local Prototypes */
     54 
     55 static ACPI_STATUS
     56 AcpiExConvertToObjectTypeString (
     57     ACPI_OPERAND_OBJECT     *ObjDesc,
     58     ACPI_OPERAND_OBJECT     **ResultDesc);
     59 
     60 
     61 /*******************************************************************************
     62  *
     63  * FUNCTION:    AcpiExDoConcatenate
     64  *
     65  * PARAMETERS:  Operand0            - First source object
     66  *              Operand1            - Second source object
     67  *              ActualReturnDesc    - Where to place the return object
     68  *              WalkState           - Current walk state
     69  *
     70  * RETURN:      Status
     71  *
     72  * DESCRIPTION: Concatenate two objects with the ACPI-defined conversion
     73  *              rules as necessary.
     74  * NOTE:
     75  * Per the ACPI spec (up to 6.1), Concatenate only supports Integer,
     76  * String, and Buffer objects. However, we support all objects here
     77  * as an extension. This improves the usefulness of both Concatenate
     78  * and the Printf/Fprintf macros. The extension returns a string
     79  * describing the object type for the other objects.
     80  * 02/2016.
     81  *
     82  ******************************************************************************/
     83 
     84 ACPI_STATUS
     85 AcpiExDoConcatenate (
     86     ACPI_OPERAND_OBJECT     *Operand0,
     87     ACPI_OPERAND_OBJECT     *Operand1,
     88     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
     89     ACPI_WALK_STATE         *WalkState)
     90 {
     91     ACPI_OPERAND_OBJECT     *LocalOperand0 = Operand0;
     92     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
     93     ACPI_OPERAND_OBJECT     *TempOperand1 = NULL;
     94     ACPI_OPERAND_OBJECT     *ReturnDesc;
     95     char                    *Buffer;
     96     ACPI_OBJECT_TYPE        Operand0Type;
     97     ACPI_OBJECT_TYPE        Operand1Type;
     98     ACPI_STATUS             Status;
     99 
    100 
    101     ACPI_FUNCTION_TRACE (ExDoConcatenate);
    102 
    103 
    104     /* Operand 0 preprocessing */
    105 
    106     switch (Operand0->Common.Type)
    107     {
    108     case ACPI_TYPE_INTEGER:
    109     case ACPI_TYPE_STRING:
    110     case ACPI_TYPE_BUFFER:
    111 
    112         Operand0Type = Operand0->Common.Type;
    113         break;
    114 
    115     default:
    116 
    117         /* For all other types, get the "object type" string */
    118 
    119         Status = AcpiExConvertToObjectTypeString (
    120             Operand0, &LocalOperand0);
    121         if (ACPI_FAILURE (Status))
    122         {
    123             goto Cleanup;
    124         }
    125 
    126         Operand0Type = ACPI_TYPE_STRING;
    127         break;
    128     }
    129 
    130     /* Operand 1 preprocessing */
    131 
    132     switch (Operand1->Common.Type)
    133     {
    134     case ACPI_TYPE_INTEGER:
    135     case ACPI_TYPE_STRING:
    136     case ACPI_TYPE_BUFFER:
    137 
    138         Operand1Type = Operand1->Common.Type;
    139         break;
    140 
    141     default:
    142 
    143         /* For all other types, get the "object type" string */
    144 
    145         Status = AcpiExConvertToObjectTypeString (
    146             Operand1, &LocalOperand1);
    147         if (ACPI_FAILURE (Status))
    148         {
    149             goto Cleanup;
    150         }
    151 
    152         Operand1Type = ACPI_TYPE_STRING;
    153         break;
    154     }
    155 
    156     /*
    157      * Convert the second operand if necessary. The first operand (0)
    158      * determines the type of the second operand (1) (See the Data Types
    159      * section of the ACPI specification). Both object types are
    160      * guaranteed to be either Integer/String/Buffer by the operand
    161      * resolution mechanism.
    162      */
    163     switch (Operand0Type)
    164     {
    165     case ACPI_TYPE_INTEGER:
    166 
    167         Status = AcpiExConvertToInteger (LocalOperand1, &TempOperand1, 16);
    168         break;
    169 
    170     case ACPI_TYPE_BUFFER:
    171 
    172         Status = AcpiExConvertToBuffer (LocalOperand1, &TempOperand1);
    173         break;
    174 
    175     case ACPI_TYPE_STRING:
    176 
    177         switch (Operand1Type)
    178         {
    179         case ACPI_TYPE_INTEGER:
    180         case ACPI_TYPE_STRING:
    181         case ACPI_TYPE_BUFFER:
    182 
    183             /* Other types have already been converted to string */
    184 
    185             Status = AcpiExConvertToString (
    186                 LocalOperand1, &TempOperand1, ACPI_IMPLICIT_CONVERT_HEX);
    187             break;
    188 
    189         default:
    190 
    191             Status = AE_OK;
    192             break;
    193         }
    194         break;
    195 
    196     default:
    197 
    198         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
    199             Operand0->Common.Type));
    200         Status = AE_AML_INTERNAL;
    201     }
    202 
    203     if (ACPI_FAILURE (Status))
    204     {
    205         goto Cleanup;
    206     }
    207 
    208     /* Take care with any newly created operand objects */
    209 
    210     if ((LocalOperand1 != Operand1) &&
    211         (LocalOperand1 != TempOperand1))
    212     {
    213         AcpiUtRemoveReference (LocalOperand1);
    214     }
    215 
    216     LocalOperand1 = TempOperand1;
    217 
    218     /*
    219      * Both operands are now known to be the same object type
    220      * (Both are Integer, String, or Buffer), and we can now perform
    221      * the concatenation.
    222      *
    223      * There are three cases to handle, as per the ACPI spec:
    224      *
    225      * 1) Two Integers concatenated to produce a new Buffer
    226      * 2) Two Strings concatenated to produce a new String
    227      * 3) Two Buffers concatenated to produce a new Buffer
    228      */
    229     switch (Operand0Type)
    230     {
    231     case ACPI_TYPE_INTEGER:
    232 
    233         /* Result of two Integers is a Buffer */
    234         /* Need enough buffer space for two integers */
    235 
    236         ReturnDesc = AcpiUtCreateBufferObject (
    237             (ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth));
    238         if (!ReturnDesc)
    239         {
    240             Status = AE_NO_MEMORY;
    241             goto Cleanup;
    242         }
    243 
    244         Buffer = (char *) ReturnDesc->Buffer.Pointer;
    245 
    246         /* Copy the first integer, LSB first */
    247 
    248         memcpy (Buffer, &Operand0->Integer.Value,
    249             AcpiGbl_IntegerByteWidth);
    250 
    251         /* Copy the second integer (LSB first) after the first */
    252 
    253         memcpy (Buffer + AcpiGbl_IntegerByteWidth,
    254             &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth);
    255         break;
    256 
    257     case ACPI_TYPE_STRING:
    258 
    259         /* Result of two Strings is a String */
    260 
    261         ReturnDesc = AcpiUtCreateStringObject (
    262             ((ACPI_SIZE) LocalOperand0->String.Length +
    263             LocalOperand1->String.Length));
    264         if (!ReturnDesc)
    265         {
    266             Status = AE_NO_MEMORY;
    267             goto Cleanup;
    268         }
    269 
    270         Buffer = ReturnDesc->String.Pointer;
    271 
    272         /* Concatenate the strings */
    273 
    274         strcpy (Buffer, LocalOperand0->String.Pointer);
    275         strcat (Buffer, LocalOperand1->String.Pointer);
    276         break;
    277 
    278     case ACPI_TYPE_BUFFER:
    279 
    280         /* Result of two Buffers is a Buffer */
    281 
    282         ReturnDesc = AcpiUtCreateBufferObject (
    283             ((ACPI_SIZE) Operand0->Buffer.Length +
    284             LocalOperand1->Buffer.Length));
    285         if (!ReturnDesc)
    286         {
    287             Status = AE_NO_MEMORY;
    288             goto Cleanup;
    289         }
    290 
    291         Buffer = (char *) ReturnDesc->Buffer.Pointer;
    292 
    293         /* Concatenate the buffers */
    294 
    295         memcpy (Buffer, Operand0->Buffer.Pointer,
    296             Operand0->Buffer.Length);
    297         memcpy (Buffer + Operand0->Buffer.Length,
    298             LocalOperand1->Buffer.Pointer,
    299             LocalOperand1->Buffer.Length);
    300         break;
    301 
    302     default:
    303 
    304         /* Invalid object type, should not happen here */
    305 
    306         ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X",
    307             Operand0->Common.Type));
    308         Status = AE_AML_INTERNAL;
    309         goto Cleanup;
    310     }
    311 
    312     *ActualReturnDesc = ReturnDesc;
    313 
    314 Cleanup:
    315     if (LocalOperand0 != Operand0)
    316     {
    317         AcpiUtRemoveReference (LocalOperand0);
    318     }
    319 
    320     if (LocalOperand1 != Operand1)
    321     {
    322         AcpiUtRemoveReference (LocalOperand1);
    323     }
    324 
    325     return_ACPI_STATUS (Status);
    326 }
    327 
    328 
    329 /*******************************************************************************
    330  *
    331  * FUNCTION:    AcpiExConvertToObjectTypeString
    332  *
    333  * PARAMETERS:  ObjDesc             - Object to be converted
    334  *              ReturnDesc          - Where to place the return object
    335  *
    336  * RETURN:      Status
    337  *
    338  * DESCRIPTION: Convert an object of arbitrary type to a string object that
    339  *              contains the namestring for the object. Used for the
    340  *              concatenate operator.
    341  *
    342  ******************************************************************************/
    343 
    344 static ACPI_STATUS
    345 AcpiExConvertToObjectTypeString (
    346     ACPI_OPERAND_OBJECT     *ObjDesc,
    347     ACPI_OPERAND_OBJECT     **ResultDesc)
    348 {
    349     ACPI_OPERAND_OBJECT     *ReturnDesc;
    350     const char              *TypeString;
    351 
    352 
    353     TypeString = AcpiUtGetTypeName (ObjDesc->Common.Type);
    354 
    355     ReturnDesc = AcpiUtCreateStringObject (
    356         ((ACPI_SIZE) strlen (TypeString) + 9)); /* 9 For "[ Object]" */
    357     if (!ReturnDesc)
    358     {
    359         return (AE_NO_MEMORY);
    360     }
    361 
    362     strcpy (ReturnDesc->String.Pointer, "[");
    363     strcat (ReturnDesc->String.Pointer, TypeString);
    364     strcat (ReturnDesc->String.Pointer, " Object]");
    365 
    366     *ResultDesc = ReturnDesc;
    367     return (AE_OK);
    368 }
    369 
    370 
    371 /*******************************************************************************
    372  *
    373  * FUNCTION:    AcpiExConcatTemplate
    374  *
    375  * PARAMETERS:  Operand0            - First source object
    376  *              Operand1            - Second source object
    377  *              ActualReturnDesc    - Where to place the return object
    378  *              WalkState           - Current walk state
    379  *
    380  * RETURN:      Status
    381  *
    382  * DESCRIPTION: Concatenate two resource templates
    383  *
    384  ******************************************************************************/
    385 
    386 ACPI_STATUS
    387 AcpiExConcatTemplate (
    388     ACPI_OPERAND_OBJECT     *Operand0,
    389     ACPI_OPERAND_OBJECT     *Operand1,
    390     ACPI_OPERAND_OBJECT     **ActualReturnDesc,
    391     ACPI_WALK_STATE         *WalkState)
    392 {
    393     ACPI_STATUS             Status;
    394     ACPI_OPERAND_OBJECT     *ReturnDesc;
    395     UINT8                   *NewBuf;
    396     UINT8                   *EndTag;
    397     ACPI_SIZE               Length0;
    398     ACPI_SIZE               Length1;
    399     ACPI_SIZE               NewLength;
    400 
    401 
    402     ACPI_FUNCTION_TRACE (ExConcatTemplate);
    403 
    404 
    405     /*
    406      * Find the EndTag descriptor in each resource template.
    407      * Note1: returned pointers point TO the EndTag, not past it.
    408      * Note2: zero-length buffers are allowed; treated like one EndTag
    409      */
    410 
    411     /* Get the length of the first resource template */
    412 
    413     Status = AcpiUtGetResourceEndTag (Operand0, &EndTag);
    414     if (ACPI_FAILURE (Status))
    415     {
    416         return_ACPI_STATUS (Status);
    417     }
    418 
    419     Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer);
    420 
    421     /* Get the length of the second resource template */
    422 
    423     Status = AcpiUtGetResourceEndTag (Operand1, &EndTag);
    424     if (ACPI_FAILURE (Status))
    425     {
    426         return_ACPI_STATUS (Status);
    427     }
    428 
    429     Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer);
    430 
    431     /* Combine both lengths, minimum size will be 2 for EndTag */
    432 
    433     NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG);
    434 
    435     /* Create a new buffer object for the result (with one EndTag) */
    436 
    437     ReturnDesc = AcpiUtCreateBufferObject (NewLength);
    438     if (!ReturnDesc)
    439     {
    440         return_ACPI_STATUS (AE_NO_MEMORY);
    441     }
    442 
    443     /*
    444      * Copy the templates to the new buffer, 0 first, then 1 follows. One
    445      * EndTag descriptor is copied from Operand1.
    446      */
    447     NewBuf = ReturnDesc->Buffer.Pointer;
    448     memcpy (NewBuf, Operand0->Buffer.Pointer, Length0);
    449     memcpy (NewBuf + Length0, Operand1->Buffer.Pointer, Length1);
    450 
    451     /* Insert EndTag and set the checksum to zero, means "ignore checksum" */
    452 
    453     NewBuf[NewLength - 1] = 0;
    454     NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1;
    455 
    456     /* Return the completed resource template */
    457 
    458     *ActualReturnDesc = ReturnDesc;
    459     return_ACPI_STATUS (AE_OK);
    460 }
    461