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