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