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