Branch data Line data Source code
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 - 2020, 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 : 9604 : 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 : 9604 : acpi_status status = AE_OK;
83 : :
84 : 9604 : ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple);
85 : :
86 : 9604 : *buffer_space_used = 0;
87 : :
88 : : /*
89 : : * Check for NULL object case (could be an uninitialized
90 : : * package element)
91 : : */
92 [ + - ]: 9604 : if (!internal_object) {
93 : : return_ACPI_STATUS(AE_OK);
94 : : }
95 : :
96 : : /* Always clear the external object */
97 : :
98 : 9604 : 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 : 9604 : external_object->type = internal_object->common.type;
105 : :
106 : : /* However, only a limited number of external types are supported */
107 : :
108 [ - + + - : 9604 : switch (internal_object->common.type) {
+ - - ]
109 : 0 : case ACPI_TYPE_STRING:
110 : :
111 : 0 : external_object->string.pointer = (char *)data_space;
112 : 0 : external_object->string.length = internal_object->string.length;
113 : 0 : *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
114 : : internal_object->
115 : : string.
116 : : length + 1);
117 : :
118 : 0 : memcpy((void *)data_space,
119 : 0 : (void *)internal_object->string.pointer,
120 : 0 : (acpi_size)internal_object->string.length + 1);
121 : 0 : break;
122 : :
123 : 56 : case ACPI_TYPE_BUFFER:
124 : :
125 : 56 : external_object->buffer.pointer = data_space;
126 : 56 : external_object->buffer.length = internal_object->buffer.length;
127 : 56 : *buffer_space_used =
128 : 56 : ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string.
129 : : length);
130 : :
131 : 56 : memcpy((void *)data_space,
132 : 56 : (void *)internal_object->buffer.pointer,
133 : 56 : internal_object->buffer.length);
134 : 56 : break;
135 : :
136 : 9464 : case ACPI_TYPE_INTEGER:
137 : :
138 : 9464 : external_object->integer.value = internal_object->integer.value;
139 : 9464 : break;
140 : :
141 : 0 : case ACPI_TYPE_LOCAL_REFERENCE:
142 : :
143 : : /* This is an object reference. */
144 : :
145 [ # # ]: 0 : switch (internal_object->reference.class) {
146 : 0 : case ACPI_REFCLASS_NAME:
147 : : /*
148 : : * For namepath, return the object handle ("reference")
149 : : * We are referring to the namespace node
150 : : */
151 : 0 : external_object->reference.handle =
152 : 0 : internal_object->reference.node;
153 : 0 : external_object->reference.actual_type =
154 : 0 : acpi_ns_get_type(internal_object->reference.node);
155 : 0 : break;
156 : :
157 : : default:
158 : :
159 : : /* All other reference types are unsupported */
160 : :
161 : : return_ACPI_STATUS(AE_TYPE);
162 : : }
163 : 0 : break;
164 : :
165 : 84 : case ACPI_TYPE_PROCESSOR:
166 : :
167 : 84 : external_object->processor.proc_id =
168 : 84 : internal_object->processor.proc_id;
169 : 84 : external_object->processor.pblk_address =
170 : 84 : internal_object->processor.address;
171 : 84 : external_object->processor.pblk_length =
172 : 84 : internal_object->processor.length;
173 : 84 : break;
174 : :
175 : 0 : case ACPI_TYPE_POWER:
176 : :
177 : 0 : external_object->power_resource.system_level =
178 : 0 : internal_object->power_resource.system_level;
179 : :
180 : 0 : external_object->power_resource.resource_order =
181 : 0 : internal_object->power_resource.resource_order;
182 : 0 : break;
183 : :
184 : 0 : default:
185 : : /*
186 : : * There is no corresponding external object type
187 : : */
188 : 0 : 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 : 0 : 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 : 0 : 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 : 0 : acpi_status status = AE_OK;
218 : 0 : struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
219 : 0 : acpi_size object_space;
220 : 0 : u32 this_index;
221 : 0 : union acpi_object *target_object;
222 : :
223 : 0 : ACPI_FUNCTION_ENTRY();
224 : :
225 : 0 : this_index = state->pkg.index;
226 : 0 : target_object = (union acpi_object *)&((union acpi_object *)
227 : 0 : (state->pkg.dest_object))->
228 : 0 : package.elements[this_index];
229 : :
230 [ # # # ]: 0 : switch (object_type) {
231 : 0 : case ACPI_COPY_TYPE_SIMPLE:
232 : : /*
233 : : * This is a simple or null object
234 : : */
235 : 0 : status = acpi_ut_copy_isimple_to_esimple(source_object,
236 : : target_object,
237 : : info->free_space,
238 : : &object_space);
239 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
240 : : return (status);
241 : : }
242 : : break;
243 : :
244 : 0 : case ACPI_COPY_TYPE_PACKAGE:
245 : : /*
246 : : * Build the package object
247 : : */
248 : 0 : target_object->type = ACPI_TYPE_PACKAGE;
249 : 0 : target_object->package.count = source_object->package.count;
250 : 0 : target_object->package.elements =
251 : 0 : 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 : 0 : 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 : 0 : object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
263 : : target_object->
264 : : package.count *
265 : : sizeof(union
266 : : acpi_object));
267 : 0 : break;
268 : :
269 : : default:
270 : :
271 : : return (AE_BAD_PARAMETER);
272 : : }
273 : :
274 : 0 : info->free_space += object_space;
275 : 0 : info->length += object_space;
276 : 0 : 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 : 0 : acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
300 : : u8 *buffer, acpi_size *space_used)
301 : : {
302 : 0 : union acpi_object *external_object;
303 : 0 : acpi_status status;
304 : 0 : struct acpi_pkg_info info;
305 : :
306 : 0 : ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage);
307 : :
308 : : /*
309 : : * First package at head of the buffer
310 : : */
311 : 0 : external_object = ACPI_CAST_PTR(union acpi_object, buffer);
312 : :
313 : : /*
314 : : * Free space begins right after the first package
315 : : */
316 : 0 : info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
317 : 0 : info.free_space = buffer +
318 : : ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
319 : 0 : info.object_space = 0;
320 : 0 : info.num_packages = 1;
321 : :
322 : 0 : external_object->type = internal_object->common.type;
323 : 0 : external_object->package.count = internal_object->package.count;
324 : 0 : 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 : 0 : info.length += (acpi_size)external_object->package.count *
332 : : ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
333 : 0 : info.free_space += external_object->package.count *
334 : : ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
335 : :
336 : 0 : status = acpi_ut_walk_package_tree(internal_object, external_object,
337 : : acpi_ut_copy_ielement_to_eelement,
338 : : &info);
339 : :
340 : 0 : *space_used = info.length;
341 : 0 : 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 : 9604 : acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
360 : : struct acpi_buffer *ret_buffer)
361 : : {
362 : 9604 : acpi_status status;
363 : :
364 : 9604 : ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject);
365 : :
366 [ - + ]: 9604 : if (internal_object->common.type == ACPI_TYPE_PACKAGE) {
367 : : /*
368 : : * Package object: Copy all subobjects (including
369 : : * nested packages)
370 : : */
371 : 0 : status = acpi_ut_copy_ipackage_to_epackage(internal_object,
372 : 0 : ret_buffer->pointer,
373 : : &ret_buffer->length);
374 : : } else {
375 : : /*
376 : : * Build a simple object (no nested objects)
377 : : */
378 : 9604 : status = acpi_ut_copy_isimple_to_esimple(internal_object,
379 : : ACPI_CAST_PTR(union
380 : : acpi_object,
381 : : ret_buffer->
382 : : pointer),
383 : 9604 : ACPI_ADD_PTR(u8,
384 : : ret_buffer->
385 : : pointer,
386 : : ACPI_ROUND_UP_TO_NATIVE_WORD
387 : : (sizeof
388 : : (union
389 : : acpi_object))),
390 : : &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 : 9604 : ret_buffer->length += sizeof(union acpi_object);
396 : : }
397 : :
398 : 9604 : 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 : 1428 : acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
419 : : union acpi_operand_object **ret_internal_object)
420 : : {
421 : 1428 : union acpi_operand_object *internal_object;
422 : :
423 : 1428 : ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple);
424 : :
425 : : /*
426 : : * Simple types supported are: String, Buffer, Integer
427 : : */
428 [ + - - ]: 1428 : switch (external_object->type) {
429 : 1428 : case ACPI_TYPE_STRING:
430 : : case ACPI_TYPE_BUFFER:
431 : : case ACPI_TYPE_INTEGER:
432 : : case ACPI_TYPE_LOCAL_REFERENCE:
433 : :
434 : 1428 : internal_object = acpi_ut_create_internal_object((u8)
435 : : external_object->
436 : : type);
437 [ + - ]: 1428 : if (!internal_object) {
438 : : return_ACPI_STATUS(AE_NO_MEMORY);
439 : : }
440 : 1428 : break;
441 : :
442 : 0 : case ACPI_TYPE_ANY: /* This is the case for a NULL object */
443 : :
444 : 0 : *ret_internal_object = NULL;
445 : 0 : return_ACPI_STATUS(AE_OK);
446 : :
447 : 0 : default:
448 : :
449 : : /* All other types are not supported */
450 : :
451 : 0 : 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 : 0 : return_ACPI_STATUS(AE_SUPPORT);
456 : : }
457 : :
458 : : /* Must COPY string and buffer contents */
459 : :
460 [ - + + - : 1428 : switch (external_object->type) {
- ]
461 : 0 : case ACPI_TYPE_STRING:
462 : :
463 : 0 : internal_object->string.pointer =
464 : 0 : ACPI_ALLOCATE_ZEROED((acpi_size)
465 : : external_object->string.length + 1);
466 : :
467 [ # # ]: 0 : if (!internal_object->string.pointer) {
468 : 0 : goto error_exit;
469 : : }
470 : :
471 : 0 : memcpy(internal_object->string.pointer,
472 : 0 : external_object->string.pointer,
473 : 0 : external_object->string.length);
474 : :
475 : 0 : internal_object->string.length = external_object->string.length;
476 : 0 : break;
477 : :
478 : 504 : case ACPI_TYPE_BUFFER:
479 : :
480 : 1008 : internal_object->buffer.pointer =
481 : 504 : ACPI_ALLOCATE_ZEROED(external_object->buffer.length);
482 [ - + ]: 504 : if (!internal_object->buffer.pointer) {
483 : 0 : goto error_exit;
484 : : }
485 : :
486 : 504 : memcpy(internal_object->buffer.pointer,
487 : 504 : external_object->buffer.pointer,
488 : 504 : external_object->buffer.length);
489 : :
490 : 504 : internal_object->buffer.length = external_object->buffer.length;
491 : :
492 : : /* Mark buffer data valid */
493 : :
494 : 504 : internal_object->buffer.flags |= AOPOBJ_DATA_VALID;
495 : 504 : break;
496 : :
497 : 924 : case ACPI_TYPE_INTEGER:
498 : :
499 : 924 : internal_object->integer.value = external_object->integer.value;
500 : 924 : break;
501 : :
502 : 0 : case ACPI_TYPE_LOCAL_REFERENCE:
503 : :
504 : : /* An incoming reference is defined to be a namespace node */
505 : :
506 : 0 : internal_object->reference.class = ACPI_REFCLASS_REFOF;
507 : 0 : internal_object->reference.object =
508 : 0 : external_object->reference.handle;
509 : 0 : break;
510 : :
511 : : default:
512 : :
513 : : /* Other types can't get here */
514 : :
515 : : break;
516 : : }
517 : :
518 : 1428 : *ret_internal_object = internal_object;
519 : 1428 : return_ACPI_STATUS(AE_OK);
520 : :
521 : 0 : error_exit:
522 : 0 : acpi_ut_remove_reference(internal_object);
523 : 0 : 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 : 392 : acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
542 : : union acpi_operand_object **internal_object)
543 : : {
544 : 392 : acpi_status status = AE_OK;
545 : 392 : union acpi_operand_object *package_object;
546 : 392 : union acpi_operand_object **package_elements;
547 : 392 : u32 i;
548 : :
549 : 392 : ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
550 : :
551 : : /* Create the package object */
552 : :
553 : 392 : package_object =
554 : 392 : acpi_ut_create_package_object(external_object->package.count);
555 [ + - ]: 392 : if (!package_object) {
556 : : return_ACPI_STATUS(AE_NO_MEMORY);
557 : : }
558 : :
559 : 392 : 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 [ - + ]: 392 : for (i = 0; i < external_object->package.count; i++) {
566 : 0 : status =
567 : 0 : acpi_ut_copy_eobject_to_iobject(&external_object->package.
568 : 0 : elements[i],
569 : 0 : &package_elements[i]);
570 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
571 : :
572 : : /* Truncate package and delete it */
573 : :
574 : 0 : package_object->package.count = i;
575 : 0 : package_elements[i] = NULL;
576 : 0 : acpi_ut_remove_reference(package_object);
577 : 0 : return_ACPI_STATUS(status);
578 : : }
579 : : }
580 : :
581 : : /* Mark package data valid */
582 : :
583 : 392 : package_object->package.flags |= AOPOBJ_DATA_VALID;
584 : :
585 : 392 : *internal_object = package_object;
586 : 392 : 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 : 1820 : acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
604 : : union acpi_operand_object **internal_object)
605 : : {
606 : 1820 : acpi_status status;
607 : :
608 : 1820 : ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
609 : :
610 [ + + ]: 1820 : if (external_object->type == ACPI_TYPE_PACKAGE) {
611 : 392 : status =
612 : 392 : acpi_ut_copy_epackage_to_ipackage(external_object,
613 : : internal_object);
614 : : } else {
615 : : /*
616 : : * Build a simple object (no nested objects)
617 : : */
618 : 1428 : status = acpi_ut_copy_esimple_to_isimple(external_object,
619 : : internal_object);
620 : : }
621 : :
622 : 1820 : 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 : 48176 : acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
641 : : union acpi_operand_object *dest_desc)
642 : : {
643 : 48176 : u16 reference_count;
644 : 48176 : union acpi_operand_object *next_object;
645 : 48176 : acpi_status status;
646 : 48176 : acpi_size copy_size;
647 : :
648 : : /* Save fields from destination that we don't want to overwrite */
649 : :
650 : 48176 : reference_count = dest_desc->common.reference_count;
651 : 48176 : 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 : 48176 : copy_size = sizeof(union acpi_operand_object);
658 [ - + ]: 48176 : if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_NAMED) {
659 : 0 : copy_size = sizeof(struct acpi_namespace_node);
660 : : }
661 : :
662 : 48176 : memcpy(ACPI_CAST_PTR(char, dest_desc),
663 : : ACPI_CAST_PTR(char, source_desc), copy_size);
664 : :
665 : : /* Restore the saved fields */
666 : :
667 : 48176 : dest_desc->common.reference_count = reference_count;
668 : 48176 : dest_desc->common.next_object = next_object;
669 : :
670 : : /* New object is not static, regardless of source */
671 : :
672 : 48176 : dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
673 : :
674 : : /* Handle the objects with extra data */
675 : :
676 [ - - + - : 48176 : switch (dest_desc->common.type) {
- - + ]
677 : 0 : 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 [ # # ]: 0 : if ((source_desc->buffer.pointer) &&
684 [ # # ]: 0 : (source_desc->buffer.length)) {
685 : 0 : dest_desc->buffer.pointer =
686 : 0 : ACPI_ALLOCATE(source_desc->buffer.length);
687 [ # # ]: 0 : if (!dest_desc->buffer.pointer) {
688 : : return (AE_NO_MEMORY);
689 : : }
690 : :
691 : : /* Copy the actual buffer data */
692 : :
693 : 0 : memcpy(dest_desc->buffer.pointer,
694 : 0 : source_desc->buffer.pointer,
695 : 0 : source_desc->buffer.length);
696 : : }
697 : : break;
698 : :
699 : 0 : 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 [ # # ]: 0 : if (source_desc->string.pointer) {
706 : 0 : dest_desc->string.pointer =
707 : 0 : ACPI_ALLOCATE((acpi_size)source_desc->string.
708 : : length + 1);
709 [ # # ]: 0 : if (!dest_desc->string.pointer) {
710 : : return (AE_NO_MEMORY);
711 : : }
712 : :
713 : : /* Copy the actual string data */
714 : :
715 : 0 : memcpy(dest_desc->string.pointer,
716 : 0 : source_desc->string.pointer,
717 : 0 : (acpi_size)source_desc->string.length + 1);
718 : : }
719 : : break;
720 : :
721 : 7936 : 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 [ - + ]: 7936 : if (source_desc->reference.class == ACPI_REFCLASS_TABLE) {
731 : : break;
732 : : }
733 : :
734 : 7936 : acpi_ut_add_reference(source_desc->reference.object);
735 : 7936 : break;
736 : :
737 : 0 : case ACPI_TYPE_REGION:
738 : : /*
739 : : * We copied the Region Handler, so we now must add a reference
740 : : */
741 [ # # ]: 0 : if (dest_desc->region.handler) {
742 : 0 : acpi_ut_add_reference(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 : 0 : case ACPI_TYPE_MUTEX:
751 : :
752 : 0 : status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex);
753 : 0 : if (ACPI_FAILURE(status)) {
754 : : return (status);
755 : : }
756 : : break;
757 : :
758 : 0 : case ACPI_TYPE_EVENT:
759 : :
760 : 0 : status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
761 : : &dest_desc->event.
762 : : os_semaphore);
763 : 0 : 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 : 0 : 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 : 35712 : 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 : 35712 : acpi_status status = AE_OK;
797 : 35712 : u32 this_index;
798 : 35712 : union acpi_operand_object **this_target_ptr;
799 : 35712 : union acpi_operand_object *target_object;
800 : :
801 : 35712 : ACPI_FUNCTION_ENTRY();
802 : :
803 : 35712 : this_index = state->pkg.index;
804 : 35712 : this_target_ptr = (union acpi_operand_object **)
805 : 35712 : &state->pkg.dest_object->package.elements[this_index];
806 : :
807 [ + - - ]: 35712 : switch (object_type) {
808 : 35712 : case ACPI_COPY_TYPE_SIMPLE:
809 : :
810 : : /* A null source object indicates a (legal) null package element */
811 : :
812 [ + + ]: 35712 : if (source_object) {
813 : : /*
814 : : * This is a simple object, just copy it
815 : : */
816 : 31744 : target_object =
817 : 31744 : acpi_ut_create_internal_object(source_object->
818 : : common.type);
819 [ + - ]: 31744 : if (!target_object) {
820 : : return (AE_NO_MEMORY);
821 : : }
822 : :
823 : 31744 : status =
824 : 31744 : acpi_ut_copy_simple_object(source_object,
825 : : target_object);
826 [ - + ]: 31744 : if (ACPI_FAILURE(status)) {
827 : 0 : goto error_exit;
828 : : }
829 : :
830 : 31744 : *this_target_ptr = target_object;
831 : : } else {
832 : : /* Pass through a null element */
833 : :
834 : 3968 : *this_target_ptr = NULL;
835 : : }
836 : : break;
837 : :
838 : 0 : 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 : 0 : target_object =
844 : 0 : acpi_ut_create_package_object(source_object->package.count);
845 [ # # ]: 0 : if (!target_object) {
846 : : return (AE_NO_MEMORY);
847 : : }
848 : :
849 : 0 : target_object->common.flags = source_object->common.flags;
850 : :
851 : : /* Pass the new package object back to the package walk routine */
852 : :
853 : 0 : state->pkg.this_target_obj = target_object;
854 : :
855 : : /* Store the object pointer in the parent package object */
856 : :
857 : 0 : *this_target_ptr = target_object;
858 : 0 : break;
859 : :
860 : : default:
861 : :
862 : : return (AE_BAD_PARAMETER);
863 : : }
864 : :
865 : : return (status);
866 : :
867 : : error_exit:
868 : 0 : acpi_ut_remove_reference(target_object);
869 : 0 : 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 : 7967 : 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 : 7967 : acpi_status status = AE_OK;
893 : :
894 : 7967 : ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage);
895 : :
896 : 7967 : dest_obj->common.type = source_obj->common.type;
897 : 7967 : dest_obj->common.flags = source_obj->common.flags;
898 : 7967 : dest_obj->package.count = source_obj->package.count;
899 : :
900 : : /*
901 : : * Create the object array and walk the source package tree
902 : : */
903 : 7967 : dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
904 : : source_obj->package.
905 : : count +
906 : : 1) * sizeof(void *));
907 [ - + ]: 7967 : if (!dest_obj->package.elements) {
908 : 0 : ACPI_ERROR((AE_INFO, "Package allocation failure"));
909 : 0 : 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 : 7967 : status = acpi_ut_walk_package_tree(source_obj, dest_obj,
917 : : acpi_ut_copy_ielement_to_ielement,
918 : : walk_state);
919 [ - + ]: 7967 : if (ACPI_FAILURE(status)) {
920 : :
921 : : /* On failure, delete the destination package object */
922 : :
923 : 0 : acpi_ut_remove_reference(dest_obj);
924 : : }
925 : :
926 : : return_ACPI_STATUS(status);
927 : : }
928 : :
929 : : /*******************************************************************************
930 : : *
931 : : * FUNCTION: acpi_ut_copy_iobject_to_iobject
932 : : *
933 : : * PARAMETERS: source_desc - The internal object to be copied
934 : : * dest_desc - Where the copied object is returned
935 : : * walk_state - Current walk state
936 : : *
937 : : * RETURN: Status
938 : : *
939 : : * DESCRIPTION: Copy an internal object to a new internal object
940 : : *
941 : : ******************************************************************************/
942 : :
943 : : acpi_status
944 : 24399 : acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
945 : : union acpi_operand_object **dest_desc,
946 : : struct acpi_walk_state *walk_state)
947 : : {
948 : 24399 : acpi_status status = AE_OK;
949 : :
950 : 24399 : ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject);
951 : :
952 : : /* Create the top level object */
953 : :
954 : 24399 : *dest_desc = acpi_ut_create_internal_object(source_desc->common.type);
955 [ + - ]: 24399 : if (!*dest_desc) {
956 : : return_ACPI_STATUS(AE_NO_MEMORY);
957 : : }
958 : :
959 : : /* Copy the object and possible subobjects */
960 : :
961 [ + + ]: 24399 : if (source_desc->common.type == ACPI_TYPE_PACKAGE) {
962 : 7967 : status =
963 : 7967 : acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc,
964 : : walk_state);
965 : : } else {
966 : 16432 : status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
967 : : }
968 : :
969 : : /* Delete the allocated object if copy failed */
970 : :
971 [ - + ]: 24399 : if (ACPI_FAILURE(status)) {
972 : 0 : acpi_ut_remove_reference(*dest_desc);
973 : : }
974 : :
975 : : return_ACPI_STATUS(status);
976 : : }
|