xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/utilities/utcopy.c (revision 529cd177b573aaba391c8adc9c9f5ad76a14bf81)
1 /******************************************************************************
2  *
3  * Module Name: utcopy - Internal to external object translation utilities
4  *
5  *****************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2014, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 #define __UTCOPY_C__
117 
118 #include "acpi.h"
119 #include "accommon.h"
120 #include "acnamesp.h"
121 
122 
123 #define _COMPONENT          ACPI_UTILITIES
124         ACPI_MODULE_NAME    ("utcopy")
125 
126 /* Local prototypes */
127 
128 static ACPI_STATUS
129 AcpiUtCopyIsimpleToEsimple (
130     ACPI_OPERAND_OBJECT     *InternalObject,
131     ACPI_OBJECT             *ExternalObject,
132     UINT8                   *DataSpace,
133     ACPI_SIZE               *BufferSpaceUsed);
134 
135 static ACPI_STATUS
136 AcpiUtCopyIelementToIelement (
137     UINT8                   ObjectType,
138     ACPI_OPERAND_OBJECT     *SourceObject,
139     ACPI_GENERIC_STATE      *State,
140     void                    *Context);
141 
142 static ACPI_STATUS
143 AcpiUtCopyIpackageToEpackage (
144     ACPI_OPERAND_OBJECT     *InternalObject,
145     UINT8                   *Buffer,
146     ACPI_SIZE               *SpaceUsed);
147 
148 static ACPI_STATUS
149 AcpiUtCopyEsimpleToIsimple(
150     ACPI_OBJECT             *UserObj,
151     ACPI_OPERAND_OBJECT     **ReturnObj);
152 
153 static ACPI_STATUS
154 AcpiUtCopyEpackageToIpackage (
155     ACPI_OBJECT             *ExternalObject,
156     ACPI_OPERAND_OBJECT     **InternalObject);
157 
158 static ACPI_STATUS
159 AcpiUtCopySimpleObject (
160     ACPI_OPERAND_OBJECT     *SourceDesc,
161     ACPI_OPERAND_OBJECT     *DestDesc);
162 
163 static ACPI_STATUS
164 AcpiUtCopyIelementToEelement (
165     UINT8                   ObjectType,
166     ACPI_OPERAND_OBJECT     *SourceObject,
167     ACPI_GENERIC_STATE      *State,
168     void                    *Context);
169 
170 static ACPI_STATUS
171 AcpiUtCopyIpackageToIpackage (
172     ACPI_OPERAND_OBJECT     *SourceObj,
173     ACPI_OPERAND_OBJECT     *DestObj,
174     ACPI_WALK_STATE         *WalkState);
175 
176 
177 /*******************************************************************************
178  *
179  * FUNCTION:    AcpiUtCopyIsimpleToEsimple
180  *
181  * PARAMETERS:  InternalObject      - Source object to be copied
182  *              ExternalObject      - Where to return the copied object
183  *              DataSpace           - Where object data is returned (such as
184  *                                    buffer and string data)
185  *              BufferSpaceUsed     - Length of DataSpace that was used
186  *
187  * RETURN:      Status
188  *
189  * DESCRIPTION: This function is called to copy a simple internal object to
190  *              an external object.
191  *
192  *              The DataSpace buffer is assumed to have sufficient space for
193  *              the object.
194  *
195  ******************************************************************************/
196 
197 static ACPI_STATUS
198 AcpiUtCopyIsimpleToEsimple (
199     ACPI_OPERAND_OBJECT     *InternalObject,
200     ACPI_OBJECT             *ExternalObject,
201     UINT8                   *DataSpace,
202     ACPI_SIZE               *BufferSpaceUsed)
203 {
204     ACPI_STATUS             Status = AE_OK;
205 
206 
207     ACPI_FUNCTION_TRACE (UtCopyIsimpleToEsimple);
208 
209 
210     *BufferSpaceUsed = 0;
211 
212     /*
213      * Check for NULL object case (could be an uninitialized
214      * package element)
215      */
216     if (!InternalObject)
217     {
218         return_ACPI_STATUS (AE_OK);
219     }
220 
221     /* Always clear the external object */
222 
223     ACPI_MEMSET (ExternalObject, 0, sizeof (ACPI_OBJECT));
224 
225     /*
226      * In general, the external object will be the same type as
227      * the internal object
228      */
229     ExternalObject->Type = InternalObject->Common.Type;
230 
231     /* However, only a limited number of external types are supported */
232 
233     switch (InternalObject->Common.Type)
234     {
235     case ACPI_TYPE_STRING:
236 
237         ExternalObject->String.Pointer = (char *) DataSpace;
238         ExternalObject->String.Length  = InternalObject->String.Length;
239         *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
240                             (ACPI_SIZE) InternalObject->String.Length + 1);
241 
242         ACPI_MEMCPY ((void *) DataSpace,
243             (void *) InternalObject->String.Pointer,
244             (ACPI_SIZE) InternalObject->String.Length + 1);
245         break;
246 
247     case ACPI_TYPE_BUFFER:
248 
249         ExternalObject->Buffer.Pointer = DataSpace;
250         ExternalObject->Buffer.Length  = InternalObject->Buffer.Length;
251         *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
252                             InternalObject->String.Length);
253 
254         ACPI_MEMCPY ((void *) DataSpace,
255             (void *) InternalObject->Buffer.Pointer,
256             InternalObject->Buffer.Length);
257         break;
258 
259     case ACPI_TYPE_INTEGER:
260 
261         ExternalObject->Integer.Value = InternalObject->Integer.Value;
262         break;
263 
264     case ACPI_TYPE_LOCAL_REFERENCE:
265 
266         /* This is an object reference. */
267 
268         switch (InternalObject->Reference.Class)
269         {
270         case ACPI_REFCLASS_NAME:
271             /*
272              * For namepath, return the object handle ("reference")
273              * We are referring to the namespace node
274              */
275             ExternalObject->Reference.Handle =
276                 InternalObject->Reference.Node;
277             ExternalObject->Reference.ActualType =
278                 AcpiNsGetType (InternalObject->Reference.Node);
279             break;
280 
281         default:
282 
283             /* All other reference types are unsupported */
284 
285             return_ACPI_STATUS (AE_TYPE);
286         }
287         break;
288 
289     case ACPI_TYPE_PROCESSOR:
290 
291         ExternalObject->Processor.ProcId =
292             InternalObject->Processor.ProcId;
293         ExternalObject->Processor.PblkAddress =
294             InternalObject->Processor.Address;
295         ExternalObject->Processor.PblkLength =
296             InternalObject->Processor.Length;
297         break;
298 
299     case ACPI_TYPE_POWER:
300 
301         ExternalObject->PowerResource.SystemLevel =
302             InternalObject->PowerResource.SystemLevel;
303 
304         ExternalObject->PowerResource.ResourceOrder =
305             InternalObject->PowerResource.ResourceOrder;
306         break;
307 
308     default:
309         /*
310          * There is no corresponding external object type
311          */
312         ACPI_ERROR ((AE_INFO,
313             "Unsupported object type, cannot convert to external object: %s",
314             AcpiUtGetTypeName (InternalObject->Common.Type)));
315 
316         return_ACPI_STATUS (AE_SUPPORT);
317     }
318 
319     return_ACPI_STATUS (Status);
320 }
321 
322 
323 /*******************************************************************************
324  *
325  * FUNCTION:    AcpiUtCopyIelementToEelement
326  *
327  * PARAMETERS:  ACPI_PKG_CALLBACK
328  *
329  * RETURN:      Status
330  *
331  * DESCRIPTION: Copy one package element to another package element
332  *
333  ******************************************************************************/
334 
335 static ACPI_STATUS
336 AcpiUtCopyIelementToEelement (
337     UINT8                   ObjectType,
338     ACPI_OPERAND_OBJECT     *SourceObject,
339     ACPI_GENERIC_STATE      *State,
340     void                    *Context)
341 {
342     ACPI_STATUS             Status = AE_OK;
343     ACPI_PKG_INFO           *Info = (ACPI_PKG_INFO *) Context;
344     ACPI_SIZE               ObjectSpace;
345     UINT32                  ThisIndex;
346     ACPI_OBJECT             *TargetObject;
347 
348 
349     ACPI_FUNCTION_ENTRY ();
350 
351 
352     ThisIndex    = State->Pkg.Index;
353     TargetObject = (ACPI_OBJECT *)
354         &((ACPI_OBJECT *)(State->Pkg.DestObject))->Package.Elements[ThisIndex];
355 
356     switch (ObjectType)
357     {
358     case ACPI_COPY_TYPE_SIMPLE:
359         /*
360          * This is a simple or null object
361          */
362         Status = AcpiUtCopyIsimpleToEsimple (SourceObject,
363                         TargetObject, Info->FreeSpace, &ObjectSpace);
364         if (ACPI_FAILURE (Status))
365         {
366             return (Status);
367         }
368         break;
369 
370     case ACPI_COPY_TYPE_PACKAGE:
371         /*
372          * Build the package object
373          */
374         TargetObject->Type              = ACPI_TYPE_PACKAGE;
375         TargetObject->Package.Count     = SourceObject->Package.Count;
376         TargetObject->Package.Elements  =
377             ACPI_CAST_PTR (ACPI_OBJECT, Info->FreeSpace);
378 
379         /*
380          * Pass the new package object back to the package walk routine
381          */
382         State->Pkg.ThisTargetObj = TargetObject;
383 
384         /*
385          * Save space for the array of objects (Package elements)
386          * update the buffer length counter
387          */
388         ObjectSpace = ACPI_ROUND_UP_TO_NATIVE_WORD (
389                             (ACPI_SIZE) TargetObject->Package.Count *
390                             sizeof (ACPI_OBJECT));
391         break;
392 
393     default:
394 
395         return (AE_BAD_PARAMETER);
396     }
397 
398     Info->FreeSpace   += ObjectSpace;
399     Info->Length      += ObjectSpace;
400     return (Status);
401 }
402 
403 
404 /*******************************************************************************
405  *
406  * FUNCTION:    AcpiUtCopyIpackageToEpackage
407  *
408  * PARAMETERS:  InternalObject      - Pointer to the object we are returning
409  *              Buffer              - Where the object is returned
410  *              SpaceUsed           - Where the object length is returned
411  *
412  * RETURN:      Status
413  *
414  * DESCRIPTION: This function is called to place a package object in a user
415  *              buffer. A package object by definition contains other objects.
416  *
417  *              The buffer is assumed to have sufficient space for the object.
418  *              The caller must have verified the buffer length needed using
419  *              the AcpiUtGetObjectSize function before calling this function.
420  *
421  ******************************************************************************/
422 
423 static ACPI_STATUS
424 AcpiUtCopyIpackageToEpackage (
425     ACPI_OPERAND_OBJECT     *InternalObject,
426     UINT8                   *Buffer,
427     ACPI_SIZE               *SpaceUsed)
428 {
429     ACPI_OBJECT             *ExternalObject;
430     ACPI_STATUS             Status;
431     ACPI_PKG_INFO           Info;
432 
433 
434     ACPI_FUNCTION_TRACE (UtCopyIpackageToEpackage);
435 
436 
437     /*
438      * First package at head of the buffer
439      */
440     ExternalObject = ACPI_CAST_PTR (ACPI_OBJECT, Buffer);
441 
442     /*
443      * Free space begins right after the first package
444      */
445     Info.Length      = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
446     Info.FreeSpace   = Buffer + ACPI_ROUND_UP_TO_NATIVE_WORD (
447                                     sizeof (ACPI_OBJECT));
448     Info.ObjectSpace = 0;
449     Info.NumPackages = 1;
450 
451     ExternalObject->Type             = InternalObject->Common.Type;
452     ExternalObject->Package.Count    = InternalObject->Package.Count;
453     ExternalObject->Package.Elements = ACPI_CAST_PTR (ACPI_OBJECT,
454                                             Info.FreeSpace);
455 
456     /*
457      * Leave room for an array of ACPI_OBJECTS in the buffer
458      * and move the free space past it
459      */
460     Info.Length    += (ACPI_SIZE) ExternalObject->Package.Count *
461                             ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
462     Info.FreeSpace += ExternalObject->Package.Count *
463                             ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
464 
465     Status = AcpiUtWalkPackageTree (InternalObject, ExternalObject,
466                 AcpiUtCopyIelementToEelement, &Info);
467 
468     *SpaceUsed = Info.Length;
469     return_ACPI_STATUS (Status);
470 }
471 
472 
473 /*******************************************************************************
474  *
475  * FUNCTION:    AcpiUtCopyIobjectToEobject
476  *
477  * PARAMETERS:  InternalObject      - The internal object to be converted
478  *              RetBuffer           - Where the object is returned
479  *
480  * RETURN:      Status
481  *
482  * DESCRIPTION: This function is called to build an API object to be returned
483  *              to the caller.
484  *
485  ******************************************************************************/
486 
487 ACPI_STATUS
488 AcpiUtCopyIobjectToEobject (
489     ACPI_OPERAND_OBJECT     *InternalObject,
490     ACPI_BUFFER             *RetBuffer)
491 {
492     ACPI_STATUS             Status;
493 
494 
495     ACPI_FUNCTION_TRACE (UtCopyIobjectToEobject);
496 
497 
498     if (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)
499     {
500         /*
501          * Package object:  Copy all subobjects (including
502          * nested packages)
503          */
504         Status = AcpiUtCopyIpackageToEpackage (InternalObject,
505                         RetBuffer->Pointer, &RetBuffer->Length);
506     }
507     else
508     {
509         /*
510          * Build a simple object (no nested objects)
511          */
512         Status = AcpiUtCopyIsimpleToEsimple (InternalObject,
513                     ACPI_CAST_PTR (ACPI_OBJECT, RetBuffer->Pointer),
514                     ACPI_ADD_PTR (UINT8, RetBuffer->Pointer,
515                         ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))),
516                     &RetBuffer->Length);
517         /*
518          * build simple does not include the object size in the length
519          * so we add it in here
520          */
521         RetBuffer->Length += sizeof (ACPI_OBJECT);
522     }
523 
524     return_ACPI_STATUS (Status);
525 }
526 
527 
528 /*******************************************************************************
529  *
530  * FUNCTION:    AcpiUtCopyEsimpleToIsimple
531  *
532  * PARAMETERS:  ExternalObject      - The external object to be converted
533  *              RetInternalObject   - Where the internal object is returned
534  *
535  * RETURN:      Status
536  *
537  * DESCRIPTION: This function copies an external object to an internal one.
538  *              NOTE: Pointers can be copied, we don't need to copy data.
539  *              (The pointers have to be valid in our address space no matter
540  *              what we do with them!)
541  *
542  ******************************************************************************/
543 
544 static ACPI_STATUS
545 AcpiUtCopyEsimpleToIsimple (
546     ACPI_OBJECT             *ExternalObject,
547     ACPI_OPERAND_OBJECT     **RetInternalObject)
548 {
549     ACPI_OPERAND_OBJECT     *InternalObject;
550 
551 
552     ACPI_FUNCTION_TRACE (UtCopyEsimpleToIsimple);
553 
554 
555     /*
556      * Simple types supported are: String, Buffer, Integer
557      */
558     switch (ExternalObject->Type)
559     {
560     case ACPI_TYPE_STRING:
561     case ACPI_TYPE_BUFFER:
562     case ACPI_TYPE_INTEGER:
563     case ACPI_TYPE_LOCAL_REFERENCE:
564 
565         InternalObject = AcpiUtCreateInternalObject (
566                             (UINT8) ExternalObject->Type);
567         if (!InternalObject)
568         {
569             return_ACPI_STATUS (AE_NO_MEMORY);
570         }
571         break;
572 
573     case ACPI_TYPE_ANY: /* This is the case for a NULL object */
574 
575         *RetInternalObject = NULL;
576         return_ACPI_STATUS (AE_OK);
577 
578     default:
579 
580         /* All other types are not supported */
581 
582         ACPI_ERROR ((AE_INFO,
583             "Unsupported object type, cannot convert to internal object: %s",
584             AcpiUtGetTypeName (ExternalObject->Type)));
585 
586         return_ACPI_STATUS (AE_SUPPORT);
587     }
588 
589 
590     /* Must COPY string and buffer contents */
591 
592     switch (ExternalObject->Type)
593     {
594     case ACPI_TYPE_STRING:
595 
596         InternalObject->String.Pointer =
597             ACPI_ALLOCATE_ZEROED ((ACPI_SIZE)
598                 ExternalObject->String.Length + 1);
599 
600         if (!InternalObject->String.Pointer)
601         {
602             goto ErrorExit;
603         }
604 
605         ACPI_MEMCPY (InternalObject->String.Pointer,
606                      ExternalObject->String.Pointer,
607                      ExternalObject->String.Length);
608 
609         InternalObject->String.Length  = ExternalObject->String.Length;
610         break;
611 
612     case ACPI_TYPE_BUFFER:
613 
614         InternalObject->Buffer.Pointer =
615             ACPI_ALLOCATE_ZEROED (ExternalObject->Buffer.Length);
616         if (!InternalObject->Buffer.Pointer)
617         {
618             goto ErrorExit;
619         }
620 
621         ACPI_MEMCPY (InternalObject->Buffer.Pointer,
622                      ExternalObject->Buffer.Pointer,
623                      ExternalObject->Buffer.Length);
624 
625         InternalObject->Buffer.Length  = ExternalObject->Buffer.Length;
626 
627         /* Mark buffer data valid */
628 
629         InternalObject->Buffer.Flags |= AOPOBJ_DATA_VALID;
630         break;
631 
632     case ACPI_TYPE_INTEGER:
633 
634         InternalObject->Integer.Value   = ExternalObject->Integer.Value;
635         break;
636 
637     case ACPI_TYPE_LOCAL_REFERENCE:
638 
639         /* An incoming reference is defined to be a namespace node */
640 
641         InternalObject->Reference.Class = ACPI_REFCLASS_REFOF;
642         InternalObject->Reference.Object = ExternalObject->Reference.Handle;
643         break;
644 
645     default:
646 
647         /* Other types can't get here */
648 
649         break;
650     }
651 
652     *RetInternalObject = InternalObject;
653     return_ACPI_STATUS (AE_OK);
654 
655 
656 ErrorExit:
657     AcpiUtRemoveReference (InternalObject);
658     return_ACPI_STATUS (AE_NO_MEMORY);
659 }
660 
661 
662 /*******************************************************************************
663  *
664  * FUNCTION:    AcpiUtCopyEpackageToIpackage
665  *
666  * PARAMETERS:  ExternalObject      - The external object to be converted
667  *              InternalObject      - Where the internal object is returned
668  *
669  * RETURN:      Status
670  *
671  * DESCRIPTION: Copy an external package object to an internal package.
672  *              Handles nested packages.
673  *
674  ******************************************************************************/
675 
676 static ACPI_STATUS
677 AcpiUtCopyEpackageToIpackage (
678     ACPI_OBJECT             *ExternalObject,
679     ACPI_OPERAND_OBJECT     **InternalObject)
680 {
681     ACPI_STATUS             Status = AE_OK;
682     ACPI_OPERAND_OBJECT     *PackageObject;
683     ACPI_OPERAND_OBJECT     **PackageElements;
684     UINT32                  i;
685 
686 
687     ACPI_FUNCTION_TRACE (UtCopyEpackageToIpackage);
688 
689 
690     /* Create the package object */
691 
692     PackageObject = AcpiUtCreatePackageObject (ExternalObject->Package.Count);
693     if (!PackageObject)
694     {
695         return_ACPI_STATUS (AE_NO_MEMORY);
696     }
697 
698     PackageElements = PackageObject->Package.Elements;
699 
700     /*
701      * Recursive implementation. Probably ok, since nested external packages
702      * as parameters should be very rare.
703      */
704     for (i = 0; i < ExternalObject->Package.Count; i++)
705     {
706         Status = AcpiUtCopyEobjectToIobject (
707                     &ExternalObject->Package.Elements[i],
708                     &PackageElements[i]);
709         if (ACPI_FAILURE (Status))
710         {
711             /* Truncate package and delete it */
712 
713             PackageObject->Package.Count = i;
714             PackageElements[i] = NULL;
715             AcpiUtRemoveReference (PackageObject);
716             return_ACPI_STATUS (Status);
717         }
718     }
719 
720     /* Mark package data valid */
721 
722     PackageObject->Package.Flags |= AOPOBJ_DATA_VALID;
723 
724     *InternalObject = PackageObject;
725     return_ACPI_STATUS (Status);
726 }
727 
728 
729 /*******************************************************************************
730  *
731  * FUNCTION:    AcpiUtCopyEobjectToIobject
732  *
733  * PARAMETERS:  ExternalObject      - The external object to be converted
734  *              InternalObject      - Where the internal object is returned
735  *
736  * RETURN:      Status
737  *
738  * DESCRIPTION: Converts an external object to an internal object.
739  *
740  ******************************************************************************/
741 
742 ACPI_STATUS
743 AcpiUtCopyEobjectToIobject (
744     ACPI_OBJECT             *ExternalObject,
745     ACPI_OPERAND_OBJECT     **InternalObject)
746 {
747     ACPI_STATUS             Status;
748 
749 
750     ACPI_FUNCTION_TRACE (UtCopyEobjectToIobject);
751 
752 
753     if (ExternalObject->Type == ACPI_TYPE_PACKAGE)
754     {
755         Status = AcpiUtCopyEpackageToIpackage (ExternalObject, InternalObject);
756     }
757     else
758     {
759         /*
760          * Build a simple object (no nested objects)
761          */
762         Status = AcpiUtCopyEsimpleToIsimple (ExternalObject, InternalObject);
763     }
764 
765     return_ACPI_STATUS (Status);
766 }
767 
768 
769 /*******************************************************************************
770  *
771  * FUNCTION:    AcpiUtCopySimpleObject
772  *
773  * PARAMETERS:  SourceDesc          - The internal object to be copied
774  *              DestDesc            - New target object
775  *
776  * RETURN:      Status
777  *
778  * DESCRIPTION: Simple copy of one internal object to another. Reference count
779  *              of the destination object is preserved.
780  *
781  ******************************************************************************/
782 
783 static ACPI_STATUS
784 AcpiUtCopySimpleObject (
785     ACPI_OPERAND_OBJECT     *SourceDesc,
786     ACPI_OPERAND_OBJECT     *DestDesc)
787 {
788     UINT16                  ReferenceCount;
789     ACPI_OPERAND_OBJECT     *NextObject;
790     ACPI_STATUS             Status;
791     ACPI_SIZE               CopySize;
792 
793 
794     /* Save fields from destination that we don't want to overwrite */
795 
796     ReferenceCount = DestDesc->Common.ReferenceCount;
797     NextObject = DestDesc->Common.NextObject;
798 
799     /*
800      * Copy the entire source object over the destination object.
801      * Note: Source can be either an operand object or namespace node.
802      */
803     CopySize = sizeof (ACPI_OPERAND_OBJECT);
804     if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
805     {
806         CopySize = sizeof (ACPI_NAMESPACE_NODE);
807     }
808 
809     ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc),
810         ACPI_CAST_PTR (char, SourceDesc), CopySize);
811 
812     /* Restore the saved fields */
813 
814     DestDesc->Common.ReferenceCount = ReferenceCount;
815     DestDesc->Common.NextObject = NextObject;
816 
817     /* New object is not static, regardless of source */
818 
819     DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
820 
821     /* Handle the objects with extra data */
822 
823     switch (DestDesc->Common.Type)
824     {
825     case ACPI_TYPE_BUFFER:
826         /*
827          * Allocate and copy the actual buffer if and only if:
828          * 1) There is a valid buffer pointer
829          * 2) The buffer has a length > 0
830          */
831         if ((SourceDesc->Buffer.Pointer) &&
832             (SourceDesc->Buffer.Length))
833         {
834             DestDesc->Buffer.Pointer =
835                 ACPI_ALLOCATE (SourceDesc->Buffer.Length);
836             if (!DestDesc->Buffer.Pointer)
837             {
838                 return (AE_NO_MEMORY);
839             }
840 
841             /* Copy the actual buffer data */
842 
843             ACPI_MEMCPY (DestDesc->Buffer.Pointer,
844                 SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
845         }
846         break;
847 
848     case ACPI_TYPE_STRING:
849         /*
850          * Allocate and copy the actual string if and only if:
851          * 1) There is a valid string pointer
852          * (Pointer to a NULL string is allowed)
853          */
854         if (SourceDesc->String.Pointer)
855         {
856             DestDesc->String.Pointer =
857                 ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
858             if (!DestDesc->String.Pointer)
859             {
860                 return (AE_NO_MEMORY);
861             }
862 
863             /* Copy the actual string data */
864 
865             ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
866                 (ACPI_SIZE) SourceDesc->String.Length + 1);
867         }
868         break;
869 
870     case ACPI_TYPE_LOCAL_REFERENCE:
871         /*
872          * We copied the reference object, so we now must add a reference
873          * to the object pointed to by the reference
874          *
875          * DDBHandle reference (from Load/LoadTable) is a special reference,
876          * it does not have a Reference.Object, so does not need to
877          * increase the reference count
878          */
879         if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
880         {
881             break;
882         }
883 
884         AcpiUtAddReference (SourceDesc->Reference.Object);
885         break;
886 
887     case ACPI_TYPE_REGION:
888         /*
889          * We copied the Region Handler, so we now must add a reference
890          */
891         if (DestDesc->Region.Handler)
892         {
893             AcpiUtAddReference (DestDesc->Region.Handler);
894         }
895         break;
896 
897     /*
898      * For Mutex and Event objects, we cannot simply copy the underlying
899      * OS object. We must create a new one.
900      */
901     case ACPI_TYPE_MUTEX:
902 
903         Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex);
904         if (ACPI_FAILURE (Status))
905         {
906             return (Status);
907         }
908         break;
909 
910     case ACPI_TYPE_EVENT:
911 
912         Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
913                     &DestDesc->Event.OsSemaphore);
914         if (ACPI_FAILURE (Status))
915         {
916             return (Status);
917         }
918         break;
919 
920     default:
921 
922         /* Nothing to do for other simple objects */
923 
924         break;
925     }
926 
927     return (AE_OK);
928 }
929 
930 
931 /*******************************************************************************
932  *
933  * FUNCTION:    AcpiUtCopyIelementToIelement
934  *
935  * PARAMETERS:  ACPI_PKG_CALLBACK
936  *
937  * RETURN:      Status
938  *
939  * DESCRIPTION: Copy one package element to another package element
940  *
941  ******************************************************************************/
942 
943 static ACPI_STATUS
944 AcpiUtCopyIelementToIelement (
945     UINT8                   ObjectType,
946     ACPI_OPERAND_OBJECT     *SourceObject,
947     ACPI_GENERIC_STATE      *State,
948     void                    *Context)
949 {
950     ACPI_STATUS             Status = AE_OK;
951     UINT32                  ThisIndex;
952     ACPI_OPERAND_OBJECT     **ThisTargetPtr;
953     ACPI_OPERAND_OBJECT     *TargetObject;
954 
955 
956     ACPI_FUNCTION_ENTRY ();
957 
958 
959     ThisIndex     = State->Pkg.Index;
960     ThisTargetPtr = (ACPI_OPERAND_OBJECT **)
961                         &State->Pkg.DestObject->Package.Elements[ThisIndex];
962 
963     switch (ObjectType)
964     {
965     case ACPI_COPY_TYPE_SIMPLE:
966 
967         /* A null source object indicates a (legal) null package element */
968 
969         if (SourceObject)
970         {
971             /*
972              * This is a simple object, just copy it
973              */
974             TargetObject = AcpiUtCreateInternalObject (
975                                 SourceObject->Common.Type);
976             if (!TargetObject)
977             {
978                 return (AE_NO_MEMORY);
979             }
980 
981             Status = AcpiUtCopySimpleObject (SourceObject, TargetObject);
982             if (ACPI_FAILURE (Status))
983             {
984                 goto ErrorExit;
985             }
986 
987             *ThisTargetPtr = TargetObject;
988         }
989         else
990         {
991             /* Pass through a null element */
992 
993             *ThisTargetPtr = NULL;
994         }
995         break;
996 
997     case ACPI_COPY_TYPE_PACKAGE:
998         /*
999          * This object is a package - go down another nesting level
1000          * Create and build the package object
1001          */
1002         TargetObject = AcpiUtCreatePackageObject (SourceObject->Package.Count);
1003         if (!TargetObject)
1004         {
1005             return (AE_NO_MEMORY);
1006         }
1007 
1008         TargetObject->Common.Flags = SourceObject->Common.Flags;
1009 
1010         /* Pass the new package object back to the package walk routine */
1011 
1012         State->Pkg.ThisTargetObj = TargetObject;
1013 
1014         /* Store the object pointer in the parent package object */
1015 
1016         *ThisTargetPtr = TargetObject;
1017         break;
1018 
1019     default:
1020 
1021         return (AE_BAD_PARAMETER);
1022     }
1023 
1024     return (Status);
1025 
1026 ErrorExit:
1027     AcpiUtRemoveReference (TargetObject);
1028     return (Status);
1029 }
1030 
1031 
1032 /*******************************************************************************
1033  *
1034  * FUNCTION:    AcpiUtCopyIpackageToIpackage
1035  *
1036  * PARAMETERS:  SourceObj       - Pointer to the source package object
1037  *              DestObj         - Where the internal object is returned
1038  *              WalkState       - Current Walk state descriptor
1039  *
1040  * RETURN:      Status
1041  *
1042  * DESCRIPTION: This function is called to copy an internal package object
1043  *              into another internal package object.
1044  *
1045  ******************************************************************************/
1046 
1047 static ACPI_STATUS
1048 AcpiUtCopyIpackageToIpackage (
1049     ACPI_OPERAND_OBJECT     *SourceObj,
1050     ACPI_OPERAND_OBJECT     *DestObj,
1051     ACPI_WALK_STATE         *WalkState)
1052 {
1053     ACPI_STATUS             Status = AE_OK;
1054 
1055 
1056     ACPI_FUNCTION_TRACE (UtCopyIpackageToIpackage);
1057 
1058 
1059     DestObj->Common.Type    = SourceObj->Common.Type;
1060     DestObj->Common.Flags   = SourceObj->Common.Flags;
1061     DestObj->Package.Count  = SourceObj->Package.Count;
1062 
1063     /*
1064      * Create the object array and walk the source package tree
1065      */
1066     DestObj->Package.Elements = ACPI_ALLOCATE_ZEROED (
1067                                     ((ACPI_SIZE) SourceObj->Package.Count + 1) *
1068                                     sizeof (void *));
1069     if (!DestObj->Package.Elements)
1070     {
1071         ACPI_ERROR ((AE_INFO, "Package allocation failure"));
1072         return_ACPI_STATUS (AE_NO_MEMORY);
1073     }
1074 
1075     /*
1076      * Copy the package element-by-element by walking the package "tree".
1077      * This handles nested packages of arbitrary depth.
1078      */
1079     Status = AcpiUtWalkPackageTree (SourceObj, DestObj,
1080                 AcpiUtCopyIelementToIelement, WalkState);
1081     if (ACPI_FAILURE (Status))
1082     {
1083         /* On failure, delete the destination package object */
1084 
1085         AcpiUtRemoveReference (DestObj);
1086     }
1087 
1088     return_ACPI_STATUS (Status);
1089 }
1090 
1091 
1092 /*******************************************************************************
1093  *
1094  * FUNCTION:    AcpiUtCopyIobjectToIobject
1095  *
1096  * PARAMETERS:  SourceDesc          - The internal object to be copied
1097  *              DestDesc            - Where the copied object is returned
1098  *              WalkState           - Current walk state
1099  *
1100  * RETURN:      Status
1101  *
1102  * DESCRIPTION: Copy an internal object to a new internal object
1103  *
1104  ******************************************************************************/
1105 
1106 ACPI_STATUS
1107 AcpiUtCopyIobjectToIobject (
1108     ACPI_OPERAND_OBJECT     *SourceDesc,
1109     ACPI_OPERAND_OBJECT     **DestDesc,
1110     ACPI_WALK_STATE         *WalkState)
1111 {
1112     ACPI_STATUS             Status = AE_OK;
1113 
1114 
1115     ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject);
1116 
1117 
1118     /* Create the top level object */
1119 
1120     *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type);
1121     if (!*DestDesc)
1122     {
1123         return_ACPI_STATUS (AE_NO_MEMORY);
1124     }
1125 
1126     /* Copy the object and possible subobjects */
1127 
1128     if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE)
1129     {
1130         Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc,
1131                         WalkState);
1132     }
1133     else
1134     {
1135         Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc);
1136     }
1137 
1138     /* Delete the allocated object if copy failed */
1139 
1140     if (ACPI_FAILURE (Status))
1141     {
1142         AcpiUtRemoveReference(*DestDesc);
1143     }
1144 
1145     return_ACPI_STATUS (Status);
1146 }
1147