xref: /freebsd/sys/contrib/dev/acpica/components/utilities/utcopy.c (revision ec65e4f8d0654361df5e97d4de3518edebf76b46)
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 <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/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