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.  It accepts, but
98 *  ignores, an `l' as in %ld, %lo, %lx, and %lu, and therefore will not
99 *  work correctly on machines for which sizeof(long) != sizeof(int).
100 *
101 *  As mentioned, this version does not return any reasonable value.
102 *
103 *  Permission is granted to use, modify, or propagate this code as
104 *  long as this notice is incorporated.
105 *
106 *  Steve Summit 3/25/87
107 *
108 *  Tweaked for long long support and extended to support the hexdump %D
109 *  specifier by dbg 05/02/02.
110 */
111
112/*
113 * Added formats for decoding device registers:
114 *
115 * printf("reg = %b", regval, "<base><arg>*")
116 *
117 * where <base> is the output base expressed as a control character:
118 * i.e. '\10' gives octal, '\20' gives hex.  Each <arg> is a sequence of
119 * characters, the first of which gives the bit number to be inspected
120 * (origin 1), and the rest (up to a control character (<= 32)) give the
121 * name of the register.  Thus
122 *	printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE")
123 * would produce
124 *	reg = 3<BITTWO,BITONE>
125 *
126 * If the second character in <arg> is also a control character, it
127 * indicates the last bit of a bit field.  In this case, printf will extract
128 * bits <1> to <2> and print it.  Characters following the second control
129 * character are printed before the bit field.
130 *	printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE")
131 * would produce
132 *	reg = b<FIELD1=2,BITONE>
133 *
134 * The %B format is like %b but the bits are numbered from the most
135 * significant (the bit weighted 31), which is called 1, to the least
136 * significant, called 32.
137 */
138/*
139 * Added for general use:
140 *	#	prefix for alternate format:
141 *		0x (0X) for hex
142 *		leading 0 for octal
143 *	+	print '+' if positive
144 *	blank	print ' ' if positive
145 *
146 *	z	signed hexadecimal
147 *	r	signed, 'radix'
148 *	n	unsigned, 'radix'
149 *
150 *	D,U,O,Z	same as corresponding lower-case versions
151 *		(compatibility)
152 */
153/*
154 * Added support for print long long (64-bit) integers.
155 * Use %lld, %Ld or %qd to print a 64-bit int.  Other
156 * output bases such as x, X, u, U, o, and O also work.
157 */
158
159#include <debug.h>
160#include <mach_kdb.h>
161#include <mach_kdp.h>
162#include <platforms.h>
163#include <mach/boolean.h>
164#include <kern/cpu_number.h>
165#include <kern/lock.h>
166#include <kern/thread.h>
167#include <kern/sched_prim.h>
168#include <kern/misc_protos.h>
169#include <stdarg.h>
170#include <string.h>
171#include <mach_assert.h>
172#ifdef  MACH_BSD
173#include <sys/msgbuf.h>
174#endif
175#include <console/serial_protos.h>
176
177#ifdef __ppc__
178#include <ppc/Firmware.h>
179#endif
180
181#define isdigit(d) ((d) >= '0' && (d) <= '9')
182#define Ctod(c) ((c) - '0')
183
184#define MAXBUF (sizeof(long long int) * 8)	/* enough for binary */
185static char digs[] = "0123456789abcdef";
186
187
188#if CONFIG_NO_PRINTF_STRINGS
189#undef printf(x, ...)
190#endif
191
192static int
193printnum(
194	unsigned long long int	u,	/* number to print */
195	int		base,
196	void			(*putc)(int, void *),
197	void                    *arg)
198{
199	char	buf[MAXBUF];	/* build number here */
200	char *	p = &buf[MAXBUF-1];
201	int nprinted = 0;
202
203	do {
204	    *p-- = digs[u % base];
205	    u /= base;
206	} while (u != 0);
207
208	while (++p != &buf[MAXBUF]) {
209	    (*putc)(*p, arg);
210	    nprinted++;
211	}
212
213	return nprinted;
214}
215
216boolean_t	_doprnt_truncates = FALSE;
217
218int
219__doprnt(
220	const char	*fmt,
221	va_list			*argp,
222						/* character output routine */
223	void			(*putc)(int, void *arg),
224	void                    *arg,
225	int			radix)		/* default radix - for '%r' */
226{
227	int		length;
228	int		prec;
229	boolean_t	ladjust;
230	char		padc;
231	long long		n;
232	unsigned long long	u;
233	int		plus_sign;
234	int		sign_char;
235	boolean_t	altfmt, truncate;
236	int		base;
237	char	c;
238	int		capitals;
239	int		long_long;
240	int             nprinted = 0;
241
242	while ((c = *fmt) != '\0') {
243	    if (c != '%') {
244		(*putc)(c, arg);
245		nprinted++;
246		fmt++;
247		continue;
248	    }
249
250	    fmt++;
251
252	    long_long = 0;
253	    length = 0;
254	    prec = -1;
255	    ladjust = FALSE;
256	    padc = ' ';
257	    plus_sign = 0;
258	    sign_char = 0;
259	    altfmt = FALSE;
260
261	    while (TRUE) {
262		c = *fmt;
263		if (c == '#') {
264		    altfmt = TRUE;
265		}
266		else if (c == '-') {
267		    ladjust = TRUE;
268		}
269		else if (c == '+') {
270		    plus_sign = '+';
271		}
272		else if (c == ' ') {
273		    if (plus_sign == 0)
274			plus_sign = ' ';
275		}
276		else
277		    break;
278		fmt++;
279	    }
280
281	    if (c == '0') {
282		padc = '0';
283		c = *++fmt;
284	    }
285
286	    if (isdigit(c)) {
287		while(isdigit(c)) {
288		    length = 10 * length + Ctod(c);
289		    c = *++fmt;
290		}
291	    }
292	    else if (c == '*') {
293		length = va_arg(*argp, int);
294		c = *++fmt;
295		if (length < 0) {
296		    ladjust = !ladjust;
297		    length = -length;
298		}
299	    }
300
301	    if (c == '.') {
302		c = *++fmt;
303		if (isdigit(c)) {
304		    prec = 0;
305		    while(isdigit(c)) {
306			prec = 10 * prec + Ctod(c);
307			c = *++fmt;
308		    }
309		}
310		else if (c == '*') {
311		    prec = va_arg(*argp, int);
312		    c = *++fmt;
313		}
314	    }
315
316	    if (c == 'l') {
317		c = *++fmt;	/* need it if sizeof(int) < sizeof(long) */
318		if (c == 'l') {
319		    long_long = 1;
320		    c = *++fmt;
321		}
322	    } else if (c == 'q' || c == 'L') {
323	    	long_long = 1;
324		c = *++fmt;
325	    }
326
327	    truncate = FALSE;
328	    capitals=0;		/* Assume lower case printing */
329
330	    switch(c) {
331		case 'b':
332		case 'B':
333		{
334		    register char *p;
335		    boolean_t	  any;
336		    register int  i;
337
338		    if (long_long) {
339			u = va_arg(*argp, unsigned long long);
340		    } else {
341			u = va_arg(*argp, unsigned long);
342		    }
343		    p = va_arg(*argp, char *);
344		    base = *p++;
345		    nprinted += printnum(u, base, putc, arg);
346
347		    if (u == 0)
348			break;
349
350		    any = FALSE;
351		    while ((i = *p++) != '\0') {
352			if (*fmt == 'B')
353			    i = 33 - i;
354			if (*p <= 32) {
355			    /*
356			     * Bit field
357			     */
358			    register int j;
359			    if (any)
360				(*putc)(',', arg);
361			    else {
362				(*putc)('<', arg);
363				any = TRUE;
364			    }
365			    nprinted++;
366			    j = *p++;
367			    if (*fmt == 'B')
368				j = 32 - j;
369			    for (; (c = *p) > 32; p++) {
370				(*putc)(c, arg);
371				nprinted++;
372			    }
373			    nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)),
374						 base, putc, arg);
375			}
376			else if (u & (1<<(i-1))) {
377			    if (any)
378				(*putc)(',', arg);
379			    else {
380				(*putc)('<', arg);
381				any = TRUE;
382			    }
383			    nprinted++;
384			    for (; (c = *p) > 32; p++) {
385				(*putc)(c, arg);
386				nprinted++;
387			    }
388			}
389			else {
390			    for (; *p > 32; p++)
391				continue;
392			}
393		    }
394		    if (any) {
395			(*putc)('>', arg);
396			nprinted++;
397		    }
398		    break;
399		}
400
401		case 'c':
402		    c = va_arg(*argp, int);
403		    (*putc)(c, arg);
404		    nprinted++;
405		    break;
406
407		case 's':
408		{
409		    register const char *p;
410		    register const char *p2;
411
412		    if (prec == -1)
413			prec = 0x7fffffff;	/* MAXINT */
414
415		    p = va_arg(*argp, char *);
416
417		    if (p == NULL)
418			p = "";
419
420		    if (length > 0 && !ladjust) {
421			n = 0;
422			p2 = p;
423
424			for (; *p != '\0' && n < prec; p++)
425			    n++;
426
427			p = p2;
428
429			while (n < length) {
430			    (*putc)(' ', arg);
431			    n++;
432			    nprinted++;
433			}
434		    }
435
436		    n = 0;
437
438		    while ((n < prec) && (!(length > 0 && n >= length))) {
439			    if (*p == '\0') {
440				    break;
441			    }
442			    (*putc)(*p++, arg);
443			    nprinted++;
444			    n++;
445		    }
446
447		    if (n < length && ladjust) {
448			while (n < length) {
449			    (*putc)(' ', arg);
450			    n++;
451			    nprinted++;
452			}
453		    }
454
455		    break;
456		}
457
458		case 'o':
459		    truncate = _doprnt_truncates;
460		case 'O':
461		    base = 8;
462		    goto print_unsigned;
463
464		case 'D': {
465		    unsigned char *up;
466		    char *q, *p;
467
468			up = (unsigned char *)va_arg(*argp, unsigned char *);
469			p = (char *)va_arg(*argp, char *);
470			if (length == -1)
471				length = 16;
472			while(length--) {
473				(*putc)(digs[(*up >> 4)], arg);
474				(*putc)(digs[(*up & 0x0f)], arg);
475				nprinted += 2;
476				up++;
477				if (length) {
478				    for (q=p;*q;q++) {
479						(*putc)(*q, arg);
480						nprinted++;
481				    }
482				}
483			}
484			break;
485		}
486
487		case 'd':
488		    truncate = _doprnt_truncates;
489		    base = 10;
490		    goto print_signed;
491
492		case 'u':
493		    truncate = _doprnt_truncates;
494		case 'U':
495		    base = 10;
496		    goto print_unsigned;
497
498		case 'p':
499		    altfmt = TRUE;
500		case 'x':
501		    truncate = _doprnt_truncates;
502		    base = 16;
503		    goto print_unsigned;
504
505		case 'X':
506		    base = 16;
507		    capitals=16;	/* Print in upper case */
508		    goto print_unsigned;
509
510		case 'z':
511		    truncate = _doprnt_truncates;
512		    base = 16;
513		    goto print_signed;
514
515		case 'Z':
516		    base = 16;
517		    capitals=16;	/* Print in upper case */
518		    goto print_signed;
519
520		case 'r':
521		    truncate = _doprnt_truncates;
522		case 'R':
523		    base = radix;
524		    goto print_signed;
525
526		case 'n':
527		    truncate = _doprnt_truncates;
528		case 'N':
529		    base = radix;
530		    goto print_unsigned;
531
532		print_signed:
533		    if (long_long) {
534			n = va_arg(*argp, long long);
535		    } else {
536			n = va_arg(*argp, long);
537		    }
538		    if (n >= 0) {
539			u = n;
540			sign_char = plus_sign;
541		    }
542		    else {
543			u = -n;
544			sign_char = '-';
545		    }
546		    goto print_num;
547
548		print_unsigned:
549		    if (long_long) {
550			u = va_arg(*argp, unsigned long long);
551		    } else {
552			u = va_arg(*argp, unsigned long);
553		    }
554		    goto print_num;
555
556		print_num:
557		{
558		    char	buf[MAXBUF];	/* build number here */
559		    register char *	p = &buf[MAXBUF-1];
560		    static char digits[] = "0123456789abcdef0123456789ABCDEF";
561		    const char *prefix = NULL;
562
563		    if (truncate) u = (long long)((int)(u));
564
565		    if (u != 0 && altfmt) {
566			if (base == 8)
567			    prefix = "0";
568			else if (base == 16)
569			    prefix = "0x";
570		    }
571
572		    do {
573			/* Print in the correct case */
574			*p-- = digits[(u % base)+capitals];
575			u /= base;
576		    } while (u != 0);
577
578		    length -= (&buf[MAXBUF-1] - p);
579		    if (sign_char)
580			length--;
581		    if (prefix)
582			length -= strlen(prefix);
583
584		    if (padc == ' ' && !ladjust) {
585			/* blank padding goes before prefix */
586			while (--length >= 0) {
587			    (*putc)(' ', arg);
588			    nprinted++;
589			}
590		    }
591		    if (sign_char) {
592			(*putc)(sign_char, arg);
593			nprinted++;
594		    }
595		    if (prefix) {
596			while (*prefix) {
597			    (*putc)(*prefix++, arg);
598			    nprinted++;
599			}
600		    }
601		    if (padc == '0') {
602			/* zero padding goes after sign and prefix */
603			while (--length >= 0) {
604			    (*putc)('0', arg);
605			    nprinted++;
606			}
607		    }
608		    while (++p != &buf[MAXBUF]) {
609			(*putc)(*p, arg);
610			nprinted++;
611		    }
612
613		    if (ladjust) {
614			while (--length >= 0) {
615			    (*putc)(' ', arg);
616			    nprinted++;
617			}
618		    }
619		    break;
620		}
621
622		case '\0':
623		    fmt--;
624		    break;
625
626		default:
627		    (*putc)(c, arg);
628		    nprinted++;
629	    }
630	fmt++;
631	}
632
633	return nprinted;
634}
635
636static void
637dummy_putc(int ch, void *arg)
638{
639    void (*real_putc)(char) = arg;
640
641    real_putc(ch);
642}
643
644void
645_doprnt(
646	register const char	*fmt,
647	va_list			*argp,
648						/* character output routine */
649	void			(*putc)(char),
650	int			radix)		/* default radix - for '%r' */
651{
652    __doprnt(fmt, argp, dummy_putc, putc, radix);
653}
654
655#if	MP_PRINTF
656boolean_t	new_printf_cpu_number = FALSE;
657#endif	/* MP_PRINTF */
658
659
660decl_simple_lock_data(,printf_lock)
661decl_simple_lock_data(,bsd_log_spinlock)
662extern void bsd_log_init(void);
663void bsd_log_lock(void);
664void bsd_log_unlock(void);
665
666void
667printf_init(void)
668{
669	/*
670	 * Lock is only really needed after the first thread is created.
671	 */
672	simple_lock_init(&printf_lock, 0);
673	simple_lock_init(&bsd_log_spinlock, 0);
674	bsd_log_init();
675}
676
677void
678bsd_log_lock(void)
679{
680	simple_lock(&bsd_log_spinlock);
681}
682
683void
684bsd_log_unlock(void)
685{
686	simple_unlock(&bsd_log_spinlock);
687}
688
689/* derived from boot_gets */
690void
691safe_gets(
692	char	*str,
693	int	maxlen)
694{
695	register char *lp;
696	register int c;
697	char *strmax = str + maxlen - 1; /* allow space for trailing 0 */
698
699	lp = str;
700	for (;;) {
701		c = cngetc();
702		switch (c) {
703		case '\n':
704		case '\r':
705			printf("\n");
706			*lp++ = 0;
707			return;
708
709		case '\b':
710		case '#':
711		case '\177':
712			if (lp > str) {
713				printf("\b \b");
714				lp--;
715			}
716			continue;
717
718		case '@':
719		case 'u'&037:
720			lp = str;
721			printf("\n\r");
722			continue;
723
724		default:
725			if (c >= ' ' && c < '\177') {
726				if (lp < strmax) {
727					*lp++ = c;
728					printf("%c", c);
729				}
730				else {
731					printf("%c", '\007'); /* beep */
732				}
733			}
734		}
735	}
736}
737
738extern int disableConsoleOutput;
739
740void
741conslog_putc(
742	char c)
743{
744	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
745		cnputc(c);
746
747#ifdef	MACH_BSD
748	if (debug_mode == 0)
749		log_putc(c);
750#endif
751}
752
753#if	MACH_KDB
754extern void db_putchar(char c);
755#endif
756
757void
758dbugprintf(__unused const char *fmt, ...)
759{
760
761#if	MACH_KDB
762	va_list	listp;
763
764	va_start(listp, fmt);
765	_doprnt(fmt, &listp, db_putchar, 16);
766	va_end(listp);
767#endif
768	return;
769}
770
771int
772printf(const char *fmt, ...)
773{
774	va_list	listp;
775
776	if (fmt) {
777		disable_preemption();
778		va_start(listp, fmt);
779		_doprnt(fmt, &listp, conslog_putc, 16);
780		va_end(listp);
781		enable_preemption();
782	}
783	return 0;
784}
785
786void
787consdebug_putc(char c)
788{
789	if ((debug_mode && !disable_debug_output) || !disableConsoleOutput)
790		cnputc(c);
791
792	debug_putc(c);
793
794	if (!console_is_serial())
795		if (!disable_serial_output)
796			PE_kputc(c);
797}
798
799
800void
801consdebug_log(char c)
802{
803	debug_putc(c);
804}
805
806int
807kdb_printf(const char *fmt, ...)
808{
809	va_list	listp;
810
811	va_start(listp, fmt);
812	_doprnt(fmt, &listp, consdebug_putc, 16);
813	va_end(listp);
814	return 0;
815}
816
817int
818kdb_log(const char *fmt, ...)
819{
820	va_list	listp;
821
822	va_start(listp, fmt);
823	_doprnt(fmt, &listp, consdebug_log, 16);
824	va_end(listp);
825	return 0;
826}
827
828static void
829copybyte(int c, void *arg)
830{
831	/*
832	 * arg is a pointer (outside pointer) to the pointer
833	 * (inside pointer) which points to the character.
834	 * We pass a double pointer, so that we can increment
835	 * the inside pointer.
836	 */
837	char** p = arg;	/* cast outside pointer */
838	**p = c;	/* store character */
839	(*p)++;		/* increment inside pointer */
840}
841
842/*
843 * Deprecation Warning:
844 *	sprintf() is being deprecated. Please use snprintf() instead.
845 */
846int
847sprintf(char *buf, const char *fmt, ...)
848{
849        va_list listp;
850	char *copybyte_str;
851
852        va_start(listp, fmt);
853        copybyte_str = buf;
854        __doprnt(fmt, &listp, copybyte, &copybyte_str, 16);
855        va_end(listp);
856	*copybyte_str = '\0';
857        return strlen(buf);
858}
859