195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: exconvrt - Object conversion routines
595b482a8SLen Brown *
6*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown *
895857638SErik Schmauss *****************************************************************************/
995b482a8SLen Brown
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "acinterp.h"
13e2f7a777SLen Brown #include "amlcode.h"
1495b482a8SLen Brown
1595b482a8SLen Brown #define _COMPONENT ACPI_EXECUTER
1695b482a8SLen Brown ACPI_MODULE_NAME("exconvrt")
1795b482a8SLen Brown
1895b482a8SLen Brown /* Local prototypes */
1995b482a8SLen Brown static u32
205df7e6cbSBob Moore acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length);
2195b482a8SLen Brown
2295b482a8SLen Brown /*******************************************************************************
2395b482a8SLen Brown *
2495b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_integer
2595b482a8SLen Brown *
2695b482a8SLen Brown * PARAMETERS: obj_desc - Object to be converted. Must be an
2795b482a8SLen Brown * Integer, Buffer, or String
2895b482a8SLen Brown * result_desc - Where the new Integer object is returned
29fe97d287SBob Moore * implicit_conversion - Used for string conversion
3095b482a8SLen Brown *
3195b482a8SLen Brown * RETURN: Status
3295b482a8SLen Brown *
3395b482a8SLen Brown * DESCRIPTION: Convert an ACPI Object to an integer.
3495b482a8SLen Brown *
3595b482a8SLen Brown ******************************************************************************/
3695b482a8SLen Brown
3795b482a8SLen Brown acpi_status
acpi_ex_convert_to_integer(union acpi_operand_object * obj_desc,union acpi_operand_object ** result_desc,u32 implicit_conversion)3895b482a8SLen Brown acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
39fe97d287SBob Moore union acpi_operand_object **result_desc,
40fe97d287SBob Moore u32 implicit_conversion)
4195b482a8SLen Brown {
4295b482a8SLen Brown union acpi_operand_object *return_desc;
4395b482a8SLen Brown u8 *pointer;
445df7e6cbSBob Moore u64 result;
4595b482a8SLen Brown u32 i;
4695b482a8SLen Brown u32 count;
4795b482a8SLen Brown
4895b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc);
4995b482a8SLen Brown
503371c19cSBob Moore switch (obj_desc->common.type) {
5195b482a8SLen Brown case ACPI_TYPE_INTEGER:
5295b482a8SLen Brown
5395b482a8SLen Brown /* No conversion necessary */
5495b482a8SLen Brown
5595b482a8SLen Brown *result_desc = obj_desc;
5695b482a8SLen Brown return_ACPI_STATUS(AE_OK);
5795b482a8SLen Brown
5895b482a8SLen Brown case ACPI_TYPE_BUFFER:
5995b482a8SLen Brown case ACPI_TYPE_STRING:
6095b482a8SLen Brown
6195b482a8SLen Brown /* Note: Takes advantage of common buffer/string fields */
6295b482a8SLen Brown
6395b482a8SLen Brown pointer = obj_desc->buffer.pointer;
6495b482a8SLen Brown count = obj_desc->buffer.length;
6595b482a8SLen Brown break;
6695b482a8SLen Brown
6795b482a8SLen Brown default:
681d1ea1b7SChao Guan
6995b482a8SLen Brown return_ACPI_STATUS(AE_TYPE);
7095b482a8SLen Brown }
7195b482a8SLen Brown
7295b482a8SLen Brown /*
7395b482a8SLen Brown * Convert the buffer/string to an integer. Note that both buffers and
7495b482a8SLen Brown * strings are treated as raw data - we don't convert ascii to hex for
7595b482a8SLen Brown * strings.
7695b482a8SLen Brown *
7795b482a8SLen Brown * There are two terminating conditions for the loop:
7895b482a8SLen Brown * 1) The size of an integer has been reached, or
7995b482a8SLen Brown * 2) The end of the buffer or string has been reached
8095b482a8SLen Brown */
8195b482a8SLen Brown result = 0;
8295b482a8SLen Brown
8395b482a8SLen Brown /* String conversion is different than Buffer conversion */
8495b482a8SLen Brown
853371c19cSBob Moore switch (obj_desc->common.type) {
8695b482a8SLen Brown case ACPI_TYPE_STRING:
8795b482a8SLen Brown /*
8895b482a8SLen Brown * Convert string to an integer - for most cases, the string must be
8995b482a8SLen Brown * hexadecimal as per the ACPI specification. The only exception (as
9095b482a8SLen Brown * of ACPI 3.0) is that the to_integer() operator allows both decimal
9195b482a8SLen Brown * and hexadecimal strings (hex prefixed with "0x").
92fe97d287SBob Moore *
93fe97d287SBob Moore * Explicit conversion is used only by to_integer.
94fe97d287SBob Moore * All other string-to-integer conversions are implicit conversions.
9595b482a8SLen Brown */
96fe97d287SBob Moore if (implicit_conversion) {
97fe97d287SBob Moore result =
98fe97d287SBob Moore acpi_ut_implicit_strtoul64(ACPI_CAST_PTR
99fe97d287SBob Moore (char, pointer));
100fe97d287SBob Moore } else {
101fe97d287SBob Moore result =
102fe97d287SBob Moore acpi_ut_explicit_strtoul64(ACPI_CAST_PTR
103fe97d287SBob Moore (char, pointer));
10495b482a8SLen Brown }
10595b482a8SLen Brown break;
10695b482a8SLen Brown
10795b482a8SLen Brown case ACPI_TYPE_BUFFER:
10895b482a8SLen Brown
10995b482a8SLen Brown /* Check for zero-length buffer */
11095b482a8SLen Brown
11195b482a8SLen Brown if (!count) {
11295b482a8SLen Brown return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
11395b482a8SLen Brown }
11495b482a8SLen Brown
11595b482a8SLen Brown /* Transfer no more than an integer's worth of data */
11695b482a8SLen Brown
11795b482a8SLen Brown if (count > acpi_gbl_integer_byte_width) {
11895b482a8SLen Brown count = acpi_gbl_integer_byte_width;
11995b482a8SLen Brown }
12095b482a8SLen Brown
12195b482a8SLen Brown /*
12295b482a8SLen Brown * Convert buffer to an integer - we simply grab enough raw data
12395b482a8SLen Brown * from the buffer to fill an integer
12495b482a8SLen Brown */
12595b482a8SLen Brown for (i = 0; i < count; i++) {
12695b482a8SLen Brown /*
12795b482a8SLen Brown * Get next byte and shift it into the Result.
12895b482a8SLen Brown * Little endian is used, meaning that the first byte of the buffer
12995b482a8SLen Brown * is the LSB of the integer
13095b482a8SLen Brown */
1315df7e6cbSBob Moore result |= (((u64) pointer[i]) << (i * 8));
13295b482a8SLen Brown }
13395b482a8SLen Brown break;
13495b482a8SLen Brown
13595b482a8SLen Brown default:
13695b482a8SLen Brown
13795b482a8SLen Brown /* No other types can get here */
1381d1ea1b7SChao Guan
13995b482a8SLen Brown break;
14095b482a8SLen Brown }
14195b482a8SLen Brown
14295b482a8SLen Brown /* Create a new integer */
14395b482a8SLen Brown
144dc95a270SBob Moore return_desc = acpi_ut_create_integer_object(result);
14595b482a8SLen Brown if (!return_desc) {
14695b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
14795b482a8SLen Brown }
14895b482a8SLen Brown
14995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
15095b482a8SLen Brown ACPI_FORMAT_UINT64(result)));
15195b482a8SLen Brown
15295b482a8SLen Brown /* Save the Result */
15395b482a8SLen Brown
154ef42e53fSBob Moore (void)acpi_ex_truncate_for32bit_table(return_desc);
15595b482a8SLen Brown *result_desc = return_desc;
15695b482a8SLen Brown return_ACPI_STATUS(AE_OK);
15795b482a8SLen Brown }
15895b482a8SLen Brown
15995b482a8SLen Brown /*******************************************************************************
16095b482a8SLen Brown *
16195b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_buffer
16295b482a8SLen Brown *
16395b482a8SLen Brown * PARAMETERS: obj_desc - Object to be converted. Must be an
16495b482a8SLen Brown * Integer, Buffer, or String
16595b482a8SLen Brown * result_desc - Where the new buffer object is returned
16695b482a8SLen Brown *
16795b482a8SLen Brown * RETURN: Status
16895b482a8SLen Brown *
16995b482a8SLen Brown * DESCRIPTION: Convert an ACPI Object to a Buffer
17095b482a8SLen Brown *
17195b482a8SLen Brown ******************************************************************************/
17295b482a8SLen Brown
17395b482a8SLen Brown acpi_status
acpi_ex_convert_to_buffer(union acpi_operand_object * obj_desc,union acpi_operand_object ** result_desc)17495b482a8SLen Brown acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
17595b482a8SLen Brown union acpi_operand_object **result_desc)
17695b482a8SLen Brown {
17795b482a8SLen Brown union acpi_operand_object *return_desc;
17895b482a8SLen Brown u8 *new_buf;
17995b482a8SLen Brown
18095b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc);
18195b482a8SLen Brown
1823371c19cSBob Moore switch (obj_desc->common.type) {
18395b482a8SLen Brown case ACPI_TYPE_BUFFER:
18495b482a8SLen Brown
18595b482a8SLen Brown /* No conversion necessary */
18695b482a8SLen Brown
18795b482a8SLen Brown *result_desc = obj_desc;
18895b482a8SLen Brown return_ACPI_STATUS(AE_OK);
18995b482a8SLen Brown
19095b482a8SLen Brown case ACPI_TYPE_INTEGER:
19195b482a8SLen Brown /*
19295b482a8SLen Brown * Create a new Buffer object.
19395b482a8SLen Brown * Need enough space for one integer
19495b482a8SLen Brown */
19595b482a8SLen Brown return_desc =
19695b482a8SLen Brown acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width);
19795b482a8SLen Brown if (!return_desc) {
19895b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
19995b482a8SLen Brown }
20095b482a8SLen Brown
20195b482a8SLen Brown /* Copy the integer to the buffer, LSB first */
20295b482a8SLen Brown
20395b482a8SLen Brown new_buf = return_desc->buffer.pointer;
2041fad8738SBob Moore memcpy(new_buf, &obj_desc->integer.value,
2051fad8738SBob Moore acpi_gbl_integer_byte_width);
20695b482a8SLen Brown break;
20795b482a8SLen Brown
20895b482a8SLen Brown case ACPI_TYPE_STRING:
20995b482a8SLen Brown /*
21095b482a8SLen Brown * Create a new Buffer object
21195b482a8SLen Brown * Size will be the string length
21295b482a8SLen Brown *
21395b482a8SLen Brown * NOTE: Add one to the string length to include the null terminator.
21495b482a8SLen Brown * The ACPI spec is unclear on this subject, but there is existing
21595b482a8SLen Brown * ASL/AML code that depends on the null being transferred to the new
21695b482a8SLen Brown * buffer.
21795b482a8SLen Brown */
21895b482a8SLen Brown return_desc = acpi_ut_create_buffer_object((acpi_size)
21995b482a8SLen Brown obj_desc->string.
22095b482a8SLen Brown length + 1);
22195b482a8SLen Brown if (!return_desc) {
22295b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
22395b482a8SLen Brown }
22495b482a8SLen Brown
22595b482a8SLen Brown /* Copy the string to the buffer */
22695b482a8SLen Brown
22795b482a8SLen Brown new_buf = return_desc->buffer.pointer;
2284fa4616eSBob Moore strncpy((char *)new_buf, (char *)obj_desc->string.pointer,
22995b482a8SLen Brown obj_desc->string.length);
23095b482a8SLen Brown break;
23195b482a8SLen Brown
23295b482a8SLen Brown default:
2331d1ea1b7SChao Guan
23495b482a8SLen Brown return_ACPI_STATUS(AE_TYPE);
23595b482a8SLen Brown }
23695b482a8SLen Brown
23795b482a8SLen Brown /* Mark buffer initialized */
23895b482a8SLen Brown
23995b482a8SLen Brown return_desc->common.flags |= AOPOBJ_DATA_VALID;
24095b482a8SLen Brown *result_desc = return_desc;
24195b482a8SLen Brown return_ACPI_STATUS(AE_OK);
24295b482a8SLen Brown }
24395b482a8SLen Brown
24495b482a8SLen Brown /*******************************************************************************
24595b482a8SLen Brown *
24695b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_ascii
24795b482a8SLen Brown *
248ba494beeSBob Moore * PARAMETERS: integer - Value to be converted
249ba494beeSBob Moore * base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
250ba494beeSBob Moore * string - Where the string is returned
25195b482a8SLen Brown * data_width - Size of data item to be converted, in bytes
25295b482a8SLen Brown *
25395b482a8SLen Brown * RETURN: Actual string length
25495b482a8SLen Brown *
25595b482a8SLen Brown * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
25695b482a8SLen Brown *
25795b482a8SLen Brown ******************************************************************************/
25895b482a8SLen Brown
25995b482a8SLen Brown static u32
acpi_ex_convert_to_ascii(u64 integer,u16 base,u8 * string,u8 data_width)2605df7e6cbSBob Moore acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width)
26195b482a8SLen Brown {
2625df7e6cbSBob Moore u64 digit;
26395b482a8SLen Brown u32 i;
26495b482a8SLen Brown u32 j;
26595b482a8SLen Brown u32 k = 0;
26695b482a8SLen Brown u32 hex_length;
26795b482a8SLen Brown u32 decimal_length;
26895b482a8SLen Brown u32 remainder;
26995b482a8SLen Brown u8 supress_zeros;
27095b482a8SLen Brown
27195b482a8SLen Brown ACPI_FUNCTION_ENTRY();
27295b482a8SLen Brown
27395b482a8SLen Brown switch (base) {
27495b482a8SLen Brown case 10:
27595b482a8SLen Brown
27695b482a8SLen Brown /* Setup max length for the decimal number */
27795b482a8SLen Brown
27895b482a8SLen Brown switch (data_width) {
27995b482a8SLen Brown case 1:
2801d1ea1b7SChao Guan
28195b482a8SLen Brown decimal_length = ACPI_MAX8_DECIMAL_DIGITS;
28295b482a8SLen Brown break;
28395b482a8SLen Brown
28495b482a8SLen Brown case 4:
2851d1ea1b7SChao Guan
28695b482a8SLen Brown decimal_length = ACPI_MAX32_DECIMAL_DIGITS;
28795b482a8SLen Brown break;
28895b482a8SLen Brown
28995b482a8SLen Brown case 8:
29095b482a8SLen Brown default:
2911d1ea1b7SChao Guan
29295b482a8SLen Brown decimal_length = ACPI_MAX64_DECIMAL_DIGITS;
29395b482a8SLen Brown break;
29495b482a8SLen Brown }
29595b482a8SLen Brown
29695b482a8SLen Brown supress_zeros = TRUE; /* No leading zeros */
29795b482a8SLen Brown remainder = 0;
29895b482a8SLen Brown
29995b482a8SLen Brown for (i = decimal_length; i > 0; i--) {
30095b482a8SLen Brown
30195b482a8SLen Brown /* Divide by nth factor of 10 */
30295b482a8SLen Brown
30395b482a8SLen Brown digit = integer;
30495b482a8SLen Brown for (j = 0; j < i; j++) {
30595b482a8SLen Brown (void)acpi_ut_short_divide(digit, 10, &digit,
30695b482a8SLen Brown &remainder);
30795b482a8SLen Brown }
30895b482a8SLen Brown
30995b482a8SLen Brown /* Handle leading zeros */
31095b482a8SLen Brown
31195b482a8SLen Brown if (remainder != 0) {
31295b482a8SLen Brown supress_zeros = FALSE;
31395b482a8SLen Brown }
31495b482a8SLen Brown
31595b482a8SLen Brown if (!supress_zeros) {
31695b482a8SLen Brown string[k] = (u8) (ACPI_ASCII_ZERO + remainder);
31795b482a8SLen Brown k++;
31895b482a8SLen Brown }
31995b482a8SLen Brown }
32095b482a8SLen Brown break;
32195b482a8SLen Brown
32295b482a8SLen Brown case 16:
32395b482a8SLen Brown
32495b482a8SLen Brown /* hex_length: 2 ascii hex chars per data byte */
32595b482a8SLen Brown
326c4751176SBob Moore hex_length = (data_width * 2);
32795b482a8SLen Brown for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
32895b482a8SLen Brown
32995b482a8SLen Brown /* Get one hex digit, most significant digits first */
33095b482a8SLen Brown
3311fad8738SBob Moore string[k] = (u8)
3321fad8738SBob Moore acpi_ut_hex_to_ascii_char(integer, ACPI_MUL_4(j));
33395b482a8SLen Brown k++;
33495b482a8SLen Brown }
33595b482a8SLen Brown break;
33695b482a8SLen Brown
33795b482a8SLen Brown default:
33895b482a8SLen Brown return (0);
33995b482a8SLen Brown }
34095b482a8SLen Brown
34195b482a8SLen Brown /*
34295b482a8SLen Brown * Since leading zeros are suppressed, we must check for the case where
34395b482a8SLen Brown * the integer equals 0
34495b482a8SLen Brown *
34595b482a8SLen Brown * Finally, null terminate the string and return the length
34695b482a8SLen Brown */
34795b482a8SLen Brown if (!k) {
34895b482a8SLen Brown string[0] = ACPI_ASCII_ZERO;
34995b482a8SLen Brown k = 1;
35095b482a8SLen Brown }
35195b482a8SLen Brown
35295b482a8SLen Brown string[k] = 0;
35395b482a8SLen Brown return ((u32) k);
35495b482a8SLen Brown }
35595b482a8SLen Brown
35695b482a8SLen Brown /*******************************************************************************
35795b482a8SLen Brown *
35895b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_string
35995b482a8SLen Brown *
36095b482a8SLen Brown * PARAMETERS: obj_desc - Object to be converted. Must be an
36195b482a8SLen Brown * Integer, Buffer, or String
36295b482a8SLen Brown * result_desc - Where the string object is returned
363ba494beeSBob Moore * type - String flags (base and conversion type)
36495b482a8SLen Brown *
36595b482a8SLen Brown * RETURN: Status
36695b482a8SLen Brown *
367c4751176SBob Moore * DESCRIPTION: Convert an ACPI Object to a string. Supports both implicit
368c4751176SBob Moore * and explicit conversions and related rules.
36995b482a8SLen Brown *
37095b482a8SLen Brown ******************************************************************************/
37195b482a8SLen Brown
37295b482a8SLen Brown acpi_status
acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,union acpi_operand_object ** result_desc,u32 type)37395b482a8SLen Brown acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
37495b482a8SLen Brown union acpi_operand_object ** result_desc, u32 type)
37595b482a8SLen Brown {
37695b482a8SLen Brown union acpi_operand_object *return_desc;
37795b482a8SLen Brown u8 *new_buf;
37895b482a8SLen Brown u32 i;
37995b482a8SLen Brown u32 string_length = 0;
38095b482a8SLen Brown u16 base = 16;
38195b482a8SLen Brown u8 separator = ',';
38295b482a8SLen Brown
38395b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc);
38495b482a8SLen Brown
3853371c19cSBob Moore switch (obj_desc->common.type) {
38695b482a8SLen Brown case ACPI_TYPE_STRING:
38795b482a8SLen Brown
38895b482a8SLen Brown /* No conversion necessary */
38995b482a8SLen Brown
39095b482a8SLen Brown *result_desc = obj_desc;
39195b482a8SLen Brown return_ACPI_STATUS(AE_OK);
39295b482a8SLen Brown
39395b482a8SLen Brown case ACPI_TYPE_INTEGER:
39495b482a8SLen Brown
39595b482a8SLen Brown switch (type) {
39695b482a8SLen Brown case ACPI_EXPLICIT_CONVERT_DECIMAL:
397c4751176SBob Moore /*
398c4751176SBob Moore * From to_decimal_string, integer source.
399c4751176SBob Moore *
400c4751176SBob Moore * Make room for the maximum decimal number size
401c4751176SBob Moore */
40295b482a8SLen Brown string_length = ACPI_MAX_DECIMAL_DIGITS;
40395b482a8SLen Brown base = 10;
40495b482a8SLen Brown break;
40595b482a8SLen Brown
40695b482a8SLen Brown default:
40795b482a8SLen Brown
40895b482a8SLen Brown /* Two hex string characters for each integer byte */
40995b482a8SLen Brown
41095b482a8SLen Brown string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width);
41195b482a8SLen Brown break;
41295b482a8SLen Brown }
41395b482a8SLen Brown
41495b482a8SLen Brown /*
41595b482a8SLen Brown * Create a new String
41695b482a8SLen Brown * Need enough space for one ASCII integer (plus null terminator)
41795b482a8SLen Brown */
41895b482a8SLen Brown return_desc =
41995b482a8SLen Brown acpi_ut_create_string_object((acpi_size)string_length);
42095b482a8SLen Brown if (!return_desc) {
42195b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
42295b482a8SLen Brown }
42395b482a8SLen Brown
42495b482a8SLen Brown new_buf = return_desc->buffer.pointer;
42595b482a8SLen Brown
42695b482a8SLen Brown /* Convert integer to string */
42795b482a8SLen Brown
42895b482a8SLen Brown string_length =
42995b482a8SLen Brown acpi_ex_convert_to_ascii(obj_desc->integer.value, base,
43095b482a8SLen Brown new_buf,
43195b482a8SLen Brown acpi_gbl_integer_byte_width);
43295b482a8SLen Brown
43395b482a8SLen Brown /* Null terminate at the correct place */
43495b482a8SLen Brown
43595b482a8SLen Brown return_desc->string.length = string_length;
43695b482a8SLen Brown new_buf[string_length] = 0;
43795b482a8SLen Brown break;
43895b482a8SLen Brown
43995b482a8SLen Brown case ACPI_TYPE_BUFFER:
44095b482a8SLen Brown
44195b482a8SLen Brown /* Setup string length, base, and separator */
44295b482a8SLen Brown
44395b482a8SLen Brown switch (type) {
44495b482a8SLen Brown case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */
44595b482a8SLen Brown /*
446c4751176SBob Moore * Explicit conversion from the to_decimal_string ASL operator.
447c4751176SBob Moore *
448c4751176SBob Moore * From ACPI: "If the input is a buffer, it is converted to a
449c4751176SBob Moore * a string of decimal values separated by commas."
45095b482a8SLen Brown */
45195b482a8SLen Brown base = 10;
45295b482a8SLen Brown
45395b482a8SLen Brown /*
45495b482a8SLen Brown * Calculate the final string length. Individual string values
45595b482a8SLen Brown * are variable length (include separator for each)
45695b482a8SLen Brown */
45795b482a8SLen Brown for (i = 0; i < obj_desc->buffer.length; i++) {
45895b482a8SLen Brown if (obj_desc->buffer.pointer[i] >= 100) {
45995b482a8SLen Brown string_length += 4;
46095b482a8SLen Brown } else if (obj_desc->buffer.pointer[i] >= 10) {
46195b482a8SLen Brown string_length += 3;
46295b482a8SLen Brown } else {
46395b482a8SLen Brown string_length += 2;
46495b482a8SLen Brown }
46595b482a8SLen Brown }
46695b482a8SLen Brown break;
46795b482a8SLen Brown
46895b482a8SLen Brown case ACPI_IMPLICIT_CONVERT_HEX:
46995b482a8SLen Brown /*
470c4751176SBob Moore * Implicit buffer-to-string conversion
471c4751176SBob Moore *
47295b482a8SLen Brown * From the ACPI spec:
47395b482a8SLen Brown * "The entire contents of the buffer are converted to a string of
47495b482a8SLen Brown * two-character hexadecimal numbers, each separated by a space."
475c4751176SBob Moore *
476c4751176SBob Moore * Each hex number is prefixed with 0x (11/2018)
47795b482a8SLen Brown */
47895b482a8SLen Brown separator = ' ';
479c4751176SBob Moore string_length = (obj_desc->buffer.length * 5);
48095b482a8SLen Brown break;
48195b482a8SLen Brown
482c4751176SBob Moore case ACPI_EXPLICIT_CONVERT_HEX:
48395b482a8SLen Brown /*
484c4751176SBob Moore * Explicit conversion from the to_hex_string ASL operator.
485c4751176SBob Moore *
48695b482a8SLen Brown * From ACPI: "If Data is a buffer, it is converted to a string of
48795b482a8SLen Brown * hexadecimal values separated by commas."
488c4751176SBob Moore *
489c4751176SBob Moore * Each hex number is prefixed with 0x (11/2018)
49095b482a8SLen Brown */
491c4751176SBob Moore separator = ',';
492c4751176SBob Moore string_length = (obj_desc->buffer.length * 5);
49395b482a8SLen Brown break;
49495b482a8SLen Brown
49595b482a8SLen Brown default:
49695b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER);
49795b482a8SLen Brown }
49895b482a8SLen Brown
49995b482a8SLen Brown /*
50095b482a8SLen Brown * Create a new string object and string buffer
50195b482a8SLen Brown * (-1 because of extra separator included in string_length from above)
50295b482a8SLen Brown * Allow creation of zero-length strings from zero-length buffers.
50395b482a8SLen Brown */
50495b482a8SLen Brown if (string_length) {
50595b482a8SLen Brown string_length--;
50695b482a8SLen Brown }
50795b482a8SLen Brown
5081f86e8c1SLv Zheng return_desc =
5091f86e8c1SLv Zheng acpi_ut_create_string_object((acpi_size)string_length);
51095b482a8SLen Brown if (!return_desc) {
51195b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
51295b482a8SLen Brown }
51395b482a8SLen Brown
51495b482a8SLen Brown new_buf = return_desc->buffer.pointer;
51595b482a8SLen Brown
51695b482a8SLen Brown /*
51795b482a8SLen Brown * Convert buffer bytes to hex or decimal values
51895b482a8SLen Brown * (separated by commas or spaces)
51995b482a8SLen Brown */
52095b482a8SLen Brown for (i = 0; i < obj_desc->buffer.length; i++) {
521c4751176SBob Moore if (base == 16) {
522c4751176SBob Moore
523c163f90cSErik Schmauss /* Emit 0x prefix for explicit/implicit hex conversion */
524c4751176SBob Moore
525c4751176SBob Moore *new_buf++ = '0';
526c4751176SBob Moore *new_buf++ = 'x';
527c4751176SBob Moore }
528c4751176SBob Moore
5295df7e6cbSBob Moore new_buf += acpi_ex_convert_to_ascii((u64) obj_desc->
5305df7e6cbSBob Moore buffer.pointer[i],
5315df7e6cbSBob Moore base, new_buf, 1);
532c4751176SBob Moore
533c4751176SBob Moore /* Each digit is separated by either a comma or space */
534c4751176SBob Moore
535c4751176SBob Moore *new_buf++ = separator;
53695b482a8SLen Brown }
53795b482a8SLen Brown
53895b482a8SLen Brown /*
53995b482a8SLen Brown * Null terminate the string
54095b482a8SLen Brown * (overwrites final comma/space from above)
54195b482a8SLen Brown */
54295b482a8SLen Brown if (obj_desc->buffer.length) {
54395b482a8SLen Brown new_buf--;
54495b482a8SLen Brown }
54595b482a8SLen Brown *new_buf = 0;
54695b482a8SLen Brown break;
54795b482a8SLen Brown
54895b482a8SLen Brown default:
5491d1ea1b7SChao Guan
55095b482a8SLen Brown return_ACPI_STATUS(AE_TYPE);
55195b482a8SLen Brown }
55295b482a8SLen Brown
55395b482a8SLen Brown *result_desc = return_desc;
55495b482a8SLen Brown return_ACPI_STATUS(AE_OK);
55595b482a8SLen Brown }
55695b482a8SLen Brown
55795b482a8SLen Brown /*******************************************************************************
55895b482a8SLen Brown *
55995b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_target_type
56095b482a8SLen Brown *
56195b482a8SLen Brown * PARAMETERS: destination_type - Current type of the destination
56295b482a8SLen Brown * source_desc - Source object to be converted.
56395b482a8SLen Brown * result_desc - Where the converted object is returned
56495b482a8SLen Brown * walk_state - Current method state
56595b482a8SLen Brown *
56695b482a8SLen Brown * RETURN: Status
56795b482a8SLen Brown *
56895b482a8SLen Brown * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
56995b482a8SLen Brown *
57095b482a8SLen Brown ******************************************************************************/
57195b482a8SLen Brown
57295b482a8SLen Brown acpi_status
acpi_ex_convert_to_target_type(acpi_object_type destination_type,union acpi_operand_object * source_desc,union acpi_operand_object ** result_desc,struct acpi_walk_state * walk_state)57395b482a8SLen Brown acpi_ex_convert_to_target_type(acpi_object_type destination_type,
57495b482a8SLen Brown union acpi_operand_object *source_desc,
57595b482a8SLen Brown union acpi_operand_object **result_desc,
57695b482a8SLen Brown struct acpi_walk_state *walk_state)
57795b482a8SLen Brown {
57895b482a8SLen Brown acpi_status status = AE_OK;
57995b482a8SLen Brown
58095b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_convert_to_target_type);
58195b482a8SLen Brown
58295b482a8SLen Brown /* Default behavior */
58395b482a8SLen Brown
58495b482a8SLen Brown *result_desc = source_desc;
58595b482a8SLen Brown
58695b482a8SLen Brown /*
58795b482a8SLen Brown * If required by the target,
58895b482a8SLen Brown * perform implicit conversion on the source before we store it.
58995b482a8SLen Brown */
59095b482a8SLen Brown switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) {
59195b482a8SLen Brown case ARGI_SIMPLE_TARGET:
5927decc66dSBob Moore case ARGI_FIXED_TARGET:
59395b482a8SLen Brown case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
59495b482a8SLen Brown
59595b482a8SLen Brown switch (destination_type) {
59695b482a8SLen Brown case ACPI_TYPE_LOCAL_REGION_FIELD:
59795b482a8SLen Brown /*
59895b482a8SLen Brown * Named field can always handle conversions
59995b482a8SLen Brown */
60095b482a8SLen Brown break;
60195b482a8SLen Brown
60295b482a8SLen Brown default:
6031d1ea1b7SChao Guan
60495b482a8SLen Brown /* No conversion allowed for these types */
60595b482a8SLen Brown
6063371c19cSBob Moore if (destination_type != source_desc->common.type) {
60795b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO,
60895b482a8SLen Brown "Explicit operator, will store (%s) over existing type (%s)\n",
60995b482a8SLen Brown acpi_ut_get_object_type_name
61095b482a8SLen Brown (source_desc),
61195b482a8SLen Brown acpi_ut_get_type_name
61295b482a8SLen Brown (destination_type)));
61395b482a8SLen Brown status = AE_TYPE;
61495b482a8SLen Brown }
61595b482a8SLen Brown }
61695b482a8SLen Brown break;
61795b482a8SLen Brown
61895b482a8SLen Brown case ARGI_TARGETREF:
619a5922a1fSBob Moore case ARGI_STORE_TARGET:
62095b482a8SLen Brown
62195b482a8SLen Brown switch (destination_type) {
62295b482a8SLen Brown case ACPI_TYPE_INTEGER:
62395b482a8SLen Brown case ACPI_TYPE_BUFFER_FIELD:
62495b482a8SLen Brown case ACPI_TYPE_LOCAL_BANK_FIELD:
62595b482a8SLen Brown case ACPI_TYPE_LOCAL_INDEX_FIELD:
62695b482a8SLen Brown /*
62795b482a8SLen Brown * These types require an Integer operand. We can convert
62895b482a8SLen Brown * a Buffer or a String to an Integer if necessary.
62995b482a8SLen Brown */
63095b482a8SLen Brown status =
63195b482a8SLen Brown acpi_ex_convert_to_integer(source_desc, result_desc,
632fe97d287SBob Moore ACPI_IMPLICIT_CONVERSION);
63395b482a8SLen Brown break;
63495b482a8SLen Brown
63595b482a8SLen Brown case ACPI_TYPE_STRING:
63695b482a8SLen Brown /*
63795b482a8SLen Brown * The operand must be a String. We can convert an
63895b482a8SLen Brown * Integer or Buffer if necessary
63995b482a8SLen Brown */
64095b482a8SLen Brown status =
64195b482a8SLen Brown acpi_ex_convert_to_string(source_desc, result_desc,
64295b482a8SLen Brown ACPI_IMPLICIT_CONVERT_HEX);
64395b482a8SLen Brown break;
64495b482a8SLen Brown
64595b482a8SLen Brown case ACPI_TYPE_BUFFER:
64695b482a8SLen Brown /*
64795b482a8SLen Brown * The operand must be a Buffer. We can convert an
64895b482a8SLen Brown * Integer or String if necessary
64995b482a8SLen Brown */
65095b482a8SLen Brown status =
65195b482a8SLen Brown acpi_ex_convert_to_buffer(source_desc, result_desc);
65295b482a8SLen Brown break;
65395b482a8SLen Brown
65495b482a8SLen Brown default:
6551d1ea1b7SChao Guan
65695b482a8SLen Brown ACPI_ERROR((AE_INFO,
657f6a22b0bSBob Moore "Bad destination type during conversion: 0x%X",
65895b482a8SLen Brown destination_type));
65995b482a8SLen Brown status = AE_AML_INTERNAL;
66095b482a8SLen Brown break;
66195b482a8SLen Brown }
66295b482a8SLen Brown break;
66395b482a8SLen Brown
66495b482a8SLen Brown case ARGI_REFERENCE:
66595b482a8SLen Brown /*
66695b482a8SLen Brown * create_xxxx_field cases - we are storing the field object into the name
66795b482a8SLen Brown */
66895b482a8SLen Brown break;
66995b482a8SLen Brown
67095b482a8SLen Brown default:
6711d1ea1b7SChao Guan
67295b482a8SLen Brown ACPI_ERROR((AE_INFO,
673f6a22b0bSBob Moore "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s",
67495b482a8SLen Brown GET_CURRENT_ARG_TYPE(walk_state->op_info->
67595b482a8SLen Brown runtime_args),
67695b482a8SLen Brown walk_state->opcode,
67795b482a8SLen Brown acpi_ut_get_type_name(destination_type)));
67895b482a8SLen Brown status = AE_AML_INTERNAL;
67995b482a8SLen Brown }
68095b482a8SLen Brown
68195b482a8SLen Brown /*
68295b482a8SLen Brown * Source-to-Target conversion semantics:
68395b482a8SLen Brown *
68495b482a8SLen Brown * If conversion to the target type cannot be performed, then simply
68595b482a8SLen Brown * overwrite the target with the new object and type.
68695b482a8SLen Brown */
68795b482a8SLen Brown if (status == AE_TYPE) {
68895b482a8SLen Brown status = AE_OK;
68995b482a8SLen Brown }
69095b482a8SLen Brown
69195b482a8SLen Brown return_ACPI_STATUS(status);
69295b482a8SLen Brown }
693