1/*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31
32/*
33 * Mach Operating System
34 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
35 * All Rights Reserved.
36 *
37 * Permission to use, copy, modify and distribute this software and its
38 * documentation is hereby granted, provided that both the copyright
39 * notice and this permission notice appear in all copies of the
40 * software, derivative works or modified versions, and any portions
41 * thereof, and that both notices appear in supporting documentation.
42 *
43 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
44 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
45 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 *
47 * Carnegie Mellon requests users of this software to return to
48 *
49 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
50 *  School of Computer Science
51 *  Carnegie Mellon University
52 *  Pittsburgh PA 15213-3890
53 *
54 * any improvements or extensions that they make and grant Carnegie Mellon
55 * the rights to redistribute these changes.
56 */
57
58/*
59 *  Common code for printf et al.
60 *
61 *  The calling routine typically takes a variable number of arguments,
62 *  and passes the address of the first one.  This implementation
63 *  assumes a straightforward, stack implementation, aligned to the
64 *  machine's wordsize.  Increasing addresses are assumed to point to
65 *  successive arguments (left-to-right), as is the case for a machine
66 *  with a downward-growing stack with arguments pushed right-to-left.
67 *
68 *  To write, for example, fprintf() using this routine, the code
69 *
70 *	fprintf(fd, format, args)
71 *	FILE *fd;
72 *	char *format;
73 *	{
74 *	_doprnt(format, &args, fd);
75 *	}
76 *
77 *  would suffice.  (This example does not handle the fprintf's "return
78 *  value" correctly, but who looks at the return value of fprintf
79 *  anyway?)
80 *
81 *  This version implements the following printf features:
82 *
83 *	%d	decimal conversion
84 *	%u	unsigned conversion
85 *	%x	hexadecimal conversion
86 *	%X	hexadecimal conversion with capital letters
87 *      %D      hexdump, ptr & separator string ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
88 *              if you use, "%*D" then there's a length, the data ptr and then the separator
89 *	%o	octal conversion
90 *	%c	character
91 *	%s	string
92 *	%m.n	field width, precision
93 *	%-m.n	left adjustment
94 *	%0m.n	zero-padding
95 *	%*.*	width and precision taken from arguments
96 *
97 *  This version does not implement %f, %e, or %g.
98 *
99 *  As mentioned, this version does not return any reasonable value.
100 *
101 *  Permission is granted to use, modify, or propagate this code as
102 *  long as this notice is incorporated.
103 *
104 *  Steve Summit 3/25/87
105 *
106 *  Tweaked for long long support and extended to support the hexdump %D
107 *  specifier by dbg 05/02/02.
108 */
109
110/*
111 * Added formats for decoding device registers:
112 *
113 * printf("reg = %b", regval, "<base><arg>*")
114 *
115 * where <base> is the output base expressed as a control character:
116 * i.e. '\10' gives octal, '\20' gives hex.  Each <arg> is a sequence of
117 * characters, the first of which gives the bit number to be inspected
118 * (origin 1), and the rest (up to a control character (<= 32)) give the
119 * name of the register.  Thus
120 *	printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
121 * would produce
122 *	reg = 3<BITTWO,BITONE>
123 *
124 * If the second character in <arg> is also a control character, it
125 * indicates the last bit of a bit field.  In this case, printf will extract
126 * bits <1> to <2> and print it.  Characters following the second control
127 * character are printed before the bit field.
128 *	printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
129 * would produce
130 *	reg = b<FIELD1=2,BITONE>
131 *
132 * The %B format is like %b but the bits are numbered from the most
133 * significant (the bit weighted 31), which is called 1, to the least
134 * significant, called 32.
135 */
136/*
137 * Added for general use:
138 *	#	prefix for alternate format:
139 *		0x (0X) for hex
140 *		leading 0 for octal
141 *	+	print '+' if positive
142 *	blank	print ' ' if positive
143 *
144 *	z	signed hexadecimal
145 *	r	signed, 'radix'
146 *	n	unsigned, 'radix'
147 *
148 *	D,U,O,Z	same as corresponding lower-case versions
149 *		(compatibility)
150 */
151/*
152 * Added support for print long long (64-bit) integers.
153 * Use %lld, %Ld or %qd to print a 64-bit int.  Other
154 * output bases such as x, X, u, U, o, and O also work.
155 */
156
157#include <debug.h>
158#include <mach_kdp.h>
159#include <platforms.h>
160#include <mach/boolean.h>
161#include <kern/cpu_number.h>
162#include <kern/lock.h>
163#include <kern/thread.h>
164#include <kern/sched_prim.h>
165#include <kern/misc_protos.h>
166#include <stdarg.h>
167#include <string.h>
168#include <mach_assert.h>
169#ifdef  MACH_BSD
170#include <sys/msgbuf.h>
171#endif
172#include <console/serial_protos.h>
173
174#define isdigit(d) ((d) >= '0' && (d) <= '9')
175#define Ctod(c) ((c) - '0')
176
177#define MAXBUF (sizeof(long long int) * 8)	/* enough for binary */
178static char digs[] = "0123456789abcdef";
179
180#if CONFIG_NO_PRINTF_STRINGS
181/* Prevent CPP from breaking the definition below */
182#undef printf
183#endif
184
185int _consume_printf_args(int a __unused, ...)
186{
187    return 0;
188}
189void _consume_kprintf_args(int a __unused, ...)
190{
191}
192
193static int
194printnum(
195	unsigned long long int	u,	/* number to print */
196	int		base,
197	void			(*putc)(int, void *),
198	void                    *arg)
199{
200	char	buf[MAXBUF];	/* build number here */
201	char *	p = &buf[MAXBUF-1];
202	int nprinted = 0;
203
204	do {
205	    *p-- = digs[u % base];
206	    u /= base;
207	} while (u != 0);
208
209	while (++p != &buf[MAXBUF]) {
210	    (*putc)(*p, arg);
211	    nprinted++;
212	}
213
214	return nprinted;
215}
216
217boolean_t	_doprnt_truncates = FALSE;
218
219int
220__doprnt(
221	const char	*fmt,
222	va_list			argp,
223						/* character output routine */
224	void			(*putc)(int, void *arg),
225	void                    *arg,
226	int			radix)		/* default radix - for '%r' */
227{
228	int		length;
229	int		prec;
230	boolean_t	ladjust;
231	char		padc;
232	long long		n;
233	unsigned long long	u;
234	int		plus_sign;
235	int		sign_char;
236	boolean_t	altfmt, truncate;
237	int		base;
238	char	c;
239	int		capitals;
240	int		long_long;
241	int             nprinted = 0;
242
243	while ((c = *fmt) != '\0') {
244	    if (c != '%') {
245		(*putc)(c, arg);
246		nprinted++;
247		fmt++;
248		continue;
249	    }
250
251	    fmt++;
252
253	    long_long = 0;
254	    length = 0;
255	    prec = -1;
256	    ladjust = FALSE;
257	    padc = ' ';
258	    plus_sign = 0;
259	    sign_char = 0;
260	    altfmt = FALSE;
261
262	    while (TRUE) {
263		c = *fmt;
264		if (c == '#') {
265		    altfmt = TRUE;
266		}
267		else if (c == '-') {
268		    ladjust = TRUE;
269		}
270		else if (c == '+') {
271		    plus_sign = '+';
272		}
273		else if (c == ' ') {
274		    if (plus_sign == 0)
275			plus_sign = ' ';
276		}
277		else
278		    break;
279		fmt++;
280	    }
281
282	    if (c == '0') {
283		padc = '0';
284		c = *++fmt;
285	    }
286
287	    if (isdigit(c)) {
288		while(isdigit(c)) {
289		    length = 10 * length + Ctod(c);
290		    c = *++fmt;
291		}
292	    }
293	    else if (c == '*') {
294		length = va_arg(argp, int);
295		c = *++fmt;
296		if (length < 0) {
297		    ladjust = !ladjust;
298		    length = -length;
299		}
300	    }
301
302	    if (c == '.') {
303		c = *++fmt;
304		if (isdigit(c)) {
305		    prec = 0;
306		    while(isdigit(c)) {
307			prec = 10 * prec + Ctod(c);
308			c = *++fmt;
309		    }
310		}
311		else if (c == '*') {
312		    prec = va_arg(argp, int);
313		    c = *++fmt;
314		}
315	    }
316
317	    if (c == 'l') {
318		c = *++fmt;	/* need it if sizeof(int) < sizeof(long) */
319		if (sizeof(int)<sizeof(long))
320		    long_long = 1;
321		if (c == 'l') {
322		    long_long = 1;
323		    c = *++fmt;
324		}
325	    } else if (c == 'q' || c == 'L') {
326	    	long_long = 1;
327		c = *++fmt;
328	    }
329
330	    truncate = FALSE;
331	    capitals=0;		/* Assume lower case printing */
332
333	    switch(c) {
334		case 'b':
335		case 'B':
336		{
337		    register char *p;
338		    boolean_t	  any;
339		    register int  i;
340
341		    if (long_long) {
342			u = va_arg(argp, unsigned long long);
343		    } else {
344			u = va_arg(argp, unsigned int);
345		    }
346		    p = va_arg(argp, char *);
347		    base = *p++;
348		    nprinted += printnum(u, base, putc, arg);
349
350		    if (u == 0)
351			break;
352
353		    any = FALSE;
354		    while ((i = *p++) != '\0') {
355			if (*fmt == 'B')
356			    i = 33 - i;
357			if (*p <= 32) {
358			    /*
359			     * Bit field
360			     */
361			    register int j;
362			    if (any)
363				(*putc)(',', arg);
364			    else {
365				(*putc)('<', arg);
366				any = TRUE;
367			    }
368			    nprinted++;
369			    j = *p++;
370			    if (*fmt == 'B')
371				j = 32 - j;
372			    for (; (c = *p) > 32; p++) {
373				(*putc)(c, arg);
374				nprinted++;
375			    }
376			    nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
377						 base, putc, arg);
378			}
379			else if (u & (1<<(i-1))) {
380			    if (any)
381				(*putc)(',', arg);
382			    else {
383				(*putc)('<', arg);
384				any = TRUE;
385			    }
386			    nprinted++;
387			    for (; (c = *p) > 32; p++) {
388				(*putc)(c, arg);
389				nprinted++;
390			    }
391			}
392			else {
393			    for (; *p > 32; p++)
394				continue;
395			}
396		    }
397		    if (any) {
398			(*putc)('>', arg);
399			nprinted++;
400		    }
401		    break;
402		}
403
404		case 'c':
405		    c = va_arg(argp, int);
406		    (*putc)(c, arg);
407		    nprinted++;
408		    break;
409
410		case 's':
411		{
412		    register const char *p;
413		    register const char *p2;
414
415		    if (prec == -1)
416			prec = 0x7fffffff;	/* MAXINT */
417
418		    p = va_arg(argp, char *);
419
420		    if (p == NULL)
421			p = "";
422
423		    if (length > 0 && !ladjust) {
424			n = 0;
425			p2 = p;
426
427			for (; *p != '\0' && n < prec; p++)
428			    n++;
429
430			p = p2;
431
432			while (n < length) {
433			    (*putc)(' ', arg);
434			    n++;
435			    nprinted++;
436			}
437		    }
438
439		    n = 0;
440
441		    while ((n < prec) && (!(length > 0 && n >= length))) {
442			    if (*p == '\0') {
443				    break;
444			    }
445			    (*putc)(*p++, arg);
446			    nprinted++;
447			    n++;
448		    }
449
450		    if (n < length && ladjust) {
451			while (n < length) {
452			    (*putc)(' ', arg);
453			    n++;
454			    nprinted++;
455			}
456		    }
457
458		    break;
459		}
460
461		case 'o':
462		    truncate = _doprnt_truncates;
463		case 'O':
464		    base = 8;
465		    goto print_unsigned;
466
467		case 'D': {
468		    unsigned char *up;
469		    char *q, *p;
470
471			up = (unsigned char *)va_arg(argp, unsigned char *);
472			p = (char *)va_arg(argp, char *);
473			if (length == -1)
474				length = 16;
475			while(length--) {
476				(*putc)(digs[(*up >> 4)], arg);
477				(*putc)(digs[(*up & 0x0f)], arg);
478				nprinted += 2;
479				up++;
480				if (length) {
481				    for (q=p;*q;q++) {
482						(*putc)(*q, arg);
483						nprinted++;
484				    }
485				}
486			}
487			break;
488		}
489
490		case 'd':
491		    truncate = _doprnt_truncates;
492		    base = 10;
493		    goto print_signed;
494
495		case 'u':
496		    truncate = _doprnt_truncates;
497		case 'U':
498		    base = 10;
499		    goto print_unsigned;
500
501		case 'p':
502		    altfmt = TRUE;
503		    if (sizeof(int)<sizeof(void *)) {
504			long_long = 1;
505		    }
506		case 'x':
507		    truncate = _doprnt_truncates;
508		    base = 16;
509		    goto print_unsigned;
510
511		case 'X':
512		    base = 16;
513		    capitals=16;	/* Print in upper case */
514		    goto print_unsigned;
515
516		case 'z':
517		    truncate = _doprnt_truncates;
518		    base = 16;
519		    goto print_signed;
520
521		case 'Z':
522		    base = 16;
523		    capitals=16;	/* Print in upper case */
524		    goto print_signed;
525
526		case 'r':
527		    truncate = _doprnt_truncates;
528		case 'R':
529		    base = radix;
530		    goto print_signed;
531
532		case 'n':
533		    truncate = _doprnt_truncates;
534		case 'N':
535		    base = radix;
536		    goto print_unsigned;
537
538		print_signed:
539		    if (long_long) {
540			n = va_arg(argp, long long);
541		    } else {
542			n = va_arg(argp, int);
543		    }
544		    if (n >= 0) {
545			u = n;
546			sign_char = plus_sign;
547		    }
548		    else {
549			u = -n;
550			sign_char = '-';
551		    }
552		    goto print_num;
553
554		print_unsigned:
555		    if (long_long) {
556			u = va_arg(argp, unsigned long long);
557		    } else {
558			u = va_arg(argp, unsigned int);
559		    }
560		    goto print_num;
561
562		print_num:
563		{
564		    char	buf[MAXBUF];	/* build number here */
565		    register char *	p = &buf[MAXBUF-1];
566		    static char digits[] = "0123456789abcdef0123456789ABCDEF";
567		    const char *prefix = NULL;
568
569		    if (truncate) u = (long long)((int)(u));
570
571		    if (u != 0 && altfmt) {
572			if (base == 8)
573			    prefix = "0";
574			else if (base == 16)
575			    prefix = "0x";
576		    }
577
578		    do {
579			/* Print in the correct case */
580			*p-- = digits[(u % base)+capitals];
581			u /= base;
582		    } while (u != 0);
583
584		    length -= (int)(&buf[MAXBUF-1] - p);
585		    if (sign_char)
586			length--;
587		    if (prefix)
588			length -= (int)strlen(prefix);
589
590		    if (padc == ' ' && !ladjust) {
591			/* blank padding goes before prefix */
592			while (--length >= 0) {
593			    (*putc)(' ', arg);
594			    nprinted++;
595			}
596		    }
597		    if (sign_char) {
598			(*putc)(sign_char, arg);
599			nprinted++;
600		    }
601		    if (prefix) {
602			while (*prefix) {
603			    (*putc)(*prefix++, arg);
604			    nprinted++;
605			}
606		    }
607		    if (padc == '0') {
608			/* zero padding goes after sign and prefix */
609			while (--length >= 0) {
610			    (*putc)('0', arg);
611			    nprinted++;
612			}
613		    }
614		    while (++p != &buf[MAXBUF]) {
615			(*putc)(*p, arg);
616			nprinted++;
617		    }
618
619		    if (ladjust) {
620			while (--length >= 0) {
621			    (*putc)(' ', arg);
622			    nprinted++;
623			}
624		    }
625		    break;
626		}
627
628		case '\0':
629		    fmt--;
630		    break;
631
632		default:
633		    (*putc)(c, arg);
634		    nprinted++;
635	    }
636	fmt++;
637	}
638
639	return nprinted;
640}
641
642static void
643dummy_putc(int ch, void *arg)
644{
645    void (*real_putc)(char) = arg;
646
647    real_putc(ch);
648}
649
650int enable_timing = 1;
651
652void
653_doprnt(
654	register const char	*fmt,
655	va_list			*argp,
656						/* character output routine */
657	void			(*putc)(char),
658	int			radix)		/* default radix - for '%r' */
659{
660#if 0
661	/* timing information */
662	if(enable_timing) {
663		char tbuf[50], *tp;
664		uint64_t t = mach_absolute_time();
665		uint64_t ns; absolutetime_to_nanoseconds(t, &ns);
666		/* truncate the end of the timing information */
667		int tlen = sprintf(tbuf, "[%5llu.%06llu] ", (uint64_t)(ns / NSEC_PER_SEC), (uint64_t)((ns % NSEC_PER_SEC) / 1000));
668		for(tp = tbuf; tp < tbuf + tlen; tp++)
669			putc(*tp);
670	}
671#endif
672    __doprnt(fmt, *argp, dummy_putc, putc, radix);
673}
674
675#if	MP_PRINTF
676boolean_t	new_printf_cpu_number = FALSE;
677#endif	/* MP_PRINTF */
678
679
680decl_simple_lock_data(,printf_lock)
681decl_simple_lock_data(,bsd_log_spinlock)
682extern void bsd_log_init(void);
683void bsd_log_lock(void);
684void bsd_log_unlock(void);
685
686void
687printf_init(void)
688{
689	/*
690	 * Lock is only really needed after the first thread is created.
691	 */
692	simple_lock_init(&printf_lock, 0);
693	simple_lock_init(&bsd_log_spinlock, 0);
694	bsd_log_init();
695}
696
697void
698bsd_log_lock(void)
699{
700	simple_lock(&bsd_log_spinlock);
701}
702
703void
704bsd_log_unlock(void)
705{
706	simple_unlock(&bsd_log_spinlock);
707}
708
709/* derived from boot_gets */
710void
711safe_gets(
712	char	*str,
713	int	maxlen)
714{
715	register char *lp;
716	register int c;
717	char *strmax = str + maxlen - 1; /* allow space for trailing 0 */
718
719	lp = str;
720	for (;;) {
721		c = cngetc();
722		switch (c) {
723		case '\n':
724		case '\r':
725			printf("\n");
726			*lp++ = 0;
727			return;
728
729		case '\b':
730		case '#':
731		case '\177':
732			if (lp > str) {
733				printf("\b \b");
734				lp--;
735			}
736			continue;
737
738		case '@':
739		case 'u'&037:
740			lp = str;
741			printf("\n\r");
742			continue;
743
744		default:
745			if (c >= ' ' && c < '\177') {
746				if (lp < strmax) {
747					*lp++ = c;
748					printf("%c", c);
749				}
750				else {
751					printf("%c", '\007'); /* beep */
752				}
753			}
754		}
755	}
756}
757
758extern int disableConsoleOutput;
759
760void
761conslog_putc(
762	char c)
763{
764	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
765		cnputc(c);
766
767#ifdef	MACH_BSD
768	if (debug_mode == 0)
769		log_putc(c);
770#endif
771}
772
773void
774cons_putc_locked(
775	char c)
776{
777	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
778		cnputc(c);
779}
780
781int
782printf(const char *fmt, ...)
783{
784	va_list	listp;
785
786	if (fmt) {
787		disable_preemption();
788		va_start(listp, fmt);
789		_doprnt(fmt, &listp, conslog_putc, 16);
790		va_end(listp);
791		enable_preemption();
792	}
793	return 0;
794}
795
796void
797consdebug_putc(char c)
798{
799	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
800		cnputc(c);
801
802	debug_putc(c);
803
804	if (!console_is_serial())
805		if (!disable_serial_output)
806			PE_kputc(c);
807}
808
809void
810consdebug_putc_unbuffered(char c)
811{
812	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
813		cnputc_unbuffered(c);
814
815	debug_putc(c);
816
817	if (!console_is_serial())
818		if (!disable_serial_output)
819			PE_kputc(c);
820}
821
822void
823consdebug_log(char c)
824{
825	debug_putc(c);
826}
827
828int
829kdb_printf(const char *fmt, ...)
830{
831	va_list	listp;
832
833	va_start(listp, fmt);
834	_doprnt(fmt, &listp, consdebug_putc, 16);
835	va_end(listp);
836	return 0;
837}
838
839int
840kdb_log(const char *fmt, ...)
841{
842	va_list	listp;
843
844	va_start(listp, fmt);
845	_doprnt(fmt, &listp, consdebug_log, 16);
846	va_end(listp);
847	return 0;
848}
849
850int
851kdb_printf_unbuffered(const char *fmt, ...)
852{
853	va_list	listp;
854
855	va_start(listp, fmt);
856	_doprnt(fmt, &listp, consdebug_putc_unbuffered, 16);
857	va_end(listp);
858	return 0;
859}
860
861#ifdef __arm__  /* I don't want to rebuild my symbolsets. */
862#undef CONFIG_EMBEDDED
863#define CONFIG_EMBEDDED 0
864#endif
865
866#if !CONFIG_EMBEDDED
867
868static void
869copybyte(int c, void *arg)
870{
871	/*
872	 * arg is a pointer (outside pointer) to the pointer
873	 * (inside pointer) which points to the character.
874	 * We pass a double pointer, so that we can increment
875	 * the inside pointer.
876	 */
877	char** p = arg;	/* cast outside pointer */
878	**p = c;	/* store character */
879	(*p)++;		/* increment inside pointer */
880}
881
882/*
883 * Deprecation Warning:
884 *	sprintf() is being deprecated. Please use snprintf() instead.
885 */
886int
887sprintf(char *buf, const char *fmt, ...)
888{
889        va_list listp;
890	char *copybyte_str;
891
892        va_start(listp, fmt);
893        copybyte_str = buf;
894        __doprnt(fmt, listp, copybyte, &copybyte_str, 16);
895        va_end(listp);
896	*copybyte_str = '\0';
897        return (int)strlen(buf);
898}
899#endif /* !CONFIG_EMBEDDED */
900