xref: /openbmc/linux/drivers/acpi/acpica/utprint.c (revision f8e17c17)
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 - 2020, 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
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 
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 
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 
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 
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 
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 
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 	end = string + size;
336 
337 	for (; *format; ++format) {
338 		if (*format != '%') {
339 			pos = acpi_ut_bound_string_output(pos, end, *format);
340 			continue;
341 		}
342 
343 		type = 0;
344 		base = 10;
345 
346 		/* Process sign */
347 
348 		do {
349 			++format;
350 			if (*format == '#') {
351 				type |= ACPI_FORMAT_PREFIX;
352 			} else if (*format == '0') {
353 				type |= ACPI_FORMAT_ZERO;
354 			} else if (*format == '+') {
355 				type |= ACPI_FORMAT_SIGN_PLUS;
356 			} else if (*format == ' ') {
357 				type |= ACPI_FORMAT_SIGN_PLUS_SPACE;
358 			} else if (*format == '-') {
359 				type |= ACPI_FORMAT_LEFT;
360 			} else {
361 				break;
362 			}
363 
364 		} while (1);
365 
366 		/* Process width */
367 
368 		width = -1;
369 		if (isdigit((int)*format)) {
370 			format = acpi_ut_scan_number(format, &number);
371 			width = (s32)number;
372 		} else if (*format == '*') {
373 			++format;
374 			width = va_arg(args, int);
375 			if (width < 0) {
376 				width = -width;
377 				type |= ACPI_FORMAT_LEFT;
378 			}
379 		}
380 
381 		/* Process precision */
382 
383 		precision = -1;
384 		if (*format == '.') {
385 			++format;
386 			if (isdigit((int)*format)) {
387 				format = acpi_ut_scan_number(format, &number);
388 				precision = (s32)number;
389 			} else if (*format == '*') {
390 				++format;
391 				precision = va_arg(args, int);
392 			}
393 
394 			if (precision < 0) {
395 				precision = 0;
396 			}
397 		}
398 
399 		/* Process qualifier */
400 
401 		qualifier = -1;
402 		if (*format == 'h' || *format == 'l' || *format == 'L') {
403 			qualifier = *format;
404 			++format;
405 
406 			if (qualifier == 'l' && *format == 'l') {
407 				qualifier = 'L';
408 				++format;
409 			}
410 		}
411 
412 		switch (*format) {
413 		case '%':
414 
415 			pos = acpi_ut_bound_string_output(pos, end, '%');
416 			continue;
417 
418 		case 'c':
419 
420 			if (!(type & ACPI_FORMAT_LEFT)) {
421 				while (--width > 0) {
422 					pos =
423 					    acpi_ut_bound_string_output(pos,
424 									end,
425 									' ');
426 				}
427 			}
428 
429 			c = (char)va_arg(args, int);
430 			pos = acpi_ut_bound_string_output(pos, end, c);
431 
432 			while (--width > 0) {
433 				pos =
434 				    acpi_ut_bound_string_output(pos, end, ' ');
435 			}
436 			continue;
437 
438 		case 's':
439 
440 			s = va_arg(args, char *);
441 			if (!s) {
442 				s = "<NULL>";
443 			}
444 			length = (s32)acpi_ut_bound_string_length(s, precision);
445 			if (!(type & ACPI_FORMAT_LEFT)) {
446 				while (length < width--) {
447 					pos =
448 					    acpi_ut_bound_string_output(pos,
449 									end,
450 									' ');
451 				}
452 			}
453 
454 			for (i = 0; i < length; ++i) {
455 				pos = acpi_ut_bound_string_output(pos, end, *s);
456 				++s;
457 			}
458 
459 			while (length < width--) {
460 				pos =
461 				    acpi_ut_bound_string_output(pos, end, ' ');
462 			}
463 			continue;
464 
465 		case 'o':
466 
467 			base = 8;
468 			break;
469 
470 		case 'X':
471 
472 			type |= ACPI_FORMAT_UPPER;
473 			/* FALLTHROUGH */
474 
475 		case 'x':
476 
477 			base = 16;
478 			break;
479 
480 		case 'd':
481 		case 'i':
482 
483 			type |= ACPI_FORMAT_SIGN;
484 
485 		case 'u':
486 
487 			break;
488 
489 		case 'p':
490 
491 			if (width == -1) {
492 				width = 2 * sizeof(void *);
493 				type |= ACPI_FORMAT_ZERO;
494 			}
495 
496 			p = va_arg(args, void *);
497 			pos =
498 			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
499 						  16, width, precision, type);
500 			continue;
501 
502 		default:
503 
504 			pos = acpi_ut_bound_string_output(pos, end, '%');
505 			if (*format) {
506 				pos =
507 				    acpi_ut_bound_string_output(pos, end,
508 								*format);
509 			} else {
510 				--format;
511 			}
512 			continue;
513 		}
514 
515 		if (qualifier == 'L') {
516 			number = va_arg(args, u64);
517 			if (type & ACPI_FORMAT_SIGN) {
518 				number = (s64)number;
519 			}
520 		} else if (qualifier == 'l') {
521 			number = va_arg(args, unsigned long);
522 			if (type & ACPI_FORMAT_SIGN) {
523 				number = (s32)number;
524 			}
525 		} else if (qualifier == 'h') {
526 			number = (u16)va_arg(args, int);
527 			if (type & ACPI_FORMAT_SIGN) {
528 				number = (s16)number;
529 			}
530 		} else {
531 			number = va_arg(args, unsigned int);
532 			if (type & ACPI_FORMAT_SIGN) {
533 				number = (signed int)number;
534 			}
535 		}
536 
537 		pos = acpi_ut_format_number(pos, end, number, base,
538 					    width, precision, type);
539 	}
540 
541 	if (size > 0) {
542 		if (pos < end) {
543 			*pos = '\0';
544 		} else {
545 			end[-1] = '\0';
546 		}
547 	}
548 
549 	return ((int)ACPI_PTR_DIFF(pos, string));
550 }
551 
552 /*******************************************************************************
553  *
554  * FUNCTION:    snprintf
555  *
556  * PARAMETERS:  string              - String with boundary
557  *              size                - Boundary of the string
558  *              Format, ...         - Standard printf format
559  *
560  * RETURN:      Number of bytes actually written.
561  *
562  * DESCRIPTION: Formatted output to a string.
563  *
564  ******************************************************************************/
565 
566 int snprintf(char *string, acpi_size size, const char *format, ...)
567 {
568 	va_list args;
569 	int length;
570 
571 	va_start(args, format);
572 	length = vsnprintf(string, size, format, args);
573 	va_end(args);
574 
575 	return (length);
576 }
577 
578 /*******************************************************************************
579  *
580  * FUNCTION:    sprintf
581  *
582  * PARAMETERS:  string              - String with boundary
583  *              Format, ...         - Standard printf format
584  *
585  * RETURN:      Number of bytes actually written.
586  *
587  * DESCRIPTION: Formatted output to a string.
588  *
589  ******************************************************************************/
590 
591 int sprintf(char *string, const char *format, ...)
592 {
593 	va_list args;
594 	int length;
595 
596 	va_start(args, format);
597 	length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
598 	va_end(args);
599 
600 	return (length);
601 }
602 
603 #ifdef ACPI_APPLICATION
604 /*******************************************************************************
605  *
606  * FUNCTION:    vprintf
607  *
608  * PARAMETERS:  format              - Standard printf format
609  *              args                - Argument list
610  *
611  * RETURN:      Number of bytes actually written.
612  *
613  * DESCRIPTION: Formatted output to stdout using argument list pointer.
614  *
615  ******************************************************************************/
616 
617 int vprintf(const char *format, va_list args)
618 {
619 	acpi_cpu_flags flags;
620 	int length;
621 
622 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
623 	length = vsnprintf(acpi_gbl_print_buffer,
624 			   sizeof(acpi_gbl_print_buffer), format, args);
625 
626 	(void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
627 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
628 
629 	return (length);
630 }
631 
632 /*******************************************************************************
633  *
634  * FUNCTION:    printf
635  *
636  * PARAMETERS:  Format, ...         - Standard printf format
637  *
638  * RETURN:      Number of bytes actually written.
639  *
640  * DESCRIPTION: Formatted output to stdout.
641  *
642  ******************************************************************************/
643 
644 int printf(const char *format, ...)
645 {
646 	va_list args;
647 	int length;
648 
649 	va_start(args, format);
650 	length = vprintf(format, args);
651 	va_end(args);
652 
653 	return (length);
654 }
655 
656 /*******************************************************************************
657  *
658  * FUNCTION:    vfprintf
659  *
660  * PARAMETERS:  file                - File descriptor
661  *              format              - Standard printf format
662  *              args                - Argument list
663  *
664  * RETURN:      Number of bytes actually written.
665  *
666  * DESCRIPTION: Formatted output to a file using argument list pointer.
667  *
668  ******************************************************************************/
669 
670 int vfprintf(FILE * file, const char *format, va_list args)
671 {
672 	acpi_cpu_flags flags;
673 	int length;
674 
675 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
676 	length = vsnprintf(acpi_gbl_print_buffer,
677 			   sizeof(acpi_gbl_print_buffer), format, args);
678 
679 	(void)fwrite(acpi_gbl_print_buffer, length, 1, file);
680 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
681 
682 	return (length);
683 }
684 
685 /*******************************************************************************
686  *
687  * FUNCTION:    fprintf
688  *
689  * PARAMETERS:  file                - File descriptor
690  *              Format, ...         - Standard printf format
691  *
692  * RETURN:      Number of bytes actually written.
693  *
694  * DESCRIPTION: Formatted output to a file.
695  *
696  ******************************************************************************/
697 
698 int fprintf(FILE * file, const char *format, ...)
699 {
700 	va_list args;
701 	int length;
702 
703 	va_start(args, format);
704 	length = vfprintf(file, format, args);
705 	va_end(args);
706 
707 	return (length);
708 }
709 #endif
710