/ duct-tape / xnu / osfmk / kern / printf.c
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, &copybyte_str, 16, FALSE);
1079  	va_end(listp);
1080  	*copybyte_str = '\0';
1081  	return (int)strlen(buf);
1082  }
1083  #endif /* CONFIG_VSPRINTF */