Home | History | Annotate | Line # | Download | only in utilities
utcopy.c revision 1.1.1.5
      1 /******************************************************************************
      2  *
      3  * Module Name: utcopy - Internal to external object translation utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2015, 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     ACPI_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         ACPI_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         ACPI_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 *)
    280         &((ACPI_OBJECT *)(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 + ACPI_ROUND_UP_TO_NATIVE_WORD (
    373                                     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 = ACPI_CAST_PTR (ACPI_OBJECT,
    380                                             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         ACPI_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         ACPI_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 (ExternalObject->Package.Count);
    619     if (!PackageObject)
    620     {
    621         return_ACPI_STATUS (AE_NO_MEMORY);
    622     }
    623 
    624     PackageElements = PackageObject->Package.Elements;
    625 
    626     /*
    627      * Recursive implementation. Probably ok, since nested external packages
    628      * as parameters should be very rare.
    629      */
    630     for (i = 0; i < ExternalObject->Package.Count; i++)
    631     {
    632         Status = AcpiUtCopyEobjectToIobject (
    633                     &ExternalObject->Package.Elements[i],
    634                     &PackageElements[i]);
    635         if (ACPI_FAILURE (Status))
    636         {
    637             /* Truncate package and delete it */
    638 
    639             PackageObject->Package.Count = i;
    640             PackageElements[i] = NULL;
    641             AcpiUtRemoveReference (PackageObject);
    642             return_ACPI_STATUS (Status);
    643         }
    644     }
    645 
    646     /* Mark package data valid */
    647 
    648     PackageObject->Package.Flags |= AOPOBJ_DATA_VALID;
    649 
    650     *InternalObject = PackageObject;
    651     return_ACPI_STATUS (Status);
    652 }
    653 
    654 
    655 /*******************************************************************************
    656  *
    657  * FUNCTION:    AcpiUtCopyEobjectToIobject
    658  *
    659  * PARAMETERS:  ExternalObject      - The external object to be converted
    660  *              InternalObject      - Where the internal object is returned
    661  *
    662  * RETURN:      Status
    663  *
    664  * DESCRIPTION: Converts an external object to an internal object.
    665  *
    666  ******************************************************************************/
    667 
    668 ACPI_STATUS
    669 AcpiUtCopyEobjectToIobject (
    670     ACPI_OBJECT             *ExternalObject,
    671     ACPI_OPERAND_OBJECT     **InternalObject)
    672 {
    673     ACPI_STATUS             Status;
    674 
    675 
    676     ACPI_FUNCTION_TRACE (UtCopyEobjectToIobject);
    677 
    678 
    679     if (ExternalObject->Type == ACPI_TYPE_PACKAGE)
    680     {
    681         Status = AcpiUtCopyEpackageToIpackage (ExternalObject, InternalObject);
    682     }
    683     else
    684     {
    685         /*
    686          * Build a simple object (no nested objects)
    687          */
    688         Status = AcpiUtCopyEsimpleToIsimple (ExternalObject, InternalObject);
    689     }
    690 
    691     return_ACPI_STATUS (Status);
    692 }
    693 
    694 
    695 /*******************************************************************************
    696  *
    697  * FUNCTION:    AcpiUtCopySimpleObject
    698  *
    699  * PARAMETERS:  SourceDesc          - The internal object to be copied
    700  *              DestDesc            - New target object
    701  *
    702  * RETURN:      Status
    703  *
    704  * DESCRIPTION: Simple copy of one internal object to another. Reference count
    705  *              of the destination object is preserved.
    706  *
    707  ******************************************************************************/
    708 
    709 static ACPI_STATUS
    710 AcpiUtCopySimpleObject (
    711     ACPI_OPERAND_OBJECT     *SourceDesc,
    712     ACPI_OPERAND_OBJECT     *DestDesc)
    713 {
    714     UINT16                  ReferenceCount;
    715     ACPI_OPERAND_OBJECT     *NextObject;
    716     ACPI_STATUS             Status;
    717     ACPI_SIZE               CopySize;
    718 
    719 
    720     /* Save fields from destination that we don't want to overwrite */
    721 
    722     ReferenceCount = DestDesc->Common.ReferenceCount;
    723     NextObject = DestDesc->Common.NextObject;
    724 
    725     /*
    726      * Copy the entire source object over the destination object.
    727      * Note: Source can be either an operand object or namespace node.
    728      */
    729     CopySize = sizeof (ACPI_OPERAND_OBJECT);
    730     if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
    731     {
    732         CopySize = sizeof (ACPI_NAMESPACE_NODE);
    733     }
    734 
    735     ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc),
    736         ACPI_CAST_PTR (char, SourceDesc), CopySize);
    737 
    738     /* Restore the saved fields */
    739 
    740     DestDesc->Common.ReferenceCount = ReferenceCount;
    741     DestDesc->Common.NextObject = NextObject;
    742 
    743     /* New object is not static, regardless of source */
    744 
    745     DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
    746 
    747     /* Handle the objects with extra data */
    748 
    749     switch (DestDesc->Common.Type)
    750     {
    751     case ACPI_TYPE_BUFFER:
    752         /*
    753          * Allocate and copy the actual buffer if and only if:
    754          * 1) There is a valid buffer pointer
    755          * 2) The buffer has a length > 0
    756          */
    757         if ((SourceDesc->Buffer.Pointer) &&
    758             (SourceDesc->Buffer.Length))
    759         {
    760             DestDesc->Buffer.Pointer =
    761                 ACPI_ALLOCATE (SourceDesc->Buffer.Length);
    762             if (!DestDesc->Buffer.Pointer)
    763             {
    764                 return (AE_NO_MEMORY);
    765             }
    766 
    767             /* Copy the actual buffer data */
    768 
    769             ACPI_MEMCPY (DestDesc->Buffer.Pointer,
    770                 SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
    771         }
    772         break;
    773 
    774     case ACPI_TYPE_STRING:
    775         /*
    776          * Allocate and copy the actual string if and only if:
    777          * 1) There is a valid string pointer
    778          * (Pointer to a NULL string is allowed)
    779          */
    780         if (SourceDesc->String.Pointer)
    781         {
    782             DestDesc->String.Pointer =
    783                 ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
    784             if (!DestDesc->String.Pointer)
    785             {
    786                 return (AE_NO_MEMORY);
    787             }
    788 
    789             /* Copy the actual string data */
    790 
    791             ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
    792                 (ACPI_SIZE) SourceDesc->String.Length + 1);
    793         }
    794         break;
    795 
    796     case ACPI_TYPE_LOCAL_REFERENCE:
    797         /*
    798          * We copied the reference object, so we now must add a reference
    799          * to the object pointed to by the reference
    800          *
    801          * DDBHandle reference (from Load/LoadTable) is a special reference,
    802          * it does not have a Reference.Object, so does not need to
    803          * increase the reference count
    804          */
    805         if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
    806         {
    807             break;
    808         }
    809 
    810         AcpiUtAddReference (SourceDesc->Reference.Object);
    811         break;
    812 
    813     case ACPI_TYPE_REGION:
    814         /*
    815          * We copied the Region Handler, so we now must add a reference
    816          */
    817         if (DestDesc->Region.Handler)
    818         {
    819             AcpiUtAddReference (DestDesc->Region.Handler);
    820         }
    821         break;
    822 
    823     /*
    824      * For Mutex and Event objects, we cannot simply copy the underlying
    825      * OS object. We must create a new one.
    826      */
    827     case ACPI_TYPE_MUTEX:
    828 
    829         Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex);
    830         if (ACPI_FAILURE (Status))
    831         {
    832             return (Status);
    833         }
    834         break;
    835 
    836     case ACPI_TYPE_EVENT:
    837 
    838         Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
    839                     &DestDesc->Event.OsSemaphore);
    840         if (ACPI_FAILURE (Status))
    841         {
    842             return (Status);
    843         }
    844         break;
    845 
    846     default:
    847 
    848         /* Nothing to do for other simple objects */
    849 
    850         break;
    851     }
    852 
    853     return (AE_OK);
    854 }
    855 
    856 
    857 /*******************************************************************************
    858  *
    859  * FUNCTION:    AcpiUtCopyIelementToIelement
    860  *
    861  * PARAMETERS:  ACPI_PKG_CALLBACK
    862  *
    863  * RETURN:      Status
    864  *
    865  * DESCRIPTION: Copy one package element to another package element
    866  *
    867  ******************************************************************************/
    868 
    869 static ACPI_STATUS
    870 AcpiUtCopyIelementToIelement (
    871     UINT8                   ObjectType,
    872     ACPI_OPERAND_OBJECT     *SourceObject,
    873     ACPI_GENERIC_STATE      *State,
    874     void                    *Context)
    875 {
    876     ACPI_STATUS             Status = AE_OK;
    877     UINT32                  ThisIndex;
    878     ACPI_OPERAND_OBJECT     **ThisTargetPtr;
    879     ACPI_OPERAND_OBJECT     *TargetObject;
    880 
    881 
    882     ACPI_FUNCTION_ENTRY ();
    883 
    884 
    885     ThisIndex     = State->Pkg.Index;
    886     ThisTargetPtr = (ACPI_OPERAND_OBJECT **)
    887                         &State->Pkg.DestObject->Package.Elements[ThisIndex];
    888 
    889     switch (ObjectType)
    890     {
    891     case ACPI_COPY_TYPE_SIMPLE:
    892 
    893         /* A null source object indicates a (legal) null package element */
    894 
    895         if (SourceObject)
    896         {
    897             /*
    898              * This is a simple object, just copy it
    899              */
    900             TargetObject = AcpiUtCreateInternalObject (
    901                                 SourceObject->Common.Type);
    902             if (!TargetObject)
    903             {
    904                 return (AE_NO_MEMORY);
    905             }
    906 
    907             Status = AcpiUtCopySimpleObject (SourceObject, TargetObject);
    908             if (ACPI_FAILURE (Status))
    909             {
    910                 goto ErrorExit;
    911             }
    912 
    913             *ThisTargetPtr = TargetObject;
    914         }
    915         else
    916         {
    917             /* Pass through a null element */
    918 
    919             *ThisTargetPtr = NULL;
    920         }
    921         break;
    922 
    923     case ACPI_COPY_TYPE_PACKAGE:
    924         /*
    925          * This object is a package - go down another nesting level
    926          * Create and build the package object
    927          */
    928         TargetObject = AcpiUtCreatePackageObject (SourceObject->Package.Count);
    929         if (!TargetObject)
    930         {
    931             return (AE_NO_MEMORY);
    932         }
    933 
    934         TargetObject->Common.Flags = SourceObject->Common.Flags;
    935 
    936         /* Pass the new package object back to the package walk routine */
    937 
    938         State->Pkg.ThisTargetObj = TargetObject;
    939 
    940         /* Store the object pointer in the parent package object */
    941 
    942         *ThisTargetPtr = TargetObject;
    943         break;
    944 
    945     default:
    946 
    947         return (AE_BAD_PARAMETER);
    948     }
    949 
    950     return (Status);
    951 
    952 ErrorExit:
    953     AcpiUtRemoveReference (TargetObject);
    954     return (Status);
    955 }
    956 
    957 
    958 /*******************************************************************************
    959  *
    960  * FUNCTION:    AcpiUtCopyIpackageToIpackage
    961  *
    962  * PARAMETERS:  SourceObj       - Pointer to the source package object
    963  *              DestObj         - Where the internal object is returned
    964  *              WalkState       - Current Walk state descriptor
    965  *
    966  * RETURN:      Status
    967  *
    968  * DESCRIPTION: This function is called to copy an internal package object
    969  *              into another internal package object.
    970  *
    971  ******************************************************************************/
    972 
    973 static ACPI_STATUS
    974 AcpiUtCopyIpackageToIpackage (
    975     ACPI_OPERAND_OBJECT     *SourceObj,
    976     ACPI_OPERAND_OBJECT     *DestObj,
    977     ACPI_WALK_STATE         *WalkState)
    978 {
    979     ACPI_STATUS             Status = AE_OK;
    980 
    981 
    982     ACPI_FUNCTION_TRACE (UtCopyIpackageToIpackage);
    983 
    984 
    985     DestObj->Common.Type    = SourceObj->Common.Type;
    986     DestObj->Common.Flags   = SourceObj->Common.Flags;
    987     DestObj->Package.Count  = SourceObj->Package.Count;
    988 
    989     /*
    990      * Create the object array and walk the source package tree
    991      */
    992     DestObj->Package.Elements = ACPI_ALLOCATE_ZEROED (
    993                                     ((ACPI_SIZE) SourceObj->Package.Count + 1) *
    994                                     sizeof (void *));
    995     if (!DestObj->Package.Elements)
    996     {
    997         ACPI_ERROR ((AE_INFO, "Package allocation failure"));
    998         return_ACPI_STATUS (AE_NO_MEMORY);
    999     }
   1000 
   1001     /*
   1002      * Copy the package element-by-element by walking the package "tree".
   1003      * This handles nested packages of arbitrary depth.
   1004      */
   1005     Status = AcpiUtWalkPackageTree (SourceObj, DestObj,
   1006                 AcpiUtCopyIelementToIelement, WalkState);
   1007     if (ACPI_FAILURE (Status))
   1008     {
   1009         /* On failure, delete the destination package object */
   1010 
   1011         AcpiUtRemoveReference (DestObj);
   1012     }
   1013 
   1014     return_ACPI_STATUS (Status);
   1015 }
   1016 
   1017 
   1018 /*******************************************************************************
   1019  *
   1020  * FUNCTION:    AcpiUtCopyIobjectToIobject
   1021  *
   1022  * PARAMETERS:  SourceDesc          - The internal object to be copied
   1023  *              DestDesc            - Where the copied object is returned
   1024  *              WalkState           - Current walk state
   1025  *
   1026  * RETURN:      Status
   1027  *
   1028  * DESCRIPTION: Copy an internal object to a new internal object
   1029  *
   1030  ******************************************************************************/
   1031 
   1032 ACPI_STATUS
   1033 AcpiUtCopyIobjectToIobject (
   1034     ACPI_OPERAND_OBJECT     *SourceDesc,
   1035     ACPI_OPERAND_OBJECT     **DestDesc,
   1036     ACPI_WALK_STATE         *WalkState)
   1037 {
   1038     ACPI_STATUS             Status = AE_OK;
   1039 
   1040 
   1041     ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject);
   1042 
   1043 
   1044     /* Create the top level object */
   1045 
   1046     *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type);
   1047     if (!*DestDesc)
   1048     {
   1049         return_ACPI_STATUS (AE_NO_MEMORY);
   1050     }
   1051 
   1052     /* Copy the object and possible subobjects */
   1053 
   1054     if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE)
   1055     {
   1056         Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc,
   1057                         WalkState);
   1058     }
   1059     else
   1060     {
   1061         Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc);
   1062     }
   1063 
   1064     /* Delete the allocated object if copy failed */
   1065 
   1066     if (ACPI_FAILURE (Status))
   1067     {
   1068         AcpiUtRemoveReference(*DestDesc);
   1069     }
   1070 
   1071     return_ACPI_STATUS (Status);
   1072 }
   1073