utcopy.c revision 281075
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
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    ACPI_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        ACPI_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        ACPI_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 *)
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
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 + 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
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        ACPI_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        ACPI_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 (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
668ACPI_STATUS
669AcpiUtCopyEobjectToIobject (
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
709static ACPI_STATUS
710AcpiUtCopySimpleObject (
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    ACPI_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            ACPI_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            ACPI_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
869static ACPI_STATUS
870AcpiUtCopyIelementToIelement (
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
952ErrorExit:
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
973static ACPI_STATUS
974AcpiUtCopyIpackageToIpackage (
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
1032ACPI_STATUS
1033AcpiUtCopyIobjectToIobject (
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