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