xref: /openbmc/linux/drivers/acpi/acpica/utprint.c (revision 612c2932)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: utprint - Formatted printing routines
5  *
6  * Copyright (C) 2000 - 2023, Intel Corp.
7  *
8  *****************************************************************************/
9 
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 
13 #define _COMPONENT          ACPI_UTILITIES
14 ACPI_MODULE_NAME("utprint")
15 
16 #define ACPI_FORMAT_SIGN            0x01
17 #define ACPI_FORMAT_SIGN_PLUS       0x02
18 #define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04
19 #define ACPI_FORMAT_ZERO            0x08
20 #define ACPI_FORMAT_LEFT            0x10
21 #define ACPI_FORMAT_UPPER           0x20
22 #define ACPI_FORMAT_PREFIX          0x40
23 /* Local prototypes */
24 static acpi_size
25 acpi_ut_bound_string_length(const char *string, acpi_size count);
26 
27 static char *acpi_ut_bound_string_output(char *string, const char *end, char c);
28 
29 static char *acpi_ut_format_number(char *string,
30 				   char *end,
31 				   u64 number,
32 				   u8 base, s32 width, s32 precision, u8 type);
33 
34 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper);
35 
36 /*******************************************************************************
37  *
38  * FUNCTION:    acpi_ut_bound_string_length
39  *
40  * PARAMETERS:  string              - String with boundary
41  *              count               - Boundary of the string
42  *
43  * RETURN:      Length of the string. Less than or equal to Count.
44  *
45  * DESCRIPTION: Calculate the length of a string with boundary.
46  *
47  ******************************************************************************/
48 
49 static acpi_size
acpi_ut_bound_string_length(const char * string,acpi_size count)50 acpi_ut_bound_string_length(const char *string, acpi_size count)
51 {
52 	u32 length = 0;
53 
54 	while (*string && count) {
55 		length++;
56 		string++;
57 		count--;
58 	}
59 
60 	return (length);
61 }
62 
63 /*******************************************************************************
64  *
65  * FUNCTION:    acpi_ut_bound_string_output
66  *
67  * PARAMETERS:  string              - String with boundary
68  *              end                 - Boundary of the string
69  *              c                   - Character to be output to the string
70  *
71  * RETURN:      Updated position for next valid character
72  *
73  * DESCRIPTION: Output a character into a string with boundary check.
74  *
75  ******************************************************************************/
76 
acpi_ut_bound_string_output(char * string,const char * end,char c)77 static char *acpi_ut_bound_string_output(char *string, const char *end, char c)
78 {
79 
80 	if (string < end) {
81 		*string = c;
82 	}
83 
84 	++string;
85 	return (string);
86 }
87 
88 /*******************************************************************************
89  *
90  * FUNCTION:    acpi_ut_put_number
91  *
92  * PARAMETERS:  string              - Buffer to hold reverse-ordered string
93  *              number              - Integer to be converted
94  *              base                - Base of the integer
95  *              upper               - Whether or not using upper cased digits
96  *
97  * RETURN:      Updated position for next valid character
98  *
99  * DESCRIPTION: Convert an integer into a string, note that, the string holds a
100  *              reversed ordered number without the trailing zero.
101  *
102  ******************************************************************************/
103 
acpi_ut_put_number(char * string,u64 number,u8 base,u8 upper)104 static char *acpi_ut_put_number(char *string, u64 number, u8 base, u8 upper)
105 {
106 	const char *digits;
107 	u64 digit_index;
108 	char *pos;
109 
110 	pos = string;
111 	digits = upper ? acpi_gbl_upper_hex_digits : acpi_gbl_lower_hex_digits;
112 
113 	if (number == 0) {
114 		*(pos++) = '0';
115 	} else {
116 		while (number) {
117 			(void)acpi_ut_divide(number, base, &number,
118 					     &digit_index);
119 			*(pos++) = digits[digit_index];
120 		}
121 	}
122 
123 	/* *(Pos++) = '0'; */
124 	return (pos);
125 }
126 
127 /*******************************************************************************
128  *
129  * FUNCTION:    acpi_ut_scan_number
130  *
131  * PARAMETERS:  string              - String buffer
132  *              number_ptr          - Where the number is returned
133  *
134  * RETURN:      Updated position for next valid character
135  *
136  * DESCRIPTION: Scan a string for a decimal integer.
137  *
138  ******************************************************************************/
139 
acpi_ut_scan_number(const char * string,u64 * number_ptr)140 const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
141 {
142 	u64 number = 0;
143 
144 	while (isdigit((int)*string)) {
145 		acpi_ut_short_multiply(number, 10, &number);
146 		number += *(string++) - '0';
147 	}
148 
149 	*number_ptr = number;
150 	return (string);
151 }
152 
153 /*******************************************************************************
154  *
155  * FUNCTION:    acpi_ut_print_number
156  *
157  * PARAMETERS:  string              - String buffer
158  *              number              - The number to be converted
159  *
160  * RETURN:      Updated position for next valid character
161  *
162  * DESCRIPTION: Print a decimal integer into a string.
163  *
164  ******************************************************************************/
165 
acpi_ut_print_number(char * string,u64 number)166 const char *acpi_ut_print_number(char *string, u64 number)
167 {
168 	char ascii_string[20];
169 	const char *pos1;
170 	char *pos2;
171 
172 	pos1 = acpi_ut_put_number(ascii_string, number, 10, FALSE);
173 	pos2 = string;
174 
175 	while (pos1 != ascii_string) {
176 		*(pos2++) = *(--pos1);
177 	}
178 
179 	*pos2 = 0;
180 	return (string);
181 }
182 
183 /*******************************************************************************
184  *
185  * FUNCTION:    acpi_ut_format_number
186  *
187  * PARAMETERS:  string              - String buffer with boundary
188  *              end                 - Boundary of the string
189  *              number              - The number to be converted
190  *              base                - Base of the integer
191  *              width               - Field width
192  *              precision           - Precision of the integer
193  *              type                - Special printing flags
194  *
195  * RETURN:      Updated position for next valid character
196  *
197  * DESCRIPTION: Print an integer into a string with any base and any precision.
198  *
199  ******************************************************************************/
200 
acpi_ut_format_number(char * string,char * end,u64 number,u8 base,s32 width,s32 precision,u8 type)201 static char *acpi_ut_format_number(char *string,
202 				   char *end,
203 				   u64 number,
204 				   u8 base, s32 width, s32 precision, u8 type)
205 {
206 	char *pos;
207 	char sign;
208 	char zero;
209 	u8 need_prefix;
210 	u8 upper;
211 	s32 i;
212 	char reversed_string[66];
213 
214 	/* Parameter validation */
215 
216 	if (base < 2 || base > 16) {
217 		return (NULL);
218 	}
219 
220 	if (type & ACPI_FORMAT_LEFT) {
221 		type &= ~ACPI_FORMAT_ZERO;
222 	}
223 
224 	need_prefix = ((type & ACPI_FORMAT_PREFIX)
225 		       && base != 10) ? TRUE : FALSE;
226 	upper = (type & ACPI_FORMAT_UPPER) ? TRUE : FALSE;
227 	zero = (type & ACPI_FORMAT_ZERO) ? '0' : ' ';
228 
229 	/* Calculate size according to sign and prefix */
230 
231 	sign = '\0';
232 	if (type & ACPI_FORMAT_SIGN) {
233 		if ((s64)number < 0) {
234 			sign = '-';
235 			number = -(s64)number;
236 			width--;
237 		} else if (type & ACPI_FORMAT_SIGN_PLUS) {
238 			sign = '+';
239 			width--;
240 		} else if (type & ACPI_FORMAT_SIGN_PLUS_SPACE) {
241 			sign = ' ';
242 			width--;
243 		}
244 	}
245 	if (need_prefix) {
246 		width--;
247 		if (base == 16) {
248 			width--;
249 		}
250 	}
251 
252 	/* Generate full string in reverse order */
253 
254 	pos = acpi_ut_put_number(reversed_string, number, base, upper);
255 	i = (s32)ACPI_PTR_DIFF(pos, reversed_string);
256 
257 	/* Printing 100 using %2d gives "100", not "00" */
258 
259 	if (i > precision) {
260 		precision = i;
261 	}
262 
263 	width -= precision;
264 
265 	/* Output the string */
266 
267 	if (!(type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) {
268 		while (--width >= 0) {
269 			string = acpi_ut_bound_string_output(string, end, ' ');
270 		}
271 	}
272 	if (sign) {
273 		string = acpi_ut_bound_string_output(string, end, sign);
274 	}
275 	if (need_prefix) {
276 		string = acpi_ut_bound_string_output(string, end, '0');
277 		if (base == 16) {
278 			string =
279 			    acpi_ut_bound_string_output(string, end,
280 							upper ? 'X' : 'x');
281 		}
282 	}
283 	if (!(type & ACPI_FORMAT_LEFT)) {
284 		while (--width >= 0) {
285 			string = acpi_ut_bound_string_output(string, end, zero);
286 		}
287 	}
288 
289 	while (i <= --precision) {
290 		string = acpi_ut_bound_string_output(string, end, '0');
291 	}
292 	while (--i >= 0) {
293 		string = acpi_ut_bound_string_output(string, end,
294 						     reversed_string[i]);
295 	}
296 	while (--width >= 0) {
297 		string = acpi_ut_bound_string_output(string, end, ' ');
298 	}
299 
300 	return (string);
301 }
302 
303 /*******************************************************************************
304  *
305  * FUNCTION:    vsnprintf
306  *
307  * PARAMETERS:  string              - String with boundary
308  *              size                - Boundary of the string
309  *              format              - Standard printf format
310  *              args                - Argument list
311  *
312  * RETURN:      Number of bytes actually written.
313  *
314  * DESCRIPTION: Formatted output to a string using argument list pointer.
315  *
316  ******************************************************************************/
317 
vsnprintf(char * string,acpi_size size,const char * format,va_list args)318 int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
319 {
320 	u8 base;
321 	u8 type;
322 	s32 width;
323 	s32 precision;
324 	char qualifier;
325 	u64 number;
326 	char *pos;
327 	char *end;
328 	char c;
329 	const char *s;
330 	const void *p;
331 	s32 length;
332 	int i;
333 
334 	pos = string;
335 
336 	if (size != ACPI_UINT32_MAX) {
337 		end = string + size;
338 	} else {
339 		end = ACPI_CAST_PTR(char, ACPI_UINT32_MAX);
340 	}
341 
342 	for (; *format; ++format) {
343 		if (*format != '%') {
344 			pos = acpi_ut_bound_string_output(pos, end, *format);
345 			continue;
346 		}
347 
348 		type = 0;
349 		base = 10;
350 
351 		/* Process sign */
352 
353 		do {
354 			++format;
355 			if (*format == '#') {
356 				type |= ACPI_FORMAT_PREFIX;
357 			} else if (*format == '0') {
358 				type |= ACPI_FORMAT_ZERO;
359 			} else if (*format == '+') {
360 				type |= ACPI_FORMAT_SIGN_PLUS;
361 			} else if (*format == ' ') {
362 				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
363 			} else if (*format == '-') {
364 				type |= ACPI_FORMAT_LEFT;
365 			} else {
366 				break;
367 			}
368 
369 		} while (1);
370 
371 		/* Process width */
372 
373 		width = -1;
374 		if (isdigit((int)*format)) {
375 			format = acpi_ut_scan_number(format, &number);
376 			width = (s32)number;
377 		} else if (*format == '*') {
378 			++format;
379 			width = va_arg(args, int);
380 			if (width < 0) {
381 				width = -width;
382 				type |= ACPI_FORMAT_LEFT;
383 			}
384 		}
385 
386 		/* Process precision */
387 
388 		precision = -1;
389 		if (*format == '.') {
390 			++format;
391 			if (isdigit((int)*format)) {
392 				format = acpi_ut_scan_number(format, &number);
393 				precision = (s32)number;
394 			} else if (*format == '*') {
395 				++format;
396 				precision = va_arg(args, int);
397 			}
398 
399 			if (precision < 0) {
400 				precision = 0;
401 			}
402 		}
403 
404 		/* Process qualifier */
405 
406 		qualifier = -1;
407 		if (*format == 'h' || *format == 'l' || *format == 'L') {
408 			qualifier = *format;
409 			++format;
410 
411 			if (qualifier == 'l' && *format == 'l') {
412 				qualifier = 'L';
413 				++format;
414 			}
415 		}
416 
417 		switch (*format) {
418 		case '%':
419 
420 			pos = acpi_ut_bound_string_output(pos, end, '%');
421 			continue;
422 
423 		case 'c':
424 
425 			if (!(type & ACPI_FORMAT_LEFT)) {
426 				while (--width > 0) {
427 					pos =
428 					    acpi_ut_bound_string_output(pos,
429 									end,
430 									' ');
431 				}
432 			}
433 
434 			c = (char)va_arg(args, int);
435 			pos = acpi_ut_bound_string_output(pos, end, c);
436 
437 			while (--width > 0) {
438 				pos =
439 				    acpi_ut_bound_string_output(pos, end, ' ');
440 			}
441 			continue;
442 
443 		case 's':
444 
445 			s = va_arg(args, char *);
446 			if (!s) {
447 				s = "<NULL>";
448 			}
449 			length = (s32)acpi_ut_bound_string_length(s, precision);
450 			if (!(type & ACPI_FORMAT_LEFT)) {
451 				while (length < width--) {
452 					pos =
453 					    acpi_ut_bound_string_output(pos,
454 									end,
455 									' ');
456 				}
457 			}
458 
459 			for (i = 0; i < length; ++i) {
460 				pos = acpi_ut_bound_string_output(pos, end, *s);
461 				++s;
462 			}
463 
464 			while (length < width--) {
465 				pos =
466 				    acpi_ut_bound_string_output(pos, end, ' ');
467 			}
468 			continue;
469 
470 		case 'o':
471 
472 			base = 8;
473 			break;
474 
475 		case 'X':
476 
477 			type |= ACPI_FORMAT_UPPER;
478 			ACPI_FALLTHROUGH;
479 
480 		case 'x':
481 
482 			base = 16;
483 			break;
484 
485 		case 'd':
486 		case 'i':
487 
488 			type |= ACPI_FORMAT_SIGN;
489 
490 		case 'u':
491 
492 			break;
493 
494 		case 'p':
495 
496 			if (width == -1) {
497 				width = 2 * sizeof(void *);
498 				type |= ACPI_FORMAT_ZERO;
499 			}
500 
501 			p = va_arg(args, void *);
502 			pos =
503 			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
504 						  16, width, precision, type);
505 			continue;
506 
507 		default:
508 
509 			pos = acpi_ut_bound_string_output(pos, end, '%');
510 			if (*format) {
511 				pos =
512 				    acpi_ut_bound_string_output(pos, end,
513 								*format);
514 			} else {
515 				--format;
516 			}
517 			continue;
518 		}
519 
520 		if (qualifier == 'L') {
521 			number = va_arg(args, u64);
522 			if (type & ACPI_FORMAT_SIGN) {
523 				number = (s64)number;
524 			}
525 		} else if (qualifier == 'l') {
526 			number = va_arg(args, unsigned long);
527 			if (type & ACPI_FORMAT_SIGN) {
528 				number = (s32)number;
529 			}
530 		} else if (qualifier == 'h') {
531 			number = (u16)va_arg(args, int);
532 			if (type & ACPI_FORMAT_SIGN) {
533 				number = (s16)number;
534 			}
535 		} else {
536 			number = va_arg(args, unsigned int);
537 			if (type & ACPI_FORMAT_SIGN) {
538 				number = (signed int)number;
539 			}
540 		}
541 
542 		pos = acpi_ut_format_number(pos, end, number, base,
543 					    width, precision, type);
544 	}
545 
546 	if (size > 0) {
547 		if (pos < end) {
548 			*pos = '\0';
549 		} else {
550 			end[-1] = '\0';
551 		}
552 	}
553 
554 	return ((int)ACPI_PTR_DIFF(pos, string));
555 }
556 
557 /*******************************************************************************
558  *
559  * FUNCTION:    snprintf
560  *
561  * PARAMETERS:  string              - String with boundary
562  *              size                - Boundary of the string
563  *              Format, ...         - Standard printf format
564  *
565  * RETURN:      Number of bytes actually written.
566  *
567  * DESCRIPTION: Formatted output to a string.
568  *
569  ******************************************************************************/
570 
snprintf(char * string,acpi_size size,const char * format,...)571 int snprintf(char *string, acpi_size size, const char *format, ...)
572 {
573 	va_list args;
574 	int length;
575 
576 	va_start(args, format);
577 	length = vsnprintf(string, size, format, args);
578 	va_end(args);
579 
580 	return (length);
581 }
582 
583 /*******************************************************************************
584  *
585  * FUNCTION:    sprintf
586  *
587  * PARAMETERS:  string              - String with boundary
588  *              Format, ...         - Standard printf format
589  *
590  * RETURN:      Number of bytes actually written.
591  *
592  * DESCRIPTION: Formatted output to a string.
593  *
594  ******************************************************************************/
595 
sprintf(char * string,const char * format,...)596 int sprintf(char *string, const char *format, ...)
597 {
598 	va_list args;
599 	int length;
600 
601 	va_start(args, format);
602 	length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
603 	va_end(args);
604 
605 	return (length);
606 }
607 
608 #ifdef ACPI_APPLICATION
609 /*******************************************************************************
610  *
611  * FUNCTION:    vprintf
612  *
613  * PARAMETERS:  format              - Standard printf format
614  *              args                - Argument list
615  *
616  * RETURN:      Number of bytes actually written.
617  *
618  * DESCRIPTION: Formatted output to stdout using argument list pointer.
619  *
620  ******************************************************************************/
621 
vprintf(const char * format,va_list args)622 int vprintf(const char *format, va_list args)
623 {
624 	acpi_cpu_flags flags;
625 	int length;
626 
627 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
628 	length = vsnprintf(acpi_gbl_print_buffer,
629 			   sizeof(acpi_gbl_print_buffer), format, args);
630 
631 	(void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
632 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
633 
634 	return (length);
635 }
636 
637 /*******************************************************************************
638  *
639  * FUNCTION:    printf
640  *
641  * PARAMETERS:  Format, ...         - Standard printf format
642  *
643  * RETURN:      Number of bytes actually written.
644  *
645  * DESCRIPTION: Formatted output to stdout.
646  *
647  ******************************************************************************/
648 
printf(const char * format,...)649 int printf(const char *format, ...)
650 {
651 	va_list args;
652 	int length;
653 
654 	va_start(args, format);
655 	length = vprintf(format, args);
656 	va_end(args);
657 
658 	return (length);
659 }
660 
661 /*******************************************************************************
662  *
663  * FUNCTION:    vfprintf
664  *
665  * PARAMETERS:  file                - File descriptor
666  *              format              - Standard printf format
667  *              args                - Argument list
668  *
669  * RETURN:      Number of bytes actually written.
670  *
671  * DESCRIPTION: Formatted output to a file using argument list pointer.
672  *
673  ******************************************************************************/
674 
vfprintf(FILE * file,const char * format,va_list args)675 int vfprintf(FILE * file, const char *format, va_list args)
676 {
677 	acpi_cpu_flags flags;
678 	int length;
679 
680 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
681 	length = vsnprintf(acpi_gbl_print_buffer,
682 			   sizeof(acpi_gbl_print_buffer), format, args);
683 
684 	(void)fwrite(acpi_gbl_print_buffer, length, 1, file);
685 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
686 
687 	return (length);
688 }
689 
690 /*******************************************************************************
691  *
692  * FUNCTION:    fprintf
693  *
694  * PARAMETERS:  file                - File descriptor
695  *              Format, ...         - Standard printf format
696  *
697  * RETURN:      Number of bytes actually written.
698  *
699  * DESCRIPTION: Formatted output to a file.
700  *
701  ******************************************************************************/
702 
fprintf(FILE * file,const char * format,...)703 int fprintf(FILE * file, const char *format, ...)
704 {
705 	va_list args;
706 	int length;
707 
708 	va_start(args, format);
709 	length = vfprintf(file, format, args);
710 	va_end(args);
711 
712 	return (length);
713 }
714 #endif
715