162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: exconvrt - Object conversion routines
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *****************************************************************************/
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <acpi/acpi.h>
1162306a36Sopenharmony_ci#include "accommon.h"
1262306a36Sopenharmony_ci#include "acinterp.h"
1362306a36Sopenharmony_ci#include "amlcode.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define _COMPONENT          ACPI_EXECUTER
1662306a36Sopenharmony_ciACPI_MODULE_NAME("exconvrt")
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* Local prototypes */
1962306a36Sopenharmony_cistatic u32
2062306a36Sopenharmony_ciacpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length);
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/*******************************************************************************
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * FUNCTION:    acpi_ex_convert_to_integer
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * PARAMETERS:  obj_desc            - Object to be converted. Must be an
2762306a36Sopenharmony_ci *                                    Integer, Buffer, or String
2862306a36Sopenharmony_ci *              result_desc         - Where the new Integer object is returned
2962306a36Sopenharmony_ci *              implicit_conversion - Used for string conversion
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * RETURN:      Status
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * DESCRIPTION: Convert an ACPI Object to an integer.
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci ******************************************************************************/
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ciacpi_status
3862306a36Sopenharmony_ciacpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
3962306a36Sopenharmony_ci			   union acpi_operand_object **result_desc,
4062306a36Sopenharmony_ci			   u32 implicit_conversion)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	union acpi_operand_object *return_desc;
4362306a36Sopenharmony_ci	u8 *pointer;
4462306a36Sopenharmony_ci	u64 result;
4562306a36Sopenharmony_ci	u32 i;
4662306a36Sopenharmony_ci	u32 count;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	switch (obj_desc->common.type) {
5162306a36Sopenharmony_ci	case ACPI_TYPE_INTEGER:
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci		/* No conversion necessary */
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci		*result_desc = obj_desc;
5662306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	case ACPI_TYPE_BUFFER:
5962306a36Sopenharmony_ci	case ACPI_TYPE_STRING:
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci		/* Note: Takes advantage of common buffer/string fields */
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci		pointer = obj_desc->buffer.pointer;
6462306a36Sopenharmony_ci		count = obj_desc->buffer.length;
6562306a36Sopenharmony_ci		break;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	default:
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci		return_ACPI_STATUS(AE_TYPE);
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	/*
7362306a36Sopenharmony_ci	 * Convert the buffer/string to an integer. Note that both buffers and
7462306a36Sopenharmony_ci	 * strings are treated as raw data - we don't convert ascii to hex for
7562306a36Sopenharmony_ci	 * strings.
7662306a36Sopenharmony_ci	 *
7762306a36Sopenharmony_ci	 * There are two terminating conditions for the loop:
7862306a36Sopenharmony_ci	 * 1) The size of an integer has been reached, or
7962306a36Sopenharmony_ci	 * 2) The end of the buffer or string has been reached
8062306a36Sopenharmony_ci	 */
8162306a36Sopenharmony_ci	result = 0;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/* String conversion is different than Buffer conversion */
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	switch (obj_desc->common.type) {
8662306a36Sopenharmony_ci	case ACPI_TYPE_STRING:
8762306a36Sopenharmony_ci		/*
8862306a36Sopenharmony_ci		 * Convert string to an integer - for most cases, the string must be
8962306a36Sopenharmony_ci		 * hexadecimal as per the ACPI specification. The only exception (as
9062306a36Sopenharmony_ci		 * of ACPI 3.0) is that the to_integer() operator allows both decimal
9162306a36Sopenharmony_ci		 * and hexadecimal strings (hex prefixed with "0x").
9262306a36Sopenharmony_ci		 *
9362306a36Sopenharmony_ci		 * Explicit conversion is used only by to_integer.
9462306a36Sopenharmony_ci		 * All other string-to-integer conversions are implicit conversions.
9562306a36Sopenharmony_ci		 */
9662306a36Sopenharmony_ci		if (implicit_conversion) {
9762306a36Sopenharmony_ci			result =
9862306a36Sopenharmony_ci			    acpi_ut_implicit_strtoul64(ACPI_CAST_PTR
9962306a36Sopenharmony_ci						       (char, pointer));
10062306a36Sopenharmony_ci		} else {
10162306a36Sopenharmony_ci			result =
10262306a36Sopenharmony_ci			    acpi_ut_explicit_strtoul64(ACPI_CAST_PTR
10362306a36Sopenharmony_ci						       (char, pointer));
10462306a36Sopenharmony_ci		}
10562306a36Sopenharmony_ci		break;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	case ACPI_TYPE_BUFFER:
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci		/* Check for zero-length buffer */
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		if (!count) {
11262306a36Sopenharmony_ci			return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
11362306a36Sopenharmony_ci		}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci		/* Transfer no more than an integer's worth of data */
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci		if (count > acpi_gbl_integer_byte_width) {
11862306a36Sopenharmony_ci			count = acpi_gbl_integer_byte_width;
11962306a36Sopenharmony_ci		}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci		/*
12262306a36Sopenharmony_ci		 * Convert buffer to an integer - we simply grab enough raw data
12362306a36Sopenharmony_ci		 * from the buffer to fill an integer
12462306a36Sopenharmony_ci		 */
12562306a36Sopenharmony_ci		for (i = 0; i < count; i++) {
12662306a36Sopenharmony_ci			/*
12762306a36Sopenharmony_ci			 * Get next byte and shift it into the Result.
12862306a36Sopenharmony_ci			 * Little endian is used, meaning that the first byte of the buffer
12962306a36Sopenharmony_ci			 * is the LSB of the integer
13062306a36Sopenharmony_ci			 */
13162306a36Sopenharmony_ci			result |= (((u64) pointer[i]) << (i * 8));
13262306a36Sopenharmony_ci		}
13362306a36Sopenharmony_ci		break;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	default:
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci		/* No other types can get here */
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci		break;
14062306a36Sopenharmony_ci	}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	/* Create a new integer */
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	return_desc = acpi_ut_create_integer_object(result);
14562306a36Sopenharmony_ci	if (!return_desc) {
14662306a36Sopenharmony_ci		return_ACPI_STATUS(AE_NO_MEMORY);
14762306a36Sopenharmony_ci	}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
15062306a36Sopenharmony_ci			  ACPI_FORMAT_UINT64(result)));
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	/* Save the Result */
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	(void)acpi_ex_truncate_for32bit_table(return_desc);
15562306a36Sopenharmony_ci	*result_desc = return_desc;
15662306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci/*******************************************************************************
16062306a36Sopenharmony_ci *
16162306a36Sopenharmony_ci * FUNCTION:    acpi_ex_convert_to_buffer
16262306a36Sopenharmony_ci *
16362306a36Sopenharmony_ci * PARAMETERS:  obj_desc        - Object to be converted. Must be an
16462306a36Sopenharmony_ci *                                Integer, Buffer, or String
16562306a36Sopenharmony_ci *              result_desc     - Where the new buffer object is returned
16662306a36Sopenharmony_ci *
16762306a36Sopenharmony_ci * RETURN:      Status
16862306a36Sopenharmony_ci *
16962306a36Sopenharmony_ci * DESCRIPTION: Convert an ACPI Object to a Buffer
17062306a36Sopenharmony_ci *
17162306a36Sopenharmony_ci ******************************************************************************/
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ciacpi_status
17462306a36Sopenharmony_ciacpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
17562306a36Sopenharmony_ci			  union acpi_operand_object **result_desc)
17662306a36Sopenharmony_ci{
17762306a36Sopenharmony_ci	union acpi_operand_object *return_desc;
17862306a36Sopenharmony_ci	u8 *new_buf;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc);
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	switch (obj_desc->common.type) {
18362306a36Sopenharmony_ci	case ACPI_TYPE_BUFFER:
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci		/* No conversion necessary */
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci		*result_desc = obj_desc;
18862306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	case ACPI_TYPE_INTEGER:
19162306a36Sopenharmony_ci		/*
19262306a36Sopenharmony_ci		 * Create a new Buffer object.
19362306a36Sopenharmony_ci		 * Need enough space for one integer
19462306a36Sopenharmony_ci		 */
19562306a36Sopenharmony_ci		return_desc =
19662306a36Sopenharmony_ci		    acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width);
19762306a36Sopenharmony_ci		if (!return_desc) {
19862306a36Sopenharmony_ci			return_ACPI_STATUS(AE_NO_MEMORY);
19962306a36Sopenharmony_ci		}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci		/* Copy the integer to the buffer, LSB first */
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci		new_buf = return_desc->buffer.pointer;
20462306a36Sopenharmony_ci		memcpy(new_buf, &obj_desc->integer.value,
20562306a36Sopenharmony_ci		       acpi_gbl_integer_byte_width);
20662306a36Sopenharmony_ci		break;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	case ACPI_TYPE_STRING:
20962306a36Sopenharmony_ci		/*
21062306a36Sopenharmony_ci		 * Create a new Buffer object
21162306a36Sopenharmony_ci		 * Size will be the string length
21262306a36Sopenharmony_ci		 *
21362306a36Sopenharmony_ci		 * NOTE: Add one to the string length to include the null terminator.
21462306a36Sopenharmony_ci		 * The ACPI spec is unclear on this subject, but there is existing
21562306a36Sopenharmony_ci		 * ASL/AML code that depends on the null being transferred to the new
21662306a36Sopenharmony_ci		 * buffer.
21762306a36Sopenharmony_ci		 */
21862306a36Sopenharmony_ci		return_desc = acpi_ut_create_buffer_object((acpi_size)
21962306a36Sopenharmony_ci							   obj_desc->string.
22062306a36Sopenharmony_ci							   length + 1);
22162306a36Sopenharmony_ci		if (!return_desc) {
22262306a36Sopenharmony_ci			return_ACPI_STATUS(AE_NO_MEMORY);
22362306a36Sopenharmony_ci		}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci		/* Copy the string to the buffer */
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci		new_buf = return_desc->buffer.pointer;
22862306a36Sopenharmony_ci		strncpy((char *)new_buf, (char *)obj_desc->string.pointer,
22962306a36Sopenharmony_ci			obj_desc->string.length);
23062306a36Sopenharmony_ci		break;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	default:
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci		return_ACPI_STATUS(AE_TYPE);
23562306a36Sopenharmony_ci	}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* Mark buffer initialized */
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	return_desc->common.flags |= AOPOBJ_DATA_VALID;
24062306a36Sopenharmony_ci	*result_desc = return_desc;
24162306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
24262306a36Sopenharmony_ci}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci/*******************************************************************************
24562306a36Sopenharmony_ci *
24662306a36Sopenharmony_ci * FUNCTION:    acpi_ex_convert_to_ascii
24762306a36Sopenharmony_ci *
24862306a36Sopenharmony_ci * PARAMETERS:  integer         - Value to be converted
24962306a36Sopenharmony_ci *              base            - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
25062306a36Sopenharmony_ci *              string          - Where the string is returned
25162306a36Sopenharmony_ci *              data_width      - Size of data item to be converted, in bytes
25262306a36Sopenharmony_ci *
25362306a36Sopenharmony_ci * RETURN:      Actual string length
25462306a36Sopenharmony_ci *
25562306a36Sopenharmony_ci * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
25662306a36Sopenharmony_ci *
25762306a36Sopenharmony_ci ******************************************************************************/
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_cistatic u32
26062306a36Sopenharmony_ciacpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	u64 digit;
26362306a36Sopenharmony_ci	u32 i;
26462306a36Sopenharmony_ci	u32 j;
26562306a36Sopenharmony_ci	u32 k = 0;
26662306a36Sopenharmony_ci	u32 hex_length;
26762306a36Sopenharmony_ci	u32 decimal_length;
26862306a36Sopenharmony_ci	u32 remainder;
26962306a36Sopenharmony_ci	u8 supress_zeros;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	ACPI_FUNCTION_ENTRY();
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	switch (base) {
27462306a36Sopenharmony_ci	case 10:
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci		/* Setup max length for the decimal number */
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci		switch (data_width) {
27962306a36Sopenharmony_ci		case 1:
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci			decimal_length = ACPI_MAX8_DECIMAL_DIGITS;
28262306a36Sopenharmony_ci			break;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci		case 4:
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci			decimal_length = ACPI_MAX32_DECIMAL_DIGITS;
28762306a36Sopenharmony_ci			break;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci		case 8:
29062306a36Sopenharmony_ci		default:
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci			decimal_length = ACPI_MAX64_DECIMAL_DIGITS;
29362306a36Sopenharmony_ci			break;
29462306a36Sopenharmony_ci		}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci		supress_zeros = TRUE;	/* No leading zeros */
29762306a36Sopenharmony_ci		remainder = 0;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci		for (i = decimal_length; i > 0; i--) {
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci			/* Divide by nth factor of 10 */
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci			digit = integer;
30462306a36Sopenharmony_ci			for (j = 0; j < i; j++) {
30562306a36Sopenharmony_ci				(void)acpi_ut_short_divide(digit, 10, &digit,
30662306a36Sopenharmony_ci							   &remainder);
30762306a36Sopenharmony_ci			}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci			/* Handle leading zeros */
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci			if (remainder != 0) {
31262306a36Sopenharmony_ci				supress_zeros = FALSE;
31362306a36Sopenharmony_ci			}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci			if (!supress_zeros) {
31662306a36Sopenharmony_ci				string[k] = (u8) (ACPI_ASCII_ZERO + remainder);
31762306a36Sopenharmony_ci				k++;
31862306a36Sopenharmony_ci			}
31962306a36Sopenharmony_ci		}
32062306a36Sopenharmony_ci		break;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	case 16:
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci		/* hex_length: 2 ascii hex chars per data byte */
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci		hex_length = (data_width * 2);
32762306a36Sopenharmony_ci		for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci			/* Get one hex digit, most significant digits first */
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci			string[k] = (u8)
33262306a36Sopenharmony_ci			    acpi_ut_hex_to_ascii_char(integer, ACPI_MUL_4(j));
33362306a36Sopenharmony_ci			k++;
33462306a36Sopenharmony_ci		}
33562306a36Sopenharmony_ci		break;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	default:
33862306a36Sopenharmony_ci		return (0);
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	/*
34262306a36Sopenharmony_ci	 * Since leading zeros are suppressed, we must check for the case where
34362306a36Sopenharmony_ci	 * the integer equals 0
34462306a36Sopenharmony_ci	 *
34562306a36Sopenharmony_ci	 * Finally, null terminate the string and return the length
34662306a36Sopenharmony_ci	 */
34762306a36Sopenharmony_ci	if (!k) {
34862306a36Sopenharmony_ci		string[0] = ACPI_ASCII_ZERO;
34962306a36Sopenharmony_ci		k = 1;
35062306a36Sopenharmony_ci	}
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	string[k] = 0;
35362306a36Sopenharmony_ci	return ((u32) k);
35462306a36Sopenharmony_ci}
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci/*******************************************************************************
35762306a36Sopenharmony_ci *
35862306a36Sopenharmony_ci * FUNCTION:    acpi_ex_convert_to_string
35962306a36Sopenharmony_ci *
36062306a36Sopenharmony_ci * PARAMETERS:  obj_desc        - Object to be converted. Must be an
36162306a36Sopenharmony_ci *                                Integer, Buffer, or String
36262306a36Sopenharmony_ci *              result_desc     - Where the string object is returned
36362306a36Sopenharmony_ci *              type            - String flags (base and conversion type)
36462306a36Sopenharmony_ci *
36562306a36Sopenharmony_ci * RETURN:      Status
36662306a36Sopenharmony_ci *
36762306a36Sopenharmony_ci * DESCRIPTION: Convert an ACPI Object to a string. Supports both implicit
36862306a36Sopenharmony_ci *              and explicit conversions and related rules.
36962306a36Sopenharmony_ci *
37062306a36Sopenharmony_ci ******************************************************************************/
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ciacpi_status
37362306a36Sopenharmony_ciacpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
37462306a36Sopenharmony_ci			  union acpi_operand_object ** result_desc, u32 type)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	union acpi_operand_object *return_desc;
37762306a36Sopenharmony_ci	u8 *new_buf;
37862306a36Sopenharmony_ci	u32 i;
37962306a36Sopenharmony_ci	u32 string_length = 0;
38062306a36Sopenharmony_ci	u16 base = 16;
38162306a36Sopenharmony_ci	u8 separator = ',';
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	switch (obj_desc->common.type) {
38662306a36Sopenharmony_ci	case ACPI_TYPE_STRING:
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci		/* No conversion necessary */
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci		*result_desc = obj_desc;
39162306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	case ACPI_TYPE_INTEGER:
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci		switch (type) {
39662306a36Sopenharmony_ci		case ACPI_EXPLICIT_CONVERT_DECIMAL:
39762306a36Sopenharmony_ci			/*
39862306a36Sopenharmony_ci			 * From to_decimal_string, integer source.
39962306a36Sopenharmony_ci			 *
40062306a36Sopenharmony_ci			 * Make room for the maximum decimal number size
40162306a36Sopenharmony_ci			 */
40262306a36Sopenharmony_ci			string_length = ACPI_MAX_DECIMAL_DIGITS;
40362306a36Sopenharmony_ci			base = 10;
40462306a36Sopenharmony_ci			break;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci		default:
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci			/* Two hex string characters for each integer byte */
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci			string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width);
41162306a36Sopenharmony_ci			break;
41262306a36Sopenharmony_ci		}
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci		/*
41562306a36Sopenharmony_ci		 * Create a new String
41662306a36Sopenharmony_ci		 * Need enough space for one ASCII integer (plus null terminator)
41762306a36Sopenharmony_ci		 */
41862306a36Sopenharmony_ci		return_desc =
41962306a36Sopenharmony_ci		    acpi_ut_create_string_object((acpi_size)string_length);
42062306a36Sopenharmony_ci		if (!return_desc) {
42162306a36Sopenharmony_ci			return_ACPI_STATUS(AE_NO_MEMORY);
42262306a36Sopenharmony_ci		}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci		new_buf = return_desc->buffer.pointer;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci		/* Convert integer to string */
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci		string_length =
42962306a36Sopenharmony_ci		    acpi_ex_convert_to_ascii(obj_desc->integer.value, base,
43062306a36Sopenharmony_ci					     new_buf,
43162306a36Sopenharmony_ci					     acpi_gbl_integer_byte_width);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci		/* Null terminate at the correct place */
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci		return_desc->string.length = string_length;
43662306a36Sopenharmony_ci		new_buf[string_length] = 0;
43762306a36Sopenharmony_ci		break;
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	case ACPI_TYPE_BUFFER:
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci		/* Setup string length, base, and separator */
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci		switch (type) {
44462306a36Sopenharmony_ci		case ACPI_EXPLICIT_CONVERT_DECIMAL:	/* Used by to_decimal_string */
44562306a36Sopenharmony_ci			/*
44662306a36Sopenharmony_ci			 * Explicit conversion from the to_decimal_string ASL operator.
44762306a36Sopenharmony_ci			 *
44862306a36Sopenharmony_ci			 * From ACPI: "If the input is a buffer, it is converted to a
44962306a36Sopenharmony_ci			 * a string of decimal values separated by commas."
45062306a36Sopenharmony_ci			 */
45162306a36Sopenharmony_ci			base = 10;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci			/*
45462306a36Sopenharmony_ci			 * Calculate the final string length. Individual string values
45562306a36Sopenharmony_ci			 * are variable length (include separator for each)
45662306a36Sopenharmony_ci			 */
45762306a36Sopenharmony_ci			for (i = 0; i < obj_desc->buffer.length; i++) {
45862306a36Sopenharmony_ci				if (obj_desc->buffer.pointer[i] >= 100) {
45962306a36Sopenharmony_ci					string_length += 4;
46062306a36Sopenharmony_ci				} else if (obj_desc->buffer.pointer[i] >= 10) {
46162306a36Sopenharmony_ci					string_length += 3;
46262306a36Sopenharmony_ci				} else {
46362306a36Sopenharmony_ci					string_length += 2;
46462306a36Sopenharmony_ci				}
46562306a36Sopenharmony_ci			}
46662306a36Sopenharmony_ci			break;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci		case ACPI_IMPLICIT_CONVERT_HEX:
46962306a36Sopenharmony_ci			/*
47062306a36Sopenharmony_ci			 * Implicit buffer-to-string conversion
47162306a36Sopenharmony_ci			 *
47262306a36Sopenharmony_ci			 * From the ACPI spec:
47362306a36Sopenharmony_ci			 * "The entire contents of the buffer are converted to a string of
47462306a36Sopenharmony_ci			 * two-character hexadecimal numbers, each separated by a space."
47562306a36Sopenharmony_ci			 *
47662306a36Sopenharmony_ci			 * Each hex number is prefixed with 0x (11/2018)
47762306a36Sopenharmony_ci			 */
47862306a36Sopenharmony_ci			separator = ' ';
47962306a36Sopenharmony_ci			string_length = (obj_desc->buffer.length * 5);
48062306a36Sopenharmony_ci			break;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci		case ACPI_EXPLICIT_CONVERT_HEX:
48362306a36Sopenharmony_ci			/*
48462306a36Sopenharmony_ci			 * Explicit conversion from the to_hex_string ASL operator.
48562306a36Sopenharmony_ci			 *
48662306a36Sopenharmony_ci			 * From ACPI: "If Data is a buffer, it is converted to a string of
48762306a36Sopenharmony_ci			 * hexadecimal values separated by commas."
48862306a36Sopenharmony_ci			 *
48962306a36Sopenharmony_ci			 * Each hex number is prefixed with 0x (11/2018)
49062306a36Sopenharmony_ci			 */
49162306a36Sopenharmony_ci			separator = ',';
49262306a36Sopenharmony_ci			string_length = (obj_desc->buffer.length * 5);
49362306a36Sopenharmony_ci			break;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci		default:
49662306a36Sopenharmony_ci			return_ACPI_STATUS(AE_BAD_PARAMETER);
49762306a36Sopenharmony_ci		}
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci		/*
50062306a36Sopenharmony_ci		 * Create a new string object and string buffer
50162306a36Sopenharmony_ci		 * (-1 because of extra separator included in string_length from above)
50262306a36Sopenharmony_ci		 * Allow creation of zero-length strings from zero-length buffers.
50362306a36Sopenharmony_ci		 */
50462306a36Sopenharmony_ci		if (string_length) {
50562306a36Sopenharmony_ci			string_length--;
50662306a36Sopenharmony_ci		}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci		return_desc =
50962306a36Sopenharmony_ci		    acpi_ut_create_string_object((acpi_size)string_length);
51062306a36Sopenharmony_ci		if (!return_desc) {
51162306a36Sopenharmony_ci			return_ACPI_STATUS(AE_NO_MEMORY);
51262306a36Sopenharmony_ci		}
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci		new_buf = return_desc->buffer.pointer;
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci		/*
51762306a36Sopenharmony_ci		 * Convert buffer bytes to hex or decimal values
51862306a36Sopenharmony_ci		 * (separated by commas or spaces)
51962306a36Sopenharmony_ci		 */
52062306a36Sopenharmony_ci		for (i = 0; i < obj_desc->buffer.length; i++) {
52162306a36Sopenharmony_ci			if (base == 16) {
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci				/* Emit 0x prefix for explicit/implicit hex conversion */
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci				*new_buf++ = '0';
52662306a36Sopenharmony_ci				*new_buf++ = 'x';
52762306a36Sopenharmony_ci			}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci			new_buf += acpi_ex_convert_to_ascii((u64) obj_desc->
53062306a36Sopenharmony_ci							    buffer.pointer[i],
53162306a36Sopenharmony_ci							    base, new_buf, 1);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci			/* Each digit is separated by either a comma or space */
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci			*new_buf++ = separator;
53662306a36Sopenharmony_ci		}
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci		/*
53962306a36Sopenharmony_ci		 * Null terminate the string
54062306a36Sopenharmony_ci		 * (overwrites final comma/space from above)
54162306a36Sopenharmony_ci		 */
54262306a36Sopenharmony_ci		if (obj_desc->buffer.length) {
54362306a36Sopenharmony_ci			new_buf--;
54462306a36Sopenharmony_ci		}
54562306a36Sopenharmony_ci		*new_buf = 0;
54662306a36Sopenharmony_ci		break;
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	default:
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci		return_ACPI_STATUS(AE_TYPE);
55162306a36Sopenharmony_ci	}
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	*result_desc = return_desc;
55462306a36Sopenharmony_ci	return_ACPI_STATUS(AE_OK);
55562306a36Sopenharmony_ci}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci/*******************************************************************************
55862306a36Sopenharmony_ci *
55962306a36Sopenharmony_ci * FUNCTION:    acpi_ex_convert_to_target_type
56062306a36Sopenharmony_ci *
56162306a36Sopenharmony_ci * PARAMETERS:  destination_type    - Current type of the destination
56262306a36Sopenharmony_ci *              source_desc         - Source object to be converted.
56362306a36Sopenharmony_ci *              result_desc         - Where the converted object is returned
56462306a36Sopenharmony_ci *              walk_state          - Current method state
56562306a36Sopenharmony_ci *
56662306a36Sopenharmony_ci * RETURN:      Status
56762306a36Sopenharmony_ci *
56862306a36Sopenharmony_ci * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
56962306a36Sopenharmony_ci *
57062306a36Sopenharmony_ci ******************************************************************************/
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ciacpi_status
57362306a36Sopenharmony_ciacpi_ex_convert_to_target_type(acpi_object_type destination_type,
57462306a36Sopenharmony_ci			       union acpi_operand_object *source_desc,
57562306a36Sopenharmony_ci			       union acpi_operand_object **result_desc,
57662306a36Sopenharmony_ci			       struct acpi_walk_state *walk_state)
57762306a36Sopenharmony_ci{
57862306a36Sopenharmony_ci	acpi_status status = AE_OK;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ex_convert_to_target_type);
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	/* Default behavior */
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	*result_desc = source_desc;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	/*
58762306a36Sopenharmony_ci	 * If required by the target,
58862306a36Sopenharmony_ci	 * perform implicit conversion on the source before we store it.
58962306a36Sopenharmony_ci	 */
59062306a36Sopenharmony_ci	switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) {
59162306a36Sopenharmony_ci	case ARGI_SIMPLE_TARGET:
59262306a36Sopenharmony_ci	case ARGI_FIXED_TARGET:
59362306a36Sopenharmony_ci	case ARGI_INTEGER_REF:	/* Handles Increment, Decrement cases */
59462306a36Sopenharmony_ci
59562306a36Sopenharmony_ci		switch (destination_type) {
59662306a36Sopenharmony_ci		case ACPI_TYPE_LOCAL_REGION_FIELD:
59762306a36Sopenharmony_ci			/*
59862306a36Sopenharmony_ci			 * Named field can always handle conversions
59962306a36Sopenharmony_ci			 */
60062306a36Sopenharmony_ci			break;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci		default:
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci			/* No conversion allowed for these types */
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci			if (destination_type != source_desc->common.type) {
60762306a36Sopenharmony_ci				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
60862306a36Sopenharmony_ci						  "Explicit operator, will store (%s) over existing type (%s)\n",
60962306a36Sopenharmony_ci						  acpi_ut_get_object_type_name
61062306a36Sopenharmony_ci						  (source_desc),
61162306a36Sopenharmony_ci						  acpi_ut_get_type_name
61262306a36Sopenharmony_ci						  (destination_type)));
61362306a36Sopenharmony_ci				status = AE_TYPE;
61462306a36Sopenharmony_ci			}
61562306a36Sopenharmony_ci		}
61662306a36Sopenharmony_ci		break;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	case ARGI_TARGETREF:
61962306a36Sopenharmony_ci	case ARGI_STORE_TARGET:
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci		switch (destination_type) {
62262306a36Sopenharmony_ci		case ACPI_TYPE_INTEGER:
62362306a36Sopenharmony_ci		case ACPI_TYPE_BUFFER_FIELD:
62462306a36Sopenharmony_ci		case ACPI_TYPE_LOCAL_BANK_FIELD:
62562306a36Sopenharmony_ci		case ACPI_TYPE_LOCAL_INDEX_FIELD:
62662306a36Sopenharmony_ci			/*
62762306a36Sopenharmony_ci			 * These types require an Integer operand. We can convert
62862306a36Sopenharmony_ci			 * a Buffer or a String to an Integer if necessary.
62962306a36Sopenharmony_ci			 */
63062306a36Sopenharmony_ci			status =
63162306a36Sopenharmony_ci			    acpi_ex_convert_to_integer(source_desc, result_desc,
63262306a36Sopenharmony_ci						       ACPI_IMPLICIT_CONVERSION);
63362306a36Sopenharmony_ci			break;
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci		case ACPI_TYPE_STRING:
63662306a36Sopenharmony_ci			/*
63762306a36Sopenharmony_ci			 * The operand must be a String. We can convert an
63862306a36Sopenharmony_ci			 * Integer or Buffer if necessary
63962306a36Sopenharmony_ci			 */
64062306a36Sopenharmony_ci			status =
64162306a36Sopenharmony_ci			    acpi_ex_convert_to_string(source_desc, result_desc,
64262306a36Sopenharmony_ci						      ACPI_IMPLICIT_CONVERT_HEX);
64362306a36Sopenharmony_ci			break;
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci		case ACPI_TYPE_BUFFER:
64662306a36Sopenharmony_ci			/*
64762306a36Sopenharmony_ci			 * The operand must be a Buffer. We can convert an
64862306a36Sopenharmony_ci			 * Integer or String if necessary
64962306a36Sopenharmony_ci			 */
65062306a36Sopenharmony_ci			status =
65162306a36Sopenharmony_ci			    acpi_ex_convert_to_buffer(source_desc, result_desc);
65262306a36Sopenharmony_ci			break;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci		default:
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO,
65762306a36Sopenharmony_ci				    "Bad destination type during conversion: 0x%X",
65862306a36Sopenharmony_ci				    destination_type));
65962306a36Sopenharmony_ci			status = AE_AML_INTERNAL;
66062306a36Sopenharmony_ci			break;
66162306a36Sopenharmony_ci		}
66262306a36Sopenharmony_ci		break;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	case ARGI_REFERENCE:
66562306a36Sopenharmony_ci		/*
66662306a36Sopenharmony_ci		 * create_xxxx_field cases - we are storing the field object into the name
66762306a36Sopenharmony_ci		 */
66862306a36Sopenharmony_ci		break;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	default:
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
67362306a36Sopenharmony_ci			    "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s",
67462306a36Sopenharmony_ci			    GET_CURRENT_ARG_TYPE(walk_state->op_info->
67562306a36Sopenharmony_ci						 runtime_args),
67662306a36Sopenharmony_ci			    walk_state->opcode,
67762306a36Sopenharmony_ci			    acpi_ut_get_type_name(destination_type)));
67862306a36Sopenharmony_ci		status = AE_AML_INTERNAL;
67962306a36Sopenharmony_ci	}
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	/*
68262306a36Sopenharmony_ci	 * Source-to-Target conversion semantics:
68362306a36Sopenharmony_ci	 *
68462306a36Sopenharmony_ci	 * If conversion to the target type cannot be performed, then simply
68562306a36Sopenharmony_ci	 * overwrite the target with the new object and type.
68662306a36Sopenharmony_ci	 */
68762306a36Sopenharmony_ci	if (status == AE_TYPE) {
68862306a36Sopenharmony_ci		status = AE_OK;
68962306a36Sopenharmony_ci	}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	return_ACPI_STATUS(status);
69262306a36Sopenharmony_ci}
693