brintos

brintos / linux-shallow public Read only

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