xref: /openbmc/linux/drivers/acpi/acpica/exconvrt.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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