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