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