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