1 /******************************************************************************
3 * Module Name: cmcopy - Internal to external object translation utilities
5 *****************************************************************************/
8 * Copyright (C) 2000 R. Byron Moore
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #define _COMPONENT MISCELLANEOUS
32 MODULE_NAME ("cmcopy");
35 typedef struct search_st
37 ACPI_OBJECT_INTERNAL
*internal_obj
;
39 ACPI_OBJECT
*external_obj
;
44 /* Used to traverse nested packages */
46 PKG_SEARCH_INFO level
[MAX_PACKAGE_DEPTH
];
48 /******************************************************************************
50 * FUNCTION: Acpi_cm_build_external_simple_object
52 * PARAMETERS: *Internal_obj - Pointer to the object we are examining
53 * *Buffer - Where the object is returned
54 * *Space_used - Where the data length is returned
56 * RETURN: Status - the status of the call
58 * DESCRIPTION: This function is called to place a simple object in a user
61 * The buffer is assumed to have sufficient space for the object.
63 ******************************************************************************/
66 acpi_cm_build_external_simple_object (
67 ACPI_OBJECT_INTERNAL
*internal_obj
,
68 ACPI_OBJECT
*external_obj
,
70 u32
*buffer_space_used
)
73 char *source_ptr
= NULL
;
77 * Check for NULL object case (could be an uninitialized
82 *buffer_space_used
= 0;
86 /* Always clear the external object */
88 MEMSET (external_obj
, 0, sizeof (ACPI_OBJECT
));
91 * In general, the external object will be the same type as
95 external_obj
->type
= internal_obj
->common
.type
;
97 /* However, only a limited number of external types are supported */
99 switch (external_obj
->type
)
102 case ACPI_TYPE_STRING
:
104 length
= internal_obj
->string
.length
;
105 external_obj
->string
.length
= internal_obj
->string
.length
;
106 external_obj
->string
.pointer
= (char *) data_space
;
107 source_ptr
= internal_obj
->string
.pointer
;
111 case ACPI_TYPE_BUFFER
:
113 length
= internal_obj
->buffer
.length
;
114 external_obj
->buffer
.length
= internal_obj
->buffer
.length
;
115 external_obj
->buffer
.pointer
= data_space
;
116 source_ptr
= (char *) internal_obj
->buffer
.pointer
;
120 case ACPI_TYPE_NUMBER
:
122 external_obj
->number
.value
= internal_obj
->number
.value
;
126 case INTERNAL_TYPE_REFERENCE
:
129 * This is an object reference. We use the object type of "Any"
130 * to indicate a reference object containing a handle to an ACPI
134 external_obj
->type
= ACPI_TYPE_ANY
;
135 external_obj
->reference
.handle
= internal_obj
->reference
.nte
;
139 case ACPI_TYPE_PROCESSOR
:
141 external_obj
->processor
.proc_id
=
142 internal_obj
->processor
.proc_id
;
144 external_obj
->processor
.pblk_address
=
145 internal_obj
->processor
.pblk_address
;
147 external_obj
->processor
.pblk_length
=
148 internal_obj
->processor
.pblk_length
;
151 case ACPI_TYPE_POWER
:
153 external_obj
->power_resource
.system_level
=
154 internal_obj
->power_resource
.system_level
;
156 external_obj
->power_resource
.resource_order
=
157 internal_obj
->power_resource
.resource_order
;
161 return (AE_CTRL_RETURN_VALUE
);
166 /* Copy data if necessary (strings or buffers) */
170 * Copy the return data to the caller's buffer
172 MEMCPY ((void *) data_space
, (void *) source_ptr
, length
);
176 *buffer_space_used
= (u32
) ROUND_UP_TO_NATIVE_WORD (length
);
182 /******************************************************************************
184 * FUNCTION: Acpi_cm_build_external_package_object
186 * PARAMETERS: *Internal_obj - Pointer to the object we are returning
187 * *Buffer - Where the object is returned
188 * *Space_used - Where the object length is returned
190 * RETURN: Status - the status of the call
192 * DESCRIPTION: This function is called to place a package object in a user
193 * buffer. A package object by definition contains other objects.
195 * The buffer is assumed to have sufficient space for the object.
196 * The caller must have verified the buffer length needed using the
197 * Acpi_cm_get_object_size function before calling this function.
199 ******************************************************************************/
202 acpi_cm_build_external_package_object (
203 ACPI_OBJECT_INTERNAL
*internal_obj
,
208 ACPI_OBJECT
*external_obj
;
209 u32 current_depth
= 0;
214 ACPI_OBJECT_INTERNAL
*this_internal_obj
;
215 ACPI_OBJECT
*this_external_obj
;
216 PKG_SEARCH_INFO
*level_ptr
;
220 * First package at head of the buffer
222 external_obj
= (ACPI_OBJECT
*) buffer
;
225 * Free space begins right after the first package
227 free_space
= buffer
+ ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT
));
231 * Initialize the working variables
234 MEMSET ((void *) level
, 0, sizeof (level
));
236 level
[0].internal_obj
= internal_obj
;
237 level
[0].external_obj
= external_obj
;
239 level_ptr
= &level
[0];
242 external_obj
->type
= internal_obj
->common
.type
;
243 external_obj
->package
.count
= internal_obj
->package
.count
;
244 external_obj
->package
.elements
= (ACPI_OBJECT
*) free_space
;
248 * Build an array of ACPI_OBJECTS in the buffer
249 * and move the free space past it
252 free_space
+= external_obj
->package
.count
*
253 ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT
));
257 this_index
= level_ptr
->index
;
259 (ACPI_OBJECT_INTERNAL
*)
260 level_ptr
->internal_obj
->package
.elements
[this_index
];
263 &level_ptr
->external_obj
->package
.elements
[this_index
];
267 * Check for 1) Null object -- OK, this can happen if package
268 * element is never initialized
269 * 2) Not an internal object - can be an NTE instead
270 * 3) Any internal object other than a package.
272 * The more complex package case is handled later
275 if ((!this_internal_obj
) ||
276 (!VALID_DESCRIPTOR_TYPE (
277 this_internal_obj
, ACPI_DESC_TYPE_INTERNAL
)) ||
278 (!IS_THIS_OBJECT_TYPE (
279 this_internal_obj
, ACPI_TYPE_PACKAGE
)))
282 * This is a simple or null object -- get the size
286 acpi_cm_build_external_simple_object (this_internal_obj
,
290 if (ACPI_FAILURE (status
)) {
294 free_space
+= object_space
;
295 length
+= object_space
;
298 while (level_ptr
->index
>=
299 level_ptr
->internal_obj
->package
.count
)
302 * We've handled all of the objects at this
303 * level. This means that we have just
304 * completed a package. That package may
305 * have contained one or more packages
308 if (current_depth
== 0) {
310 * We have handled all of the objects
311 * in the top level package just add
312 * the length of the package objects
315 *space_used
= length
;
320 * go back up a level and move the index
321 * past the just completed package object.
324 level_ptr
= &level
[current_depth
];
332 * This object is a package
333 * -- we must go one level deeper
335 if (current_depth
>= MAX_PACKAGE_DEPTH
-1) {
337 * Too many nested levels of packages
344 * Build the package object
346 this_external_obj
->type
= ACPI_TYPE_PACKAGE
;
347 this_external_obj
->package
.count
=
348 this_internal_obj
->package
.count
;
349 this_external_obj
->package
.elements
=
350 (ACPI_OBJECT
*) free_space
;
353 * Save space for the array of objects (Package elements)
354 * update the buffer length counter
356 object_space
= (u32
) ROUND_UP_TO_NATIVE_WORD (
357 this_external_obj
->package
.count
*
358 sizeof (ACPI_OBJECT
));
360 free_space
+= object_space
;
361 length
+= object_space
;
364 level_ptr
= &level
[current_depth
];
365 level_ptr
->internal_obj
= this_internal_obj
;
366 level_ptr
->external_obj
= this_external_obj
;
367 level_ptr
->index
= 0;
375 /******************************************************************************
377 * FUNCTION: Acpi_cm_build_external_object
379 * PARAMETERS: *Internal_obj - The internal object to be converted
380 * *Buffer_ptr - Where the object is returned
382 * RETURN: Status - the status of the call
384 * DESCRIPTION: This function is called to build an API object to be returned to
387 ******************************************************************************/
390 acpi_cm_build_external_object (
391 ACPI_OBJECT_INTERNAL
*internal_obj
,
392 ACPI_BUFFER
*ret_buffer
)
397 if (IS_THIS_OBJECT_TYPE (internal_obj
, ACPI_TYPE_PACKAGE
)) {
399 * Package objects contain other objects (which can be objects)
400 * buildpackage does it all
403 acpi_cm_build_external_package_object (internal_obj
,
405 &ret_buffer
->length
);
410 * Build a simple object (no nested objects)
413 acpi_cm_build_external_simple_object (internal_obj
,
414 (ACPI_OBJECT
*) ret_buffer
->pointer
,
415 ((u8
*) ret_buffer
->pointer
+
416 ROUND_UP_TO_NATIVE_WORD (
417 sizeof (ACPI_OBJECT
))),
418 &ret_buffer
->length
);
420 * build simple does not include the object size in the length
421 * so we add it in here
423 ret_buffer
->length
+= sizeof (ACPI_OBJECT
);
430 /******************************************************************************
432 * FUNCTION: Acpi_cm_build_internal_simple_object
434 * PARAMETERS: *External_obj - The external object to be converted
435 * *Internal_obj - Where the internal object is returned
437 * RETURN: Status - the status of the call
439 * DESCRIPTION: This function copies an external object to an internal one.
440 * NOTE: Pointers can be copied, we don't need to copy data.
441 * (The pointers have to be valid in our address space no matter
442 * what we do with them!)
444 ******************************************************************************/
447 acpi_cm_build_internal_simple_object (
448 ACPI_OBJECT
*external_obj
,
449 ACPI_OBJECT_INTERNAL
*internal_obj
)
453 internal_obj
->common
.type
= (u8
) external_obj
->type
;
455 switch (external_obj
->type
)
458 case ACPI_TYPE_STRING
:
460 internal_obj
->string
.length
= external_obj
->string
.length
;
461 internal_obj
->string
.pointer
= external_obj
->string
.pointer
;
465 case ACPI_TYPE_BUFFER
:
467 internal_obj
->buffer
.length
= external_obj
->buffer
.length
;
468 internal_obj
->buffer
.pointer
= external_obj
->buffer
.pointer
;
472 case ACPI_TYPE_NUMBER
:
474 * Number is included in the object itself
476 internal_obj
->number
.value
= external_obj
->number
.value
;
481 return (AE_CTRL_RETURN_VALUE
);
490 /******************************************************************************
492 * FUNCTION: Acpi_cm_build_internal_package_object
494 * PARAMETERS: *Internal_obj - Pointer to the object we are returning
495 * *Buffer - Where the object is returned
496 * *Space_used - Where the length of the object is returned
498 * RETURN: Status - the status of the call
500 * DESCRIPTION: This function is called to place a package object in a user
501 * buffer. A package object by definition contains other objects.
503 * The buffer is assumed to have sufficient space for the object.
504 * The caller must have verified the buffer length needed using the
505 * Acpi_cm_get_object_size function before calling this function.
507 ******************************************************************************/
510 acpi_cm_build_internal_package_object (
511 ACPI_OBJECT_INTERNAL
*internal_obj
,
516 ACPI_OBJECT
*external_obj
;
517 u32 current_depth
= 0;
518 ACPI_STATUS status
= AE_OK
;
521 u32 object_space
= 0;
522 ACPI_OBJECT_INTERNAL
*this_internal_obj
;
523 ACPI_OBJECT
*this_external_obj
;
524 PKG_SEARCH_INFO
*level_ptr
;
528 * First package at head of the buffer
530 external_obj
= (ACPI_OBJECT
*)buffer
;
533 * Free space begins right after the first package
535 free_space
= buffer
+ sizeof(ACPI_OBJECT
);
539 * Initialize the working variables
542 MEMSET ((void *) level
, 0, sizeof(level
));
544 level
[0].internal_obj
= internal_obj
;
545 level
[0].external_obj
= external_obj
;
546 level_ptr
= &level
[0];
549 external_obj
->type
= internal_obj
->common
.type
;
550 external_obj
->package
.count
= internal_obj
->package
.count
;
551 external_obj
->package
.elements
= (ACPI_OBJECT
*)free_space
;
555 * Build an array of ACPI_OBJECTS in the buffer
556 * and move the free space past it
559 free_space
+= external_obj
->package
.count
* sizeof(ACPI_OBJECT
);
563 this_index
= level_ptr
->index
;
565 this_internal_obj
= (ACPI_OBJECT_INTERNAL
*)
566 &level_ptr
->internal_obj
->package
.elements
[this_index
];
568 this_external_obj
= (ACPI_OBJECT
*)
569 &level_ptr
->external_obj
->package
.elements
[this_index
];
571 if (IS_THIS_OBJECT_TYPE (this_internal_obj
, ACPI_TYPE_PACKAGE
)) {
573 * If this object is a package then we go one deeper
575 if (current_depth
>= MAX_PACKAGE_DEPTH
-1) {
577 * Too many nested levels of packages for us to handle
583 * Build the package object
585 this_external_obj
->type
= ACPI_TYPE_PACKAGE
;
586 this_external_obj
->package
.count
= this_internal_obj
->package
.count
;
587 this_external_obj
->package
.elements
= (ACPI_OBJECT
*) free_space
;
590 * Save space for the array of objects (Package elements)
591 * update the buffer length counter
593 object_space
= this_external_obj
->package
.count
*
594 sizeof (ACPI_OBJECT
);
596 free_space
+= object_space
;
597 length
+= object_space
;
600 level_ptr
= &level
[current_depth
];
601 level_ptr
->internal_obj
= this_internal_obj
;
602 level_ptr
->external_obj
= this_external_obj
;
603 level_ptr
->index
= 0;
605 } /* if object is a package */
608 /* Status = Acpi_cm_build_simple_object(This_internal_obj,
609 This_external_obj, Free_space,
612 if (status
!= AE_OK
) {
619 free_space
+= object_space
;
620 length
+= object_space
;
623 while (level_ptr
->index
>=
624 level_ptr
->internal_obj
->package
.count
)
627 * We've handled all of the objects at
628 * this level, This means that we have
629 * just completed a package. That package
630 * may have contained one or more packages
633 if (current_depth
== 0) {
635 * We have handled all of the objects
636 * in the top level package just add
637 * the length of the package objects
640 *space_used
= length
;
645 * go back up a level and move the index
646 * past the just completed package object.
649 level_ptr
= &level
[current_depth
];
652 } /* else object is NOT a package */
657 * We'll never get here, but the compiler whines about
664 /******************************************************************************
666 * FUNCTION: Acpi_cm_build_internal_object
668 * PARAMETERS: *Internal_obj - The external object to be converted
669 * *Buffer_ptr - Where the internal object is returned
671 * RETURN: Status - the status of the call
673 * DESCRIPTION: Converts an external object to an internal object.
675 ******************************************************************************/
678 acpi_cm_build_internal_object (
679 ACPI_OBJECT
*external_obj
,
680 ACPI_OBJECT_INTERNAL
*internal_obj
)
685 if (external_obj
->type
== ACPI_TYPE_PACKAGE
) {
687 * Package objects contain other objects (which can be objects)
688 * buildpackage does it all
691 Status = Acpi_cm_build_internal_package_object(Internal_obj,
693 &Ret_buffer->Length);
695 return (AE_NOT_IMPLEMENTED
);
700 * Build a simple object (no nested objects)
702 status
= acpi_cm_build_internal_simple_object (external_obj
, internal_obj
);
704 * build simple does not include the object size in the length
705 * so we add it in here