Home | History | Annotate | Line # | Download | only in utilities
utcopy.c revision 1.1.1.7
      1 /******************************************************************************
      2  *
      3  * Module Name: utcopy - Internal to external object translation utilities
      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 "acnamesp.h"
     47 
     48 
     49 #define _COMPONENT          ACPI_UTILITIES
     50         ACPI_MODULE_NAME    ("utcopy")
     51 
     52 /* Local prototypes */
     53 
     54 static ACPI_STATUS
     55 AcpiUtCopyIsimpleToEsimple (
     56     ACPI_OPERAND_OBJECT     *InternalObject,
     57     ACPI_OBJECT             *ExternalObject,
     58     UINT8                   *DataSpace,
     59     ACPI_SIZE               *BufferSpaceUsed);
     60 
     61 static ACPI_STATUS
     62 AcpiUtCopyIelementToIelement (
     63     UINT8                   ObjectType,
     64     ACPI_OPERAND_OBJECT     *SourceObject,
     65     ACPI_GENERIC_STATE      *State,
     66     void                    *Context);
     67 
     68 static ACPI_STATUS
     69 AcpiUtCopyIpackageToEpackage (
     70     ACPI_OPERAND_OBJECT     *InternalObject,
     71     UINT8                   *Buffer,
     72     ACPI_SIZE               *SpaceUsed);
     73 
     74 static ACPI_STATUS
     75 AcpiUtCopyEsimpleToIsimple(
     76     ACPI_OBJECT             *UserObj,
     77     ACPI_OPERAND_OBJECT     **ReturnObj);
     78 
     79 static ACPI_STATUS
     80 AcpiUtCopyEpackageToIpackage (
     81     ACPI_OBJECT             *ExternalObject,
     82     ACPI_OPERAND_OBJECT     **InternalObject);
     83 
     84 static ACPI_STATUS
     85 AcpiUtCopySimpleObject (
     86     ACPI_OPERAND_OBJECT     *SourceDesc,
     87     ACPI_OPERAND_OBJECT     *DestDesc);
     88 
     89 static ACPI_STATUS
     90 AcpiUtCopyIelementToEelement (
     91     UINT8                   ObjectType,
     92     ACPI_OPERAND_OBJECT     *SourceObject,
     93     ACPI_GENERIC_STATE      *State,
     94     void                    *Context);
     95 
     96 static ACPI_STATUS
     97 AcpiUtCopyIpackageToIpackage (
     98     ACPI_OPERAND_OBJECT     *SourceObj,
     99     ACPI_OPERAND_OBJECT     *DestObj,
    100     ACPI_WALK_STATE         *WalkState);
    101 
    102 
    103 /*******************************************************************************
    104  *
    105  * FUNCTION:    AcpiUtCopyIsimpleToEsimple
    106  *
    107  * PARAMETERS:  InternalObject      - Source object to be copied
    108  *              ExternalObject      - Where to return the copied object
    109  *              DataSpace           - Where object data is returned (such as
    110  *                                    buffer and string data)
    111  *              BufferSpaceUsed     - Length of DataSpace that was used
    112  *
    113  * RETURN:      Status
    114  *
    115  * DESCRIPTION: This function is called to copy a simple internal object to
    116  *              an external object.
    117  *
    118  *              The DataSpace buffer is assumed to have sufficient space for
    119  *              the object.
    120  *
    121  ******************************************************************************/
    122 
    123 static ACPI_STATUS
    124 AcpiUtCopyIsimpleToEsimple (
    125     ACPI_OPERAND_OBJECT     *InternalObject,
    126     ACPI_OBJECT             *ExternalObject,
    127     UINT8                   *DataSpace,
    128     ACPI_SIZE               *BufferSpaceUsed)
    129 {
    130     ACPI_STATUS             Status = AE_OK;
    131 
    132 
    133     ACPI_FUNCTION_TRACE (UtCopyIsimpleToEsimple);
    134 
    135 
    136     *BufferSpaceUsed = 0;
    137 
    138     /*
    139      * Check for NULL object case (could be an uninitialized
    140      * package element)
    141      */
    142     if (!InternalObject)
    143     {
    144         return_ACPI_STATUS (AE_OK);
    145     }
    146 
    147     /* Always clear the external object */
    148 
    149     memset (ExternalObject, 0, sizeof (ACPI_OBJECT));
    150 
    151     /*
    152      * In general, the external object will be the same type as
    153      * the internal object
    154      */
    155     ExternalObject->Type = InternalObject->Common.Type;
    156 
    157     /* However, only a limited number of external types are supported */
    158 
    159     switch (InternalObject->Common.Type)
    160     {
    161     case ACPI_TYPE_STRING:
    162 
    163         ExternalObject->String.Pointer = (char *) DataSpace;
    164         ExternalObject->String.Length  = InternalObject->String.Length;
    165         *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
    166             (ACPI_SIZE) InternalObject->String.Length + 1);
    167 
    168         memcpy ((void *) DataSpace,
    169             (void *) InternalObject->String.Pointer,
    170             (ACPI_SIZE) InternalObject->String.Length + 1);
    171         break;
    172 
    173     case ACPI_TYPE_BUFFER:
    174 
    175         ExternalObject->Buffer.Pointer = DataSpace;
    176         ExternalObject->Buffer.Length  = InternalObject->Buffer.Length;
    177         *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
    178             InternalObject->String.Length);
    179 
    180         memcpy ((void *) DataSpace,
    181             (void *) InternalObject->Buffer.Pointer,
    182             InternalObject->Buffer.Length);
    183         break;
    184 
    185     case ACPI_TYPE_INTEGER:
    186 
    187         ExternalObject->Integer.Value = InternalObject->Integer.Value;
    188         break;
    189 
    190     case ACPI_TYPE_LOCAL_REFERENCE:
    191 
    192         /* This is an object reference. */
    193 
    194         switch (InternalObject->Reference.Class)
    195         {
    196         case ACPI_REFCLASS_NAME:
    197             /*
    198              * For namepath, return the object handle ("reference")
    199              * We are referring to the namespace node
    200              */
    201             ExternalObject->Reference.Handle =
    202                 InternalObject->Reference.Node;
    203             ExternalObject->Reference.ActualType =
    204                 AcpiNsGetType (InternalObject->Reference.Node);
    205             break;
    206 
    207         default:
    208 
    209             /* All other reference types are unsupported */
    210 
    211             return_ACPI_STATUS (AE_TYPE);
    212         }
    213         break;
    214 
    215     case ACPI_TYPE_PROCESSOR:
    216 
    217         ExternalObject->Processor.ProcId =
    218             InternalObject->Processor.ProcId;
    219         ExternalObject->Processor.PblkAddress =
    220             InternalObject->Processor.Address;
    221         ExternalObject->Processor.PblkLength =
    222             InternalObject->Processor.Length;
    223         break;
    224 
    225     case ACPI_TYPE_POWER:
    226 
    227         ExternalObject->PowerResource.SystemLevel =
    228             InternalObject->PowerResource.SystemLevel;
    229 
    230         ExternalObject->PowerResource.ResourceOrder =
    231             InternalObject->PowerResource.ResourceOrder;
    232         break;
    233 
    234     default:
    235         /*
    236          * There is no corresponding external object type
    237          */
    238         ACPI_ERROR ((AE_INFO,
    239             "Unsupported object type, cannot convert to external object: %s",
    240             AcpiUtGetTypeName (InternalObject->Common.Type)));
    241 
    242         return_ACPI_STATUS (AE_SUPPORT);
    243     }
    244 
    245     return_ACPI_STATUS (Status);
    246 }
    247 
    248 
    249 /*******************************************************************************
    250  *
    251  * FUNCTION:    AcpiUtCopyIelementToEelement
    252  *
    253  * PARAMETERS:  ACPI_PKG_CALLBACK
    254  *
    255  * RETURN:      Status
    256  *
    257  * DESCRIPTION: Copy one package element to another package element
    258  *
    259  ******************************************************************************/
    260 
    261 static ACPI_STATUS
    262 AcpiUtCopyIelementToEelement (
    263     UINT8                   ObjectType,
    264     ACPI_OPERAND_OBJECT     *SourceObject,
    265     ACPI_GENERIC_STATE      *State,
    266     void                    *Context)
    267 {
    268     ACPI_STATUS             Status = AE_OK;
    269     ACPI_PKG_INFO           *Info = (ACPI_PKG_INFO *) Context;
    270     ACPI_SIZE               ObjectSpace;
    271     UINT32                  ThisIndex;
    272     ACPI_OBJECT             *TargetObject;
    273 
    274 
    275     ACPI_FUNCTION_ENTRY ();
    276 
    277 
    278     ThisIndex = State->Pkg.Index;
    279     TargetObject = (ACPI_OBJECT *) &((ACPI_OBJECT *)
    280         (State->Pkg.DestObject))->Package.Elements[ThisIndex];
    281 
    282     switch (ObjectType)
    283     {
    284     case ACPI_COPY_TYPE_SIMPLE:
    285         /*
    286          * This is a simple or null object
    287          */
    288         Status = AcpiUtCopyIsimpleToEsimple (SourceObject,
    289             TargetObject, Info->FreeSpace, &ObjectSpace);
    290         if (ACPI_FAILURE (Status))
    291         {
    292             return (Status);
    293         }
    294         break;
    295 
    296     case ACPI_COPY_TYPE_PACKAGE:
    297         /*
    298          * Build the package object
    299          */
    300         TargetObject->Type = ACPI_TYPE_PACKAGE;
    301         TargetObject->Package.Count = SourceObject->Package.Count;
    302         TargetObject->Package.Elements =
    303             ACPI_CAST_PTR (ACPI_OBJECT, Info->FreeSpace);
    304 
    305         /*
    306          * Pass the new package object back to the package walk routine
    307          */
    308         State->Pkg.ThisTargetObj = TargetObject;
    309 
    310         /*
    311          * Save space for the array of objects (Package elements)
    312          * update the buffer length counter
    313          */
    314         ObjectSpace = ACPI_ROUND_UP_TO_NATIVE_WORD (
    315             (ACPI_SIZE) TargetObject->Package.Count *
    316             sizeof (ACPI_OBJECT));
    317         break;
    318 
    319     default:
    320 
    321         return (AE_BAD_PARAMETER);
    322     }
    323 
    324     Info->FreeSpace += ObjectSpace;
    325     Info->Length += ObjectSpace;
    326     return (Status);
    327 }
    328 
    329 
    330 /*******************************************************************************
    331  *
    332  * FUNCTION:    AcpiUtCopyIpackageToEpackage
    333  *
    334  * PARAMETERS:  InternalObject      - Pointer to the object we are returning
    335  *              Buffer              - Where the object is returned
    336  *              SpaceUsed           - Where the object length is returned
    337  *
    338  * RETURN:      Status
    339  *
    340  * DESCRIPTION: This function is called to place a package object in a user
    341  *              buffer. A package object by definition contains other objects.
    342  *
    343  *              The buffer is assumed to have sufficient space for the object.
    344  *              The caller must have verified the buffer length needed using
    345  *              the AcpiUtGetObjectSize function before calling this function.
    346  *
    347  ******************************************************************************/
    348 
    349 static ACPI_STATUS
    350 AcpiUtCopyIpackageToEpackage (
    351     ACPI_OPERAND_OBJECT     *InternalObject,
    352     UINT8                   *Buffer,
    353     ACPI_SIZE               *SpaceUsed)
    354 {
    355     ACPI_OBJECT             *ExternalObject;
    356     ACPI_STATUS             Status;
    357     ACPI_PKG_INFO           Info;
    358 
    359 
    360     ACPI_FUNCTION_TRACE (UtCopyIpackageToEpackage);
    361 
    362 
    363     /*
    364      * First package at head of the buffer
    365      */
    366     ExternalObject = ACPI_CAST_PTR (ACPI_OBJECT, Buffer);
    367 
    368     /*
    369      * Free space begins right after the first package
    370      */
    371     Info.Length = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
    372     Info.FreeSpace = Buffer +
    373         ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
    374     Info.ObjectSpace = 0;
    375     Info.NumPackages = 1;
    376 
    377     ExternalObject->Type = InternalObject->Common.Type;
    378     ExternalObject->Package.Count = InternalObject->Package.Count;
    379     ExternalObject->Package.Elements =
    380         ACPI_CAST_PTR (ACPI_OBJECT, Info.FreeSpace);
    381 
    382     /*
    383      * Leave room for an array of ACPI_OBJECTS in the buffer
    384      * and move the free space past it
    385      */
    386     Info.Length += (ACPI_SIZE) ExternalObject->Package.Count *
    387         ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
    388     Info.FreeSpace += ExternalObject->Package.Count *
    389         ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
    390 
    391     Status = AcpiUtWalkPackageTree (InternalObject, ExternalObject,
    392         AcpiUtCopyIelementToEelement, &Info);
    393 
    394     *SpaceUsed = Info.Length;
    395     return_ACPI_STATUS (Status);
    396 }
    397 
    398 
    399 /*******************************************************************************
    400  *
    401  * FUNCTION:    AcpiUtCopyIobjectToEobject
    402  *
    403  * PARAMETERS:  InternalObject      - The internal object to be converted
    404  *              RetBuffer           - Where the object is returned
    405  *
    406  * RETURN:      Status
    407  *
    408  * DESCRIPTION: This function is called to build an API object to be returned
    409  *              to the caller.
    410  *
    411  ******************************************************************************/
    412 
    413 ACPI_STATUS
    414 AcpiUtCopyIobjectToEobject (
    415     ACPI_OPERAND_OBJECT     *InternalObject,
    416     ACPI_BUFFER             *RetBuffer)
    417 {
    418     ACPI_STATUS             Status;
    419 
    420 
    421     ACPI_FUNCTION_TRACE (UtCopyIobjectToEobject);
    422 
    423 
    424     if (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)
    425     {
    426         /*
    427          * Package object:  Copy all subobjects (including
    428          * nested packages)
    429          */
    430         Status = AcpiUtCopyIpackageToEpackage (InternalObject,
    431             RetBuffer->Pointer, &RetBuffer->Length);
    432     }
    433     else
    434     {
    435         /*
    436          * Build a simple object (no nested objects)
    437          */
    438         Status = AcpiUtCopyIsimpleToEsimple (InternalObject,
    439             ACPI_CAST_PTR (ACPI_OBJECT, RetBuffer->Pointer),
    440             ACPI_ADD_PTR (UINT8, RetBuffer->Pointer,
    441                 ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))),
    442             &RetBuffer->Length);
    443         /*
    444          * build simple does not include the object size in the length
    445          * so we add it in here
    446          */
    447         RetBuffer->Length += sizeof (ACPI_OBJECT);
    448     }
    449 
    450     return_ACPI_STATUS (Status);
    451 }
    452 
    453 
    454 /*******************************************************************************
    455  *
    456  * FUNCTION:    AcpiUtCopyEsimpleToIsimple
    457  *
    458  * PARAMETERS:  ExternalObject      - The external object to be converted
    459  *              RetInternalObject   - Where the internal object is returned
    460  *
    461  * RETURN:      Status
    462  *
    463  * DESCRIPTION: This function copies an external object to an internal one.
    464  *              NOTE: Pointers can be copied, we don't need to copy data.
    465  *              (The pointers have to be valid in our address space no matter
    466  *              what we do with them!)
    467  *
    468  ******************************************************************************/
    469 
    470 static ACPI_STATUS
    471 AcpiUtCopyEsimpleToIsimple (
    472     ACPI_OBJECT             *ExternalObject,
    473     ACPI_OPERAND_OBJECT     **RetInternalObject)
    474 {
    475     ACPI_OPERAND_OBJECT     *InternalObject;
    476 
    477 
    478     ACPI_FUNCTION_TRACE (UtCopyEsimpleToIsimple);
    479 
    480 
    481     /*
    482      * Simple types supported are: String, Buffer, Integer
    483      */
    484     switch (ExternalObject->Type)
    485     {
    486     case ACPI_TYPE_STRING:
    487     case ACPI_TYPE_BUFFER:
    488     case ACPI_TYPE_INTEGER:
    489     case ACPI_TYPE_LOCAL_REFERENCE:
    490 
    491         InternalObject = AcpiUtCreateInternalObject (
    492             (UINT8) ExternalObject->Type);
    493         if (!InternalObject)
    494         {
    495             return_ACPI_STATUS (AE_NO_MEMORY);
    496         }
    497         break;
    498 
    499     case ACPI_TYPE_ANY: /* This is the case for a NULL object */
    500 
    501         *RetInternalObject = NULL;
    502         return_ACPI_STATUS (AE_OK);
    503 
    504     default:
    505 
    506         /* All other types are not supported */
    507 
    508         ACPI_ERROR ((AE_INFO,
    509             "Unsupported object type, cannot convert to internal object: %s",
    510             AcpiUtGetTypeName (ExternalObject->Type)));
    511 
    512         return_ACPI_STATUS (AE_SUPPORT);
    513     }
    514 
    515 
    516     /* Must COPY string and buffer contents */
    517 
    518     switch (ExternalObject->Type)
    519     {
    520     case ACPI_TYPE_STRING:
    521 
    522         InternalObject->String.Pointer =
    523             ACPI_ALLOCATE_ZEROED ((ACPI_SIZE)
    524                 ExternalObject->String.Length + 1);
    525 
    526         if (!InternalObject->String.Pointer)
    527         {
    528             goto ErrorExit;
    529         }
    530 
    531         memcpy (InternalObject->String.Pointer,
    532             ExternalObject->String.Pointer,
    533             ExternalObject->String.Length);
    534 
    535         InternalObject->String.Length = ExternalObject->String.Length;
    536         break;
    537 
    538     case ACPI_TYPE_BUFFER:
    539 
    540         InternalObject->Buffer.Pointer =
    541             ACPI_ALLOCATE_ZEROED (ExternalObject->Buffer.Length);
    542         if (!InternalObject->Buffer.Pointer)
    543         {
    544             goto ErrorExit;
    545         }
    546 
    547         memcpy (InternalObject->Buffer.Pointer,
    548             ExternalObject->Buffer.Pointer,
    549             ExternalObject->Buffer.Length);
    550 
    551         InternalObject->Buffer.Length = ExternalObject->Buffer.Length;
    552 
    553         /* Mark buffer data valid */
    554 
    555         InternalObject->Buffer.Flags |= AOPOBJ_DATA_VALID;
    556         break;
    557 
    558     case ACPI_TYPE_INTEGER:
    559 
    560         InternalObject->Integer.Value = ExternalObject->Integer.Value;
    561         break;
    562 
    563     case ACPI_TYPE_LOCAL_REFERENCE:
    564 
    565         /* An incoming reference is defined to be a namespace node */
    566 
    567         InternalObject->Reference.Class = ACPI_REFCLASS_REFOF;
    568         InternalObject->Reference.Object = ExternalObject->Reference.Handle;
    569         break;
    570 
    571     default:
    572 
    573         /* Other types can't get here */
    574 
    575         break;
    576     }
    577 
    578     *RetInternalObject = InternalObject;
    579     return_ACPI_STATUS (AE_OK);
    580 
    581 
    582 ErrorExit:
    583     AcpiUtRemoveReference (InternalObject);
    584     return_ACPI_STATUS (AE_NO_MEMORY);
    585 }
    586 
    587 
    588 /*******************************************************************************
    589  *
    590  * FUNCTION:    AcpiUtCopyEpackageToIpackage
    591  *
    592  * PARAMETERS:  ExternalObject      - The external object to be converted
    593  *              InternalObject      - Where the internal object is returned
    594  *
    595  * RETURN:      Status
    596  *
    597  * DESCRIPTION: Copy an external package object to an internal package.
    598  *              Handles nested packages.
    599  *
    600  ******************************************************************************/
    601 
    602 static ACPI_STATUS
    603 AcpiUtCopyEpackageToIpackage (
    604     ACPI_OBJECT             *ExternalObject,
    605     ACPI_OPERAND_OBJECT     **InternalObject)
    606 {
    607     ACPI_STATUS             Status = AE_OK;
    608     ACPI_OPERAND_OBJECT     *PackageObject;
    609     ACPI_OPERAND_OBJECT     **PackageElements;
    610     UINT32                  i;
    611 
    612 
    613     ACPI_FUNCTION_TRACE (UtCopyEpackageToIpackage);
    614 
    615 
    616     /* Create the package object */
    617 
    618     PackageObject = AcpiUtCreatePackageObject (
    619         ExternalObject->Package.Count);
    620     if (!PackageObject)
    621     {
    622         return_ACPI_STATUS (AE_NO_MEMORY);
    623     }
    624 
    625     PackageElements = PackageObject->Package.Elements;
    626 
    627     /*
    628      * Recursive implementation. Probably ok, since nested external
    629      * packages as parameters should be very rare.
    630      */
    631     for (i = 0; i < ExternalObject->Package.Count; i++)
    632     {
    633         Status = AcpiUtCopyEobjectToIobject (
    634             &ExternalObject->Package.Elements[i],
    635             &PackageElements[i]);
    636         if (ACPI_FAILURE (Status))
    637         {
    638             /* Truncate package and delete it */
    639 
    640             PackageObject->Package.Count = i;
    641             PackageElements[i] = NULL;
    642             AcpiUtRemoveReference (PackageObject);
    643             return_ACPI_STATUS (Status);
    644         }
    645     }
    646 
    647     /* Mark package data valid */
    648 
    649     PackageObject->Package.Flags |= AOPOBJ_DATA_VALID;
    650 
    651     *InternalObject = PackageObject;
    652     return_ACPI_STATUS (Status);
    653 }
    654 
    655 
    656 /*******************************************************************************
    657  *
    658  * FUNCTION:    AcpiUtCopyEobjectToIobject
    659  *
    660  * PARAMETERS:  ExternalObject      - The external object to be converted
    661  *              InternalObject      - Where the internal object is returned
    662  *
    663  * RETURN:      Status
    664  *
    665  * DESCRIPTION: Converts an external object to an internal object.
    666  *
    667  ******************************************************************************/
    668 
    669 ACPI_STATUS
    670 AcpiUtCopyEobjectToIobject (
    671     ACPI_OBJECT             *ExternalObject,
    672     ACPI_OPERAND_OBJECT     **InternalObject)
    673 {
    674     ACPI_STATUS             Status;
    675 
    676 
    677     ACPI_FUNCTION_TRACE (UtCopyEobjectToIobject);
    678 
    679 
    680     if (ExternalObject->Type == ACPI_TYPE_PACKAGE)
    681     {
    682         Status = AcpiUtCopyEpackageToIpackage (
    683             ExternalObject, InternalObject);
    684     }
    685     else
    686     {
    687         /*
    688          * Build a simple object (no nested objects)
    689          */
    690         Status = AcpiUtCopyEsimpleToIsimple (ExternalObject,
    691             InternalObject);
    692     }
    693 
    694     return_ACPI_STATUS (Status);
    695 }
    696 
    697 
    698 /*******************************************************************************
    699  *
    700  * FUNCTION:    AcpiUtCopySimpleObject
    701  *
    702  * PARAMETERS:  SourceDesc          - The internal object to be copied
    703  *              DestDesc            - New target object
    704  *
    705  * RETURN:      Status
    706  *
    707  * DESCRIPTION: Simple copy of one internal object to another. Reference count
    708  *              of the destination object is preserved.
    709  *
    710  ******************************************************************************/
    711 
    712 static ACPI_STATUS
    713 AcpiUtCopySimpleObject (
    714     ACPI_OPERAND_OBJECT     *SourceDesc,
    715     ACPI_OPERAND_OBJECT     *DestDesc)
    716 {
    717     UINT16                  ReferenceCount;
    718     ACPI_OPERAND_OBJECT     *NextObject;
    719     ACPI_STATUS             Status;
    720     ACPI_SIZE               CopySize;
    721 
    722 
    723     /* Save fields from destination that we don't want to overwrite */
    724 
    725     ReferenceCount = DestDesc->Common.ReferenceCount;
    726     NextObject = DestDesc->Common.NextObject;
    727 
    728     /*
    729      * Copy the entire source object over the destination object.
    730      * Note: Source can be either an operand object or namespace node.
    731      */
    732     CopySize = sizeof (ACPI_OPERAND_OBJECT);
    733     if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
    734     {
    735         CopySize = sizeof (ACPI_NAMESPACE_NODE);
    736     }
    737 
    738     memcpy (ACPI_CAST_PTR (char, DestDesc),
    739         ACPI_CAST_PTR (char, SourceDesc), CopySize);
    740 
    741     /* Restore the saved fields */
    742 
    743     DestDesc->Common.ReferenceCount = ReferenceCount;
    744     DestDesc->Common.NextObject = NextObject;
    745 
    746     /* New object is not static, regardless of source */
    747 
    748     DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
    749 
    750     /* Handle the objects with extra data */
    751 
    752     switch (DestDesc->Common.Type)
    753     {
    754     case ACPI_TYPE_BUFFER:
    755         /*
    756          * Allocate and copy the actual buffer if and only if:
    757          * 1) There is a valid buffer pointer
    758          * 2) The buffer has a length > 0
    759          */
    760         if ((SourceDesc->Buffer.Pointer) &&
    761             (SourceDesc->Buffer.Length))
    762         {
    763             DestDesc->Buffer.Pointer =
    764                 ACPI_ALLOCATE (SourceDesc->Buffer.Length);
    765             if (!DestDesc->Buffer.Pointer)
    766             {
    767                 return (AE_NO_MEMORY);
    768             }
    769 
    770             /* Copy the actual buffer data */
    771 
    772             memcpy (DestDesc->Buffer.Pointer,
    773                 SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
    774         }
    775         break;
    776 
    777     case ACPI_TYPE_STRING:
    778         /*
    779          * Allocate and copy the actual string if and only if:
    780          * 1) There is a valid string pointer
    781          * (Pointer to a NULL string is allowed)
    782          */
    783         if (SourceDesc->String.Pointer)
    784         {
    785             DestDesc->String.Pointer =
    786                 ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
    787             if (!DestDesc->String.Pointer)
    788             {
    789                 return (AE_NO_MEMORY);
    790             }
    791 
    792             /* Copy the actual string data */
    793 
    794             memcpy (DestDesc->String.Pointer, SourceDesc->String.Pointer,
    795                 (ACPI_SIZE) SourceDesc->String.Length + 1);
    796         }
    797         break;
    798 
    799     case ACPI_TYPE_LOCAL_REFERENCE:
    800         /*
    801          * We copied the reference object, so we now must add a reference
    802          * to the object pointed to by the reference
    803          *
    804          * DDBHandle reference (from Load/LoadTable) is a special reference,
    805          * it does not have a Reference.Object, so does not need to
    806          * increase the reference count
    807          */
    808         if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
    809         {
    810             break;
    811         }
    812 
    813         AcpiUtAddReference (SourceDesc->Reference.Object);
    814         break;
    815 
    816     case ACPI_TYPE_REGION:
    817         /*
    818          * We copied the Region Handler, so we now must add a reference
    819          */
    820         if (DestDesc->Region.Handler)
    821         {
    822             AcpiUtAddReference (DestDesc->Region.Handler);
    823         }
    824         break;
    825 
    826     /*
    827      * For Mutex and Event objects, we cannot simply copy the underlying
    828      * OS object. We must create a new one.
    829      */
    830     case ACPI_TYPE_MUTEX:
    831 
    832         Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex);
    833         if (ACPI_FAILURE (Status))
    834         {
    835             return (Status);
    836         }
    837         break;
    838 
    839     case ACPI_TYPE_EVENT:
    840 
    841         Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
    842             &DestDesc->Event.OsSemaphore);
    843         if (ACPI_FAILURE (Status))
    844         {
    845             return (Status);
    846         }
    847         break;
    848 
    849     default:
    850 
    851         /* Nothing to do for other simple objects */
    852 
    853         break;
    854     }
    855 
    856     return (AE_OK);
    857 }
    858 
    859 
    860 /*******************************************************************************
    861  *
    862  * FUNCTION:    AcpiUtCopyIelementToIelement
    863  *
    864  * PARAMETERS:  ACPI_PKG_CALLBACK
    865  *
    866  * RETURN:      Status
    867  *
    868  * DESCRIPTION: Copy one package element to another package element
    869  *
    870  ******************************************************************************/
    871 
    872 static ACPI_STATUS
    873 AcpiUtCopyIelementToIelement (
    874     UINT8                   ObjectType,
    875     ACPI_OPERAND_OBJECT     *SourceObject,
    876     ACPI_GENERIC_STATE      *State,
    877     void                    *Context)
    878 {
    879     ACPI_STATUS             Status = AE_OK;
    880     UINT32                  ThisIndex;
    881     ACPI_OPERAND_OBJECT     **ThisTargetPtr;
    882     ACPI_OPERAND_OBJECT     *TargetObject;
    883 
    884 
    885     ACPI_FUNCTION_ENTRY ();
    886 
    887 
    888     ThisIndex = State->Pkg.Index;
    889     ThisTargetPtr = (ACPI_OPERAND_OBJECT **)
    890         &State->Pkg.DestObject->Package.Elements[ThisIndex];
    891 
    892     switch (ObjectType)
    893     {
    894     case ACPI_COPY_TYPE_SIMPLE:
    895 
    896         /* A null source object indicates a (legal) null package element */
    897 
    898         if (SourceObject)
    899         {
    900             /*
    901              * This is a simple object, just copy it
    902              */
    903             TargetObject = AcpiUtCreateInternalObject (
    904                 SourceObject->Common.Type);
    905             if (!TargetObject)
    906             {
    907                 return (AE_NO_MEMORY);
    908             }
    909 
    910             Status = AcpiUtCopySimpleObject (SourceObject, TargetObject);
    911             if (ACPI_FAILURE (Status))
    912             {
    913                 goto ErrorExit;
    914             }
    915 
    916             *ThisTargetPtr = TargetObject;
    917         }
    918         else
    919         {
    920             /* Pass through a null element */
    921 
    922             *ThisTargetPtr = NULL;
    923         }
    924         break;
    925 
    926     case ACPI_COPY_TYPE_PACKAGE:
    927         /*
    928          * This object is a package - go down another nesting level
    929          * Create and build the package object
    930          */
    931         TargetObject = AcpiUtCreatePackageObject (
    932             SourceObject->Package.Count);
    933         if (!TargetObject)
    934         {
    935             return (AE_NO_MEMORY);
    936         }
    937 
    938         TargetObject->Common.Flags = SourceObject->Common.Flags;
    939 
    940         /* Pass the new package object back to the package walk routine */
    941 
    942         State->Pkg.ThisTargetObj = TargetObject;
    943 
    944         /* Store the object pointer in the parent package object */
    945 
    946         *ThisTargetPtr = TargetObject;
    947         break;
    948 
    949     default:
    950 
    951         return (AE_BAD_PARAMETER);
    952     }
    953 
    954     return (Status);
    955 
    956 ErrorExit:
    957     AcpiUtRemoveReference (TargetObject);
    958     return (Status);
    959 }
    960 
    961 
    962 /*******************************************************************************
    963  *
    964  * FUNCTION:    AcpiUtCopyIpackageToIpackage
    965  *
    966  * PARAMETERS:  SourceObj       - Pointer to the source package object
    967  *              DestObj         - Where the internal object is returned
    968  *              WalkState       - Current Walk state descriptor
    969  *
    970  * RETURN:      Status
    971  *
    972  * DESCRIPTION: This function is called to copy an internal package object
    973  *              into another internal package object.
    974  *
    975  ******************************************************************************/
    976 
    977 static ACPI_STATUS
    978 AcpiUtCopyIpackageToIpackage (
    979     ACPI_OPERAND_OBJECT     *SourceObj,
    980     ACPI_OPERAND_OBJECT     *DestObj,
    981     ACPI_WALK_STATE         *WalkState)
    982 {
    983     ACPI_STATUS             Status = AE_OK;
    984 
    985 
    986     ACPI_FUNCTION_TRACE (UtCopyIpackageToIpackage);
    987 
    988 
    989     DestObj->Common.Type = SourceObj->Common.Type;
    990     DestObj->Common.Flags = SourceObj->Common.Flags;
    991     DestObj->Package.Count = SourceObj->Package.Count;
    992 
    993     /*
    994      * Create the object array and walk the source package tree
    995      */
    996     DestObj->Package.Elements = ACPI_ALLOCATE_ZEROED (
    997         ((ACPI_SIZE) SourceObj->Package.Count + 1) *
    998         sizeof (void *));
    999     if (!DestObj->Package.Elements)
   1000     {
   1001         ACPI_ERROR ((AE_INFO, "Package allocation failure"));
   1002         return_ACPI_STATUS (AE_NO_MEMORY);
   1003     }
   1004 
   1005     /*
   1006      * Copy the package element-by-element by walking the package "tree".
   1007      * This handles nested packages of arbitrary depth.
   1008      */
   1009     Status = AcpiUtWalkPackageTree (SourceObj, DestObj,
   1010         AcpiUtCopyIelementToIelement, WalkState);
   1011     if (ACPI_FAILURE (Status))
   1012     {
   1013         /* On failure, delete the destination package object */
   1014 
   1015         AcpiUtRemoveReference (DestObj);
   1016     }
   1017 
   1018     return_ACPI_STATUS (Status);
   1019 }
   1020 
   1021 
   1022 /*******************************************************************************
   1023  *
   1024  * FUNCTION:    AcpiUtCopyIobjectToIobject
   1025  *
   1026  * PARAMETERS:  SourceDesc          - The internal object to be copied
   1027  *              DestDesc            - Where the copied object is returned
   1028  *              WalkState           - Current walk state
   1029  *
   1030  * RETURN:      Status
   1031  *
   1032  * DESCRIPTION: Copy an internal object to a new internal object
   1033  *
   1034  ******************************************************************************/
   1035 
   1036 ACPI_STATUS
   1037 AcpiUtCopyIobjectToIobject (
   1038     ACPI_OPERAND_OBJECT     *SourceDesc,
   1039     ACPI_OPERAND_OBJECT     **DestDesc,
   1040     ACPI_WALK_STATE         *WalkState)
   1041 {
   1042     ACPI_STATUS             Status = AE_OK;
   1043 
   1044 
   1045     ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject);
   1046 
   1047 
   1048     /* Create the top level object */
   1049 
   1050     *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type);
   1051     if (!*DestDesc)
   1052     {
   1053         return_ACPI_STATUS (AE_NO_MEMORY);
   1054     }
   1055 
   1056     /* Copy the object and possible subobjects */
   1057 
   1058     if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE)
   1059     {
   1060         Status = AcpiUtCopyIpackageToIpackage (
   1061             SourceDesc, *DestDesc, WalkState);
   1062     }
   1063     else
   1064     {
   1065         Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc);
   1066     }
   1067 
   1068     /* Delete the allocated object if copy failed */
   1069 
   1070     if (ACPI_FAILURE (Status))
   1071     {
   1072         AcpiUtRemoveReference (*DestDesc);
   1073     }
   1074 
   1075     return_ACPI_STATUS (Status);
   1076 }
   1077