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