File Index
Files and directories
Sign in
FILE

exconvrt.c

File preview with syntax highlighting.

linux-6.19.14/drivers/acpi/acpica/exconvrt.c C
  1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2/******************************************************************************
  3 *
  4 * Module Name: exconvrt - Object conversion routines
  5 *
  6 * Copyright (C) 2000 - 2025, Intel Corp.
  7 *
  8 *****************************************************************************/
  9
 10#include <acpi/acpi.h>
 11#include "accommon.h"
 12#include "acinterp.h"
 13#include "amlcode.h"
 14
 15#define _COMPONENT          ACPI_EXECUTER
 16ACPI_MODULE_NAME("exconvrt")
 17
 18/* Local prototypes */
 19static u32
 20acpi_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_integer
 26 *
 27 * PARAMETERS:  obj_desc            - Object to be converted. Must be an
 28 *                                    Integer, Buffer, or String
 29 *              result_desc         - Where the new Integer object is returned
 30 *              implicit_conversion - Used for string conversion
 31 *
 32 * RETURN:      Status
 33 *
 34 * DESCRIPTION: Convert an ACPI Object to an integer.
 35 *
 36 ******************************************************************************/
 37
 38acpi_status
 39acpi_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 and
 75	 * strings are treated as raw data - we don't convert ascii to hex for
 76	 * strings.
 77	 *
 78	 * There are two terminating conditions for the loop:
 79	 * 1) The size of an integer has been reached, or
 80	 * 2) The end of the buffer or string has been reached
 81	 */
 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 be
 90		 * hexadecimal as per the ACPI specification. The only exception (as
 91		 * of ACPI 3.0) is that the to_integer() operator allows both decimal
 92		 * 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_PTR
100						       (char, pointer));
101		} else {
102			result =
103			    acpi_ut_explicit_strtoul64(ACPI_CAST_PTR
104						       (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 data
124		 * from the buffer to fill an integer
125		 */
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 buffer
130			 * is the LSB of the integer
131			 */
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_buffer
163 *
164 * PARAMETERS:  obj_desc        - Object to be converted. Must be an
165 *                                Integer, Buffer, or String
166 *              result_desc     - Where the new buffer object is returned
167 *
168 * RETURN:      Status
169 *
170 * DESCRIPTION: Convert an ACPI Object to a Buffer
171 *
172 ******************************************************************************/
173
174acpi_status
175acpi_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 integer
195		 */
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 object
212		 * Size will be the string length
213		 *
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 existing
216		 * ASL/AML code that depends on the null being transferred to the new
217		 * 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		memcpy((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_ascii
248 *
249 * PARAMETERS:  integer         - Value to be converted
250 *              base            - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
251 *              string          - Where the string is returned
252 *              data_width      - Size of data item to be converted, in bytes
253 *              leading_zeros   - Allow leading zeros
254 *
255 * RETURN:      Actual string length
256 *
257 * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
258 *
259 ******************************************************************************/
260
261static u32
262acpi_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 where
355	 * the integer equals 0
356	 *
357	 * Finally, null terminate the string and return the length
358	 */
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_string
371 *
372 * PARAMETERS:  obj_desc        - Object to be converted. Must be an
373 *                                Integer, Buffer, or String
374 *              result_desc     - Where the string object is returned
375 *              type            - String flags (base and conversion type)
376 *
377 * RETURN:      Status
378 *
379 * DESCRIPTION: Convert an ACPI Object to a string. Supports both implicit
380 *              and explicit conversions and related rules.
381 *
382 ******************************************************************************/
383
384acpi_status
385acpi_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 size
414			 */
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 String
441		 * 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 a
489			 * 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 values
496			 * 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 conversion
512			 *
513			 * From the ACPI spec:
514			 * "The entire contents of the buffer are converted to a string of
515			 * 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 of
529			 * 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 buffer
544		 * (-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 values
561		 * (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 string
584		 * (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_type
604 *
605 * PARAMETERS:  destination_type    - Current type of the destination
606 *              source_desc         - Source object to be converted.
607 *              result_desc         - Where the converted object is returned
608 *              walk_state          - Current method state
609 *
610 * RETURN:      Status
611 *
612 * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
613 *
614 ******************************************************************************/
615
616acpi_status
617acpi_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 conversions
643			 */
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_name
654						  (source_desc),
655						  acpi_ut_get_type_name
656						  (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 convert
672			 * 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 an
682			 * Integer or Buffer if necessary
683			 */
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 an
692			 * Integer or String if necessary
693			 */
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 name
711		 */
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 simply
729	 * 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}
~/ Read-only file preview.