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