Merge trunk HEAD (46152)
[reactos.git] / drivers / bus / acpi / executer / amconvrt.c
1 /******************************************************************************
2 *
3 * Module Name: amconvrt - Object conversion routines
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 #define _COMPONENT ACPI_EXECUTER
30 MODULE_NAME ("amconvrt")
31
32
33 /*******************************************************************************
34 *
35 * FUNCTION: Acpi_aml_convert_to_integer
36 *
37 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
38 * Integer, Buffer, or String
39 * Walk_state - Current method state
40 *
41 * RETURN: Status
42 *
43 * DESCRIPTION: Convert an ACPI Object to an integer.
44 *
45 ******************************************************************************/
46
47 ACPI_STATUS
48 acpi_aml_convert_to_integer (
49 ACPI_OPERAND_OBJECT **obj_desc,
50 ACPI_WALK_STATE *walk_state)
51 {
52 u32 i;
53 ACPI_OPERAND_OBJECT *ret_desc;
54 u32 count;
55 char *pointer;
56 ACPI_INTEGER result;
57 u32 integer_size = sizeof (ACPI_INTEGER);
58
59
60 switch ((*obj_desc)->common.type) {
61 case ACPI_TYPE_INTEGER:
62 return (AE_OK);
63
64 case ACPI_TYPE_STRING:
65 pointer = (*obj_desc)->string.pointer;
66 count = (*obj_desc)->string.length;
67 break;
68
69 case ACPI_TYPE_BUFFER:
70 pointer = (char *) (*obj_desc)->buffer.pointer;
71 count = (*obj_desc)->buffer.length;
72 break;
73
74 default:
75 return (AE_TYPE);
76 }
77
78 /*
79 * Create a new integer
80 */
81 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
82 if (!ret_desc) {
83 return (AE_NO_MEMORY);
84 }
85
86
87 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
88
89 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
90 /*
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
93 */
94 integer_size = sizeof (u32);
95 }
96
97
98 /*
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
101 * strings.
102 *
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
106 */
107 result = 0;
108
109 /* Transfer no more than an integer's worth of data */
110
111 if (count > integer_size) {
112 count = integer_size;
113 }
114
115 /*
116 * String conversion is different than Buffer conversion
117 */
118 switch ((*obj_desc)->common.type) {
119 case ACPI_TYPE_STRING:
120
121 /* TBD: Need to use 64-bit STRTOUL */
122
123 /*
124 * Convert string to an integer
125 * String must be hexadecimal as per the ACPI specification
126 */
127
128 result = STRTOUL (pointer, NULL, 16);
129 break;
130
131
132 case ACPI_TYPE_BUFFER:
133
134 /*
135 * Buffer conversion - we simply grab enough raw data from the
136 * buffer to fill an integer
137 */
138 for (i = 0; i < count; i++) {
139 /*
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
143 */
144 result |= (((ACPI_INTEGER) pointer[i]) << (i * 8));
145 }
146
147 break;
148 }
149
150 /* Save the Result, delete original descriptor, store new descriptor */
151
152 ret_desc->integer.value = result;
153
154 if (walk_state->opcode != AML_STORE_OP) {
155 acpi_cm_remove_reference (*obj_desc);
156 }
157
158 *obj_desc = ret_desc;
159
160 return (AE_OK);
161 }
162
163
164 /*******************************************************************************
165 *
166 * FUNCTION: Acpi_aml_convert_to_buffer
167 *
168 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
169 * Integer, Buffer, or String
170 * Walk_state - Current method state
171 *
172 * RETURN: Status
173 *
174 * DESCRIPTION: Convert an ACPI Object to an Buffer
175 *
176 ******************************************************************************/
177
178 ACPI_STATUS
179 acpi_aml_convert_to_buffer (
180 ACPI_OPERAND_OBJECT **obj_desc,
181 ACPI_WALK_STATE *walk_state)
182 {
183 ACPI_OPERAND_OBJECT *ret_desc;
184 u32 i;
185 u32 integer_size = sizeof (ACPI_INTEGER);
186 u8 *new_buf;
187
188
189 switch ((*obj_desc)->common.type) {
190 case ACPI_TYPE_INTEGER:
191
192 /*
193 * Create a new Buffer
194 */
195 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_BUFFER);
196 if (!ret_desc) {
197 return (AE_NO_MEMORY);
198 }
199
200 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
201
202 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
203 /*
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
206 * 32-bit field
207 */
208 integer_size = sizeof (u32);
209 }
210
211 /* Need enough space for one integers */
212
213 ret_desc->buffer.length = integer_size;
214 new_buf = acpi_cm_callocate (integer_size);
215 if (!new_buf) {
216 REPORT_ERROR
217 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
218 acpi_cm_remove_reference (ret_desc);
219 return (AE_NO_MEMORY);
220 }
221
222 /* Copy the integer to the buffer */
223
224 for (i = 0; i < integer_size; i++) {
225 new_buf[i] = (u8) ((*obj_desc)->integer.value >> (i * 8));
226 }
227 ret_desc->buffer.pointer = new_buf;
228
229 /* Return the new buffer descriptor */
230
231 if (walk_state->opcode != AML_STORE_OP) {
232 acpi_cm_remove_reference (*obj_desc);
233 }
234 *obj_desc = ret_desc;
235 break;
236
237
238 case ACPI_TYPE_STRING:
239 break;
240
241
242 case ACPI_TYPE_BUFFER:
243 break;
244
245
246 default:
247 return (AE_TYPE);
248 break;
249 }
250
251 return (AE_OK);
252 }
253
254
255 /*******************************************************************************
256 *
257 * FUNCTION: Acpi_aml_convert_to_string
258 *
259 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
260 * Integer, Buffer, or String
261 * Walk_state - Current method state
262 *
263 * RETURN: Status
264 *
265 * DESCRIPTION: Convert an ACPI Object to a string
266 *
267 ******************************************************************************/
268
269 ACPI_STATUS
270 acpi_aml_convert_to_string (
271 ACPI_OPERAND_OBJECT **obj_desc,
272 ACPI_WALK_STATE *walk_state)
273 {
274 ACPI_OPERAND_OBJECT *ret_desc;
275 u32 i;
276 u32 index;
277 u32 integer_size = sizeof (ACPI_INTEGER);
278 u8 *new_buf;
279 u8 *pointer;
280
281
282 switch ((*obj_desc)->common.type) {
283 case ACPI_TYPE_INTEGER:
284
285 /*
286 * Create a new String
287 */
288 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
289 if (!ret_desc) {
290 return (AE_NO_MEMORY);
291 }
292
293 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
294
295 if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
296 /*
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
299 * 32-bit field
300 */
301 integer_size = sizeof (u32);
302 }
303
304 /* Need enough space for one ASCII integer plus null terminator */
305
306 ret_desc->string.length = (integer_size * 2) + 1;
307 new_buf = acpi_cm_callocate (ret_desc->string.length);
308 if (!new_buf) {
309 REPORT_ERROR
310 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
311 acpi_cm_remove_reference (ret_desc);
312 return (AE_NO_MEMORY);
313 }
314
315 /* Copy the integer to the buffer */
316
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];
319 }
320
321 /* Null terminate */
322
323 new_buf [i] = 0;
324 ret_desc->buffer.pointer = new_buf;
325
326 /* Return the new buffer descriptor */
327
328 if (walk_state->opcode != AML_STORE_OP) {
329 acpi_cm_remove_reference (*obj_desc);
330 }
331 *obj_desc = ret_desc;
332
333 return (AE_OK);
334
335
336 case ACPI_TYPE_BUFFER:
337
338 if (((*obj_desc)->buffer.length * 3) > ACPI_MAX_STRING_CONVERSION) {
339 return (AE_AML_STRING_LIMIT);
340 }
341
342 /*
343 * Create a new String
344 */
345 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_STRING);
346 if (!ret_desc) {
347 return (AE_NO_MEMORY);
348 }
349
350 /* Need enough space for one ASCII integer plus null terminator */
351
352 ret_desc->string.length = (*obj_desc)->buffer.length * 3;
353 new_buf = acpi_cm_callocate (ret_desc->string.length + 1);
354 if (!new_buf) {
355 REPORT_ERROR
356 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
357 acpi_cm_remove_reference (ret_desc);
358 return (AE_NO_MEMORY);
359 }
360
361 /*
362 * Convert each byte of the buffer to two ASCII characters plus a space.
363 */
364 pointer = (*obj_desc)->buffer.pointer;
365 index = 0;
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] = ' ';
370 index += 3;
371 }
372
373 /* Null terminate */
374
375 new_buf [index] = 0;
376 ret_desc->buffer.pointer = new_buf;
377
378 /* Return the new buffer descriptor */
379
380 if (walk_state->opcode != AML_STORE_OP) {
381 acpi_cm_remove_reference (*obj_desc);
382 }
383 *obj_desc = ret_desc;
384 break;
385
386
387 case ACPI_TYPE_STRING:
388 break;
389
390
391 default:
392 return (AE_TYPE);
393 break;
394 }
395
396 return (AE_OK);
397 }
398
399
400 /*******************************************************************************
401 *
402 * FUNCTION: Acpi_aml_convert_to_target_type
403 *
404 * PARAMETERS: *Obj_desc - Object to be converted.
405 * Walk_state - Current method state
406 *
407 * RETURN: Status
408 *
409 * DESCRIPTION:
410 *
411 ******************************************************************************/
412
413 ACPI_STATUS
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)
418 {
419 ACPI_STATUS status = AE_OK;
420
421
422 /*
423 * If required by the target,
424 * perform implicit conversion on the source before we store it.
425 */
426
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 */
431
432 switch (destination_type) {
433 case INTERNAL_TYPE_DEF_FIELD:
434 /*
435 * Named field can always handle conversions
436 */
437 break;
438
439 default:
440 /* No conversion allowed for these types */
441
442 if (destination_type != (*obj_desc)->common.type) {
443 status = AE_TYPE;
444 }
445 }
446 break;
447
448
449 case ARGI_TARGETREF:
450
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:
456 /*
457 * These types require an Integer operand. We can convert
458 * a Buffer or a String to an Integer if necessary.
459 */
460 status = acpi_aml_convert_to_integer (obj_desc, walk_state);
461 break;
462
463
464 case ACPI_TYPE_STRING:
465
466 /*
467 * The operand must be a String. We can convert an
468 * Integer or Buffer if necessary
469 */
470 status = acpi_aml_convert_to_string (obj_desc, walk_state);
471 break;
472
473
474 case ACPI_TYPE_BUFFER:
475
476 /*
477 * The operand must be a String. We can convert an
478 * Integer or Buffer if necessary
479 */
480 status = acpi_aml_convert_to_buffer (obj_desc, walk_state);
481 break;
482 }
483 break;
484
485
486 case ARGI_REFERENCE:
487 /*
488 * Create_xxxx_field cases - we are storing the field object into the name
489 */
490 break;
491
492
493 default:
494 status = AE_AML_INTERNAL;
495 }
496
497
498 /*
499 * Source-to-Target conversion semantics:
500 *
501 * If conversion to the target type cannot be performed, then simply
502 * overwrite the target with the new object and type.
503 */
504 if (status == AE_TYPE) {
505 status = AE_OK;
506 }
507
508 return (status);
509 }
510
511