1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: utcopy - Internal to external object translation utilities |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | #include <acpi/acpi.h> |
11 | #include "accommon.h" |
12 | #include "acnamesp.h" |
13 | |
14 | |
15 | #define _COMPONENT ACPI_UTILITIES |
16 | ACPI_MODULE_NAME("utcopy" ) |
17 | |
18 | /* Local prototypes */ |
19 | static acpi_status |
20 | acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, |
21 | union acpi_object *external_object, |
22 | u8 *data_space, acpi_size *buffer_space_used); |
23 | |
24 | static acpi_status |
25 | acpi_ut_copy_ielement_to_ielement(u8 object_type, |
26 | union acpi_operand_object *source_object, |
27 | union acpi_generic_state *state, |
28 | void *context); |
29 | |
30 | static acpi_status |
31 | acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, |
32 | u8 *buffer, acpi_size *space_used); |
33 | |
34 | static acpi_status |
35 | acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj, |
36 | union acpi_operand_object **return_obj); |
37 | |
38 | static acpi_status |
39 | acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, |
40 | union acpi_operand_object **internal_object); |
41 | |
42 | static acpi_status |
43 | acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, |
44 | union acpi_operand_object *dest_desc); |
45 | |
46 | static acpi_status |
47 | acpi_ut_copy_ielement_to_eelement(u8 object_type, |
48 | union acpi_operand_object *source_object, |
49 | union acpi_generic_state *state, |
50 | void *context); |
51 | |
52 | static acpi_status |
53 | acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, |
54 | union acpi_operand_object *dest_obj, |
55 | struct acpi_walk_state *walk_state); |
56 | |
57 | /******************************************************************************* |
58 | * |
59 | * FUNCTION: acpi_ut_copy_isimple_to_esimple |
60 | * |
61 | * PARAMETERS: internal_object - Source object to be copied |
62 | * external_object - Where to return the copied object |
63 | * data_space - Where object data is returned (such as |
64 | * buffer and string data) |
65 | * buffer_space_used - Length of data_space that was used |
66 | * |
67 | * RETURN: Status |
68 | * |
69 | * DESCRIPTION: This function is called to copy a simple internal object to |
70 | * an external object. |
71 | * |
72 | * The data_space buffer is assumed to have sufficient space for |
73 | * the object. |
74 | * |
75 | ******************************************************************************/ |
76 | |
77 | static acpi_status |
78 | acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object, |
79 | union acpi_object *external_object, |
80 | u8 *data_space, acpi_size *buffer_space_used) |
81 | { |
82 | acpi_status status = AE_OK; |
83 | |
84 | ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple); |
85 | |
86 | *buffer_space_used = 0; |
87 | |
88 | /* |
89 | * Check for NULL object case (could be an uninitialized |
90 | * package element) |
91 | */ |
92 | if (!internal_object) { |
93 | return_ACPI_STATUS(AE_OK); |
94 | } |
95 | |
96 | /* Always clear the external object */ |
97 | |
98 | memset(external_object, 0, sizeof(union acpi_object)); |
99 | |
100 | /* |
101 | * In general, the external object will be the same type as |
102 | * the internal object |
103 | */ |
104 | external_object->type = internal_object->common.type; |
105 | |
106 | /* However, only a limited number of external types are supported */ |
107 | |
108 | switch (internal_object->common.type) { |
109 | case ACPI_TYPE_STRING: |
110 | |
111 | external_object->string.pointer = (char *)data_space; |
112 | external_object->string.length = internal_object->string.length; |
113 | *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size) |
114 | internal_object-> |
115 | string. |
116 | length + 1); |
117 | |
118 | memcpy((void *)data_space, |
119 | (void *)internal_object->string.pointer, |
120 | (acpi_size)internal_object->string.length + 1); |
121 | break; |
122 | |
123 | case ACPI_TYPE_BUFFER: |
124 | |
125 | external_object->buffer.pointer = data_space; |
126 | external_object->buffer.length = internal_object->buffer.length; |
127 | *buffer_space_used = |
128 | ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string. |
129 | length); |
130 | |
131 | memcpy((void *)data_space, |
132 | (void *)internal_object->buffer.pointer, |
133 | internal_object->buffer.length); |
134 | break; |
135 | |
136 | case ACPI_TYPE_INTEGER: |
137 | |
138 | external_object->integer.value = internal_object->integer.value; |
139 | break; |
140 | |
141 | case ACPI_TYPE_LOCAL_REFERENCE: |
142 | |
143 | /* This is an object reference. */ |
144 | |
145 | switch (internal_object->reference.class) { |
146 | case ACPI_REFCLASS_NAME: |
147 | /* |
148 | * For namepath, return the object handle ("reference") |
149 | * We are referring to the namespace node |
150 | */ |
151 | external_object->reference.handle = |
152 | internal_object->reference.node; |
153 | external_object->reference.actual_type = |
154 | acpi_ns_get_type(node: internal_object->reference.node); |
155 | break; |
156 | |
157 | default: |
158 | |
159 | /* All other reference types are unsupported */ |
160 | |
161 | return_ACPI_STATUS(AE_TYPE); |
162 | } |
163 | break; |
164 | |
165 | case ACPI_TYPE_PROCESSOR: |
166 | |
167 | external_object->processor.proc_id = |
168 | internal_object->processor.proc_id; |
169 | external_object->processor.pblk_address = |
170 | internal_object->processor.address; |
171 | external_object->processor.pblk_length = |
172 | internal_object->processor.length; |
173 | break; |
174 | |
175 | case ACPI_TYPE_POWER: |
176 | |
177 | external_object->power_resource.system_level = |
178 | internal_object->power_resource.system_level; |
179 | |
180 | external_object->power_resource.resource_order = |
181 | internal_object->power_resource.resource_order; |
182 | break; |
183 | |
184 | default: |
185 | /* |
186 | * There is no corresponding external object type |
187 | */ |
188 | ACPI_ERROR((AE_INFO, |
189 | "Unsupported object type, cannot convert to external object: %s" , |
190 | acpi_ut_get_type_name(internal_object->common. |
191 | type))); |
192 | |
193 | return_ACPI_STATUS(AE_SUPPORT); |
194 | } |
195 | |
196 | return_ACPI_STATUS(status); |
197 | } |
198 | |
199 | /******************************************************************************* |
200 | * |
201 | * FUNCTION: acpi_ut_copy_ielement_to_eelement |
202 | * |
203 | * PARAMETERS: acpi_pkg_callback |
204 | * |
205 | * RETURN: Status |
206 | * |
207 | * DESCRIPTION: Copy one package element to another package element |
208 | * |
209 | ******************************************************************************/ |
210 | |
211 | static acpi_status |
212 | acpi_ut_copy_ielement_to_eelement(u8 object_type, |
213 | union acpi_operand_object *source_object, |
214 | union acpi_generic_state *state, |
215 | void *context) |
216 | { |
217 | acpi_status status = AE_OK; |
218 | struct acpi_pkg_info *info = (struct acpi_pkg_info *)context; |
219 | acpi_size object_space; |
220 | u32 this_index; |
221 | union acpi_object *target_object; |
222 | |
223 | ACPI_FUNCTION_ENTRY(); |
224 | |
225 | this_index = state->pkg.index; |
226 | target_object = (union acpi_object *)&((union acpi_object *) |
227 | (state->pkg.dest_object))-> |
228 | package.elements[this_index]; |
229 | |
230 | switch (object_type) { |
231 | case ACPI_COPY_TYPE_SIMPLE: |
232 | /* |
233 | * This is a simple or null object |
234 | */ |
235 | status = acpi_ut_copy_isimple_to_esimple(internal_object: source_object, |
236 | external_object: target_object, |
237 | data_space: info->free_space, |
238 | buffer_space_used: &object_space); |
239 | if (ACPI_FAILURE(status)) { |
240 | return (status); |
241 | } |
242 | break; |
243 | |
244 | case ACPI_COPY_TYPE_PACKAGE: |
245 | /* |
246 | * Build the package object |
247 | */ |
248 | target_object->type = ACPI_TYPE_PACKAGE; |
249 | target_object->package.count = source_object->package.count; |
250 | target_object->package.elements = |
251 | ACPI_CAST_PTR(union acpi_object, info->free_space); |
252 | |
253 | /* |
254 | * Pass the new package object back to the package walk routine |
255 | */ |
256 | state->pkg.this_target_obj = target_object; |
257 | |
258 | /* |
259 | * Save space for the array of objects (Package elements) |
260 | * update the buffer length counter |
261 | */ |
262 | object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size) |
263 | target_object-> |
264 | package.count * |
265 | sizeof(union |
266 | acpi_object)); |
267 | break; |
268 | |
269 | default: |
270 | |
271 | return (AE_BAD_PARAMETER); |
272 | } |
273 | |
274 | info->free_space += object_space; |
275 | info->length += object_space; |
276 | return (status); |
277 | } |
278 | |
279 | /******************************************************************************* |
280 | * |
281 | * FUNCTION: acpi_ut_copy_ipackage_to_epackage |
282 | * |
283 | * PARAMETERS: internal_object - Pointer to the object we are returning |
284 | * buffer - Where the object is returned |
285 | * space_used - Where the object length is returned |
286 | * |
287 | * RETURN: Status |
288 | * |
289 | * DESCRIPTION: This function is called to place a package object in a user |
290 | * buffer. A package object by definition contains other objects. |
291 | * |
292 | * The buffer is assumed to have sufficient space for the object. |
293 | * The caller must have verified the buffer length needed using |
294 | * the acpi_ut_get_object_size function before calling this function. |
295 | * |
296 | ******************************************************************************/ |
297 | |
298 | static acpi_status |
299 | acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, |
300 | u8 *buffer, acpi_size *space_used) |
301 | { |
302 | union acpi_object *external_object; |
303 | acpi_status status; |
304 | struct acpi_pkg_info info; |
305 | |
306 | ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage); |
307 | |
308 | /* |
309 | * First package at head of the buffer |
310 | */ |
311 | external_object = ACPI_CAST_PTR(union acpi_object, buffer); |
312 | |
313 | /* |
314 | * Free space begins right after the first package |
315 | */ |
316 | info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); |
317 | info.free_space = buffer + |
318 | ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); |
319 | info.object_space = 0; |
320 | info.num_packages = 1; |
321 | |
322 | external_object->type = internal_object->common.type; |
323 | external_object->package.count = internal_object->package.count; |
324 | external_object->package.elements = |
325 | ACPI_CAST_PTR(union acpi_object, info.free_space); |
326 | |
327 | /* |
328 | * Leave room for an array of ACPI_OBJECTS in the buffer |
329 | * and move the free space past it |
330 | */ |
331 | info.length += (acpi_size)external_object->package.count * |
332 | ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); |
333 | info.free_space += external_object->package.count * |
334 | ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)); |
335 | |
336 | status = acpi_ut_walk_package_tree(source_object: internal_object, target_object: external_object, |
337 | walk_callback: acpi_ut_copy_ielement_to_eelement, |
338 | context: &info); |
339 | |
340 | *space_used = info.length; |
341 | return_ACPI_STATUS(status); |
342 | } |
343 | |
344 | /******************************************************************************* |
345 | * |
346 | * FUNCTION: acpi_ut_copy_iobject_to_eobject |
347 | * |
348 | * PARAMETERS: internal_object - The internal object to be converted |
349 | * ret_buffer - Where the object is returned |
350 | * |
351 | * RETURN: Status |
352 | * |
353 | * DESCRIPTION: This function is called to build an API object to be returned |
354 | * to the caller. |
355 | * |
356 | ******************************************************************************/ |
357 | |
358 | acpi_status |
359 | acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object, |
360 | struct acpi_buffer *ret_buffer) |
361 | { |
362 | acpi_status status; |
363 | |
364 | ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject); |
365 | |
366 | if (internal_object->common.type == ACPI_TYPE_PACKAGE) { |
367 | /* |
368 | * Package object: Copy all subobjects (including |
369 | * nested packages) |
370 | */ |
371 | status = acpi_ut_copy_ipackage_to_epackage(internal_object, |
372 | buffer: ret_buffer->pointer, |
373 | space_used: &ret_buffer->length); |
374 | } else { |
375 | /* |
376 | * Build a simple object (no nested objects) |
377 | */ |
378 | status = acpi_ut_copy_isimple_to_esimple(internal_object, |
379 | ACPI_CAST_PTR(union |
380 | acpi_object, |
381 | ret_buffer-> |
382 | pointer), |
383 | ACPI_ADD_PTR(u8, |
384 | ret_buffer-> |
385 | pointer, |
386 | ACPI_ROUND_UP_TO_NATIVE_WORD |
387 | (sizeof |
388 | (union |
389 | acpi_object))), |
390 | buffer_space_used: &ret_buffer->length); |
391 | /* |
392 | * build simple does not include the object size in the length |
393 | * so we add it in here |
394 | */ |
395 | ret_buffer->length += sizeof(union acpi_object); |
396 | } |
397 | |
398 | return_ACPI_STATUS(status); |
399 | } |
400 | |
401 | /******************************************************************************* |
402 | * |
403 | * FUNCTION: acpi_ut_copy_esimple_to_isimple |
404 | * |
405 | * PARAMETERS: external_object - The external object to be converted |
406 | * ret_internal_object - Where the internal object is returned |
407 | * |
408 | * RETURN: Status |
409 | * |
410 | * DESCRIPTION: This function copies an external object to an internal one. |
411 | * NOTE: Pointers can be copied, we don't need to copy data. |
412 | * (The pointers have to be valid in our address space no matter |
413 | * what we do with them!) |
414 | * |
415 | ******************************************************************************/ |
416 | |
417 | static acpi_status |
418 | acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object, |
419 | union acpi_operand_object **ret_internal_object) |
420 | { |
421 | union acpi_operand_object *internal_object; |
422 | |
423 | ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple); |
424 | |
425 | /* |
426 | * Simple types supported are: String, Buffer, Integer |
427 | */ |
428 | switch (external_object->type) { |
429 | case ACPI_TYPE_STRING: |
430 | case ACPI_TYPE_BUFFER: |
431 | case ACPI_TYPE_INTEGER: |
432 | case ACPI_TYPE_LOCAL_REFERENCE: |
433 | |
434 | internal_object = acpi_ut_create_internal_object((u8) |
435 | external_object-> |
436 | type); |
437 | if (!internal_object) { |
438 | return_ACPI_STATUS(AE_NO_MEMORY); |
439 | } |
440 | break; |
441 | |
442 | case ACPI_TYPE_ANY: /* This is the case for a NULL object */ |
443 | |
444 | *ret_internal_object = NULL; |
445 | return_ACPI_STATUS(AE_OK); |
446 | |
447 | default: |
448 | |
449 | /* All other types are not supported */ |
450 | |
451 | ACPI_ERROR((AE_INFO, |
452 | "Unsupported object type, cannot convert to internal object: %s" , |
453 | acpi_ut_get_type_name(external_object->type))); |
454 | |
455 | return_ACPI_STATUS(AE_SUPPORT); |
456 | } |
457 | |
458 | /* Must COPY string and buffer contents */ |
459 | |
460 | switch (external_object->type) { |
461 | case ACPI_TYPE_STRING: |
462 | |
463 | internal_object->string.pointer = |
464 | ACPI_ALLOCATE_ZEROED((acpi_size) |
465 | external_object->string.length + 1); |
466 | |
467 | if (!internal_object->string.pointer) { |
468 | goto error_exit; |
469 | } |
470 | |
471 | memcpy(internal_object->string.pointer, |
472 | external_object->string.pointer, |
473 | external_object->string.length); |
474 | |
475 | internal_object->string.length = external_object->string.length; |
476 | break; |
477 | |
478 | case ACPI_TYPE_BUFFER: |
479 | |
480 | internal_object->buffer.pointer = |
481 | ACPI_ALLOCATE_ZEROED(external_object->buffer.length); |
482 | if (!internal_object->buffer.pointer) { |
483 | goto error_exit; |
484 | } |
485 | |
486 | memcpy(internal_object->buffer.pointer, |
487 | external_object->buffer.pointer, |
488 | external_object->buffer.length); |
489 | |
490 | internal_object->buffer.length = external_object->buffer.length; |
491 | |
492 | /* Mark buffer data valid */ |
493 | |
494 | internal_object->buffer.flags |= AOPOBJ_DATA_VALID; |
495 | break; |
496 | |
497 | case ACPI_TYPE_INTEGER: |
498 | |
499 | internal_object->integer.value = external_object->integer.value; |
500 | break; |
501 | |
502 | case ACPI_TYPE_LOCAL_REFERENCE: |
503 | |
504 | /* An incoming reference is defined to be a namespace node */ |
505 | |
506 | internal_object->reference.class = ACPI_REFCLASS_REFOF; |
507 | internal_object->reference.object = |
508 | external_object->reference.handle; |
509 | break; |
510 | |
511 | default: |
512 | |
513 | /* Other types can't get here */ |
514 | |
515 | break; |
516 | } |
517 | |
518 | *ret_internal_object = internal_object; |
519 | return_ACPI_STATUS(AE_OK); |
520 | |
521 | error_exit: |
522 | acpi_ut_remove_reference(object: internal_object); |
523 | return_ACPI_STATUS(AE_NO_MEMORY); |
524 | } |
525 | |
526 | /******************************************************************************* |
527 | * |
528 | * FUNCTION: acpi_ut_copy_epackage_to_ipackage |
529 | * |
530 | * PARAMETERS: external_object - The external object to be converted |
531 | * internal_object - Where the internal object is returned |
532 | * |
533 | * RETURN: Status |
534 | * |
535 | * DESCRIPTION: Copy an external package object to an internal package. |
536 | * Handles nested packages. |
537 | * |
538 | ******************************************************************************/ |
539 | |
540 | static acpi_status |
541 | acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, |
542 | union acpi_operand_object **internal_object) |
543 | { |
544 | acpi_status status = AE_OK; |
545 | union acpi_operand_object *package_object; |
546 | union acpi_operand_object **package_elements; |
547 | u32 i; |
548 | |
549 | ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage); |
550 | |
551 | /* Create the package object */ |
552 | |
553 | package_object = |
554 | acpi_ut_create_package_object(count: external_object->package.count); |
555 | if (!package_object) { |
556 | return_ACPI_STATUS(AE_NO_MEMORY); |
557 | } |
558 | |
559 | package_elements = package_object->package.elements; |
560 | |
561 | /* |
562 | * Recursive implementation. Probably ok, since nested external |
563 | * packages as parameters should be very rare. |
564 | */ |
565 | for (i = 0; i < external_object->package.count; i++) { |
566 | status = |
567 | acpi_ut_copy_eobject_to_iobject(obj: &external_object->package. |
568 | elements[i], |
569 | internal_obj: &package_elements[i]); |
570 | if (ACPI_FAILURE(status)) { |
571 | |
572 | /* Truncate package and delete it */ |
573 | |
574 | package_object->package.count = i; |
575 | package_elements[i] = NULL; |
576 | acpi_ut_remove_reference(object: package_object); |
577 | return_ACPI_STATUS(status); |
578 | } |
579 | } |
580 | |
581 | /* Mark package data valid */ |
582 | |
583 | package_object->package.flags |= AOPOBJ_DATA_VALID; |
584 | |
585 | *internal_object = package_object; |
586 | return_ACPI_STATUS(status); |
587 | } |
588 | |
589 | /******************************************************************************* |
590 | * |
591 | * FUNCTION: acpi_ut_copy_eobject_to_iobject |
592 | * |
593 | * PARAMETERS: external_object - The external object to be converted |
594 | * internal_object - Where the internal object is returned |
595 | * |
596 | * RETURN: Status |
597 | * |
598 | * DESCRIPTION: Converts an external object to an internal object. |
599 | * |
600 | ******************************************************************************/ |
601 | |
602 | acpi_status |
603 | acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object, |
604 | union acpi_operand_object **internal_object) |
605 | { |
606 | acpi_status status; |
607 | |
608 | ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject); |
609 | |
610 | if (external_object->type == ACPI_TYPE_PACKAGE) { |
611 | status = |
612 | acpi_ut_copy_epackage_to_ipackage(external_object, |
613 | internal_object); |
614 | } else { |
615 | /* |
616 | * Build a simple object (no nested objects) |
617 | */ |
618 | status = acpi_ut_copy_esimple_to_isimple(external_object, |
619 | ret_internal_object: internal_object); |
620 | } |
621 | |
622 | return_ACPI_STATUS(status); |
623 | } |
624 | |
625 | /******************************************************************************* |
626 | * |
627 | * FUNCTION: acpi_ut_copy_simple_object |
628 | * |
629 | * PARAMETERS: source_desc - The internal object to be copied |
630 | * dest_desc - New target object |
631 | * |
632 | * RETURN: Status |
633 | * |
634 | * DESCRIPTION: Simple copy of one internal object to another. Reference count |
635 | * of the destination object is preserved. |
636 | * |
637 | ******************************************************************************/ |
638 | |
639 | static acpi_status |
640 | acpi_ut_copy_simple_object(union acpi_operand_object *source_desc, |
641 | union acpi_operand_object *dest_desc) |
642 | { |
643 | u16 reference_count; |
644 | union acpi_operand_object *next_object; |
645 | acpi_status status; |
646 | acpi_size copy_size; |
647 | |
648 | /* Save fields from destination that we don't want to overwrite */ |
649 | |
650 | reference_count = dest_desc->common.reference_count; |
651 | next_object = dest_desc->common.next_object; |
652 | |
653 | /* |
654 | * Copy the entire source object over the destination object. |
655 | * Note: Source can be either an operand object or namespace node. |
656 | */ |
657 | copy_size = sizeof(union acpi_operand_object); |
658 | if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_NAMED) { |
659 | copy_size = sizeof(struct acpi_namespace_node); |
660 | } |
661 | |
662 | memcpy(ACPI_CAST_PTR(char, dest_desc), |
663 | ACPI_CAST_PTR(char, source_desc), copy_size); |
664 | |
665 | /* Restore the saved fields */ |
666 | |
667 | dest_desc->common.reference_count = reference_count; |
668 | dest_desc->common.next_object = next_object; |
669 | |
670 | /* New object is not static, regardless of source */ |
671 | |
672 | dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER; |
673 | |
674 | /* Handle the objects with extra data */ |
675 | |
676 | switch (dest_desc->common.type) { |
677 | case ACPI_TYPE_BUFFER: |
678 | /* |
679 | * Allocate and copy the actual buffer if and only if: |
680 | * 1) There is a valid buffer pointer |
681 | * 2) The buffer has a length > 0 |
682 | */ |
683 | if ((source_desc->buffer.pointer) && |
684 | (source_desc->buffer.length)) { |
685 | dest_desc->buffer.pointer = |
686 | ACPI_ALLOCATE(source_desc->buffer.length); |
687 | if (!dest_desc->buffer.pointer) { |
688 | return (AE_NO_MEMORY); |
689 | } |
690 | |
691 | /* Copy the actual buffer data */ |
692 | |
693 | memcpy(dest_desc->buffer.pointer, |
694 | source_desc->buffer.pointer, |
695 | source_desc->buffer.length); |
696 | } |
697 | break; |
698 | |
699 | case ACPI_TYPE_STRING: |
700 | /* |
701 | * Allocate and copy the actual string if and only if: |
702 | * 1) There is a valid string pointer |
703 | * (Pointer to a NULL string is allowed) |
704 | */ |
705 | if (source_desc->string.pointer) { |
706 | dest_desc->string.pointer = |
707 | ACPI_ALLOCATE((acpi_size)source_desc->string. |
708 | length + 1); |
709 | if (!dest_desc->string.pointer) { |
710 | return (AE_NO_MEMORY); |
711 | } |
712 | |
713 | /* Copy the actual string data */ |
714 | |
715 | memcpy(dest_desc->string.pointer, |
716 | source_desc->string.pointer, |
717 | (acpi_size)source_desc->string.length + 1); |
718 | } |
719 | break; |
720 | |
721 | case ACPI_TYPE_LOCAL_REFERENCE: |
722 | /* |
723 | * We copied the reference object, so we now must add a reference |
724 | * to the object pointed to by the reference |
725 | * |
726 | * DDBHandle reference (from Load/load_table) is a special reference, |
727 | * it does not have a Reference.Object, so does not need to |
728 | * increase the reference count |
729 | */ |
730 | if (source_desc->reference.class == ACPI_REFCLASS_TABLE) { |
731 | break; |
732 | } |
733 | |
734 | acpi_ut_add_reference(object: source_desc->reference.object); |
735 | break; |
736 | |
737 | case ACPI_TYPE_REGION: |
738 | /* |
739 | * We copied the Region Handler, so we now must add a reference |
740 | */ |
741 | if (dest_desc->region.handler) { |
742 | acpi_ut_add_reference(object: dest_desc->region.handler); |
743 | } |
744 | break; |
745 | |
746 | /* |
747 | * For Mutex and Event objects, we cannot simply copy the underlying |
748 | * OS object. We must create a new one. |
749 | */ |
750 | case ACPI_TYPE_MUTEX: |
751 | |
752 | status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex); |
753 | if (ACPI_FAILURE(status)) { |
754 | return (status); |
755 | } |
756 | break; |
757 | |
758 | case ACPI_TYPE_EVENT: |
759 | |
760 | status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, initial_units: 0, |
761 | out_handle: &dest_desc->event. |
762 | os_semaphore); |
763 | if (ACPI_FAILURE(status)) { |
764 | return (status); |
765 | } |
766 | break; |
767 | |
768 | default: |
769 | |
770 | /* Nothing to do for other simple objects */ |
771 | |
772 | break; |
773 | } |
774 | |
775 | return (AE_OK); |
776 | } |
777 | |
778 | /******************************************************************************* |
779 | * |
780 | * FUNCTION: acpi_ut_copy_ielement_to_ielement |
781 | * |
782 | * PARAMETERS: acpi_pkg_callback |
783 | * |
784 | * RETURN: Status |
785 | * |
786 | * DESCRIPTION: Copy one package element to another package element |
787 | * |
788 | ******************************************************************************/ |
789 | |
790 | static acpi_status |
791 | acpi_ut_copy_ielement_to_ielement(u8 object_type, |
792 | union acpi_operand_object *source_object, |
793 | union acpi_generic_state *state, |
794 | void *context) |
795 | { |
796 | acpi_status status = AE_OK; |
797 | u32 this_index; |
798 | union acpi_operand_object **this_target_ptr; |
799 | union acpi_operand_object *target_object; |
800 | |
801 | ACPI_FUNCTION_ENTRY(); |
802 | |
803 | this_index = state->pkg.index; |
804 | this_target_ptr = (union acpi_operand_object **) |
805 | &state->pkg.dest_object->package.elements[this_index]; |
806 | |
807 | switch (object_type) { |
808 | case ACPI_COPY_TYPE_SIMPLE: |
809 | |
810 | /* A null source object indicates a (legal) null package element */ |
811 | |
812 | if (source_object) { |
813 | /* |
814 | * This is a simple object, just copy it |
815 | */ |
816 | target_object = |
817 | acpi_ut_create_internal_object(source_object-> |
818 | common.type); |
819 | if (!target_object) { |
820 | return (AE_NO_MEMORY); |
821 | } |
822 | |
823 | status = |
824 | acpi_ut_copy_simple_object(source_desc: source_object, |
825 | dest_desc: target_object); |
826 | if (ACPI_FAILURE(status)) { |
827 | goto error_exit; |
828 | } |
829 | |
830 | *this_target_ptr = target_object; |
831 | } else { |
832 | /* Pass through a null element */ |
833 | |
834 | *this_target_ptr = NULL; |
835 | } |
836 | break; |
837 | |
838 | case ACPI_COPY_TYPE_PACKAGE: |
839 | /* |
840 | * This object is a package - go down another nesting level |
841 | * Create and build the package object |
842 | */ |
843 | target_object = |
844 | acpi_ut_create_package_object(count: source_object->package.count); |
845 | if (!target_object) { |
846 | return (AE_NO_MEMORY); |
847 | } |
848 | |
849 | target_object->common.flags = source_object->common.flags; |
850 | |
851 | /* Pass the new package object back to the package walk routine */ |
852 | |
853 | state->pkg.this_target_obj = target_object; |
854 | |
855 | /* Store the object pointer in the parent package object */ |
856 | |
857 | *this_target_ptr = target_object; |
858 | break; |
859 | |
860 | default: |
861 | |
862 | return (AE_BAD_PARAMETER); |
863 | } |
864 | |
865 | return (status); |
866 | |
867 | error_exit: |
868 | acpi_ut_remove_reference(object: target_object); |
869 | return (status); |
870 | } |
871 | |
872 | /******************************************************************************* |
873 | * |
874 | * FUNCTION: acpi_ut_copy_ipackage_to_ipackage |
875 | * |
876 | * PARAMETERS: source_obj - Pointer to the source package object |
877 | * dest_obj - Where the internal object is returned |
878 | * walk_state - Current Walk state descriptor |
879 | * |
880 | * RETURN: Status |
881 | * |
882 | * DESCRIPTION: This function is called to copy an internal package object |
883 | * into another internal package object. |
884 | * |
885 | ******************************************************************************/ |
886 | |
887 | static acpi_status |
888 | acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj, |
889 | union acpi_operand_object *dest_obj, |
890 | struct acpi_walk_state *walk_state) |
891 | { |
892 | acpi_status status = AE_OK; |
893 | |
894 | ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage); |
895 | |
896 | dest_obj->common.type = source_obj->common.type; |
897 | dest_obj->common.flags = source_obj->common.flags; |
898 | dest_obj->package.count = source_obj->package.count; |
899 | |
900 | /* |
901 | * Create the object array and walk the source package tree |
902 | */ |
903 | dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) |
904 | source_obj->package. |
905 | count + |
906 | 1) * sizeof(void *)); |
907 | if (!dest_obj->package.elements) { |
908 | ACPI_ERROR((AE_INFO, "Package allocation failure" )); |
909 | return_ACPI_STATUS(AE_NO_MEMORY); |
910 | } |
911 | |
912 | /* |
913 | * Copy the package element-by-element by walking the package "tree". |
914 | * This handles nested packages of arbitrary depth. |
915 | */ |
916 | status = acpi_ut_walk_package_tree(source_object: source_obj, target_object: dest_obj, |
917 | walk_callback: acpi_ut_copy_ielement_to_ielement, |
918 | context: walk_state); |
919 | return_ACPI_STATUS(status); |
920 | } |
921 | |
922 | /******************************************************************************* |
923 | * |
924 | * FUNCTION: acpi_ut_copy_iobject_to_iobject |
925 | * |
926 | * PARAMETERS: source_desc - The internal object to be copied |
927 | * dest_desc - Where the copied object is returned |
928 | * walk_state - Current walk state |
929 | * |
930 | * RETURN: Status |
931 | * |
932 | * DESCRIPTION: Copy an internal object to a new internal object |
933 | * |
934 | ******************************************************************************/ |
935 | |
936 | acpi_status |
937 | acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc, |
938 | union acpi_operand_object **dest_desc, |
939 | struct acpi_walk_state *walk_state) |
940 | { |
941 | acpi_status status = AE_OK; |
942 | |
943 | ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject); |
944 | |
945 | /* Create the top level object */ |
946 | |
947 | *dest_desc = acpi_ut_create_internal_object(source_desc->common.type); |
948 | if (!*dest_desc) { |
949 | return_ACPI_STATUS(AE_NO_MEMORY); |
950 | } |
951 | |
952 | /* Copy the object and possible subobjects */ |
953 | |
954 | if (source_desc->common.type == ACPI_TYPE_PACKAGE) { |
955 | status = |
956 | acpi_ut_copy_ipackage_to_ipackage(source_obj: source_desc, dest_obj: *dest_desc, |
957 | walk_state); |
958 | } else { |
959 | status = acpi_ut_copy_simple_object(source_desc, dest_desc: *dest_desc); |
960 | } |
961 | |
962 | /* Delete the allocated object if copy failed */ |
963 | |
964 | if (ACPI_FAILURE(status)) { |
965 | acpi_ut_remove_reference(object: *dest_desc); |
966 | } |
967 | |
968 | return_ACPI_STATUS(status); |
969 | } |
970 | |