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