1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Module Name: exconvrt - Object conversion routines |
5 | * |
6 | * Copyright (C) 2000 - 2023, Intel Corp. |
7 | * |
8 | *****************************************************************************/ |
9 | |
10 | #include <acpi/acpi.h> |
11 | #include "accommon.h" |
12 | #include "acinterp.h" |
13 | #include "amlcode.h" |
14 | |
15 | #define _COMPONENT ACPI_EXECUTER |
16 | ACPI_MODULE_NAME("exconvrt" ) |
17 | |
18 | /* Local prototypes */ |
19 | static u32 |
20 | acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length); |
21 | |
22 | /******************************************************************************* |
23 | * |
24 | * FUNCTION: acpi_ex_convert_to_integer |
25 | * |
26 | * PARAMETERS: obj_desc - Object to be converted. Must be an |
27 | * Integer, Buffer, or String |
28 | * result_desc - Where the new Integer object is returned |
29 | * implicit_conversion - Used for string conversion |
30 | * |
31 | * RETURN: Status |
32 | * |
33 | * DESCRIPTION: Convert an ACPI Object to an integer. |
34 | * |
35 | ******************************************************************************/ |
36 | |
37 | acpi_status |
38 | acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, |
39 | union acpi_operand_object **result_desc, |
40 | u32 implicit_conversion) |
41 | { |
42 | union acpi_operand_object *return_desc; |
43 | u8 *pointer; |
44 | u64 result; |
45 | u32 i; |
46 | u32 count; |
47 | |
48 | ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); |
49 | |
50 | switch (obj_desc->common.type) { |
51 | case ACPI_TYPE_INTEGER: |
52 | |
53 | /* No conversion necessary */ |
54 | |
55 | *result_desc = obj_desc; |
56 | return_ACPI_STATUS(AE_OK); |
57 | |
58 | case ACPI_TYPE_BUFFER: |
59 | case ACPI_TYPE_STRING: |
60 | |
61 | /* Note: Takes advantage of common buffer/string fields */ |
62 | |
63 | pointer = obj_desc->buffer.pointer; |
64 | count = obj_desc->buffer.length; |
65 | break; |
66 | |
67 | default: |
68 | |
69 | return_ACPI_STATUS(AE_TYPE); |
70 | } |
71 | |
72 | /* |
73 | * Convert the buffer/string to an integer. Note that both buffers and |
74 | * strings are treated as raw data - we don't convert ascii to hex for |
75 | * strings. |
76 | * |
77 | * There are two terminating conditions for the loop: |
78 | * 1) The size of an integer has been reached, or |
79 | * 2) The end of the buffer or string has been reached |
80 | */ |
81 | result = 0; |
82 | |
83 | /* String conversion is different than Buffer conversion */ |
84 | |
85 | switch (obj_desc->common.type) { |
86 | case ACPI_TYPE_STRING: |
87 | /* |
88 | * Convert string to an integer - for most cases, the string must be |
89 | * hexadecimal as per the ACPI specification. The only exception (as |
90 | * of ACPI 3.0) is that the to_integer() operator allows both decimal |
91 | * and hexadecimal strings (hex prefixed with "0x"). |
92 | * |
93 | * Explicit conversion is used only by to_integer. |
94 | * All other string-to-integer conversions are implicit conversions. |
95 | */ |
96 | if (implicit_conversion) { |
97 | result = |
98 | acpi_ut_implicit_strtoul64(ACPI_CAST_PTR |
99 | (char, pointer)); |
100 | } else { |
101 | result = |
102 | acpi_ut_explicit_strtoul64(ACPI_CAST_PTR |
103 | (char, pointer)); |
104 | } |
105 | break; |
106 | |
107 | case ACPI_TYPE_BUFFER: |
108 | |
109 | /* Check for zero-length buffer */ |
110 | |
111 | if (!count) { |
112 | return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); |
113 | } |
114 | |
115 | /* Transfer no more than an integer's worth of data */ |
116 | |
117 | if (count > acpi_gbl_integer_byte_width) { |
118 | count = acpi_gbl_integer_byte_width; |
119 | } |
120 | |
121 | /* |
122 | * Convert buffer to an integer - we simply grab enough raw data |
123 | * from the buffer to fill an integer |
124 | */ |
125 | for (i = 0; i < count; i++) { |
126 | /* |
127 | * Get next byte and shift it into the Result. |
128 | * Little endian is used, meaning that the first byte of the buffer |
129 | * is the LSB of the integer |
130 | */ |
131 | result |= (((u64) pointer[i]) << (i * 8)); |
132 | } |
133 | break; |
134 | |
135 | default: |
136 | |
137 | /* No other types can get here */ |
138 | |
139 | break; |
140 | } |
141 | |
142 | /* Create a new integer */ |
143 | |
144 | return_desc = acpi_ut_create_integer_object(value: result); |
145 | if (!return_desc) { |
146 | return_ACPI_STATUS(AE_NO_MEMORY); |
147 | } |
148 | |
149 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n" , |
150 | ACPI_FORMAT_UINT64(result))); |
151 | |
152 | /* Save the Result */ |
153 | |
154 | (void)acpi_ex_truncate_for32bit_table(obj_desc: return_desc); |
155 | *result_desc = return_desc; |
156 | return_ACPI_STATUS(AE_OK); |
157 | } |
158 | |
159 | /******************************************************************************* |
160 | * |
161 | * FUNCTION: acpi_ex_convert_to_buffer |
162 | * |
163 | * PARAMETERS: obj_desc - Object to be converted. Must be an |
164 | * Integer, Buffer, or String |
165 | * result_desc - Where the new buffer object is returned |
166 | * |
167 | * RETURN: Status |
168 | * |
169 | * DESCRIPTION: Convert an ACPI Object to a Buffer |
170 | * |
171 | ******************************************************************************/ |
172 | |
173 | acpi_status |
174 | acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, |
175 | union acpi_operand_object **result_desc) |
176 | { |
177 | union acpi_operand_object *return_desc; |
178 | u8 *new_buf; |
179 | |
180 | ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc); |
181 | |
182 | switch (obj_desc->common.type) { |
183 | case ACPI_TYPE_BUFFER: |
184 | |
185 | /* No conversion necessary */ |
186 | |
187 | *result_desc = obj_desc; |
188 | return_ACPI_STATUS(AE_OK); |
189 | |
190 | case ACPI_TYPE_INTEGER: |
191 | /* |
192 | * Create a new Buffer object. |
193 | * Need enough space for one integer |
194 | */ |
195 | return_desc = |
196 | acpi_ut_create_buffer_object(buffer_size: acpi_gbl_integer_byte_width); |
197 | if (!return_desc) { |
198 | return_ACPI_STATUS(AE_NO_MEMORY); |
199 | } |
200 | |
201 | /* Copy the integer to the buffer, LSB first */ |
202 | |
203 | new_buf = return_desc->buffer.pointer; |
204 | memcpy(new_buf, &obj_desc->integer.value, |
205 | acpi_gbl_integer_byte_width); |
206 | break; |
207 | |
208 | case ACPI_TYPE_STRING: |
209 | /* |
210 | * Create a new Buffer object |
211 | * Size will be the string length |
212 | * |
213 | * NOTE: Add one to the string length to include the null terminator. |
214 | * The ACPI spec is unclear on this subject, but there is existing |
215 | * ASL/AML code that depends on the null being transferred to the new |
216 | * buffer. |
217 | */ |
218 | return_desc = acpi_ut_create_buffer_object(buffer_size: (acpi_size) |
219 | obj_desc->string. |
220 | length + 1); |
221 | if (!return_desc) { |
222 | return_ACPI_STATUS(AE_NO_MEMORY); |
223 | } |
224 | |
225 | /* Copy the string to the buffer */ |
226 | |
227 | new_buf = return_desc->buffer.pointer; |
228 | strncpy(p: (char *)new_buf, q: (char *)obj_desc->string.pointer, |
229 | size: obj_desc->string.length); |
230 | break; |
231 | |
232 | default: |
233 | |
234 | return_ACPI_STATUS(AE_TYPE); |
235 | } |
236 | |
237 | /* Mark buffer initialized */ |
238 | |
239 | return_desc->common.flags |= AOPOBJ_DATA_VALID; |
240 | *result_desc = return_desc; |
241 | return_ACPI_STATUS(AE_OK); |
242 | } |
243 | |
244 | /******************************************************************************* |
245 | * |
246 | * FUNCTION: acpi_ex_convert_to_ascii |
247 | * |
248 | * PARAMETERS: integer - Value to be converted |
249 | * base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX |
250 | * string - Where the string is returned |
251 | * data_width - Size of data item to be converted, in bytes |
252 | * |
253 | * RETURN: Actual string length |
254 | * |
255 | * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string |
256 | * |
257 | ******************************************************************************/ |
258 | |
259 | static u32 |
260 | acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width) |
261 | { |
262 | u64 digit; |
263 | u32 i; |
264 | u32 j; |
265 | u32 k = 0; |
266 | u32 hex_length; |
267 | u32 decimal_length; |
268 | u32 remainder; |
269 | u8 supress_zeros; |
270 | |
271 | ACPI_FUNCTION_ENTRY(); |
272 | |
273 | switch (base) { |
274 | case 10: |
275 | |
276 | /* Setup max length for the decimal number */ |
277 | |
278 | switch (data_width) { |
279 | case 1: |
280 | |
281 | decimal_length = ACPI_MAX8_DECIMAL_DIGITS; |
282 | break; |
283 | |
284 | case 4: |
285 | |
286 | decimal_length = ACPI_MAX32_DECIMAL_DIGITS; |
287 | break; |
288 | |
289 | case 8: |
290 | default: |
291 | |
292 | decimal_length = ACPI_MAX64_DECIMAL_DIGITS; |
293 | break; |
294 | } |
295 | |
296 | supress_zeros = TRUE; /* No leading zeros */ |
297 | remainder = 0; |
298 | |
299 | for (i = decimal_length; i > 0; i--) { |
300 | |
301 | /* Divide by nth factor of 10 */ |
302 | |
303 | digit = integer; |
304 | for (j = 0; j < i; j++) { |
305 | (void)acpi_ut_short_divide(in_dividend: digit, divisor: 10, out_quotient: &digit, |
306 | out_remainder: &remainder); |
307 | } |
308 | |
309 | /* Handle leading zeros */ |
310 | |
311 | if (remainder != 0) { |
312 | supress_zeros = FALSE; |
313 | } |
314 | |
315 | if (!supress_zeros) { |
316 | string[k] = (u8) (ACPI_ASCII_ZERO + remainder); |
317 | k++; |
318 | } |
319 | } |
320 | break; |
321 | |
322 | case 16: |
323 | |
324 | /* hex_length: 2 ascii hex chars per data byte */ |
325 | |
326 | hex_length = (data_width * 2); |
327 | for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) { |
328 | |
329 | /* Get one hex digit, most significant digits first */ |
330 | |
331 | string[k] = (u8) |
332 | acpi_ut_hex_to_ascii_char(integer, ACPI_MUL_4(j)); |
333 | k++; |
334 | } |
335 | break; |
336 | |
337 | default: |
338 | return (0); |
339 | } |
340 | |
341 | /* |
342 | * Since leading zeros are suppressed, we must check for the case where |
343 | * the integer equals 0 |
344 | * |
345 | * Finally, null terminate the string and return the length |
346 | */ |
347 | if (!k) { |
348 | string[0] = ACPI_ASCII_ZERO; |
349 | k = 1; |
350 | } |
351 | |
352 | string[k] = 0; |
353 | return ((u32) k); |
354 | } |
355 | |
356 | /******************************************************************************* |
357 | * |
358 | * FUNCTION: acpi_ex_convert_to_string |
359 | * |
360 | * PARAMETERS: obj_desc - Object to be converted. Must be an |
361 | * Integer, Buffer, or String |
362 | * result_desc - Where the string object is returned |
363 | * type - String flags (base and conversion type) |
364 | * |
365 | * RETURN: Status |
366 | * |
367 | * DESCRIPTION: Convert an ACPI Object to a string. Supports both implicit |
368 | * and explicit conversions and related rules. |
369 | * |
370 | ******************************************************************************/ |
371 | |
372 | acpi_status |
373 | acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, |
374 | union acpi_operand_object ** result_desc, u32 type) |
375 | { |
376 | union acpi_operand_object *return_desc; |
377 | u8 *new_buf; |
378 | u32 i; |
379 | u32 string_length = 0; |
380 | u16 base = 16; |
381 | u8 separator = ','; |
382 | |
383 | ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc); |
384 | |
385 | switch (obj_desc->common.type) { |
386 | case ACPI_TYPE_STRING: |
387 | |
388 | /* No conversion necessary */ |
389 | |
390 | *result_desc = obj_desc; |
391 | return_ACPI_STATUS(AE_OK); |
392 | |
393 | case ACPI_TYPE_INTEGER: |
394 | |
395 | switch (type) { |
396 | case ACPI_EXPLICIT_CONVERT_DECIMAL: |
397 | /* |
398 | * From to_decimal_string, integer source. |
399 | * |
400 | * Make room for the maximum decimal number size |
401 | */ |
402 | string_length = ACPI_MAX_DECIMAL_DIGITS; |
403 | base = 10; |
404 | break; |
405 | |
406 | default: |
407 | |
408 | /* Two hex string characters for each integer byte */ |
409 | |
410 | string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width); |
411 | break; |
412 | } |
413 | |
414 | /* |
415 | * Create a new String |
416 | * Need enough space for one ASCII integer (plus null terminator) |
417 | */ |
418 | return_desc = |
419 | acpi_ut_create_string_object(string_size: (acpi_size)string_length); |
420 | if (!return_desc) { |
421 | return_ACPI_STATUS(AE_NO_MEMORY); |
422 | } |
423 | |
424 | new_buf = return_desc->buffer.pointer; |
425 | |
426 | /* Convert integer to string */ |
427 | |
428 | string_length = |
429 | acpi_ex_convert_to_ascii(integer: obj_desc->integer.value, base, |
430 | string: new_buf, |
431 | data_width: acpi_gbl_integer_byte_width); |
432 | |
433 | /* Null terminate at the correct place */ |
434 | |
435 | return_desc->string.length = string_length; |
436 | new_buf[string_length] = 0; |
437 | break; |
438 | |
439 | case ACPI_TYPE_BUFFER: |
440 | |
441 | /* Setup string length, base, and separator */ |
442 | |
443 | switch (type) { |
444 | case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */ |
445 | /* |
446 | * Explicit conversion from the to_decimal_string ASL operator. |
447 | * |
448 | * From ACPI: "If the input is a buffer, it is converted to a |
449 | * a string of decimal values separated by commas." |
450 | */ |
451 | base = 10; |
452 | |
453 | /* |
454 | * Calculate the final string length. Individual string values |
455 | * are variable length (include separator for each) |
456 | */ |
457 | for (i = 0; i < obj_desc->buffer.length; i++) { |
458 | if (obj_desc->buffer.pointer[i] >= 100) { |
459 | string_length += 4; |
460 | } else if (obj_desc->buffer.pointer[i] >= 10) { |
461 | string_length += 3; |
462 | } else { |
463 | string_length += 2; |
464 | } |
465 | } |
466 | break; |
467 | |
468 | case ACPI_IMPLICIT_CONVERT_HEX: |
469 | /* |
470 | * Implicit buffer-to-string conversion |
471 | * |
472 | * From the ACPI spec: |
473 | * "The entire contents of the buffer are converted to a string of |
474 | * two-character hexadecimal numbers, each separated by a space." |
475 | * |
476 | * Each hex number is prefixed with 0x (11/2018) |
477 | */ |
478 | separator = ' '; |
479 | string_length = (obj_desc->buffer.length * 5); |
480 | break; |
481 | |
482 | case ACPI_EXPLICIT_CONVERT_HEX: |
483 | /* |
484 | * Explicit conversion from the to_hex_string ASL operator. |
485 | * |
486 | * From ACPI: "If Data is a buffer, it is converted to a string of |
487 | * hexadecimal values separated by commas." |
488 | * |
489 | * Each hex number is prefixed with 0x (11/2018) |
490 | */ |
491 | separator = ','; |
492 | string_length = (obj_desc->buffer.length * 5); |
493 | break; |
494 | |
495 | default: |
496 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
497 | } |
498 | |
499 | /* |
500 | * Create a new string object and string buffer |
501 | * (-1 because of extra separator included in string_length from above) |
502 | * Allow creation of zero-length strings from zero-length buffers. |
503 | */ |
504 | if (string_length) { |
505 | string_length--; |
506 | } |
507 | |
508 | return_desc = |
509 | acpi_ut_create_string_object(string_size: (acpi_size)string_length); |
510 | if (!return_desc) { |
511 | return_ACPI_STATUS(AE_NO_MEMORY); |
512 | } |
513 | |
514 | new_buf = return_desc->buffer.pointer; |
515 | |
516 | /* |
517 | * Convert buffer bytes to hex or decimal values |
518 | * (separated by commas or spaces) |
519 | */ |
520 | for (i = 0; i < obj_desc->buffer.length; i++) { |
521 | if (base == 16) { |
522 | |
523 | /* Emit 0x prefix for explicit/implicit hex conversion */ |
524 | |
525 | *new_buf++ = '0'; |
526 | *new_buf++ = 'x'; |
527 | } |
528 | |
529 | new_buf += acpi_ex_convert_to_ascii(integer: (u64) obj_desc-> |
530 | buffer.pointer[i], |
531 | base, string: new_buf, data_width: 1); |
532 | |
533 | /* Each digit is separated by either a comma or space */ |
534 | |
535 | *new_buf++ = separator; |
536 | } |
537 | |
538 | /* |
539 | * Null terminate the string |
540 | * (overwrites final comma/space from above) |
541 | */ |
542 | if (obj_desc->buffer.length) { |
543 | new_buf--; |
544 | } |
545 | *new_buf = 0; |
546 | break; |
547 | |
548 | default: |
549 | |
550 | return_ACPI_STATUS(AE_TYPE); |
551 | } |
552 | |
553 | *result_desc = return_desc; |
554 | return_ACPI_STATUS(AE_OK); |
555 | } |
556 | |
557 | /******************************************************************************* |
558 | * |
559 | * FUNCTION: acpi_ex_convert_to_target_type |
560 | * |
561 | * PARAMETERS: destination_type - Current type of the destination |
562 | * source_desc - Source object to be converted. |
563 | * result_desc - Where the converted object is returned |
564 | * walk_state - Current method state |
565 | * |
566 | * RETURN: Status |
567 | * |
568 | * DESCRIPTION: Implements "implicit conversion" rules for storing an object. |
569 | * |
570 | ******************************************************************************/ |
571 | |
572 | acpi_status |
573 | acpi_ex_convert_to_target_type(acpi_object_type destination_type, |
574 | union acpi_operand_object *source_desc, |
575 | union acpi_operand_object **result_desc, |
576 | struct acpi_walk_state *walk_state) |
577 | { |
578 | acpi_status status = AE_OK; |
579 | |
580 | ACPI_FUNCTION_TRACE(ex_convert_to_target_type); |
581 | |
582 | /* Default behavior */ |
583 | |
584 | *result_desc = source_desc; |
585 | |
586 | /* |
587 | * If required by the target, |
588 | * perform implicit conversion on the source before we store it. |
589 | */ |
590 | switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) { |
591 | case ARGI_SIMPLE_TARGET: |
592 | case ARGI_FIXED_TARGET: |
593 | case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ |
594 | |
595 | switch (destination_type) { |
596 | case ACPI_TYPE_LOCAL_REGION_FIELD: |
597 | /* |
598 | * Named field can always handle conversions |
599 | */ |
600 | break; |
601 | |
602 | default: |
603 | |
604 | /* No conversion allowed for these types */ |
605 | |
606 | if (destination_type != source_desc->common.type) { |
607 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
608 | "Explicit operator, will store (%s) over existing type (%s)\n" , |
609 | acpi_ut_get_object_type_name |
610 | (source_desc), |
611 | acpi_ut_get_type_name |
612 | (destination_type))); |
613 | status = AE_TYPE; |
614 | } |
615 | } |
616 | break; |
617 | |
618 | case ARGI_TARGETREF: |
619 | case ARGI_STORE_TARGET: |
620 | |
621 | switch (destination_type) { |
622 | case ACPI_TYPE_INTEGER: |
623 | case ACPI_TYPE_BUFFER_FIELD: |
624 | case ACPI_TYPE_LOCAL_BANK_FIELD: |
625 | case ACPI_TYPE_LOCAL_INDEX_FIELD: |
626 | /* |
627 | * These types require an Integer operand. We can convert |
628 | * a Buffer or a String to an Integer if necessary. |
629 | */ |
630 | status = |
631 | acpi_ex_convert_to_integer(obj_desc: source_desc, result_desc, |
632 | ACPI_IMPLICIT_CONVERSION); |
633 | break; |
634 | |
635 | case ACPI_TYPE_STRING: |
636 | /* |
637 | * The operand must be a String. We can convert an |
638 | * Integer or Buffer if necessary |
639 | */ |
640 | status = |
641 | acpi_ex_convert_to_string(obj_desc: source_desc, result_desc, |
642 | ACPI_IMPLICIT_CONVERT_HEX); |
643 | break; |
644 | |
645 | case ACPI_TYPE_BUFFER: |
646 | /* |
647 | * The operand must be a Buffer. We can convert an |
648 | * Integer or String if necessary |
649 | */ |
650 | status = |
651 | acpi_ex_convert_to_buffer(obj_desc: source_desc, result_desc); |
652 | break; |
653 | |
654 | default: |
655 | |
656 | ACPI_ERROR((AE_INFO, |
657 | "Bad destination type during conversion: 0x%X" , |
658 | destination_type)); |
659 | status = AE_AML_INTERNAL; |
660 | break; |
661 | } |
662 | break; |
663 | |
664 | case ARGI_REFERENCE: |
665 | /* |
666 | * create_xxxx_field cases - we are storing the field object into the name |
667 | */ |
668 | break; |
669 | |
670 | default: |
671 | |
672 | ACPI_ERROR((AE_INFO, |
673 | "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s" , |
674 | GET_CURRENT_ARG_TYPE(walk_state->op_info-> |
675 | runtime_args), |
676 | walk_state->opcode, |
677 | acpi_ut_get_type_name(destination_type))); |
678 | status = AE_AML_INTERNAL; |
679 | } |
680 | |
681 | /* |
682 | * Source-to-Target conversion semantics: |
683 | * |
684 | * If conversion to the target type cannot be performed, then simply |
685 | * overwrite the target with the new object and type. |
686 | */ |
687 | if (status == AE_TYPE) { |
688 | status = AE_OK; |
689 | } |
690 | |
691 | return_ACPI_STATUS(status); |
692 | } |
693 | |