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