xref: /freebsd/sys/contrib/dev/acpica/components/utilities/utcopy.c (revision 39ee7a7a6bdd1557b1c3532abf60d139798ac88b)
1 /******************************************************************************
2  *
3  * Module Name: utcopy - Internal to external object translation utilities
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include <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 *)
280         &((ACPI_OBJECT *)(State->Pkg.DestObject))->Package.Elements[ThisIndex];
281 
282     switch (ObjectType)
283     {
284     case ACPI_COPY_TYPE_SIMPLE:
285         /*
286          * This is a simple or null object
287          */
288         Status = AcpiUtCopyIsimpleToEsimple (SourceObject,
289                         TargetObject, Info->FreeSpace, &ObjectSpace);
290         if (ACPI_FAILURE (Status))
291         {
292             return (Status);
293         }
294         break;
295 
296     case ACPI_COPY_TYPE_PACKAGE:
297         /*
298          * Build the package object
299          */
300         TargetObject->Type              = ACPI_TYPE_PACKAGE;
301         TargetObject->Package.Count     = SourceObject->Package.Count;
302         TargetObject->Package.Elements  =
303             ACPI_CAST_PTR (ACPI_OBJECT, Info->FreeSpace);
304 
305         /*
306          * Pass the new package object back to the package walk routine
307          */
308         State->Pkg.ThisTargetObj = TargetObject;
309 
310         /*
311          * Save space for the array of objects (Package elements)
312          * update the buffer length counter
313          */
314         ObjectSpace = ACPI_ROUND_UP_TO_NATIVE_WORD (
315                             (ACPI_SIZE) TargetObject->Package.Count *
316                             sizeof (ACPI_OBJECT));
317         break;
318 
319     default:
320 
321         return (AE_BAD_PARAMETER);
322     }
323 
324     Info->FreeSpace   += ObjectSpace;
325     Info->Length      += ObjectSpace;
326     return (Status);
327 }
328 
329 
330 /*******************************************************************************
331  *
332  * FUNCTION:    AcpiUtCopyIpackageToEpackage
333  *
334  * PARAMETERS:  InternalObject      - Pointer to the object we are returning
335  *              Buffer              - Where the object is returned
336  *              SpaceUsed           - Where the object length is returned
337  *
338  * RETURN:      Status
339  *
340  * DESCRIPTION: This function is called to place a package object in a user
341  *              buffer. A package object by definition contains other objects.
342  *
343  *              The buffer is assumed to have sufficient space for the object.
344  *              The caller must have verified the buffer length needed using
345  *              the AcpiUtGetObjectSize function before calling this function.
346  *
347  ******************************************************************************/
348 
349 static ACPI_STATUS
350 AcpiUtCopyIpackageToEpackage (
351     ACPI_OPERAND_OBJECT     *InternalObject,
352     UINT8                   *Buffer,
353     ACPI_SIZE               *SpaceUsed)
354 {
355     ACPI_OBJECT             *ExternalObject;
356     ACPI_STATUS             Status;
357     ACPI_PKG_INFO           Info;
358 
359 
360     ACPI_FUNCTION_TRACE (UtCopyIpackageToEpackage);
361 
362 
363     /*
364      * First package at head of the buffer
365      */
366     ExternalObject = ACPI_CAST_PTR (ACPI_OBJECT, Buffer);
367 
368     /*
369      * Free space begins right after the first package
370      */
371     Info.Length      = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
372     Info.FreeSpace   = Buffer + ACPI_ROUND_UP_TO_NATIVE_WORD (
373                                     sizeof (ACPI_OBJECT));
374     Info.ObjectSpace = 0;
375     Info.NumPackages = 1;
376 
377     ExternalObject->Type             = InternalObject->Common.Type;
378     ExternalObject->Package.Count    = InternalObject->Package.Count;
379     ExternalObject->Package.Elements = ACPI_CAST_PTR (ACPI_OBJECT,
380                                             Info.FreeSpace);
381 
382     /*
383      * Leave room for an array of ACPI_OBJECTS in the buffer
384      * and move the free space past it
385      */
386     Info.Length    += (ACPI_SIZE) ExternalObject->Package.Count *
387                             ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
388     Info.FreeSpace += ExternalObject->Package.Count *
389                             ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
390 
391     Status = AcpiUtWalkPackageTree (InternalObject, ExternalObject,
392                 AcpiUtCopyIelementToEelement, &Info);
393 
394     *SpaceUsed = Info.Length;
395     return_ACPI_STATUS (Status);
396 }
397 
398 
399 /*******************************************************************************
400  *
401  * FUNCTION:    AcpiUtCopyIobjectToEobject
402  *
403  * PARAMETERS:  InternalObject      - The internal object to be converted
404  *              RetBuffer           - Where the object is returned
405  *
406  * RETURN:      Status
407  *
408  * DESCRIPTION: This function is called to build an API object to be returned
409  *              to the caller.
410  *
411  ******************************************************************************/
412 
413 ACPI_STATUS
414 AcpiUtCopyIobjectToEobject (
415     ACPI_OPERAND_OBJECT     *InternalObject,
416     ACPI_BUFFER             *RetBuffer)
417 {
418     ACPI_STATUS             Status;
419 
420 
421     ACPI_FUNCTION_TRACE (UtCopyIobjectToEobject);
422 
423 
424     if (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)
425     {
426         /*
427          * Package object:  Copy all subobjects (including
428          * nested packages)
429          */
430         Status = AcpiUtCopyIpackageToEpackage (InternalObject,
431                         RetBuffer->Pointer, &RetBuffer->Length);
432     }
433     else
434     {
435         /*
436          * Build a simple object (no nested objects)
437          */
438         Status = AcpiUtCopyIsimpleToEsimple (InternalObject,
439                     ACPI_CAST_PTR (ACPI_OBJECT, RetBuffer->Pointer),
440                     ACPI_ADD_PTR (UINT8, RetBuffer->Pointer,
441                         ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))),
442                     &RetBuffer->Length);
443         /*
444          * build simple does not include the object size in the length
445          * so we add it in here
446          */
447         RetBuffer->Length += sizeof (ACPI_OBJECT);
448     }
449 
450     return_ACPI_STATUS (Status);
451 }
452 
453 
454 /*******************************************************************************
455  *
456  * FUNCTION:    AcpiUtCopyEsimpleToIsimple
457  *
458  * PARAMETERS:  ExternalObject      - The external object to be converted
459  *              RetInternalObject   - Where the internal object is returned
460  *
461  * RETURN:      Status
462  *
463  * DESCRIPTION: This function copies an external object to an internal one.
464  *              NOTE: Pointers can be copied, we don't need to copy data.
465  *              (The pointers have to be valid in our address space no matter
466  *              what we do with them!)
467  *
468  ******************************************************************************/
469 
470 static ACPI_STATUS
471 AcpiUtCopyEsimpleToIsimple (
472     ACPI_OBJECT             *ExternalObject,
473     ACPI_OPERAND_OBJECT     **RetInternalObject)
474 {
475     ACPI_OPERAND_OBJECT     *InternalObject;
476 
477 
478     ACPI_FUNCTION_TRACE (UtCopyEsimpleToIsimple);
479 
480 
481     /*
482      * Simple types supported are: String, Buffer, Integer
483      */
484     switch (ExternalObject->Type)
485     {
486     case ACPI_TYPE_STRING:
487     case ACPI_TYPE_BUFFER:
488     case ACPI_TYPE_INTEGER:
489     case ACPI_TYPE_LOCAL_REFERENCE:
490 
491         InternalObject = AcpiUtCreateInternalObject (
492                             (UINT8) ExternalObject->Type);
493         if (!InternalObject)
494         {
495             return_ACPI_STATUS (AE_NO_MEMORY);
496         }
497         break;
498 
499     case ACPI_TYPE_ANY: /* This is the case for a NULL object */
500 
501         *RetInternalObject = NULL;
502         return_ACPI_STATUS (AE_OK);
503 
504     default:
505 
506         /* All other types are not supported */
507 
508         ACPI_ERROR ((AE_INFO,
509             "Unsupported object type, cannot convert to internal object: %s",
510             AcpiUtGetTypeName (ExternalObject->Type)));
511 
512         return_ACPI_STATUS (AE_SUPPORT);
513     }
514 
515 
516     /* Must COPY string and buffer contents */
517 
518     switch (ExternalObject->Type)
519     {
520     case ACPI_TYPE_STRING:
521 
522         InternalObject->String.Pointer =
523             ACPI_ALLOCATE_ZEROED ((ACPI_SIZE)
524                 ExternalObject->String.Length + 1);
525 
526         if (!InternalObject->String.Pointer)
527         {
528             goto ErrorExit;
529         }
530 
531         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 (ExternalObject->Package.Count);
619     if (!PackageObject)
620     {
621         return_ACPI_STATUS (AE_NO_MEMORY);
622     }
623 
624     PackageElements = PackageObject->Package.Elements;
625 
626     /*
627      * Recursive implementation. Probably ok, since nested external packages
628      * as parameters should be very rare.
629      */
630     for (i = 0; i < ExternalObject->Package.Count; i++)
631     {
632         Status = AcpiUtCopyEobjectToIobject (
633                     &ExternalObject->Package.Elements[i],
634                     &PackageElements[i]);
635         if (ACPI_FAILURE (Status))
636         {
637             /* Truncate package and delete it */
638 
639             PackageObject->Package.Count = i;
640             PackageElements[i] = NULL;
641             AcpiUtRemoveReference (PackageObject);
642             return_ACPI_STATUS (Status);
643         }
644     }
645 
646     /* Mark package data valid */
647 
648     PackageObject->Package.Flags |= AOPOBJ_DATA_VALID;
649 
650     *InternalObject = PackageObject;
651     return_ACPI_STATUS (Status);
652 }
653 
654 
655 /*******************************************************************************
656  *
657  * FUNCTION:    AcpiUtCopyEobjectToIobject
658  *
659  * PARAMETERS:  ExternalObject      - The external object to be converted
660  *              InternalObject      - Where the internal object is returned
661  *
662  * RETURN:      Status
663  *
664  * DESCRIPTION: Converts an external object to an internal object.
665  *
666  ******************************************************************************/
667 
668 ACPI_STATUS
669 AcpiUtCopyEobjectToIobject (
670     ACPI_OBJECT             *ExternalObject,
671     ACPI_OPERAND_OBJECT     **InternalObject)
672 {
673     ACPI_STATUS             Status;
674 
675 
676     ACPI_FUNCTION_TRACE (UtCopyEobjectToIobject);
677 
678 
679     if (ExternalObject->Type == ACPI_TYPE_PACKAGE)
680     {
681         Status = AcpiUtCopyEpackageToIpackage (ExternalObject, InternalObject);
682     }
683     else
684     {
685         /*
686          * Build a simple object (no nested objects)
687          */
688         Status = AcpiUtCopyEsimpleToIsimple (ExternalObject, InternalObject);
689     }
690 
691     return_ACPI_STATUS (Status);
692 }
693 
694 
695 /*******************************************************************************
696  *
697  * FUNCTION:    AcpiUtCopySimpleObject
698  *
699  * PARAMETERS:  SourceDesc          - The internal object to be copied
700  *              DestDesc            - New target object
701  *
702  * RETURN:      Status
703  *
704  * DESCRIPTION: Simple copy of one internal object to another. Reference count
705  *              of the destination object is preserved.
706  *
707  ******************************************************************************/
708 
709 static ACPI_STATUS
710 AcpiUtCopySimpleObject (
711     ACPI_OPERAND_OBJECT     *SourceDesc,
712     ACPI_OPERAND_OBJECT     *DestDesc)
713 {
714     UINT16                  ReferenceCount;
715     ACPI_OPERAND_OBJECT     *NextObject;
716     ACPI_STATUS             Status;
717     ACPI_SIZE               CopySize;
718 
719 
720     /* Save fields from destination that we don't want to overwrite */
721 
722     ReferenceCount = DestDesc->Common.ReferenceCount;
723     NextObject = DestDesc->Common.NextObject;
724 
725     /*
726      * Copy the entire source object over the destination object.
727      * Note: Source can be either an operand object or namespace node.
728      */
729     CopySize = sizeof (ACPI_OPERAND_OBJECT);
730     if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
731     {
732         CopySize = sizeof (ACPI_NAMESPACE_NODE);
733     }
734 
735     memcpy (ACPI_CAST_PTR (char, DestDesc),
736         ACPI_CAST_PTR (char, SourceDesc), CopySize);
737 
738     /* Restore the saved fields */
739 
740     DestDesc->Common.ReferenceCount = ReferenceCount;
741     DestDesc->Common.NextObject = NextObject;
742 
743     /* New object is not static, regardless of source */
744 
745     DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
746 
747     /* Handle the objects with extra data */
748 
749     switch (DestDesc->Common.Type)
750     {
751     case ACPI_TYPE_BUFFER:
752         /*
753          * Allocate and copy the actual buffer if and only if:
754          * 1) There is a valid buffer pointer
755          * 2) The buffer has a length > 0
756          */
757         if ((SourceDesc->Buffer.Pointer) &&
758             (SourceDesc->Buffer.Length))
759         {
760             DestDesc->Buffer.Pointer =
761                 ACPI_ALLOCATE (SourceDesc->Buffer.Length);
762             if (!DestDesc->Buffer.Pointer)
763             {
764                 return (AE_NO_MEMORY);
765             }
766 
767             /* Copy the actual buffer data */
768 
769             memcpy (DestDesc->Buffer.Pointer,
770                 SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
771         }
772         break;
773 
774     case ACPI_TYPE_STRING:
775         /*
776          * Allocate and copy the actual string if and only if:
777          * 1) There is a valid string pointer
778          * (Pointer to a NULL string is allowed)
779          */
780         if (SourceDesc->String.Pointer)
781         {
782             DestDesc->String.Pointer =
783                 ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
784             if (!DestDesc->String.Pointer)
785             {
786                 return (AE_NO_MEMORY);
787             }
788 
789             /* Copy the actual string data */
790 
791             memcpy (DestDesc->String.Pointer, SourceDesc->String.Pointer,
792                 (ACPI_SIZE) SourceDesc->String.Length + 1);
793         }
794         break;
795 
796     case ACPI_TYPE_LOCAL_REFERENCE:
797         /*
798          * We copied the reference object, so we now must add a reference
799          * to the object pointed to by the reference
800          *
801          * DDBHandle reference (from Load/LoadTable) is a special reference,
802          * it does not have a Reference.Object, so does not need to
803          * increase the reference count
804          */
805         if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
806         {
807             break;
808         }
809 
810         AcpiUtAddReference (SourceDesc->Reference.Object);
811         break;
812 
813     case ACPI_TYPE_REGION:
814         /*
815          * We copied the Region Handler, so we now must add a reference
816          */
817         if (DestDesc->Region.Handler)
818         {
819             AcpiUtAddReference (DestDesc->Region.Handler);
820         }
821         break;
822 
823     /*
824      * For Mutex and Event objects, we cannot simply copy the underlying
825      * OS object. We must create a new one.
826      */
827     case ACPI_TYPE_MUTEX:
828 
829         Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex);
830         if (ACPI_FAILURE (Status))
831         {
832             return (Status);
833         }
834         break;
835 
836     case ACPI_TYPE_EVENT:
837 
838         Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
839                     &DestDesc->Event.OsSemaphore);
840         if (ACPI_FAILURE (Status))
841         {
842             return (Status);
843         }
844         break;
845 
846     default:
847 
848         /* Nothing to do for other simple objects */
849 
850         break;
851     }
852 
853     return (AE_OK);
854 }
855 
856 
857 /*******************************************************************************
858  *
859  * FUNCTION:    AcpiUtCopyIelementToIelement
860  *
861  * PARAMETERS:  ACPI_PKG_CALLBACK
862  *
863  * RETURN:      Status
864  *
865  * DESCRIPTION: Copy one package element to another package element
866  *
867  ******************************************************************************/
868 
869 static ACPI_STATUS
870 AcpiUtCopyIelementToIelement (
871     UINT8                   ObjectType,
872     ACPI_OPERAND_OBJECT     *SourceObject,
873     ACPI_GENERIC_STATE      *State,
874     void                    *Context)
875 {
876     ACPI_STATUS             Status = AE_OK;
877     UINT32                  ThisIndex;
878     ACPI_OPERAND_OBJECT     **ThisTargetPtr;
879     ACPI_OPERAND_OBJECT     *TargetObject;
880 
881 
882     ACPI_FUNCTION_ENTRY ();
883 
884 
885     ThisIndex     = State->Pkg.Index;
886     ThisTargetPtr = (ACPI_OPERAND_OBJECT **)
887                         &State->Pkg.DestObject->Package.Elements[ThisIndex];
888 
889     switch (ObjectType)
890     {
891     case ACPI_COPY_TYPE_SIMPLE:
892 
893         /* A null source object indicates a (legal) null package element */
894 
895         if (SourceObject)
896         {
897             /*
898              * This is a simple object, just copy it
899              */
900             TargetObject = AcpiUtCreateInternalObject (
901                                 SourceObject->Common.Type);
902             if (!TargetObject)
903             {
904                 return (AE_NO_MEMORY);
905             }
906 
907             Status = AcpiUtCopySimpleObject (SourceObject, TargetObject);
908             if (ACPI_FAILURE (Status))
909             {
910                 goto ErrorExit;
911             }
912 
913             *ThisTargetPtr = TargetObject;
914         }
915         else
916         {
917             /* Pass through a null element */
918 
919             *ThisTargetPtr = NULL;
920         }
921         break;
922 
923     case ACPI_COPY_TYPE_PACKAGE:
924         /*
925          * This object is a package - go down another nesting level
926          * Create and build the package object
927          */
928         TargetObject = AcpiUtCreatePackageObject (SourceObject->Package.Count);
929         if (!TargetObject)
930         {
931             return (AE_NO_MEMORY);
932         }
933 
934         TargetObject->Common.Flags = SourceObject->Common.Flags;
935 
936         /* Pass the new package object back to the package walk routine */
937 
938         State->Pkg.ThisTargetObj = TargetObject;
939 
940         /* Store the object pointer in the parent package object */
941 
942         *ThisTargetPtr = TargetObject;
943         break;
944 
945     default:
946 
947         return (AE_BAD_PARAMETER);
948     }
949 
950     return (Status);
951 
952 ErrorExit:
953     AcpiUtRemoveReference (TargetObject);
954     return (Status);
955 }
956 
957 
958 /*******************************************************************************
959  *
960  * FUNCTION:    AcpiUtCopyIpackageToIpackage
961  *
962  * PARAMETERS:  SourceObj       - Pointer to the source package object
963  *              DestObj         - Where the internal object is returned
964  *              WalkState       - Current Walk state descriptor
965  *
966  * RETURN:      Status
967  *
968  * DESCRIPTION: This function is called to copy an internal package object
969  *              into another internal package object.
970  *
971  ******************************************************************************/
972 
973 static ACPI_STATUS
974 AcpiUtCopyIpackageToIpackage (
975     ACPI_OPERAND_OBJECT     *SourceObj,
976     ACPI_OPERAND_OBJECT     *DestObj,
977     ACPI_WALK_STATE         *WalkState)
978 {
979     ACPI_STATUS             Status = AE_OK;
980 
981 
982     ACPI_FUNCTION_TRACE (UtCopyIpackageToIpackage);
983 
984 
985     DestObj->Common.Type    = SourceObj->Common.Type;
986     DestObj->Common.Flags   = SourceObj->Common.Flags;
987     DestObj->Package.Count  = SourceObj->Package.Count;
988 
989     /*
990      * Create the object array and walk the source package tree
991      */
992     DestObj->Package.Elements = ACPI_ALLOCATE_ZEROED (
993                                     ((ACPI_SIZE) SourceObj->Package.Count + 1) *
994                                     sizeof (void *));
995     if (!DestObj->Package.Elements)
996     {
997         ACPI_ERROR ((AE_INFO, "Package allocation failure"));
998         return_ACPI_STATUS (AE_NO_MEMORY);
999     }
1000 
1001     /*
1002      * Copy the package element-by-element by walking the package "tree".
1003      * This handles nested packages of arbitrary depth.
1004      */
1005     Status = AcpiUtWalkPackageTree (SourceObj, DestObj,
1006                 AcpiUtCopyIelementToIelement, WalkState);
1007     if (ACPI_FAILURE (Status))
1008     {
1009         /* On failure, delete the destination package object */
1010 
1011         AcpiUtRemoveReference (DestObj);
1012     }
1013 
1014     return_ACPI_STATUS (Status);
1015 }
1016 
1017 
1018 /*******************************************************************************
1019  *
1020  * FUNCTION:    AcpiUtCopyIobjectToIobject
1021  *
1022  * PARAMETERS:  SourceDesc          - The internal object to be copied
1023  *              DestDesc            - Where the copied object is returned
1024  *              WalkState           - Current walk state
1025  *
1026  * RETURN:      Status
1027  *
1028  * DESCRIPTION: Copy an internal object to a new internal object
1029  *
1030  ******************************************************************************/
1031 
1032 ACPI_STATUS
1033 AcpiUtCopyIobjectToIobject (
1034     ACPI_OPERAND_OBJECT     *SourceDesc,
1035     ACPI_OPERAND_OBJECT     **DestDesc,
1036     ACPI_WALK_STATE         *WalkState)
1037 {
1038     ACPI_STATUS             Status = AE_OK;
1039 
1040 
1041     ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject);
1042 
1043 
1044     /* Create the top level object */
1045 
1046     *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type);
1047     if (!*DestDesc)
1048     {
1049         return_ACPI_STATUS (AE_NO_MEMORY);
1050     }
1051 
1052     /* Copy the object and possible subobjects */
1053 
1054     if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE)
1055     {
1056         Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc,
1057                         WalkState);
1058     }
1059     else
1060     {
1061         Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc);
1062     }
1063 
1064     /* Delete the allocated object if copy failed */
1065 
1066     if (ACPI_FAILURE (Status))
1067     {
1068         AcpiUtRemoveReference(*DestDesc);
1069     }
1070 
1071     return_ACPI_STATUS (Status);
1072 }
1073