xref: /openbmc/linux/drivers/acpi/acpica/utprint.c (revision 4cff79e9)
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 - 2018, 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 
474 		case 'x':
475 
476 			base = 16;
477 			break;
478 
479 		case 'd':
480 		case 'i':
481 
482 			type |= ACPI_FORMAT_SIGN;
483 
484 		case 'u':
485 
486 			break;
487 
488 		case 'p':
489 
490 			if (width == -1) {
491 				width = 2 * sizeof(void *);
492 				type |= ACPI_FORMAT_ZERO;
493 			}
494 
495 			p = va_arg(args, void *);
496 			pos =
497 			    acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
498 						  16, width, precision, type);
499 			continue;
500 
501 		default:
502 
503 			pos = acpi_ut_bound_string_output(pos, end, '%');
504 			if (*format) {
505 				pos =
506 				    acpi_ut_bound_string_output(pos, end,
507 								*format);
508 			} else {
509 				--format;
510 			}
511 			continue;
512 		}
513 
514 		if (qualifier == 'L') {
515 			number = va_arg(args, u64);
516 			if (type & ACPI_FORMAT_SIGN) {
517 				number = (s64)number;
518 			}
519 		} else if (qualifier == 'l') {
520 			number = va_arg(args, unsigned long);
521 			if (type & ACPI_FORMAT_SIGN) {
522 				number = (s32)number;
523 			}
524 		} else if (qualifier == 'h') {
525 			number = (u16)va_arg(args, int);
526 			if (type & ACPI_FORMAT_SIGN) {
527 				number = (s16)number;
528 			}
529 		} else {
530 			number = va_arg(args, unsigned int);
531 			if (type & ACPI_FORMAT_SIGN) {
532 				number = (signed int)number;
533 			}
534 		}
535 
536 		pos = acpi_ut_format_number(pos, end, number, base,
537 					    width, precision, type);
538 	}
539 
540 	if (size > 0) {
541 		if (pos < end) {
542 			*pos = '\0';
543 		} else {
544 			end[-1] = '\0';
545 		}
546 	}
547 
548 	return ((int)ACPI_PTR_DIFF(pos, string));
549 }
550 
551 /*******************************************************************************
552  *
553  * FUNCTION:    snprintf
554  *
555  * PARAMETERS:  string              - String with boundary
556  *              size                - Boundary of the string
557  *              Format, ...         - Standard printf format
558  *
559  * RETURN:      Number of bytes actually written.
560  *
561  * DESCRIPTION: Formatted output to a string.
562  *
563  ******************************************************************************/
564 
565 int snprintf(char *string, acpi_size size, const char *format, ...)
566 {
567 	va_list args;
568 	int length;
569 
570 	va_start(args, format);
571 	length = vsnprintf(string, size, format, args);
572 	va_end(args);
573 
574 	return (length);
575 }
576 
577 /*******************************************************************************
578  *
579  * FUNCTION:    sprintf
580  *
581  * PARAMETERS:  string              - String with boundary
582  *              Format, ...         - Standard printf format
583  *
584  * RETURN:      Number of bytes actually written.
585  *
586  * DESCRIPTION: Formatted output to a string.
587  *
588  ******************************************************************************/
589 
590 int sprintf(char *string, const char *format, ...)
591 {
592 	va_list args;
593 	int length;
594 
595 	va_start(args, format);
596 	length = vsnprintf(string, ACPI_UINT32_MAX, format, args);
597 	va_end(args);
598 
599 	return (length);
600 }
601 
602 #ifdef ACPI_APPLICATION
603 /*******************************************************************************
604  *
605  * FUNCTION:    vprintf
606  *
607  * PARAMETERS:  format              - Standard printf format
608  *              args                - Argument list
609  *
610  * RETURN:      Number of bytes actually written.
611  *
612  * DESCRIPTION: Formatted output to stdout using argument list pointer.
613  *
614  ******************************************************************************/
615 
616 int vprintf(const char *format, va_list args)
617 {
618 	acpi_cpu_flags flags;
619 	int length;
620 
621 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
622 	length = vsnprintf(acpi_gbl_print_buffer,
623 			   sizeof(acpi_gbl_print_buffer), format, args);
624 
625 	(void)fwrite(acpi_gbl_print_buffer, length, 1, ACPI_FILE_OUT);
626 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
627 
628 	return (length);
629 }
630 
631 /*******************************************************************************
632  *
633  * FUNCTION:    printf
634  *
635  * PARAMETERS:  Format, ...         - Standard printf format
636  *
637  * RETURN:      Number of bytes actually written.
638  *
639  * DESCRIPTION: Formatted output to stdout.
640  *
641  ******************************************************************************/
642 
643 int printf(const char *format, ...)
644 {
645 	va_list args;
646 	int length;
647 
648 	va_start(args, format);
649 	length = vprintf(format, args);
650 	va_end(args);
651 
652 	return (length);
653 }
654 
655 /*******************************************************************************
656  *
657  * FUNCTION:    vfprintf
658  *
659  * PARAMETERS:  file                - File descriptor
660  *              format              - Standard printf format
661  *              args                - Argument list
662  *
663  * RETURN:      Number of bytes actually written.
664  *
665  * DESCRIPTION: Formatted output to a file using argument list pointer.
666  *
667  ******************************************************************************/
668 
669 int vfprintf(FILE * file, const char *format, va_list args)
670 {
671 	acpi_cpu_flags flags;
672 	int length;
673 
674 	flags = acpi_os_acquire_lock(acpi_gbl_print_lock);
675 	length = vsnprintf(acpi_gbl_print_buffer,
676 			   sizeof(acpi_gbl_print_buffer), format, args);
677 
678 	(void)fwrite(acpi_gbl_print_buffer, length, 1, file);
679 	acpi_os_release_lock(acpi_gbl_print_lock, flags);
680 
681 	return (length);
682 }
683 
684 /*******************************************************************************
685  *
686  * FUNCTION:    fprintf
687  *
688  * PARAMETERS:  file                - File descriptor
689  *              Format, ...         - Standard printf format
690  *
691  * RETURN:      Number of bytes actually written.
692  *
693  * DESCRIPTION: Formatted output to a file.
694  *
695  ******************************************************************************/
696 
697 int fprintf(FILE * file, const char *format, ...)
698 {
699 	va_list args;
700 	int length;
701 
702 	va_start(args, format);
703 	length = vfprintf(file, format, args);
704 	va_end(args);
705 
706 	return (length);
707 }
708 #endif
709