File: /usr/src/linux/drivers/acpi/executer/exconvrt.c
1 /******************************************************************************
2 *
3 * Module Name: exconvrt - Object conversion routines
4 * $Revision: 22 $
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 #include "acparser.h"
29 #include "acnamesp.h"
30 #include "acinterp.h"
31 #include "acevents.h"
32 #include "amlcode.h"
33 #include "acdispat.h"
34
35
36 #define _COMPONENT ACPI_EXECUTER
37 MODULE_NAME ("exconvrt")
38
39
40 /*******************************************************************************
41 *
42 * FUNCTION: Acpi_ex_convert_to_integer
43 *
44 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
45 * Integer, Buffer, or String
46 * Walk_state - Current method state
47 *
48 * RETURN: Status
49 *
50 * DESCRIPTION: Convert an ACPI Object to an integer.
51 *
52 ******************************************************************************/
53
54 acpi_status
55 acpi_ex_convert_to_integer (
56 acpi_operand_object *obj_desc,
57 acpi_operand_object **result_desc,
58 acpi_walk_state *walk_state)
59 {
60 u32 i;
61 acpi_operand_object *ret_desc;
62 u32 count;
63 char *pointer;
64 acpi_integer result;
65 u32 integer_size = sizeof (acpi_integer);
66
67
68 FUNCTION_ENTRY ();
69
70
71 switch (obj_desc->common.type) {
72 case ACPI_TYPE_INTEGER:
73 *result_desc = obj_desc;
74 return (AE_OK);
75
76 case ACPI_TYPE_STRING:
77 pointer = obj_desc->string.pointer;
78 count = obj_desc->string.length;
79 break;
80
81 case ACPI_TYPE_BUFFER:
82 pointer = (char *) obj_desc->buffer.pointer;
83 count = obj_desc->buffer.length;
84 break;
85
86 default:
87 return (AE_TYPE);
88 }
89
90 /*
91 * Create a new integer
92 */
93 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
94 if (!ret_desc) {
95 return (AE_NO_MEMORY);
96 }
97
98
99 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
100
101 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
102 /*
103 * We are running a method that exists in a 32-bit ACPI table.
104 * Truncate the value to 32 bits by zeroing out the upper 32-bit field
105 */
106 integer_size = sizeof (u32);
107 }
108
109
110 /*
111 * Convert the buffer/string to an integer. Note that both buffers and
112 * strings are treated as raw data - we don't convert ascii to hex for
113 * strings.
114 *
115 * There are two terminating conditions for the loop:
116 * 1) The size of an integer has been reached, or
117 * 2) The end of the buffer or string has been reached
118 */
119 result = 0;
120
121 /* Transfer no more than an integer's worth of data */
122
123 if (count > integer_size) {
124 count = integer_size;
125 }
126
127 /*
128 * String conversion is different than Buffer conversion
129 */
130 switch (obj_desc->common.type) {
131 case ACPI_TYPE_STRING:
132
133 /* TBD: Need to use 64-bit STRTOUL */
134
135 /*
136 * Convert string to an integer
137 * String must be hexadecimal as per the ACPI specification
138 */
139 result = STRTOUL (pointer, NULL, 16);
140 break;
141
142
143 case ACPI_TYPE_BUFFER:
144
145 /*
146 * Buffer conversion - we simply grab enough raw data from the
147 * buffer to fill an integer
148 */
149 for (i = 0; i < count; i++) {
150 /*
151 * Get next byte and shift it into the Result.
152 * Little endian is used, meaning that the first byte of the buffer
153 * is the LSB of the integer
154 */
155 result |= (((acpi_integer) pointer[i]) << (i * 8));
156 }
157
158 break;
159 }
160
161 /* Save the Result, delete original descriptor, store new descriptor */
162
163 ret_desc->integer.value = result;
164
165 if (*result_desc == obj_desc) {
166 if (walk_state->opcode != AML_STORE_OP) {
167 acpi_ut_remove_reference (obj_desc);
168 }
169 }
170
171 *result_desc = ret_desc;
172 return (AE_OK);
173 }
174
175
176 /*******************************************************************************
177 *
178 * FUNCTION: Acpi_ex_convert_to_buffer
179 *
180 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
181 * Integer, Buffer, or String
182 * Walk_state - Current method state
183 *
184 * RETURN: Status
185 *
186 * DESCRIPTION: Convert an ACPI Object to an Buffer
187 *
188 ******************************************************************************/
189
190 acpi_status
191 acpi_ex_convert_to_buffer (
192 acpi_operand_object *obj_desc,
193 acpi_operand_object **result_desc,
194 acpi_walk_state *walk_state)
195 {
196 acpi_operand_object *ret_desc;
197 u32 i;
198 u32 integer_size = sizeof (acpi_integer);
199 u8 *new_buf;
200
201
202 FUNCTION_ENTRY ();
203
204
205 switch (obj_desc->common.type) {
206 case ACPI_TYPE_INTEGER:
207
208 /*
209 * Create a new Buffer
210 */
211 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
212 if (!ret_desc) {
213 return (AE_NO_MEMORY);
214 }
215
216 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
217
218 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
219 /*
220 * We are running a method that exists in a 32-bit ACPI table.
221 * Truncate the value to 32 bits by zeroing out the upper
222 * 32-bit field
223 */
224 integer_size = sizeof (u32);
225 }
226
227 /* Need enough space for one integers */
228
229 ret_desc->buffer.length = integer_size;
230 new_buf = ACPI_MEM_CALLOCATE (integer_size);
231 if (!new_buf) {
232 REPORT_ERROR
233 (("Ex_dyadic2_r/Concat_op: Buffer allocation failure\n"));
234 acpi_ut_remove_reference (ret_desc);
235 return (AE_NO_MEMORY);
236 }
237
238 /* Copy the integer to the buffer */
239
240 for (i = 0; i < integer_size; i++) {
241 new_buf[i] = (u8) (obj_desc->integer.value >> (i * 8));
242 }
243 ret_desc->buffer.pointer = new_buf;
244
245 /* Return the new buffer descriptor */
246
247 if (*result_desc == obj_desc) {
248 if (walk_state->opcode != AML_STORE_OP) {
249 acpi_ut_remove_reference (obj_desc);
250 }
251 }
252
253 *result_desc = ret_desc;
254 break;
255
256
257 case ACPI_TYPE_STRING:
258 *result_desc = obj_desc;
259 break;
260
261
262 case ACPI_TYPE_BUFFER:
263 *result_desc = obj_desc;
264 break;
265
266
267 default:
268 return (AE_TYPE);
269 break;
270 }
271
272 return (AE_OK);
273 }
274
275
276 /*******************************************************************************
277 *
278 * FUNCTION: Acpi_ex_convert_ascii
279 *
280 * PARAMETERS: Integer
281 *
282 * RETURN: Actual string length
283 *
284 * DESCRIPTION: Convert an ACPI Integer to a hex string
285 *
286 ******************************************************************************/
287
288 u32
289 acpi_ex_convert_to_ascii (
290 acpi_integer integer,
291 u32 base,
292 u8 *string)
293 {
294 u32 i;
295 u32 j;
296 u32 k = 0;
297 u8 hex_digit;
298 acpi_integer digit;
299 u8 leading_zero = TRUE;
300 u32 length = sizeof (acpi_integer);
301
302
303 FUNCTION_ENTRY ();
304
305
306 switch (base) {
307 case 10:
308
309 for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0 ; i--) {
310 /* Divide by nth factor of 10 */
311
312 digit = integer;
313 for (j = 1; j < i; j++) {
314 digit = ACPI_DIVIDE (digit, 10);
315 }
316
317 /* Create the decimal digit */
318
319 if (digit != 0) {
320 leading_zero = FALSE;
321 }
322
323 if (!leading_zero) {
324 string[k] = (u8) (ASCII_ZERO + ACPI_MODULO (digit, 10));
325 k++;
326 }
327 }
328 break;
329
330 case 16:
331
332 /* Copy the integer to the buffer */
333
334 for (i = 0, j = ((length * 2) -1); i < (length * 2); i++, j--) {
335
336 hex_digit = acpi_ut_hex_to_ascii_char (integer, (j * 4));
337 if (hex_digit != ASCII_ZERO) {
338 leading_zero = FALSE;
339 }
340
341 if (!leading_zero) {
342 string[k] = hex_digit;
343 k++;
344 }
345 }
346 break;
347
348 default:
349 break;
350 }
351
352 /*
353 * Since leading zeros are supressed, we must check for the case where
354 * the integer equals 0.
355 *
356 * Finally, null terminate the string and return the length
357 */
358 if (!k) {
359 string [0] = ASCII_ZERO;
360 k = 1;
361 }
362 string [k] = 0;
363
364 return (k);
365 }
366
367
368 /*******************************************************************************
369 *
370 * FUNCTION: Acpi_ex_convert_to_string
371 *
372 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
373 * Integer, Buffer, or String
374 * Walk_state - Current method state
375 *
376 * RETURN: Status
377 *
378 * DESCRIPTION: Convert an ACPI Object to a string
379 *
380 ******************************************************************************/
381
382 acpi_status
383 acpi_ex_convert_to_string (
384 acpi_operand_object *obj_desc,
385 acpi_operand_object **result_desc,
386 u32 base,
387 u32 max_length,
388 acpi_walk_state *walk_state)
389 {
390 acpi_operand_object *ret_desc;
391 u32 i;
392 u32 index;
393 u32 string_length;
394 u32 integer_size = sizeof (acpi_integer);
395 u8 *new_buf;
396 u8 *pointer;
397
398
399 FUNCTION_ENTRY ();
400
401
402 switch (obj_desc->common.type) {
403 case ACPI_TYPE_INTEGER:
404
405 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
406
407 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
408 /*
409 * We are running a method that exists in a 32-bit ACPI table.
410 * Truncate the value to 32 bits by zeroing out the upper
411 * 32-bit field
412 */
413 integer_size = sizeof (u32);
414 }
415
416 string_length = integer_size * 2;
417 if (base == 10) {
418 string_length = ACPI_MAX_DECIMAL_DIGITS;
419 }
420
421 /*
422 * Create a new String
423 */
424 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
425 if (!ret_desc) {
426 return (AE_NO_MEMORY);
427 }
428
429 /* Need enough space for one ASCII integer plus null terminator */
430
431 new_buf = ACPI_MEM_CALLOCATE (string_length + 1);
432 if (!new_buf) {
433 REPORT_ERROR
434 (("Ex_convert_to_string: Buffer allocation failure\n"));
435 acpi_ut_remove_reference (ret_desc);
436 return (AE_NO_MEMORY);
437 }
438
439
440 /* Convert */
441
442 i = acpi_ex_convert_to_ascii (obj_desc->integer.value, base, new_buf);
443
444 /* Null terminate at the correct place */
445
446 if (max_length < i) {
447 new_buf[max_length] = 0;
448 ret_desc->string.length = max_length;
449 }
450 else {
451 new_buf [i] = 0;
452 ret_desc->string.length = i;
453 }
454
455 ret_desc->buffer.pointer = new_buf;
456
457 /* Return the new buffer descriptor */
458
459 if (*result_desc == obj_desc) {
460 if (walk_state->opcode != AML_STORE_OP) {
461 acpi_ut_remove_reference (obj_desc);
462 }
463 }
464
465 *result_desc = ret_desc;
466 break;
467
468
469 case ACPI_TYPE_BUFFER:
470
471 string_length = obj_desc->buffer.length * 3;
472 if (base == 10) {
473 string_length = obj_desc->buffer.length * 4;
474 }
475
476 if (max_length > ACPI_MAX_STRING_CONVERSION) {
477 if (string_length > ACPI_MAX_STRING_CONVERSION) {
478 return (AE_AML_STRING_LIMIT);
479 }
480 }
481
482 /*
483 * Create a new string object
484 */
485 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
486 if (!ret_desc) {
487 return (AE_NO_MEMORY);
488 }
489
490 /* String length is the lesser of the Max or the actual length */
491
492 if (max_length < string_length) {
493 string_length = max_length;
494 }
495
496 new_buf = ACPI_MEM_CALLOCATE (string_length + 1);
497 if (!new_buf) {
498 REPORT_ERROR
499 (("Ex_convert_to_string: Buffer allocation failure\n"));
500 acpi_ut_remove_reference (ret_desc);
501 return (AE_NO_MEMORY);
502 }
503
504 /*
505 * Convert each byte of the buffer to two ASCII characters plus a space.
506 */
507 pointer = obj_desc->buffer.pointer;
508 index = 0;
509 for (i = 0, index = 0; i < obj_desc->buffer.length; i++) {
510 index = acpi_ex_convert_to_ascii (pointer[i], base, &new_buf[index]);
511
512 new_buf[index] = ' ';
513 index++;
514 }
515
516 /* Null terminate */
517
518 new_buf [index-1] = 0;
519 ret_desc->buffer.pointer = new_buf;
520 ret_desc->string.length = STRLEN ((char *) new_buf);
521
522
523 /* Return the new buffer descriptor */
524
525 if (*result_desc == obj_desc) {
526 if (walk_state->opcode != AML_STORE_OP) {
527 acpi_ut_remove_reference (obj_desc);
528 }
529 }
530
531 *result_desc = ret_desc;
532 break;
533
534
535 case ACPI_TYPE_STRING:
536
537 if (max_length >= obj_desc->string.length) {
538 *result_desc = obj_desc;
539 }
540
541 else {
542 /* Must copy the string first and then truncate it */
543
544 return (AE_NOT_IMPLEMENTED);
545 }
546 break;
547
548
549 default:
550 return (AE_TYPE);
551 break;
552 }
553
554 return (AE_OK);
555 }
556
557
558 /*******************************************************************************
559 *
560 * FUNCTION: Acpi_ex_convert_to_target_type
561 *
562 * PARAMETERS: *Obj_desc - Object to be converted.
563 * Walk_state - Current method state
564 *
565 * RETURN: Status
566 *
567 * DESCRIPTION:
568 *
569 ******************************************************************************/
570
571 acpi_status
572 acpi_ex_convert_to_target_type (
573 acpi_object_type8 destination_type,
574 acpi_operand_object **obj_desc,
575 acpi_walk_state *walk_state)
576 {
577 acpi_status status = AE_OK;
578
579
580 FUNCTION_TRACE ("Ex_convert_to_target_type");
581
582
583 /*
584 * If required by the target,
585 * perform implicit conversion on the source before we store it.
586 */
587 switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) {
588 case ARGI_SIMPLE_TARGET:
589 case ARGI_FIXED_TARGET:
590 case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
591
592 switch (destination_type) {
593 case INTERNAL_TYPE_REGION_FIELD:
594 /*
595 * Named field can always handle conversions
596 */
597 break;
598
599 default:
600 /* No conversion allowed for these types */
601
602 if (destination_type != (*obj_desc)->common.type) {
603 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
604 "Target does not allow conversion of type %s to %s\n",
605 acpi_ut_get_type_name ((*obj_desc)->common.type),
606 acpi_ut_get_type_name (destination_type)));
607 status = AE_TYPE;
608 }
609 }
610 break;
611
612
613 case ARGI_TARGETREF:
614
615 switch (destination_type) {
616 case ACPI_TYPE_INTEGER:
617 case ACPI_TYPE_BUFFER_FIELD:
618 case INTERNAL_TYPE_BANK_FIELD:
619 case INTERNAL_TYPE_INDEX_FIELD:
620 /*
621 * These types require an Integer operand. We can convert
622 * a Buffer or a String to an Integer if necessary.
623 */
624 status = acpi_ex_convert_to_integer (*obj_desc, obj_desc, walk_state);
625 break;
626
627
628 case ACPI_TYPE_STRING:
629
630 /*
631 * The operand must be a String. We can convert an
632 * Integer or Buffer if necessary
633 */
634 status = acpi_ex_convert_to_string (*obj_desc, obj_desc, 16, ACPI_UINT32_MAX, walk_state);
635 break;
636
637
638 case ACPI_TYPE_BUFFER:
639
640 /*
641 * The operand must be a String. We can convert an
642 * Integer or Buffer if necessary
643 */
644 status = acpi_ex_convert_to_buffer (*obj_desc, obj_desc, walk_state);
645 break;
646 }
647 break;
648
649
650 case ARGI_REFERENCE:
651 /*
652 * Create_xxxx_field cases - we are storing the field object into the name
653 */
654 break;
655
656
657 default:
658 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
659 "Unknown Target type ID 0x%X Op %s Dest_type %s\n",
660 GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
661 walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
662
663 status = AE_AML_INTERNAL;
664 }
665
666
667 /*
668 * Source-to-Target conversion semantics:
669 *
670 * If conversion to the target type cannot be performed, then simply
671 * overwrite the target with the new object and type.
672 */
673 if (status == AE_TYPE) {
674 status = AE_OK;
675 }
676
677 return_ACPI_STATUS (status);
678 }
679
680
681