1 /*
2 * Copyright (c) 2000-2020 Apple 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 [email protected]
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 set length equal to size_t
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/debug.h>
163 #include <kern/sched_prim.h>
164 #include <kern/misc_protos.h>
165 #include <stdarg.h>
166 #include <string.h>
167 #include <mach_assert.h>
168 #ifdef MACH_BSD
169 #include <sys/msgbuf.h>
170 #endif
171 #include <console/serial_protos.h>
172 #include <os/log_private.h>
173
174 #ifdef __x86_64__
175 #include <i386/cpu_data.h>
176 #endif /* __x86_64__ */
177
178 #if __arm64__
179 #include <arm/cpu_data_internal.h>
180 #endif
181
182 #ifdef HAS_APPLE_PAC
183 #include <mach/vm_param.h>
184 #include <ptrauth.h>
185 #endif /* HAS_APPLE_PAC */
186
187 #if CONFIG_SPTM
188 #include <sptm/sptm_xnu.h>
189 #endif /* CONFIG_SPTM */
190
191 #define isdigit(d) ((d) >= '0' && (d) <= '9')
192 #define Ctod(c) ((c) - '0')
193
194 #define MAXBUF (sizeof(long long int) * 8) /* enough for binary */
195 static char digs[] = "0123456789abcdef";
196
197 #if CONFIG_NO_PRINTF_STRINGS
198 /* Prevent CPP from breaking the definition below */
199 #undef printf
200 #endif
201
202 int
_consume_printf_args(int a __unused,...)203 _consume_printf_args(int a __unused, ...)
204 {
205 return 0;
206 }
207 void
_consume_kprintf_args(int a __unused,...)208 _consume_kprintf_args(int a __unused, ...)
209 {
210 }
211
212 static int
printnum(unsigned long long int u,int base,void (* putc)(int,void *),void * arg)213 printnum(
214 unsigned long long int u, /* number to print */
215 int base,
216 void (*putc)(int, void *),
217 void *arg)
218 {
219 char buf[MAXBUF]; /* build number here */
220 char * p = &buf[MAXBUF - 1];
221 int nprinted = 0;
222
223 do {
224 *p-- = digs[u % base];
225 u /= base;
226 } while (u != 0);
227
228 while (++p != &buf[MAXBUF]) {
229 (*putc)(*p, arg);
230 nprinted++;
231 }
232
233 return nprinted;
234 }
235
236 boolean_t _doprnt_truncates = FALSE;
237
238 #if (DEVELOPMENT || DEBUG)
239 boolean_t doprnt_hide_pointers = FALSE;
240 #else
241 boolean_t doprnt_hide_pointers = TRUE;
242 #endif
243
244 int
__doprnt(const char * fmt,va_list argp,void (* putc)(int,void * arg),void * arg,int radix,int is_log)245 __doprnt(
246 const char *fmt,
247 va_list argp,
248 /* character output routine */
249 void (*putc)(int, void *arg),
250 void *arg,
251 int radix, /* default radix - for '%r' */
252 int is_log)
253 {
254 int length;
255 int prec;
256 boolean_t ladjust;
257 char padc;
258 long long n;
259 unsigned long long u;
260 int plus_sign;
261 int sign_char;
262 boolean_t altfmt, truncate;
263 int base;
264 char c;
265 int capitals;
266 int long_long;
267 enum {
268 INT,
269 SHORT,
270 CHAR,
271 } numeric_type = INT;
272 int nprinted = 0;
273
274 if (radix < 2 || radix > 36) {
275 radix = 10;
276 }
277
278 while ((c = *fmt) != '\0') {
279 if (c != '%') {
280 (*putc)(c, arg);
281 nprinted++;
282 fmt++;
283 continue;
284 }
285
286 fmt++;
287
288 long_long = 0;
289 numeric_type = INT;
290 length = 0;
291 prec = -1;
292 ladjust = FALSE;
293 padc = ' ';
294 plus_sign = 0;
295 sign_char = 0;
296 altfmt = FALSE;
297
298 while (TRUE) {
299 c = *fmt;
300 if (c == '#') {
301 altfmt = TRUE;
302 } else if (c == '-') {
303 ladjust = TRUE;
304 } else if (c == '+') {
305 plus_sign = '+';
306 } else if (c == ' ') {
307 if (plus_sign == 0) {
308 plus_sign = ' ';
309 }
310 } else {
311 break;
312 }
313 fmt++;
314 }
315
316 if (c == '0') {
317 padc = '0';
318 c = *++fmt;
319 }
320
321 if (isdigit(c)) {
322 while (isdigit(c)) {
323 length = 10 * length + Ctod(c);
324 c = *++fmt;
325 }
326 } else if (c == '*') {
327 length = va_arg(argp, int);
328 c = *++fmt;
329 if (length < 0) {
330 ladjust = !ladjust;
331 length = -length;
332 }
333 }
334
335 if (c == '.') {
336 c = *++fmt;
337 if (isdigit(c)) {
338 prec = 0;
339 while (isdigit(c)) {
340 prec = 10 * prec + Ctod(c);
341 c = *++fmt;
342 }
343 } else if (c == '*') {
344 prec = va_arg(argp, int);
345 c = *++fmt;
346 }
347 }
348
349 if (c == 'l') {
350 c = *++fmt; /* need it if sizeof(int) < sizeof(long) */
351 if (sizeof(int) < sizeof(long)) {
352 long_long = 1;
353 }
354 if (c == 'l') {
355 long_long = 1;
356 c = *++fmt;
357 }
358 } else if (c == 'h') {
359 c = *++fmt;
360 numeric_type = SHORT;
361 if (c == 'h') {
362 numeric_type = CHAR;
363 c = *++fmt;
364 }
365 } else if (c == 'q' || c == 'L') {
366 long_long = 1;
367 c = *++fmt;
368 }
369
370 if (c == 'z' || c == 'Z') {
371 c = *++fmt;
372 if (sizeof(size_t) == sizeof(unsigned long long)) {
373 long_long = 1;
374 }
375 } else if (c == 't') {
376 c = *++fmt;
377 if (sizeof(ptrdiff_t) == sizeof(unsigned long long)) {
378 long_long = 1;
379 }
380 } else if (c == 'j') {
381 c = *++fmt;
382 if (sizeof(intmax_t) == sizeof(unsigned long long)) {
383 long_long = 1;
384 }
385 }
386
387 truncate = FALSE;
388 capitals = 0; /* Assume lower case printing */
389
390 switch (c) {
391 case 'b':
392 case 'B':
393 {
394 char *p;
395 boolean_t any;
396 int i;
397
398 if (long_long) {
399 u = va_arg(argp, unsigned long long);
400 } else {
401 u = va_arg(argp, unsigned int);
402 }
403 p = va_arg(argp, char *);
404 base = *p++;
405 nprinted += printnum(u, base, putc, arg);
406
407 if (u == 0) {
408 break;
409 }
410
411 any = FALSE;
412 while ((i = *p++) != '\0') {
413 if (*fmt == 'B') {
414 i = 33 - i;
415 }
416 if (*p <= 32) {
417 /*
418 * Bit field
419 */
420 int j;
421 if (any) {
422 (*putc)(',', arg);
423 } else {
424 (*putc)('<', arg);
425 any = TRUE;
426 }
427 nprinted++;
428 j = *p++;
429 if (*fmt == 'B') {
430 j = 32 - j;
431 }
432 for (; (c = *p) > 32; p++) {
433 (*putc)(c, arg);
434 nprinted++;
435 }
436 nprinted += printnum((unsigned)((u >> (j - 1)) & ((2 << (i - j)) - 1)),
437 base, putc, arg);
438 } else if (u & (1 << (i - 1))) {
439 if (any) {
440 (*putc)(',', arg);
441 } else {
442 (*putc)('<', arg);
443 any = TRUE;
444 }
445 nprinted++;
446 for (; (c = *p) > 32; p++) {
447 (*putc)(c, arg);
448 nprinted++;
449 }
450 } else {
451 for (; *p > 32; p++) {
452 continue;
453 }
454 }
455 }
456 if (any) {
457 (*putc)('>', arg);
458 nprinted++;
459 }
460 break;
461 }
462
463 case 'c':
464 c = (char)va_arg(argp, int);
465 (*putc)(c, arg);
466 nprinted++;
467 break;
468
469 case 's':
470 {
471 const char *p;
472 const char *p2;
473
474 if (prec == -1) {
475 prec = 0x7fffffff; /* MAXINT */
476 }
477 p = va_arg(argp, char *);
478
479 if (p == NULL) {
480 p = "";
481 }
482
483 if (length > 0 && !ladjust) {
484 n = 0;
485 p2 = p;
486
487 for (; *p != '\0' && n < prec; p++) {
488 n++;
489 }
490
491 p = p2;
492
493 while (n < length) {
494 (*putc)(' ', arg);
495 n++;
496 nprinted++;
497 }
498 }
499
500 n = 0;
501
502 while ((n < prec) && (!(length > 0 && n >= length))) {
503 if (*p == '\0') {
504 break;
505 }
506 (*putc)(*p++, arg);
507 nprinted++;
508 n++;
509 }
510
511 if (n < length && ladjust) {
512 while (n < length) {
513 (*putc)(' ', arg);
514 n++;
515 nprinted++;
516 }
517 }
518
519 break;
520 }
521
522 case 'o':
523 truncate = _doprnt_truncates;
524 OS_FALLTHROUGH;
525 case 'O':
526 base = 8;
527 goto print_unsigned;
528
529 case 'D': {
530 unsigned char *up;
531 char *q, *p;
532
533 up = (unsigned char *)va_arg(argp, unsigned char *);
534 p = (char *)va_arg(argp, char *);
535 if (length == -1) {
536 length = 16;
537 }
538 while (length--) {
539 (*putc)(digs[(*up >> 4)], arg);
540 (*putc)(digs[(*up & 0x0f)], arg);
541 nprinted += 2;
542 up++;
543 if (length) {
544 for (q = p; *q; q++) {
545 (*putc)(*q, arg);
546 nprinted++;
547 }
548 }
549 }
550 break;
551 }
552
553 case 'd':
554 case 'i':
555 truncate = _doprnt_truncates;
556 base = 10;
557 goto print_signed;
558
559 case 'u':
560 truncate = _doprnt_truncates;
561 OS_FALLTHROUGH;
562 case 'U':
563 base = 10;
564 goto print_unsigned;
565
566 case 'p':
567 altfmt = TRUE;
568 if (sizeof(int) < sizeof(void *)) {
569 long_long = 1;
570 }
571 OS_FALLTHROUGH;
572 case 'x':
573 truncate = _doprnt_truncates;
574 base = 16;
575 goto print_unsigned;
576
577 case 'X':
578 base = 16;
579 capitals = 16; /* Print in upper case */
580 goto print_unsigned;
581
582 case 'r':
583 truncate = _doprnt_truncates;
584 OS_FALLTHROUGH;
585 case 'R':
586 base = radix;
587 goto print_signed;
588
589 case 'n':
590 truncate = _doprnt_truncates;
591 OS_FALLTHROUGH;
592 case 'N':
593 base = radix;
594 goto print_unsigned;
595
596 print_signed:
597 if (long_long) {
598 n = va_arg(argp, long long);
599 } else {
600 n = va_arg(argp, int);
601 }
602 switch (numeric_type) {
603 case SHORT:
604 n = (short)n;
605 break;
606 case CHAR:
607 n = (char)n;
608 break;
609 default:
610 break;
611 }
612 if (n >= 0) {
613 u = n;
614 sign_char = plus_sign;
615 } else {
616 u = -n;
617 sign_char = '-';
618 }
619 goto print_num;
620
621 print_unsigned:
622 if (long_long) {
623 u = va_arg(argp, unsigned long long);
624 } else {
625 u = va_arg(argp, unsigned int);
626 }
627 switch (numeric_type) {
628 case SHORT:
629 u = (unsigned short)u;
630 break;
631 case CHAR:
632 u = (unsigned char)u;
633 break;
634 default:
635 break;
636 }
637 goto print_num;
638
639 print_num:
640 {
641 char buf[MAXBUF];/* build number here */
642 char * p = &buf[MAXBUF - 1];
643 static char digits[] = "0123456789abcdef0123456789ABCDEF";
644 const char *prefix = NULL;
645
646 if (truncate) {
647 u = (long long)((int)(u));
648 }
649
650 if (doprnt_hide_pointers && is_log) {
651 const char str[] = "<ptr>";
652 const char* strp = str;
653 int strl = sizeof(str) - 1;
654 unsigned long long u_stripped = u;
655 #ifdef HAS_APPLE_PAC
656 /**
657 * Strip out the pointer authentication code before
658 * checking whether the pointer is a kernel address.
659 */
660 u_stripped = (unsigned long long)VM_KERNEL_STRIP_PTR(u);
661 #endif /* HAS_APPLE_PAC */
662
663 if (u_stripped >= VM_MIN_KERNEL_AND_KEXT_ADDRESS && u_stripped <= VM_MAX_KERNEL_ADDRESS) {
664 while (*strp != '\0') {
665 (*putc)(*strp, arg);
666 strp++;
667 }
668 nprinted += strl;
669 break;
670 }
671 }
672
673 if (u != 0 && altfmt) {
674 if (base == 8) {
675 prefix = "0";
676 } else if (base == 16) {
677 prefix = "0x";
678 }
679 }
680
681 do {
682 /* Print in the correct case */
683 *p-- = digits[(u % base) + capitals];
684 u /= base;
685 } while (u != 0);
686
687 length -= (int)(&buf[MAXBUF - 1] - p);
688 if (sign_char) {
689 length--;
690 }
691 if (prefix) {
692 length -= (int)strlen(prefix);
693 }
694
695 if (padc == ' ' && !ladjust) {
696 /* blank padding goes before prefix */
697 while (--length >= 0) {
698 (*putc)(' ', arg);
699 nprinted++;
700 }
701 }
702 if (sign_char) {
703 (*putc)(sign_char, arg);
704 nprinted++;
705 }
706 if (prefix) {
707 while (*prefix) {
708 (*putc)(*prefix++, arg);
709 nprinted++;
710 }
711 }
712 if (padc == '0') {
713 /* zero padding goes after sign and prefix */
714 while (--length >= 0) {
715 (*putc)('0', arg);
716 nprinted++;
717 }
718 }
719 while (++p != &buf[MAXBUF]) {
720 (*putc)(*p, arg);
721 nprinted++;
722 }
723
724 if (ladjust) {
725 while (--length >= 0) {
726 (*putc)(' ', arg);
727 nprinted++;
728 }
729 }
730 break;
731 }
732
733 case '\0':
734 fmt--;
735 break;
736
737 default:
738 (*putc)(c, arg);
739 nprinted++;
740 }
741 fmt++;
742 }
743
744 return nprinted;
745 }
746
747 static void
dummy_putc(int ch,void * arg)748 dummy_putc(int ch, void *arg)
749 {
750 void (*real_putc)(char) = arg;
751
752 /*
753 * Attempts to panic (or otherwise log to console) during early boot
754 * can result in _doprnt() and _doprnt_log() being called from
755 * _kprintf() before PE_init_kprintf() has been called. This causes
756 * the "putc" param to _doprnt() and _doprnt_log() to be passed as
757 * NULL. That NULL makes its way here, and we would try jump to it.
758 * Given that this is a poor idea, and this happens at very early
759 * boot, there is not a way to report this easily (we are likely
760 * already panicing), so we'll just do nothing instead of crashing.
761 */
762 if (real_putc) {
763 real_putc((char)ch);
764 }
765 }
766
767 void
_doprnt(const char * fmt,va_list * argp,void (* putc)(char),int radix)768 _doprnt(
769 const char *fmt,
770 va_list *argp,
771 /* character output routine */
772 void (*putc)(char),
773 int radix) /* default radix - for '%r' */
774 {
775 __doprnt(fmt, *argp, dummy_putc, putc, radix, FALSE);
776 }
777
778 void
_doprnt_log(const char * fmt,va_list * argp,void (* putc)(char),int radix)779 _doprnt_log(
780 const char *fmt,
781 va_list *argp,
782 /* character output routine */
783 void (*putc)(char),
784 int radix) /* default radix - for '%r' */
785 {
786 __doprnt(fmt, *argp, dummy_putc, putc, radix, TRUE);
787 }
788
789 #if MP_PRINTF
790 boolean_t new_printf_cpu_number = FALSE;
791 #endif /* MP_PRINTF */
792
793 LCK_GRP_DECLARE(log_lock_grp, "log_group");
794
795 #if defined(__x86_64__)
796 SIMPLE_LOCK_DECLARE(log_lock, 0);
797 #else
798 LCK_TICKET_DECLARE(log_lock, &log_lock_grp);
799 #endif /* __x86_64__ */
800
801 bool bsd_log_lock(bool);
802 void bsd_log_lock_safe(void);
803 void bsd_log_unlock(void);
804
805 /*
806 * Locks OS log lock and returns true if successful, false otherwise. Locking
807 * always succeeds in a safe context but may block. Locking in an unsafe context
808 * never blocks but fails if someone else is already holding the lock.
809 *
810 * A caller is responsible to decide whether the context is safe or not.
811 *
812 * As a rule of thumb following cases are *not* considered safe:
813 * - Interrupts are disabled
814 * - Pre-emption is disabled
815 * - When in a debugger
816 * - During a panic
817 */
818 bool
bsd_log_lock(bool safe)819 bsd_log_lock(bool safe)
820 {
821 if (!safe) {
822 assert(!oslog_is_safe());
823 #if defined(__x86_64__)
824 return simple_lock_try(&log_lock, &log_lock_grp);
825 #else
826 return lck_ticket_lock_try(&log_lock, &log_lock_grp);
827 #endif /* __x86_64__ */
828 }
829 #if defined(__x86_64__)
830 simple_lock(&log_lock, &log_lock_grp);
831 #else
832 lck_ticket_lock(&log_lock, &log_lock_grp);
833 #endif /* __x86_64__ */
834 return true;
835 }
836
837 /*
838 * Locks OS log lock assuming the context is safe. See bsd_log_lock() comment
839 * for details.
840 */
841 void
bsd_log_lock_safe(void)842 bsd_log_lock_safe(void)
843 {
844 (void) bsd_log_lock(true);
845 }
846
847 void
bsd_log_unlock(void)848 bsd_log_unlock(void)
849 {
850 #if defined(__x86_64__)
851 simple_unlock(&log_lock);
852 #else
853 lck_ticket_unlock(&log_lock);
854 #endif /* __x86_64__ */
855 }
856
857 void
conslog_putc(char c)858 conslog_putc(char c)
859 {
860 console_write_char(c);
861
862 #ifdef MACH_BSD
863 if (!kernel_debugger_entry_count) {
864 log_putc(c);
865 }
866 #endif
867 }
868
869 void
cons_putc_locked(char c)870 cons_putc_locked(char c)
871 {
872 console_write_char(c);
873 }
874
875 __printflike(1, 0)
876 static int
vprintf_internal(const char * fmt,va_list ap_in,void * caller)877 vprintf_internal(const char *fmt, va_list ap_in, void *caller)
878 {
879 if (fmt) {
880 struct console_printbuf_state info_data;
881
882 va_list ap;
883 va_copy(ap, ap_in);
884
885 #pragma clang diagnostic push
886 #pragma clang diagnostic ignored "-Wformat-nonliteral"
887 #pragma clang diagnostic ignored "-Wformat"
888 os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, fmt, ap_in, caller);
889 #pragma clang diagnostic pop
890
891 console_printbuf_state_init(&info_data, TRUE, TRUE);
892 __doprnt(fmt, ap, console_printbuf_putc, &info_data, 16, TRUE);
893 console_printbuf_clear(&info_data);
894
895 va_end(ap);
896 }
897 return 0;
898 }
899
900 __attribute__((noinline, not_tail_called))
901 int
printf(const char * fmt,...)902 printf(const char *fmt, ...)
903 {
904 int ret;
905
906 va_list ap;
907 va_start(ap, fmt);
908 ret = vprintf_internal(fmt, ap, __builtin_return_address(0));
909 va_end(ap);
910
911 return ret;
912 }
913
914 __attribute__((noinline, not_tail_called))
915 int
vprintf(const char * fmt,va_list ap)916 vprintf(const char *fmt, va_list ap)
917 {
918 return vprintf_internal(fmt, ap, __builtin_return_address(0));
919 }
920
921 #if !CONFIG_SPTM
922 #define sptm_serial_putc(c)
923 #endif
924
925 void
consdebug_putc(char c)926 consdebug_putc(char c)
927 {
928 console_write_char(c);
929
930 debug_putc(c);
931
932 /* Ignore `disable_serial_output` for early panic serial output from `sptm_serial_putc()`. */
933 if (!console_is_serial() && !disable_serial_output && (PE_kputc != NULL)) {
934 PE_kputc(c);
935 } else if (!console_is_serial() && (PE_kputc == NULL)) {
936 /* Use SPTM's serial interface for early serial output. */
937 sptm_serial_putc(c);
938 }
939 }
940
941 void
consdebug_putc_unbuffered(char c)942 consdebug_putc_unbuffered(char c)
943 {
944 console_write_unbuffered(c);
945
946 debug_putc(c);
947
948 /* Ignore `disable_serial_output` for early panic serial output from `sptm_serial_putc()`. */
949 if (!console_is_serial() && !disable_serial_output && (PE_kputc != NULL)) {
950 PE_kputc(c);
951 } else if (!console_is_serial() && (PE_kputc == NULL)) {
952 /* Use SPTM's serial interface for early serial output. */
953 sptm_serial_putc(c);
954 }
955 }
956
957 void
consdebug_log(char c)958 consdebug_log(char c)
959 {
960 debug_putc(c);
961 }
962
963 /*
964 * Append contents to the paniclog buffer but don't flush
965 * it. This is mainly used for writing the actual paniclog
966 * contents since flushing once for every line written
967 * would be prohibitively expensive for the paniclog
968 */
969 int
paniclog_append_noflush(const char * fmt,...)970 paniclog_append_noflush(const char *fmt, ...)
971 {
972 va_list listp;
973
974 va_start(listp, fmt);
975 _doprnt_log(fmt, &listp, consdebug_putc_unbuffered, 16);
976 va_end(listp);
977
978 return 0;
979 }
980
981 int
kdb_printf(const char * fmt,...)982 kdb_printf(const char *fmt, ...)
983 {
984 va_list listp;
985
986 va_start(listp, fmt);
987 _doprnt_log(fmt, &listp, consdebug_putc, 16);
988 va_end(listp);
989
990 #if defined(__arm64__)
991 paniclog_flush();
992 #endif
993
994 return 0;
995 }
996
997 int
kdb_log(const char * fmt,...)998 kdb_log(const char *fmt, ...)
999 {
1000 va_list listp;
1001
1002 va_start(listp, fmt);
1003 _doprnt(fmt, &listp, consdebug_log, 16);
1004 va_end(listp);
1005
1006 #if defined(__arm64__)
1007 paniclog_flush();
1008 #endif
1009
1010 return 0;
1011 }
1012
1013 int
kdb_printf_unbuffered(const char * fmt,...)1014 kdb_printf_unbuffered(const char *fmt, ...)
1015 {
1016 va_list listp;
1017
1018 va_start(listp, fmt);
1019 _doprnt(fmt, &listp, consdebug_putc_unbuffered, 16);
1020 va_end(listp);
1021
1022 #if defined(__arm64__)
1023 paniclog_flush();
1024 #endif
1025
1026 return 0;
1027 }
1028
1029 #if CONFIG_VSPRINTF
1030 static void
copybyte(int c,void * arg)1031 copybyte(int c, void *arg)
1032 {
1033 /*
1034 * arg is a pointer (outside pointer) to the pointer
1035 * (inside pointer) which points to the character.
1036 * We pass a double pointer, so that we can increment
1037 * the inside pointer.
1038 */
1039 char** p = arg; /* cast outside pointer */
1040 **p = (char)c; /* store character */
1041 (*p)++; /* increment inside pointer */
1042 }
1043
1044 /*
1045 * Deprecation Warning:
1046 * sprintf() is being deprecated. Please use snprintf() instead.
1047 */
1048 int
sprintf(char * buf,const char * fmt,...)1049 sprintf(char *buf, const char *fmt, ...)
1050 {
1051 va_list listp;
1052 char *copybyte_str;
1053
1054 va_start(listp, fmt);
1055 copybyte_str = buf;
1056 __doprnt(fmt, listp, copybyte, ©byte_str, 16, FALSE);
1057 va_end(listp);
1058 *copybyte_str = '\0';
1059 return (int)strlen(buf);
1060 }
1061 #endif /* CONFIG_VSPRINTF */
1062