1/* 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31 32/* 33 * Mach Operating System 34 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University 35 * All Rights Reserved. 36 * 37 * Permission to use, copy, modify and distribute this software and its 38 * documentation is hereby granted, provided that both the copyright 39 * notice and this permission notice appear in all copies of the 40 * software, derivative works or modified versions, and any portions 41 * thereof, and that both notices appear in supporting documentation. 42 * 43 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 44 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 45 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 46 * 47 * Carnegie Mellon requests users of this software to return to 48 * 49 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 50 * School of Computer Science 51 * Carnegie Mellon University 52 * Pittsburgh PA 15213-3890 53 * 54 * any improvements or extensions that they make and grant Carnegie Mellon 55 * the rights to redistribute these changes. 56 */ 57 58/* 59 * Common code for printf et al. 60 * 61 * The calling routine typically takes a variable number of arguments, 62 * and passes the address of the first one. This implementation 63 * assumes a straightforward, stack implementation, aligned to the 64 * machine's wordsize. Increasing addresses are assumed to point to 65 * successive arguments (left-to-right), as is the case for a machine 66 * with a downward-growing stack with arguments pushed right-to-left. 67 * 68 * To write, for example, fprintf() using this routine, the code 69 * 70 * fprintf(fd, format, args) 71 * FILE *fd; 72 * char *format; 73 * { 74 * _doprnt(format, &args, fd); 75 * } 76 * 77 * would suffice. (This example does not handle the fprintf's "return 78 * value" correctly, but who looks at the return value of fprintf 79 * anyway?) 80 * 81 * This version implements the following printf features: 82 * 83 * %d decimal conversion 84 * %u unsigned conversion 85 * %x hexadecimal conversion 86 * %X hexadecimal conversion with capital letters 87 * %D hexdump, ptr & separator string ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 88 * if you use, "%*D" then there's a length, the data ptr and then the separator 89 * %o octal conversion 90 * %c character 91 * %s string 92 * %m.n field width, precision 93 * %-m.n left adjustment 94 * %0m.n zero-padding 95 * %*.* width and precision taken from arguments 96 * 97 * This version does not implement %f, %e, or %g. 98 * 99 * As mentioned, this version does not return any reasonable value. 100 * 101 * Permission is granted to use, modify, or propagate this code as 102 * long as this notice is incorporated. 103 * 104 * Steve Summit 3/25/87 105 * 106 * Tweaked for long long support and extended to support the hexdump %D 107 * specifier by dbg 05/02/02. 108 */ 109 110/* 111 * Added formats for decoding device registers: 112 * 113 * printf("reg = %b", regval, "<base><arg>*") 114 * 115 * where <base> is the output base expressed as a control character: 116 * i.e. '\10' gives octal, '\20' gives hex. Each <arg> is a sequence of 117 * characters, the first of which gives the bit number to be inspected 118 * (origin 1), and the rest (up to a control character (<= 32)) give the 119 * name of the register. Thus 120 * printf("reg = %b\n", 3, "\10\2BITTWO\1BITONE") 121 * would produce 122 * reg = 3<BITTWO,BITONE> 123 * 124 * If the second character in <arg> is also a control character, it 125 * indicates the last bit of a bit field. In this case, printf will extract 126 * bits <1> to <2> and print it. Characters following the second control 127 * character are printed before the bit field. 128 * printf("reg = %b\n", 0xb, "\10\4\3FIELD1=\2BITTWO\1BITONE") 129 * would produce 130 * reg = b<FIELD1=2,BITONE> 131 * 132 * The %B format is like %b but the bits are numbered from the most 133 * significant (the bit weighted 31), which is called 1, to the least 134 * significant, called 32. 135 */ 136/* 137 * Added for general use: 138 * # prefix for alternate format: 139 * 0x (0X) for hex 140 * leading 0 for octal 141 * + print '+' if positive 142 * blank print ' ' if positive 143 * 144 * z signed hexadecimal 145 * r signed, 'radix' 146 * n unsigned, 'radix' 147 * 148 * D,U,O,Z same as corresponding lower-case versions 149 * (compatibility) 150 */ 151/* 152 * Added support for print long long (64-bit) integers. 153 * Use %lld, %Ld or %qd to print a 64-bit int. Other 154 * output bases such as x, X, u, U, o, and O also work. 155 */ 156 157#include <debug.h> 158#include <mach_kdp.h> 159#include <platforms.h> 160#include <mach/boolean.h> 161#include <kern/cpu_number.h> 162#include <kern/lock.h> 163#include <kern/thread.h> 164#include <kern/sched_prim.h> 165#include <kern/misc_protos.h> 166#include <stdarg.h> 167#include <string.h> 168#include <mach_assert.h> 169#ifdef MACH_BSD 170#include <sys/msgbuf.h> 171#endif 172#include <console/serial_protos.h> 173 174#define isdigit(d) ((d) >= '0' && (d) <= '9') 175#define Ctod(c) ((c) - '0') 176 177#define MAXBUF (sizeof(long long int) * 8) /* enough for binary */ 178static char digs[] = "0123456789abcdef"; 179 180#if CONFIG_NO_PRINTF_STRINGS 181/* Prevent CPP from breaking the definition below */ 182#undef printf 183#endif 184 185int _consume_printf_args(int a __unused, ...) 186{ 187 return 0; 188} 189void _consume_kprintf_args(int a __unused, ...) 190{ 191} 192 193static int 194printnum( 195 unsigned long long int u, /* number to print */ 196 int base, 197 void (*putc)(int, void *), 198 void *arg) 199{ 200 char buf[MAXBUF]; /* build number here */ 201 char * p = &buf[MAXBUF-1]; 202 int nprinted = 0; 203 204 do { 205 *p-- = digs[u % base]; 206 u /= base; 207 } while (u != 0); 208 209 while (++p != &buf[MAXBUF]) { 210 (*putc)(*p, arg); 211 nprinted++; 212 } 213 214 return nprinted; 215} 216 217boolean_t _doprnt_truncates = FALSE; 218 219int 220__doprnt( 221 const char *fmt, 222 va_list argp, 223 /* character output routine */ 224 void (*putc)(int, void *arg), 225 void *arg, 226 int radix) /* default radix - for '%r' */ 227{ 228 int length; 229 int prec; 230 boolean_t ladjust; 231 char padc; 232 long long n; 233 unsigned long long u; 234 int plus_sign; 235 int sign_char; 236 boolean_t altfmt, truncate; 237 int base; 238 char c; 239 int capitals; 240 int long_long; 241 int nprinted = 0; 242 243 while ((c = *fmt) != '\0') { 244 if (c != '%') { 245 (*putc)(c, arg); 246 nprinted++; 247 fmt++; 248 continue; 249 } 250 251 fmt++; 252 253 long_long = 0; 254 length = 0; 255 prec = -1; 256 ladjust = FALSE; 257 padc = ' '; 258 plus_sign = 0; 259 sign_char = 0; 260 altfmt = FALSE; 261 262 while (TRUE) { 263 c = *fmt; 264 if (c == '#') { 265 altfmt = TRUE; 266 } 267 else if (c == '-') { 268 ladjust = TRUE; 269 } 270 else if (c == '+') { 271 plus_sign = '+'; 272 } 273 else if (c == ' ') { 274 if (plus_sign == 0) 275 plus_sign = ' '; 276 } 277 else 278 break; 279 fmt++; 280 } 281 282 if (c == '0') { 283 padc = '0'; 284 c = *++fmt; 285 } 286 287 if (isdigit(c)) { 288 while(isdigit(c)) { 289 length = 10 * length + Ctod(c); 290 c = *++fmt; 291 } 292 } 293 else if (c == '*') { 294 length = va_arg(argp, int); 295 c = *++fmt; 296 if (length < 0) { 297 ladjust = !ladjust; 298 length = -length; 299 } 300 } 301 302 if (c == '.') { 303 c = *++fmt; 304 if (isdigit(c)) { 305 prec = 0; 306 while(isdigit(c)) { 307 prec = 10 * prec + Ctod(c); 308 c = *++fmt; 309 } 310 } 311 else if (c == '*') { 312 prec = va_arg(argp, int); 313 c = *++fmt; 314 } 315 } 316 317 if (c == 'l') { 318 c = *++fmt; /* need it if sizeof(int) < sizeof(long) */ 319 if (sizeof(int)<sizeof(long)) 320 long_long = 1; 321 if (c == 'l') { 322 long_long = 1; 323 c = *++fmt; 324 } 325 } else if (c == 'q' || c == 'L') { 326 long_long = 1; 327 c = *++fmt; 328 } 329 330 truncate = FALSE; 331 capitals=0; /* Assume lower case printing */ 332 333 switch(c) { 334 case 'b': 335 case 'B': 336 { 337 register char *p; 338 boolean_t any; 339 register int i; 340 341 if (long_long) { 342 u = va_arg(argp, unsigned long long); 343 } else { 344 u = va_arg(argp, unsigned int); 345 } 346 p = va_arg(argp, char *); 347 base = *p++; 348 nprinted += printnum(u, base, putc, arg); 349 350 if (u == 0) 351 break; 352 353 any = FALSE; 354 while ((i = *p++) != '\0') { 355 if (*fmt == 'B') 356 i = 33 - i; 357 if (*p <= 32) { 358 /* 359 * Bit field 360 */ 361 register int j; 362 if (any) 363 (*putc)(',', arg); 364 else { 365 (*putc)('<', arg); 366 any = TRUE; 367 } 368 nprinted++; 369 j = *p++; 370 if (*fmt == 'B') 371 j = 32 - j; 372 for (; (c = *p) > 32; p++) { 373 (*putc)(c, arg); 374 nprinted++; 375 } 376 nprinted += printnum((unsigned)( (u>>(j-1)) & ((2<<(i-j))-1)), 377 base, putc, arg); 378 } 379 else if (u & (1<<(i-1))) { 380 if (any) 381 (*putc)(',', arg); 382 else { 383 (*putc)('<', arg); 384 any = TRUE; 385 } 386 nprinted++; 387 for (; (c = *p) > 32; p++) { 388 (*putc)(c, arg); 389 nprinted++; 390 } 391 } 392 else { 393 for (; *p > 32; p++) 394 continue; 395 } 396 } 397 if (any) { 398 (*putc)('>', arg); 399 nprinted++; 400 } 401 break; 402 } 403 404 case 'c': 405 c = va_arg(argp, int); 406 (*putc)(c, arg); 407 nprinted++; 408 break; 409 410 case 's': 411 { 412 register const char *p; 413 register const char *p2; 414 415 if (prec == -1) 416 prec = 0x7fffffff; /* MAXINT */ 417 418 p = va_arg(argp, char *); 419 420 if (p == NULL) 421 p = ""; 422 423 if (length > 0 && !ladjust) { 424 n = 0; 425 p2 = p; 426 427 for (; *p != '\0' && n < prec; p++) 428 n++; 429 430 p = p2; 431 432 while (n < length) { 433 (*putc)(' ', arg); 434 n++; 435 nprinted++; 436 } 437 } 438 439 n = 0; 440 441 while ((n < prec) && (!(length > 0 && n >= length))) { 442 if (*p == '\0') { 443 break; 444 } 445 (*putc)(*p++, arg); 446 nprinted++; 447 n++; 448 } 449 450 if (n < length && ladjust) { 451 while (n < length) { 452 (*putc)(' ', arg); 453 n++; 454 nprinted++; 455 } 456 } 457 458 break; 459 } 460 461 case 'o': 462 truncate = _doprnt_truncates; 463 case 'O': 464 base = 8; 465 goto print_unsigned; 466 467 case 'D': { 468 unsigned char *up; 469 char *q, *p; 470 471 up = (unsigned char *)va_arg(argp, unsigned char *); 472 p = (char *)va_arg(argp, char *); 473 if (length == -1) 474 length = 16; 475 while(length--) { 476 (*putc)(digs[(*up >> 4)], arg); 477 (*putc)(digs[(*up & 0x0f)], arg); 478 nprinted += 2; 479 up++; 480 if (length) { 481 for (q=p;*q;q++) { 482 (*putc)(*q, arg); 483 nprinted++; 484 } 485 } 486 } 487 break; 488 } 489 490 case 'd': 491 truncate = _doprnt_truncates; 492 base = 10; 493 goto print_signed; 494 495 case 'u': 496 truncate = _doprnt_truncates; 497 case 'U': 498 base = 10; 499 goto print_unsigned; 500 501 case 'p': 502 altfmt = TRUE; 503 if (sizeof(int)<sizeof(void *)) { 504 long_long = 1; 505 } 506 case 'x': 507 truncate = _doprnt_truncates; 508 base = 16; 509 goto print_unsigned; 510 511 case 'X': 512 base = 16; 513 capitals=16; /* Print in upper case */ 514 goto print_unsigned; 515 516 case 'z': 517 truncate = _doprnt_truncates; 518 base = 16; 519 goto print_signed; 520 521 case 'Z': 522 base = 16; 523 capitals=16; /* Print in upper case */ 524 goto print_signed; 525 526 case 'r': 527 truncate = _doprnt_truncates; 528 case 'R': 529 base = radix; 530 goto print_signed; 531 532 case 'n': 533 truncate = _doprnt_truncates; 534 case 'N': 535 base = radix; 536 goto print_unsigned; 537 538 print_signed: 539 if (long_long) { 540 n = va_arg(argp, long long); 541 } else { 542 n = va_arg(argp, int); 543 } 544 if (n >= 0) { 545 u = n; 546 sign_char = plus_sign; 547 } 548 else { 549 u = -n; 550 sign_char = '-'; 551 } 552 goto print_num; 553 554 print_unsigned: 555 if (long_long) { 556 u = va_arg(argp, unsigned long long); 557 } else { 558 u = va_arg(argp, unsigned int); 559 } 560 goto print_num; 561 562 print_num: 563 { 564 char buf[MAXBUF]; /* build number here */ 565 register char * p = &buf[MAXBUF-1]; 566 static char digits[] = "0123456789abcdef0123456789ABCDEF"; 567 const char *prefix = NULL; 568 569 if (truncate) u = (long long)((int)(u)); 570 571 if (u != 0 && altfmt) { 572 if (base == 8) 573 prefix = "0"; 574 else if (base == 16) 575 prefix = "0x"; 576 } 577 578 do { 579 /* Print in the correct case */ 580 *p-- = digits[(u % base)+capitals]; 581 u /= base; 582 } while (u != 0); 583 584 length -= (int)(&buf[MAXBUF-1] - p); 585 if (sign_char) 586 length--; 587 if (prefix) 588 length -= (int)strlen(prefix); 589 590 if (padc == ' ' && !ladjust) { 591 /* blank padding goes before prefix */ 592 while (--length >= 0) { 593 (*putc)(' ', arg); 594 nprinted++; 595 } 596 } 597 if (sign_char) { 598 (*putc)(sign_char, arg); 599 nprinted++; 600 } 601 if (prefix) { 602 while (*prefix) { 603 (*putc)(*prefix++, arg); 604 nprinted++; 605 } 606 } 607 if (padc == '0') { 608 /* zero padding goes after sign and prefix */ 609 while (--length >= 0) { 610 (*putc)('0', arg); 611 nprinted++; 612 } 613 } 614 while (++p != &buf[MAXBUF]) { 615 (*putc)(*p, arg); 616 nprinted++; 617 } 618 619 if (ladjust) { 620 while (--length >= 0) { 621 (*putc)(' ', arg); 622 nprinted++; 623 } 624 } 625 break; 626 } 627 628 case '\0': 629 fmt--; 630 break; 631 632 default: 633 (*putc)(c, arg); 634 nprinted++; 635 } 636 fmt++; 637 } 638 639 return nprinted; 640} 641 642static void 643dummy_putc(int ch, void *arg) 644{ 645 void (*real_putc)(char) = arg; 646 647 real_putc(ch); 648} 649 650int enable_timing = 1; 651 652void 653_doprnt( 654 register const char *fmt, 655 va_list *argp, 656 /* character output routine */ 657 void (*putc)(char), 658 int radix) /* default radix - for '%r' */ 659{ 660#if 0 661 /* timing information */ 662 if(enable_timing) { 663 char tbuf[50], *tp; 664 uint64_t t = mach_absolute_time(); 665 uint64_t ns; absolutetime_to_nanoseconds(t, &ns); 666 /* truncate the end of the timing information */ 667 int tlen = sprintf(tbuf, "[%5llu.%06llu] ", (uint64_t)(ns / NSEC_PER_SEC), (uint64_t)((ns % NSEC_PER_SEC) / 1000)); 668 for(tp = tbuf; tp < tbuf + tlen; tp++) 669 putc(*tp); 670 } 671#endif 672 __doprnt(fmt, *argp, dummy_putc, putc, radix); 673} 674 675#if MP_PRINTF 676boolean_t new_printf_cpu_number = FALSE; 677#endif /* MP_PRINTF */ 678 679 680decl_simple_lock_data(,printf_lock) 681decl_simple_lock_data(,bsd_log_spinlock) 682extern void bsd_log_init(void); 683void bsd_log_lock(void); 684void bsd_log_unlock(void); 685 686void 687printf_init(void) 688{ 689 /* 690 * Lock is only really needed after the first thread is created. 691 */ 692 simple_lock_init(&printf_lock, 0); 693 simple_lock_init(&bsd_log_spinlock, 0); 694 bsd_log_init(); 695} 696 697void 698bsd_log_lock(void) 699{ 700 simple_lock(&bsd_log_spinlock); 701} 702 703void 704bsd_log_unlock(void) 705{ 706 simple_unlock(&bsd_log_spinlock); 707} 708 709/* derived from boot_gets */ 710void 711safe_gets( 712 char *str, 713 int maxlen) 714{ 715 register char *lp; 716 register int c; 717 char *strmax = str + maxlen - 1; /* allow space for trailing 0 */ 718 719 lp = str; 720 for (;;) { 721 c = cngetc(); 722 switch (c) { 723 case '\n': 724 case '\r': 725 printf("\n"); 726 *lp++ = 0; 727 return; 728 729 case '\b': 730 case '#': 731 case '\177': 732 if (lp > str) { 733 printf("\b \b"); 734 lp--; 735 } 736 continue; 737 738 case '@': 739 case 'u'&037: 740 lp = str; 741 printf("\n\r"); 742 continue; 743 744 default: 745 if (c >= ' ' && c < '\177') { 746 if (lp < strmax) { 747 *lp++ = c; 748 printf("%c", c); 749 } 750 else { 751 printf("%c", '\007'); /* beep */ 752 } 753 } 754 } 755 } 756} 757 758extern int disableConsoleOutput; 759 760void 761conslog_putc( 762 char c) 763{ 764 if ((debug_mode && !disable_debug_output) || !disableConsoleOutput) 765 cnputc(c); 766 767#ifdef MACH_BSD 768 if (debug_mode == 0) 769 log_putc(c); 770#endif 771} 772 773void 774cons_putc_locked( 775 char c) 776{ 777 if ((debug_mode && !disable_debug_output) || !disableConsoleOutput) 778 cnputc(c); 779} 780 781int 782printf(const char *fmt, ...) 783{ 784 va_list listp; 785 786 if (fmt) { 787 disable_preemption(); 788 va_start(listp, fmt); 789 _doprnt(fmt, &listp, conslog_putc, 16); 790 va_end(listp); 791 enable_preemption(); 792 } 793 return 0; 794} 795 796void 797consdebug_putc(char c) 798{ 799 if ((debug_mode && !disable_debug_output) || !disableConsoleOutput) 800 cnputc(c); 801 802 debug_putc(c); 803 804 if (!console_is_serial()) 805 if (!disable_serial_output) 806 PE_kputc(c); 807} 808 809void 810consdebug_putc_unbuffered(char c) 811{ 812 if ((debug_mode && !disable_debug_output) || !disableConsoleOutput) 813 cnputc_unbuffered(c); 814 815 debug_putc(c); 816 817 if (!console_is_serial()) 818 if (!disable_serial_output) 819 PE_kputc(c); 820} 821 822void 823consdebug_log(char c) 824{ 825 debug_putc(c); 826} 827 828int 829kdb_printf(const char *fmt, ...) 830{ 831 va_list listp; 832 833 va_start(listp, fmt); 834 _doprnt(fmt, &listp, consdebug_putc, 16); 835 va_end(listp); 836 return 0; 837} 838 839int 840kdb_log(const char *fmt, ...) 841{ 842 va_list listp; 843 844 va_start(listp, fmt); 845 _doprnt(fmt, &listp, consdebug_log, 16); 846 va_end(listp); 847 return 0; 848} 849 850int 851kdb_printf_unbuffered(const char *fmt, ...) 852{ 853 va_list listp; 854 855 va_start(listp, fmt); 856 _doprnt(fmt, &listp, consdebug_putc_unbuffered, 16); 857 va_end(listp); 858 return 0; 859} 860 861#ifdef __arm__ /* I don't want to rebuild my symbolsets. */ 862#undef CONFIG_EMBEDDED 863#define CONFIG_EMBEDDED 0 864#endif 865 866#if !CONFIG_EMBEDDED 867 868static void 869copybyte(int c, void *arg) 870{ 871 /* 872 * arg is a pointer (outside pointer) to the pointer 873 * (inside pointer) which points to the character. 874 * We pass a double pointer, so that we can increment 875 * the inside pointer. 876 */ 877 char** p = arg; /* cast outside pointer */ 878 **p = c; /* store character */ 879 (*p)++; /* increment inside pointer */ 880} 881 882/* 883 * Deprecation Warning: 884 * sprintf() is being deprecated. Please use snprintf() instead. 885 */ 886int 887sprintf(char *buf, const char *fmt, ...) 888{ 889 va_list listp; 890 char *copybyte_str; 891 892 va_start(listp, fmt); 893 copybyte_str = buf; 894 __doprnt(fmt, listp, copybyte, ©byte_str, 16); 895 va_end(listp); 896 *copybyte_str = '\0'; 897 return (int)strlen(buf); 898} 899#endif /* !CONFIG_EMBEDDED */ 900