1 /******************************************************************************
3 * Module Name: amconvrt - Object conversion routines
6 *****************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
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.
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.
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
29 #define _COMPONENT ACPI_EXECUTER
30 MODULE_NAME ("amconvrt")
33 /*******************************************************************************
35 * FUNCTION: Acpi_aml_convert_to_integer
37 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
38 * Integer, Buffer, or String
39 * Walk_state - Current method state
43 * DESCRIPTION: Convert an ACPI Object to an integer.
45 ******************************************************************************/
48 acpi_aml_convert_to_integer (
49 ACPI_OPERAND_OBJECT
**obj_desc
,
50 ACPI_WALK_STATE
*walk_state
)
53 ACPI_OPERAND_OBJECT
*ret_desc
;
57 u32 integer_size
= sizeof (ACPI_INTEGER
);
60 switch ((*obj_desc
)->common
.type
) {
61 case ACPI_TYPE_INTEGER
:
64 case ACPI_TYPE_STRING
:
65 pointer
= (*obj_desc
)->string
.pointer
;
66 count
= (*obj_desc
)->string
.length
;
69 case ACPI_TYPE_BUFFER
:
70 pointer
= (char *) (*obj_desc
)->buffer
.pointer
;
71 count
= (*obj_desc
)->buffer
.length
;
79 * Create a new integer
81 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_INTEGER
);
83 return (AE_NO_MEMORY
);
87 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
89 if (walk_state
->method_node
->flags
& ANOBJ_DATA_WIDTH_32
) {
91 * We are running a method that exists in a 32-bit ACPI table.
92 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
94 integer_size
= sizeof (u32
);
99 * Convert the buffer/string to an integer. Note that both buffers and
100 * strings are treated as raw data - we don't convert ascii to hex for
103 * There are two terminating conditions for the loop:
104 * 1) The size of an integer has been reached, or
105 * 2) The end of the buffer or string has been reached
109 /* Transfer no more than an integer's worth of data */
111 if (count
> integer_size
) {
112 count
= integer_size
;
116 * String conversion is different than Buffer conversion
118 switch ((*obj_desc
)->common
.type
) {
119 case ACPI_TYPE_STRING
:
121 /* TBD: Need to use 64-bit STRTOUL */
124 * Convert string to an integer
125 * String must be hexadecimal as per the ACPI specification
128 result
= STRTOUL (pointer
, NULL
, 16);
132 case ACPI_TYPE_BUFFER
:
135 * Buffer conversion - we simply grab enough raw data from the
136 * buffer to fill an integer
138 for (i
= 0; i
< count
; i
++) {
140 * Get next byte and shift it into the Result.
141 * Little endian is used, meaning that the first byte of the buffer
142 * is the LSB of the integer
144 result
|= (((ACPI_INTEGER
) pointer
[i
]) << (i
* 8));
150 /* Save the Result, delete original descriptor, store new descriptor */
152 ret_desc
->integer
.value
= result
;
154 if (walk_state
->opcode
!= AML_STORE_OP
) {
155 acpi_cm_remove_reference (*obj_desc
);
158 *obj_desc
= ret_desc
;
164 /*******************************************************************************
166 * FUNCTION: Acpi_aml_convert_to_buffer
168 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
169 * Integer, Buffer, or String
170 * Walk_state - Current method state
174 * DESCRIPTION: Convert an ACPI Object to an Buffer
176 ******************************************************************************/
179 acpi_aml_convert_to_buffer (
180 ACPI_OPERAND_OBJECT
**obj_desc
,
181 ACPI_WALK_STATE
*walk_state
)
183 ACPI_OPERAND_OBJECT
*ret_desc
;
185 u32 integer_size
= sizeof (ACPI_INTEGER
);
189 switch ((*obj_desc
)->common
.type
) {
190 case ACPI_TYPE_INTEGER
:
193 * Create a new Buffer
195 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_BUFFER
);
197 return (AE_NO_MEMORY
);
200 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
202 if (walk_state
->method_node
->flags
& ANOBJ_DATA_WIDTH_32
) {
204 * We are running a method that exists in a 32-bit ACPI table.
205 * Truncate the value to 32 bits by zeroing out the upper
208 integer_size
= sizeof (u32
);
211 /* Need enough space for one integers */
213 ret_desc
->buffer
.length
= integer_size
;
214 new_buf
= acpi_cm_callocate (integer_size
);
217 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
218 acpi_cm_remove_reference (ret_desc
);
219 return (AE_NO_MEMORY
);
222 /* Copy the integer to the buffer */
224 for (i
= 0; i
< integer_size
; i
++) {
225 new_buf
[i
] = (u8
) ((*obj_desc
)->integer
.value
>> (i
* 8));
227 ret_desc
->buffer
.pointer
= new_buf
;
229 /* Return the new buffer descriptor */
231 if (walk_state
->opcode
!= AML_STORE_OP
) {
232 acpi_cm_remove_reference (*obj_desc
);
234 *obj_desc
= ret_desc
;
238 case ACPI_TYPE_STRING
:
242 case ACPI_TYPE_BUFFER
:
255 /*******************************************************************************
257 * FUNCTION: Acpi_aml_convert_to_string
259 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
260 * Integer, Buffer, or String
261 * Walk_state - Current method state
265 * DESCRIPTION: Convert an ACPI Object to a string
267 ******************************************************************************/
270 acpi_aml_convert_to_string (
271 ACPI_OPERAND_OBJECT
**obj_desc
,
272 ACPI_WALK_STATE
*walk_state
)
274 ACPI_OPERAND_OBJECT
*ret_desc
;
277 u32 integer_size
= sizeof (ACPI_INTEGER
);
282 switch ((*obj_desc
)->common
.type
) {
283 case ACPI_TYPE_INTEGER
:
286 * Create a new String
288 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_STRING
);
290 return (AE_NO_MEMORY
);
293 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
295 if (walk_state
->method_node
->flags
& ANOBJ_DATA_WIDTH_32
) {
297 * We are running a method that exists in a 32-bit ACPI table.
298 * Truncate the value to 32 bits by zeroing out the upper
301 integer_size
= sizeof (u32
);
304 /* Need enough space for one ASCII integer plus null terminator */
306 ret_desc
->string
.length
= (integer_size
* 2) + 1;
307 new_buf
= acpi_cm_callocate (ret_desc
->string
.length
);
310 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
311 acpi_cm_remove_reference (ret_desc
);
312 return (AE_NO_MEMORY
);
315 /* Copy the integer to the buffer */
317 for (i
= 0; i
< (integer_size
* 2); i
++) {
318 new_buf
[i
] = acpi_gbl_hex_to_ascii
[((*obj_desc
)->integer
.value
>> (i
* 4)) & 0xF];
324 ret_desc
->buffer
.pointer
= new_buf
;
326 /* Return the new buffer descriptor */
328 if (walk_state
->opcode
!= AML_STORE_OP
) {
329 acpi_cm_remove_reference (*obj_desc
);
331 *obj_desc
= ret_desc
;
336 case ACPI_TYPE_BUFFER
:
338 if (((*obj_desc
)->buffer
.length
* 3) > ACPI_MAX_STRING_CONVERSION
) {
339 return (AE_AML_STRING_LIMIT
);
343 * Create a new String
345 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_STRING
);
347 return (AE_NO_MEMORY
);
350 /* Need enough space for one ASCII integer plus null terminator */
352 ret_desc
->string
.length
= (*obj_desc
)->buffer
.length
* 3;
353 new_buf
= acpi_cm_callocate (ret_desc
->string
.length
+ 1);
356 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
357 acpi_cm_remove_reference (ret_desc
);
358 return (AE_NO_MEMORY
);
362 * Convert each byte of the buffer to two ASCII characters plus a space.
364 pointer
= (*obj_desc
)->buffer
.pointer
;
366 for (i
= 0; i
< (*obj_desc
)->buffer
.length
; i
++) {
367 new_buf
[index
+ 0] = acpi_gbl_hex_to_ascii
[pointer
[i
] & 0x0F];
368 new_buf
[index
+ 1] = acpi_gbl_hex_to_ascii
[(pointer
[i
] >> 4) & 0x0F];
369 new_buf
[index
+ 2] = ' ';
376 ret_desc
->buffer
.pointer
= new_buf
;
378 /* Return the new buffer descriptor */
380 if (walk_state
->opcode
!= AML_STORE_OP
) {
381 acpi_cm_remove_reference (*obj_desc
);
383 *obj_desc
= ret_desc
;
387 case ACPI_TYPE_STRING
:
400 /*******************************************************************************
402 * FUNCTION: Acpi_aml_convert_to_target_type
404 * PARAMETERS: *Obj_desc - Object to be converted.
405 * Walk_state - Current method state
411 ******************************************************************************/
414 acpi_aml_convert_to_target_type (
415 OBJECT_TYPE_INTERNAL destination_type
,
416 ACPI_OPERAND_OBJECT
**obj_desc
,
417 ACPI_WALK_STATE
*walk_state
)
419 ACPI_STATUS status
= AE_OK
;
423 * If required by the target,
424 * perform implicit conversion on the source before we store it.
427 switch (GET_CURRENT_ARG_TYPE (walk_state
->op_info
->runtime_args
)) {
428 case ARGI_SIMPLE_TARGET
:
429 case ARGI_FIXED_TARGET
:
430 case ARGI_INTEGER_REF
: /* Handles Increment, Decrement cases */
432 switch (destination_type
) {
433 case INTERNAL_TYPE_DEF_FIELD
:
435 * Named field can always handle conversions
440 /* No conversion allowed for these types */
442 if (destination_type
!= (*obj_desc
)->common
.type
) {
451 switch (destination_type
) {
452 case ACPI_TYPE_INTEGER
:
453 case ACPI_TYPE_FIELD_UNIT
:
454 case INTERNAL_TYPE_BANK_FIELD
:
455 case INTERNAL_TYPE_INDEX_FIELD
:
457 * These types require an Integer operand. We can convert
458 * a Buffer or a String to an Integer if necessary.
460 status
= acpi_aml_convert_to_integer (obj_desc
, walk_state
);
464 case ACPI_TYPE_STRING
:
467 * The operand must be a String. We can convert an
468 * Integer or Buffer if necessary
470 status
= acpi_aml_convert_to_string (obj_desc
, walk_state
);
474 case ACPI_TYPE_BUFFER
:
477 * The operand must be a String. We can convert an
478 * Integer or Buffer if necessary
480 status
= acpi_aml_convert_to_buffer (obj_desc
, walk_state
);
488 * Create_xxxx_field cases - we are storing the field object into the name
494 status
= AE_AML_INTERNAL
;
499 * Source-to-Target conversion semantics:
501 * If conversion to the target type cannot be performed, then simply
502 * overwrite the target with the new object and type.
504 if (status
== AE_TYPE
) {