Merge trunk HEAD (46152)
[reactos.git] / drivers / bus / acpi / utils / cmcopy.c
1 /******************************************************************************
2 *
3 * Module Name: cmcopy - Internal to external object translation utilities
4 * $Revision: 1.1 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 R. Byron Moore
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26
27 #include <acpi.h>
28
29
30 #define _COMPONENT ACPI_UTILITIES
31 MODULE_NAME ("cmcopy")
32
33
34 /*******************************************************************************
35 *
36 * FUNCTION: Acpi_cm_copy_isimple_to_esimple
37 *
38 * PARAMETERS: *Internal_object - Pointer to the object we are examining
39 * *Buffer - Where the object is returned
40 * *Space_used - Where the data length is returned
41 *
42 * RETURN: Status
43 *
44 * DESCRIPTION: This function is called to place a simple object in a user
45 * buffer.
46 *
47 * The buffer is assumed to have sufficient space for the object.
48 *
49 ******************************************************************************/
50
51 static ACPI_STATUS
52 acpi_cm_copy_isimple_to_esimple (
53 ACPI_OPERAND_OBJECT *internal_object,
54 ACPI_OBJECT *external_object,
55 u8 *data_space,
56 u32 *buffer_space_used)
57 {
58 u32 length = 0;
59 ACPI_STATUS status = AE_OK;
60
61
62 /*
63 * Check for NULL object case (could be an uninitialized
64 * package element
65 */
66
67 if (!internal_object) {
68 *buffer_space_used = 0;
69 return (AE_OK);
70 }
71
72 /* Always clear the external object */
73
74 MEMSET (external_object, 0, sizeof (ACPI_OBJECT));
75
76 /*
77 * In general, the external object will be the same type as
78 * the internal object
79 */
80
81 external_object->type = internal_object->common.type;
82
83 /* However, only a limited number of external types are supported */
84
85 switch (internal_object->common.type) {
86
87 case ACPI_TYPE_STRING:
88
89 length = internal_object->string.length + 1;
90 external_object->string.length = internal_object->string.length;
91 external_object->string.pointer = (NATIVE_CHAR *) data_space;
92 MEMCPY ((void *) data_space, (void *) internal_object->string.pointer, length);
93 break;
94
95
96 case ACPI_TYPE_BUFFER:
97
98 length = internal_object->buffer.length;
99 external_object->buffer.length = internal_object->buffer.length;
100 external_object->buffer.pointer = data_space;
101 MEMCPY ((void *) data_space, (void *) internal_object->buffer.pointer, length);
102 break;
103
104
105 case ACPI_TYPE_INTEGER:
106
107 external_object->integer.value= internal_object->integer.value;
108 break;
109
110
111 case INTERNAL_TYPE_REFERENCE:
112
113 /*
114 * This is an object reference. Attempt to dereference it.
115 */
116
117 switch (internal_object->reference.opcode) {
118 case AML_ZERO_OP:
119 external_object->type = ACPI_TYPE_INTEGER;
120 external_object->integer.value = 0;
121 break;
122
123 case AML_ONE_OP:
124 external_object->type = ACPI_TYPE_INTEGER;
125 external_object->integer.value = 1;
126 break;
127
128 case AML_ONES_OP:
129 external_object->type = ACPI_TYPE_INTEGER;
130 external_object->integer.value = ACPI_INTEGER_MAX;
131 break;
132
133 case AML_NAMEPATH_OP:
134 /*
135 * This is a named reference, get the string. We already know that
136 * we have room for it, use max length
137 */
138 length = MAX_STRING_LENGTH;
139 external_object->type = ACPI_TYPE_STRING;
140 external_object->string.pointer = (NATIVE_CHAR *) data_space;
141 status = acpi_ns_handle_to_pathname ((ACPI_HANDLE *) internal_object->reference.node,
142 &length, (char *) data_space);
143
144 /* Converted (external) string length is returned from above */
145
146 external_object->string.length = length;
147 break;
148
149 default:
150 /*
151 * Use the object type of "Any" to indicate a reference
152 * to object containing a handle to an ACPI named object.
153 */
154 external_object->type = ACPI_TYPE_ANY;
155 external_object->reference.handle = internal_object->reference.node;
156 break;
157 }
158 break;
159
160
161 case ACPI_TYPE_PROCESSOR:
162
163 external_object->processor.proc_id = internal_object->processor.proc_id;
164 external_object->processor.pblk_address = internal_object->processor.address;
165 external_object->processor.pblk_length = internal_object->processor.length;
166 break;
167
168
169 case ACPI_TYPE_POWER:
170
171 external_object->power_resource.system_level =
172 internal_object->power_resource.system_level;
173
174 external_object->power_resource.resource_order =
175 internal_object->power_resource.resource_order;
176 break;
177
178
179 default:
180 /*
181 * There is no corresponding external object type
182 */
183 return (AE_SUPPORT);
184 break;
185 }
186
187
188 *buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length);
189
190 return (status);
191 }
192
193
194 /*******************************************************************************
195 *
196 * FUNCTION: Acpi_cm_copy_ielement_to_eelement
197 *
198 * PARAMETERS: ACPI_PKG_CALLBACK
199 *
200 * RETURN: Status
201 *
202 * DESCRIPTION: Copy one package element to another package element
203 *
204 ******************************************************************************/
205
206 ACPI_STATUS
207 acpi_cm_copy_ielement_to_eelement (
208 u8 object_type,
209 ACPI_OPERAND_OBJECT *source_object,
210 ACPI_GENERIC_STATE *state,
211 void *context)
212 {
213 ACPI_STATUS status = AE_OK;
214 ACPI_PKG_INFO *info = (ACPI_PKG_INFO *) context;
215 u32 object_space;
216 u32 this_index;
217 ACPI_OBJECT *target_object;
218
219
220 this_index = state->pkg.index;
221 target_object = (ACPI_OBJECT *)
222 &((ACPI_OBJECT *)(state->pkg.dest_object))->package.elements[this_index];
223
224
225 switch (object_type) {
226 case ACPI_COPY_TYPE_SIMPLE:
227
228 /*
229 * This is a simple or null object -- get the size
230 */
231
232 status = acpi_cm_copy_isimple_to_esimple (source_object,
233 target_object, info->free_space, &object_space);
234 if (ACPI_FAILURE (status)) {
235 return (status);
236 }
237
238 break;
239
240 case ACPI_COPY_TYPE_PACKAGE:
241
242 /*
243 * Build the package object
244 */
245 target_object->type = ACPI_TYPE_PACKAGE;
246 target_object->package.count = source_object->package.count;
247 target_object->package.elements = (ACPI_OBJECT *) info->free_space;
248
249 /*
250 * Pass the new package object back to the package walk routine
251 */
252 state->pkg.this_target_obj = target_object;
253
254 /*
255 * Save space for the array of objects (Package elements)
256 * update the buffer length counter
257 */
258 object_space = (u32) ROUND_UP_TO_NATIVE_WORD (
259 target_object->package.count * sizeof (ACPI_OBJECT));
260 break;
261
262 default:
263 return (AE_BAD_PARAMETER);
264 }
265
266
267 info->free_space += object_space;
268 info->length += object_space;
269
270 return (status);
271 }
272
273
274 /*******************************************************************************
275 *
276 * FUNCTION: Acpi_cm_copy_ipackage_to_epackage
277 *
278 * PARAMETERS: *Internal_object - Pointer to the object we are returning
279 * *Buffer - Where the object is returned
280 * *Space_used - Where the object length is returned
281 *
282 * RETURN: Status
283 *
284 * DESCRIPTION: This function is called to place a package object in a user
285 * buffer. A package object by definition contains other objects.
286 *
287 * The buffer is assumed to have sufficient space for the object.
288 * The caller must have verified the buffer length needed using the
289 * Acpi_cm_get_object_size function before calling this function.
290 *
291 ******************************************************************************/
292
293 static ACPI_STATUS
294 acpi_cm_copy_ipackage_to_epackage (
295 ACPI_OPERAND_OBJECT *internal_object,
296 u8 *buffer,
297 u32 *space_used)
298 {
299 ACPI_OBJECT *external_object;
300 ACPI_STATUS status;
301 ACPI_PKG_INFO info;
302
303
304 /*
305 * First package at head of the buffer
306 */
307 external_object = (ACPI_OBJECT *) buffer;
308
309 /*
310 * Free space begins right after the first package
311 */
312 info.length = 0;
313 info.object_space = 0;
314 info.num_packages = 1;
315 info.free_space = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
316
317
318 external_object->type = internal_object->common.type;
319 external_object->package.count = internal_object->package.count;
320 external_object->package.elements = (ACPI_OBJECT *) info.free_space;
321
322
323 /*
324 * Build an array of ACPI_OBJECTS in the buffer
325 * and move the free space past it
326 */
327
328 info.free_space += external_object->package.count *
329 ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
330
331
332 status = acpi_cm_walk_package_tree (internal_object, external_object,
333 acpi_cm_copy_ielement_to_eelement, &info);
334
335 *space_used = info.length;
336
337 return (status);
338
339 }
340
341 /*******************************************************************************
342 *
343 * FUNCTION: Acpi_cm_copy_iobject_to_eobject
344 *
345 * PARAMETERS: *Internal_object - The internal object to be converted
346 * *Buffer_ptr - Where the object is returned
347 *
348 * RETURN: Status
349 *
350 * DESCRIPTION: This function is called to build an API object to be returned to
351 * the caller.
352 *
353 ******************************************************************************/
354
355 ACPI_STATUS
356 acpi_cm_copy_iobject_to_eobject (
357 ACPI_OPERAND_OBJECT *internal_object,
358 ACPI_BUFFER *ret_buffer)
359 {
360 ACPI_STATUS status;
361
362
363 if (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE)) {
364 /*
365 * Package object: Copy all subobjects (including
366 * nested packages)
367 */
368 status = acpi_cm_copy_ipackage_to_epackage (internal_object,
369 ret_buffer->pointer, &ret_buffer->length);
370 }
371
372 else {
373 /*
374 * Build a simple object (no nested objects)
375 */
376 status = acpi_cm_copy_isimple_to_esimple (internal_object,
377 (ACPI_OBJECT *) ret_buffer->pointer,
378 ((u8 *) ret_buffer->pointer +
379 ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))),
380 &ret_buffer->length);
381 /*
382 * build simple does not include the object size in the length
383 * so we add it in here
384 */
385 ret_buffer->length += sizeof (ACPI_OBJECT);
386 }
387
388 return (status);
389 }
390
391
392 /*******************************************************************************
393 *
394 * FUNCTION: Acpi_cm_copy_esimple_to_isimple
395 *
396 * PARAMETERS: *External_object - The external object to be converted
397 * *Internal_object - Where the internal object is returned
398 *
399 * RETURN: Status
400 *
401 * DESCRIPTION: This function copies an external object to an internal one.
402 * NOTE: Pointers can be copied, we don't need to copy data.
403 * (The pointers have to be valid in our address space no matter
404 * what we do with them!)
405 *
406 ******************************************************************************/
407
408 ACPI_STATUS
409 acpi_cm_copy_esimple_to_isimple (
410 ACPI_OBJECT *external_object,
411 ACPI_OPERAND_OBJECT *internal_object)
412 {
413
414
415 internal_object->common.type = (u8) external_object->type;
416
417 switch (external_object->type) {
418
419 case ACPI_TYPE_STRING:
420
421 internal_object->string.length = external_object->string.length;
422 internal_object->string.pointer = external_object->string.pointer;
423 break;
424
425
426 case ACPI_TYPE_BUFFER:
427
428 internal_object->buffer.length = external_object->buffer.length;
429 internal_object->buffer.pointer = external_object->buffer.pointer;
430 break;
431
432
433 case ACPI_TYPE_INTEGER:
434 /*
435 * Number is included in the object itself
436 */
437 internal_object->integer.value = external_object->integer.value;
438 break;
439
440
441 default:
442 return (AE_CTRL_RETURN_VALUE);
443 break;
444 }
445
446
447 return (AE_OK);
448 }
449
450
451 #ifdef ACPI_FUTURE_IMPLEMENTATION
452
453 /* Code to convert packages that are parameters to control methods */
454
455 /*******************************************************************************
456 *
457 * FUNCTION: Acpi_cm_copy_epackage_to_ipackage
458 *
459 * PARAMETERS: *Internal_object - Pointer to the object we are returning
460 * *Buffer - Where the object is returned
461 * *Space_used - Where the length of the object is returned
462 *
463 * RETURN: Status - the status of the call
464 *
465 * DESCRIPTION: This function is called to place a package object in a user
466 * buffer. A package object by definition contains other objects.
467 *
468 * The buffer is assumed to have sufficient space for the object.
469 * The caller must have verified the buffer length needed using the
470 * Acpi_cm_get_object_size function before calling this function.
471 *
472 ******************************************************************************/
473
474 static ACPI_STATUS
475 acpi_cm_copy_epackage_to_ipackage (
476 ACPI_OPERAND_OBJECT *internal_object,
477 u8 *buffer,
478 u32 *space_used)
479 {
480 u8 *free_space;
481 ACPI_OBJECT *external_object;
482 u32 length = 0;
483 u32 this_index;
484 u32 object_space = 0;
485 ACPI_OPERAND_OBJECT *this_internal_obj;
486 ACPI_OBJECT *this_external_obj;
487
488
489 /*
490 * First package at head of the buffer
491 */
492 external_object = (ACPI_OBJECT *)buffer;
493
494 /*
495 * Free space begins right after the first package
496 */
497 free_space = buffer + sizeof(ACPI_OBJECT);
498
499
500 external_object->type = internal_object->common.type;
501 external_object->package.count = internal_object->package.count;
502 external_object->package.elements = (ACPI_OBJECT *)free_space;
503
504
505 /*
506 * Build an array of ACPI_OBJECTS in the buffer
507 * and move the free space past it
508 */
509
510 free_space += external_object->package.count * sizeof(ACPI_OBJECT);
511
512
513 /* Call Walk_package */
514
515 }
516
517 #endif /* Future implementation */
518
519
520 /*******************************************************************************
521 *
522 * FUNCTION: Acpi_cm_copy_eobject_to_iobject
523 *
524 * PARAMETERS: *Internal_object - The external object to be converted
525 * *Buffer_ptr - Where the internal object is returned
526 *
527 * RETURN: Status - the status of the call
528 *
529 * DESCRIPTION: Converts an external object to an internal object.
530 *
531 ******************************************************************************/
532
533 ACPI_STATUS
534 acpi_cm_copy_eobject_to_iobject (
535 ACPI_OBJECT *external_object,
536 ACPI_OPERAND_OBJECT *internal_object)
537 {
538 ACPI_STATUS status;
539
540
541 if (external_object->type == ACPI_TYPE_PACKAGE) {
542 /*
543 * Package objects contain other objects (which can be objects)
544 * buildpackage does it all
545 *
546 * TBD: Package conversion must be completed and tested
547 * NOTE: this code converts packages as input parameters to
548 * control methods only. This is a very, very rare case.
549 */
550 /*
551 Status = Acpi_cm_copy_epackage_to_ipackage(Internal_object,
552 Ret_buffer->Pointer,
553 &Ret_buffer->Length);
554 */
555 return (AE_NOT_IMPLEMENTED);
556 }
557
558 else {
559 /*
560 * Build a simple object (no nested objects)
561 */
562 status = acpi_cm_copy_esimple_to_isimple (external_object, internal_object);
563 /*
564 * build simple does not include the object size in the length
565 * so we add it in here
566 */
567 }
568
569 return (status);
570 }
571
572
573 /*******************************************************************************
574 *
575 * FUNCTION: Acpi_cm_copy_ielement_to_ielement
576 *
577 * PARAMETERS: ACPI_PKG_CALLBACK
578 *
579 * RETURN: Status - the status of the call
580 *
581 * DESCRIPTION: Copy one package element to another package element
582 *
583 ******************************************************************************/
584
585 ACPI_STATUS
586 acpi_cm_copy_ielement_to_ielement (
587 u8 object_type,
588 ACPI_OPERAND_OBJECT *source_object,
589 ACPI_GENERIC_STATE *state,
590 void *context)
591 {
592 ACPI_STATUS status = AE_OK;
593 u32 this_index;
594 ACPI_OPERAND_OBJECT **this_target_ptr;
595 ACPI_OPERAND_OBJECT *target_object;
596
597
598 this_index = state->pkg.index;
599 this_target_ptr = (ACPI_OPERAND_OBJECT **)
600 &state->pkg.dest_object->package.elements[this_index];
601
602 switch (object_type) {
603 case 0:
604
605 /*
606 * This is a simple object, just copy it
607 */
608 target_object = acpi_cm_create_internal_object (source_object->common.type);
609 if (!target_object) {
610 return (AE_NO_MEMORY);
611 }
612
613 status = acpi_aml_store_object_to_object (source_object, target_object,
614 (ACPI_WALK_STATE *) context);
615 if (ACPI_FAILURE (status)) {
616 return (status);
617 }
618
619 *this_target_ptr = target_object;
620 break;
621
622
623 case 1:
624 /*
625 * This object is a package - go down another nesting level
626 * Create and build the package object
627 */
628 target_object = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE);
629 if (!target_object) {
630 /* TBD: must delete package created up to this point */
631
632 return (AE_NO_MEMORY);
633 }
634
635 target_object->package.count = source_object->package.count;
636
637 /*
638 * Pass the new package object back to the package walk routine
639 */
640 state->pkg.this_target_obj = target_object;
641
642 /*
643 * Store the object pointer in the parent package object
644 */
645 *this_target_ptr = target_object;
646 break;
647
648 default:
649 return (AE_BAD_PARAMETER);
650 }
651
652
653 return (status);
654 }
655
656
657 /*******************************************************************************
658 *
659 * FUNCTION: Acpi_cm_copy_ipackage_to_ipackage
660 *
661 * PARAMETERS: *Source_obj - Pointer to the source package object
662 * *Dest_obj - Where the internal object is returned
663 *
664 * RETURN: Status - the status of the call
665 *
666 * DESCRIPTION: This function is called to copy an internal package object
667 * into another internal package object.
668 *
669 ******************************************************************************/
670
671 ACPI_STATUS
672 acpi_cm_copy_ipackage_to_ipackage (
673 ACPI_OPERAND_OBJECT *source_obj,
674 ACPI_OPERAND_OBJECT *dest_obj,
675 ACPI_WALK_STATE *walk_state)
676 {
677 ACPI_STATUS status = AE_OK;
678
679
680 dest_obj->common.type = source_obj->common.type;
681 dest_obj->package.count = source_obj->package.count;
682
683
684 /*
685 * Create the object array and walk the source package tree
686 */
687
688 dest_obj->package.elements = acpi_cm_callocate ((source_obj->package.count + 1) *
689 sizeof (void *));
690 dest_obj->package.next_element = dest_obj->package.elements;
691
692 if (!dest_obj->package.elements) {
693 REPORT_ERROR (
694 ("Aml_build_copy_internal_package_object: Package allocation failure\n"));
695 return (AE_NO_MEMORY);
696 }
697
698
699 status = acpi_cm_walk_package_tree (source_obj, dest_obj,
700 acpi_cm_copy_ielement_to_ielement, walk_state);
701
702 return (status);
703 }
704