1 /******************************************************************************
3 * Module Name: exconvrt - Object conversion routines
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2004, R. Byron Moore
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
45 #include <acpi/acpi.h>
46 #include <acpi/acinterp.h>
47 #include <acpi/amlcode.h>
50 #define _COMPONENT ACPI_EXECUTER
51 ACPI_MODULE_NAME ("exconvrt")
54 /*******************************************************************************
56 * FUNCTION: acpi_ex_convert_to_integer
58 * PARAMETERS: obj_desc - Object to be converted. Must be an
59 * Integer, Buffer, or String
60 * result_desc - Where the new Integer object is returned
61 * walk_state - Current method state
65 * DESCRIPTION: Convert an ACPI Object to an integer.
67 ******************************************************************************/
70 acpi_ex_convert_to_integer (
71 union acpi_operand_object
*obj_desc
,
72 union acpi_operand_object
**result_desc
,
73 struct acpi_walk_state
*walk_state
)
76 union acpi_operand_object
*ret_desc
;
83 ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_integer", obj_desc
);
86 switch (ACPI_GET_OBJECT_TYPE (obj_desc
)) {
87 case ACPI_TYPE_INTEGER
:
88 *result_desc
= obj_desc
;
89 return_ACPI_STATUS (AE_OK
);
91 case ACPI_TYPE_STRING
:
92 pointer
= (u8
*) obj_desc
->string
.pointer
;
93 count
= obj_desc
->string
.length
;
96 case ACPI_TYPE_BUFFER
:
97 pointer
= obj_desc
->buffer
.pointer
;
98 count
= obj_desc
->buffer
.length
;
102 return_ACPI_STATUS (AE_TYPE
);
106 * Convert the buffer/string to an integer. Note that both buffers and
107 * strings are treated as raw data - we don't convert ascii to hex for
110 * There are two terminating conditions for the loop:
111 * 1) The size of an integer has been reached, or
112 * 2) The end of the buffer or string has been reached
116 /* Transfer no more than an integer's worth of data */
118 if (count
> acpi_gbl_integer_byte_width
) {
119 count
= acpi_gbl_integer_byte_width
;
123 * String conversion is different than Buffer conversion
125 switch (ACPI_GET_OBJECT_TYPE (obj_desc
)) {
126 case ACPI_TYPE_STRING
:
129 * Convert string to an integer
130 * String must be hexadecimal as per the ACPI specification
132 status
= acpi_ut_strtoul64 ((char *) pointer
, 16, &result
);
133 if (ACPI_FAILURE (status
)) {
134 return_ACPI_STATUS (status
);
139 case ACPI_TYPE_BUFFER
:
142 * Buffer conversion - we simply grab enough raw data from the
143 * buffer to fill an integer
145 for (i
= 0; i
< count
; i
++) {
147 * Get next byte and shift it into the Result.
148 * Little endian is used, meaning that the first byte of the buffer
149 * is the LSB of the integer
151 result
|= (((acpi_integer
) pointer
[i
]) << (i
* 8));
157 /* No other types can get here */
162 * Create a new integer
164 ret_desc
= acpi_ut_create_internal_object (ACPI_TYPE_INTEGER
);
166 return_ACPI_STATUS (AE_NO_MEMORY
);
169 /* Save the Result */
171 ret_desc
->integer
.value
= result
;
174 * If we are about to overwrite the original object on the operand stack,
175 * we must remove a reference on the original object because we are
176 * essentially removing it from the stack.
178 if (*result_desc
== obj_desc
) {
179 if (walk_state
->opcode
!= AML_STORE_OP
) {
180 acpi_ut_remove_reference (obj_desc
);
184 *result_desc
= ret_desc
;
185 return_ACPI_STATUS (AE_OK
);
189 /*******************************************************************************
191 * FUNCTION: acpi_ex_convert_to_buffer
193 * PARAMETERS: obj_desc - Object to be converted. Must be an
194 * Integer, Buffer, or String
195 * result_desc - Where the new buffer object is returned
196 * walk_state - Current method state
200 * DESCRIPTION: Convert an ACPI Object to a Buffer
202 ******************************************************************************/
205 acpi_ex_convert_to_buffer (
206 union acpi_operand_object
*obj_desc
,
207 union acpi_operand_object
**result_desc
,
208 struct acpi_walk_state
*walk_state
)
210 union acpi_operand_object
*ret_desc
;
215 ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_buffer", obj_desc
);
218 switch (ACPI_GET_OBJECT_TYPE (obj_desc
)) {
219 case ACPI_TYPE_BUFFER
:
221 /* No conversion necessary */
223 *result_desc
= obj_desc
;
224 return_ACPI_STATUS (AE_OK
);
227 case ACPI_TYPE_INTEGER
:
230 * Create a new Buffer object.
231 * Need enough space for one integer
233 ret_desc
= acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width
);
235 return_ACPI_STATUS (AE_NO_MEMORY
);
238 /* Copy the integer to the buffer */
240 new_buf
= ret_desc
->buffer
.pointer
;
241 for (i
= 0; i
< acpi_gbl_integer_byte_width
; i
++) {
242 new_buf
[i
] = (u8
) (obj_desc
->integer
.value
>> (i
* 8));
247 case ACPI_TYPE_STRING
:
250 * Create a new Buffer object
251 * Size will be the string length
253 ret_desc
= acpi_ut_create_buffer_object ((acpi_size
) obj_desc
->string
.length
);
255 return_ACPI_STATUS (AE_NO_MEMORY
);
258 /* Copy the string to the buffer */
260 new_buf
= ret_desc
->buffer
.pointer
;
261 ACPI_STRNCPY ((char *) new_buf
, (char *) obj_desc
->string
.pointer
,
262 obj_desc
->string
.length
);
267 return_ACPI_STATUS (AE_TYPE
);
270 /* Mark buffer initialized */
272 ret_desc
->common
.flags
|= AOPOBJ_DATA_VALID
;
275 * If we are about to overwrite the original object on the operand stack,
276 * we must remove a reference on the original object because we are
277 * essentially removing it from the stack.
279 if (*result_desc
== obj_desc
) {
280 if (walk_state
->opcode
!= AML_STORE_OP
) {
281 acpi_ut_remove_reference (obj_desc
);
285 *result_desc
= ret_desc
;
286 return_ACPI_STATUS (AE_OK
);
290 /*******************************************************************************
292 * FUNCTION: acpi_ex_convert_ascii
294 * PARAMETERS: Integer - Value to be converted
296 * String - Where the string is returned
297 * data_width - Size of data item to be converted
299 * RETURN: Actual string length
301 * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
303 ******************************************************************************/
306 acpi_ex_convert_to_ascii (
307 acpi_integer integer
,
322 ACPI_FUNCTION_ENTRY ();
325 if (data_width
< sizeof (acpi_integer
)) {
326 leading_zero
= FALSE
;
331 length
= sizeof (acpi_integer
);
338 for (i
= ACPI_MAX_DECIMAL_DIGITS
; i
> 0; i
--) {
339 /* Divide by nth factor of 10 */
342 for (j
= 0; j
< i
; j
++) {
343 (void) acpi_ut_short_divide (&digit
, 10, &digit
, &remainder
);
346 /* Create the decimal digit */
348 if (remainder
!= 0) {
349 leading_zero
= FALSE
;
353 string
[k
] = (u8
) (ACPI_ASCII_ZERO
+ remainder
);
362 /* Copy the integer to the buffer */
364 for (i
= 0, j
= ((length
* 2) -1); i
< (length
* 2); i
++, j
--) {
366 hex_digit
= acpi_ut_hex_to_ascii_char (integer
, (j
* 4));
367 if (hex_digit
!= ACPI_ASCII_ZERO
) {
368 leading_zero
= FALSE
;
372 string
[k
] = (u8
) hex_digit
;
384 * Since leading zeros are supressed, we must check for the case where
385 * the integer equals 0
387 * Finally, null terminate the string and return the length
390 string
[0] = ACPI_ASCII_ZERO
;
399 /*******************************************************************************
401 * FUNCTION: acpi_ex_convert_to_string
403 * PARAMETERS: obj_desc - Object to be converted. Must be an
404 * Integer, Buffer, or String
405 * result_desc - Where the string object is returned
407 * max_length - Max length of the returned string
408 * walk_state - Current method state
412 * DESCRIPTION: Convert an ACPI Object to a string
414 ******************************************************************************/
417 acpi_ex_convert_to_string (
418 union acpi_operand_object
*obj_desc
,
419 union acpi_operand_object
**result_desc
,
422 struct acpi_walk_state
*walk_state
)
424 union acpi_operand_object
*ret_desc
;
431 ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc
);
434 switch (ACPI_GET_OBJECT_TYPE (obj_desc
)) {
435 case ACPI_TYPE_STRING
:
437 if (max_length
>= obj_desc
->string
.length
) {
438 *result_desc
= obj_desc
;
439 return_ACPI_STATUS (AE_OK
);
442 /* Must copy the string first and then truncate it */
444 return_ACPI_STATUS (AE_NOT_IMPLEMENTED
);
448 case ACPI_TYPE_INTEGER
:
450 string_length
= acpi_gbl_integer_byte_width
* 2;
452 string_length
= ACPI_MAX_DECIMAL_DIGITS
;
456 * Create a new String
458 ret_desc
= acpi_ut_create_internal_object (ACPI_TYPE_STRING
);
460 return_ACPI_STATUS (AE_NO_MEMORY
);
463 /* Need enough space for one ASCII integer plus null terminator */
465 new_buf
= ACPI_MEM_CALLOCATE ((acpi_size
) string_length
+ 1);
468 (("ex_convert_to_string: Buffer allocation failure\n"));
469 acpi_ut_remove_reference (ret_desc
);
470 return_ACPI_STATUS (AE_NO_MEMORY
);
475 i
= acpi_ex_convert_to_ascii (obj_desc
->integer
.value
, base
, new_buf
, sizeof (acpi_integer
));
477 /* Null terminate at the correct place */
479 if (max_length
< i
) {
480 new_buf
[max_length
] = 0;
481 ret_desc
->string
.length
= max_length
;
485 ret_desc
->string
.length
= i
;
488 ret_desc
->buffer
.pointer
= new_buf
;
492 case ACPI_TYPE_BUFFER
:
494 /* Find the string length */
496 pointer
= obj_desc
->buffer
.pointer
;
497 for (string_length
= 0; string_length
< obj_desc
->buffer
.length
; string_length
++) {
498 /* Exit on null terminator */
500 if (!pointer
[string_length
]) {
505 if (max_length
> ACPI_MAX_STRING_CONVERSION
) {
506 if (string_length
> ACPI_MAX_STRING_CONVERSION
) {
507 return_ACPI_STATUS (AE_AML_STRING_LIMIT
);
512 * Create a new string object
514 ret_desc
= acpi_ut_create_internal_object (ACPI_TYPE_STRING
);
516 return_ACPI_STATUS (AE_NO_MEMORY
);
519 /* String length is the lesser of the Max or the actual length */
521 if (max_length
< string_length
) {
522 string_length
= max_length
;
525 new_buf
= ACPI_MEM_CALLOCATE ((acpi_size
) string_length
+ 1);
528 (("ex_convert_to_string: Buffer allocation failure\n"));
529 acpi_ut_remove_reference (ret_desc
);
530 return_ACPI_STATUS (AE_NO_MEMORY
);
533 /* Copy the appropriate number of buffer characters */
535 ACPI_MEMCPY (new_buf
, pointer
, string_length
);
539 new_buf
[string_length
] = 0;
540 ret_desc
->buffer
.pointer
= new_buf
;
541 ret_desc
->string
.length
= string_length
;
546 return_ACPI_STATUS (AE_TYPE
);
550 * If we are about to overwrite the original object on the operand stack,
551 * we must remove a reference on the original object because we are
552 * essentially removing it from the stack.
554 if (*result_desc
== obj_desc
) {
555 if (walk_state
->opcode
!= AML_STORE_OP
) {
556 acpi_ut_remove_reference (obj_desc
);
560 *result_desc
= ret_desc
;
561 return_ACPI_STATUS (AE_OK
);
565 /*******************************************************************************
567 * FUNCTION: acpi_ex_convert_to_target_type
569 * PARAMETERS: destination_type - Current type of the destination
570 * source_desc - Source object to be converted.
571 * result_desc - Where the converted object is returned
572 * walk_state - Current method state
576 * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
578 ******************************************************************************/
581 acpi_ex_convert_to_target_type (
582 acpi_object_type destination_type
,
583 union acpi_operand_object
*source_desc
,
584 union acpi_operand_object
**result_desc
,
585 struct acpi_walk_state
*walk_state
)
587 acpi_status status
= AE_OK
;
590 ACPI_FUNCTION_TRACE ("ex_convert_to_target_type");
593 /* Default behavior */
595 *result_desc
= source_desc
;
598 * If required by the target,
599 * perform implicit conversion on the source before we store it.
601 switch (GET_CURRENT_ARG_TYPE (walk_state
->op_info
->runtime_args
)) {
602 case ARGI_SIMPLE_TARGET
:
603 case ARGI_FIXED_TARGET
:
604 case ARGI_INTEGER_REF
: /* Handles Increment, Decrement cases */
606 switch (destination_type
) {
607 case ACPI_TYPE_LOCAL_REGION_FIELD
:
609 * Named field can always handle conversions
614 /* No conversion allowed for these types */
616 if (destination_type
!= ACPI_GET_OBJECT_TYPE (source_desc
)) {
617 ACPI_DEBUG_PRINT ((ACPI_DB_INFO
,
618 "Explicit operator, will store (%s) over existing type (%s)\n",
619 acpi_ut_get_object_type_name (source_desc
),
620 acpi_ut_get_type_name (destination_type
)));
629 switch (destination_type
) {
630 case ACPI_TYPE_INTEGER
:
631 case ACPI_TYPE_BUFFER_FIELD
:
632 case ACPI_TYPE_LOCAL_BANK_FIELD
:
633 case ACPI_TYPE_LOCAL_INDEX_FIELD
:
635 * These types require an Integer operand. We can convert
636 * a Buffer or a String to an Integer if necessary.
638 status
= acpi_ex_convert_to_integer (source_desc
, result_desc
, walk_state
);
642 case ACPI_TYPE_STRING
:
645 * The operand must be a String. We can convert an
646 * Integer or Buffer if necessary
648 status
= acpi_ex_convert_to_string (source_desc
, result_desc
, 16, ACPI_UINT32_MAX
, walk_state
);
652 case ACPI_TYPE_BUFFER
:
655 * The operand must be a Buffer. We can convert an
656 * Integer or String if necessary
658 status
= acpi_ex_convert_to_buffer (source_desc
, result_desc
, walk_state
);
663 ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n",
665 status
= AE_AML_INTERNAL
;
673 * create_xxxx_field cases - we are storing the field object into the name
679 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR
,
680 "Unknown Target type ID 0x%X Op %s dest_type %s\n",
681 GET_CURRENT_ARG_TYPE (walk_state
->op_info
->runtime_args
),
682 walk_state
->op_info
->name
, acpi_ut_get_type_name (destination_type
)));
684 ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n",
685 GET_CURRENT_ARG_TYPE (walk_state
->op_info
->runtime_args
)))
686 status
= AE_AML_INTERNAL
;
690 * Source-to-Target conversion semantics:
692 * If conversion to the target type cannot be performed, then simply
693 * overwrite the target with the new object and type.
695 if (status
== AE_TYPE
) {
699 return_ACPI_STATUS (status
);