2 * linux/kernel/printk.c 4 * Copyright (C) 1991, 1992 Linus Torvalds 6 * Modified to make sys_syslog() more flexible: added commands to 7 * return the last 4k of kernel messages, regardless of whether 8 * they've been read or not. Added option to suppress kernel printk's 9 * to the console. Added hook for sending the console messages 10 * elsewhere, in preparation for a serial line console (someday). 12 * Modified for sysctl support, 1/8/97, Chris Horn. 13 * Fixed SMP synchronization, 08/08/99, Manfred Spraul 14 * manfreds@colorfullife.com 18 #include <linux/tty_driver.h> 19 #include <linux/smp_lock.h> 20 #include <linux/console.h> 21 #include <linux/init.h> 23 #include <asm/uaccess.h> 25 #define LOG_BUF_LEN (16384) 26 #define LOG_BUF_MASK (LOG_BUF_LEN-1) 28 static char buf
[1024]; 30 /* printk's without a loglevel use this.. */ 31 #define DEFAULT_MESSAGE_LOGLEVEL 4/* KERN_WARNING */ 33 /* We show everything that is MORE important than this.. */ 34 #define MINIMUM_CONSOLE_LOGLEVEL 1/* Minimum loglevel we let people use */ 35 #define DEFAULT_CONSOLE_LOGLEVEL 7/* anything MORE serious than KERN_DEBUG */ 37 unsigned long log_size
; 38 DECLARE_WAIT_QUEUE_HEAD(log_wait
); 40 /* Keep together for sysctl support */ 41 int console_loglevel
= DEFAULT_CONSOLE_LOGLEVEL
; 42 int default_message_loglevel
= DEFAULT_MESSAGE_LOGLEVEL
; 43 int minimum_console_loglevel
= MINIMUM_CONSOLE_LOGLEVEL
; 44 int default_console_loglevel
= DEFAULT_CONSOLE_LOGLEVEL
; 46 spinlock_t console_lock
= SPIN_LOCK_UNLOCKED
; 48 struct console
*console_drivers
; 49 static char log_buf
[LOG_BUF_LEN
]; 50 static unsigned long log_start
; 51 static unsigned long logged_chars
; 52 struct console_cmdline console_cmdline
[MAX_CMDLINECONSOLES
]; 53 static int preferred_console
= -1; 56 * Setup a list of consoles. Called from init/main.c 58 static int __init
console_setup(char*str
) 60 struct console_cmdline
*c
; 61 char name
[sizeof(c
->name
)]; 66 * Decode str into name, index, options. 68 if(str
[0] >='0'&& str
[0] <='9') { 70 strncpy(name
+4, str
,sizeof(name
) -5); 72 strncpy(name
, str
,sizeof(name
) -1); 73 name
[sizeof(name
) -1] =0; 74 if((options
=strchr(str
,',')) != NULL
) 77 if(!strcmp(str
,"ttya")) 79 if(!strcmp(str
,"ttyb")) 82 for(s
= name
; *s
; s
++) 83 if(*s
>='0'&& *s
<='9') 85 idx
=simple_strtoul(s
, NULL
,10); 89 * See if this tty is not yet registered, and 90 * if we have a slot free. 92 for(i
=0; i
< MAX_CMDLINECONSOLES
&& console_cmdline
[i
].name
[0]; i
++) 93 if(strcmp(console_cmdline
[i
].name
, name
) ==0&& 94 console_cmdline
[i
].index
== idx
) { 95 preferred_console
= i
; 98 if(i
== MAX_CMDLINECONSOLES
) 100 preferred_console
= i
; 101 c
= &console_cmdline
[i
]; 102 memcpy(c
->name
, name
,sizeof(c
->name
)); 103 c
->options
= options
; 108 __setup("console=", console_setup
); 111 * Commands to do_syslog: 113 * 0 -- Close the log. Currently a NOP. 114 * 1 -- Open the log. Currently a NOP. 115 * 2 -- Read from the log. 116 * 3 -- Read all messages remaining in the ring buffer. 117 * 4 -- Read and clear all messages remaining in the ring buffer 118 * 5 -- Clear ring buffer. 119 * 6 -- Disable printk's to console 120 * 7 -- Enable printk's to console 121 * 8 -- Set level of messages printed to console 123 intdo_syslog(int type
,char* buf
,int len
) 125 unsigned long i
, j
, limit
, count
; 132 case0:/* Close log */ 136 case2:/* Read from log */ 143 error
=verify_area(VERIFY_WRITE
,buf
,len
); 146 error
=wait_event_interruptible(log_wait
, log_size
); 150 spin_lock_irq(&console_lock
); 151 while(log_size
&& i
< len
) { 152 c
= log_buf
[log_start
& LOG_BUF_MASK
]; 155 spin_unlock_irq(&console_lock
); 159 spin_lock_irq(&console_lock
); 161 spin_unlock_irq(&console_lock
); 164 case4:/* Read/clear last kernel messages */ 167 case3:/* Read last kernel messages */ 174 error
=verify_area(VERIFY_WRITE
,buf
,len
); 178 if(count
> LOG_BUF_LEN
) 180 spin_lock_irq(&console_lock
); 181 if(count
> logged_chars
) 182 count
= logged_chars
; 185 limit
= log_start
+ log_size
; 187 * __put_user() could sleep, and while we sleep 188 * printk() could overwrite the messages 189 * we try to copy to user space. Therefore 190 * the messages are copied in reverse. <manfreds> 192 for(i
=0;i
< count
;i
++) { 194 if(j
+LOG_BUF_LEN
< log_start
+log_size
) 196 c
= log_buf
[ j
& LOG_BUF_MASK
]; 197 spin_unlock_irq(&console_lock
); 198 __put_user(c
,&buf
[count
-1-i
]); 199 spin_lock_irq(&console_lock
); 201 spin_unlock_irq(&console_lock
); 204 int offset
= count
-error
; 205 /* buffer overflow during copy, correct user buffer. */ 206 for(i
=0;i
<error
;i
++) { 207 __get_user(c
,&buf
[i
+offset
]); 208 __put_user(c
,&buf
[i
]); 213 case5:/* Clear ring buffer */ 214 spin_lock_irq(&console_lock
); 216 spin_unlock_irq(&console_lock
); 218 case6:/* Disable logging to console */ 219 spin_lock_irq(&console_lock
); 220 console_loglevel
= minimum_console_loglevel
; 221 spin_unlock_irq(&console_lock
); 223 case7:/* Enable logging to console */ 224 spin_lock_irq(&console_lock
); 225 console_loglevel
= default_console_loglevel
; 226 spin_unlock_irq(&console_lock
); 232 if(len
< minimum_console_loglevel
) 233 len
= minimum_console_loglevel
; 234 spin_lock_irq(&console_lock
); 235 console_loglevel
= len
; 236 spin_unlock_irq(&console_lock
); 247 asmlinkage
longsys_syslog(int type
,char* buf
,int len
) 249 if((type
!=3) && !capable(CAP_SYS_ADMIN
)) 251 returndo_syslog(type
, buf
, len
); 254 asmlinkage
intprintk(const char*fmt
, ...) 258 char*msg
, *p
, *buf_end
; 260 static signed char msg_level
= -1; 263 spin_lock_irqsave(&console_lock
, flags
); 265 i
=vsprintf(buf
+3, fmt
, args
);/* hopefully i < sizeof(buf)-4 */ 268 for(p
= buf
+3; p
< buf_end
; p
++) { 279 p
[1] = default_message_loglevel
+'0'; 283 msg_level
= p
[1] -'0'; 286 for(; p
< buf_end
; p
++) { 287 log_buf
[(log_start
+log_size
) & LOG_BUF_MASK
] = *p
; 288 if(log_size
< LOG_BUF_LEN
) 299 if(msg_level
< console_loglevel
&& console_drivers
) { 300 struct console
*c
= console_drivers
; 302 if((c
->flags
& CON_ENABLED
) && c
->write
) 303 c
->write(c
, msg
, p
- msg
+ line_feed
); 310 spin_unlock_irqrestore(&console_lock
, flags
); 311 wake_up_interruptible(&log_wait
); 315 voidconsole_print(const char*s
) 321 spin_lock_irqsave(&console_lock
, flags
); 324 if((c
->flags
& CON_ENABLED
) && c
->write
) 328 spin_unlock_irqrestore(&console_lock
, flags
); 331 voidunblank_console(void) 336 spin_lock_irqsave(&console_lock
, flags
); 339 if((c
->flags
& CON_ENABLED
) && c
->unblank
) 343 spin_unlock_irqrestore(&console_lock
, flags
); 347 * The console driver calls this routine during kernel initialization 348 * to register the console printing procedure with printk() and to 349 * print any messages that were printed by the kernel before the 350 * console driver was initialized. 352 voidregister_console(struct console
* console
) 357 signed char msg_level
= -1; 362 * See if we want to use this console driver. If we 363 * didn't select a console we take the first one 364 * that registers here. 366 if(preferred_console
<0) { 367 if(console
->index
<0) 369 if(console
->setup
== NULL
|| 370 console
->setup(console
, NULL
) ==0) { 371 console
->flags
|= CON_ENABLED
| CON_CONSDEV
; 372 preferred_console
=0; 377 * See if this console matches one we selected on 380 for(i
=0; i
< MAX_CMDLINECONSOLES
&& console_cmdline
[i
].name
[0]; i
++) { 381 if(strcmp(console_cmdline
[i
].name
, console
->name
) !=0) 383 if(console
->index
>=0&& 384 console
->index
!= console_cmdline
[i
].index
) 386 if(console
->index
<0) 387 console
->index
= console_cmdline
[i
].index
; 389 console
->setup(console
, console_cmdline
[i
].options
) !=0) 391 console
->flags
|= CON_ENABLED
; 392 console
->index
= console_cmdline
[i
].index
; 393 if(i
== preferred_console
) 394 console
->flags
|= CON_CONSDEV
; 398 if(!(console
->flags
& CON_ENABLED
)) 402 * Put this console in the list - keep the 403 * preferred driver at the head of the list. 405 spin_lock_irqsave(&console_lock
, flags
); 406 if((console
->flags
& CON_CONSDEV
) || console_drivers
== NULL
) { 407 console
->next
= console_drivers
; 408 console_drivers
= console
; 410 console
->next
= console_drivers
->next
; 411 console_drivers
->next
= console
; 413 if((console
->flags
& CON_PRINTBUFFER
) ==0) 416 * Print out buffered log messages. 418 p
= log_start
& LOG_BUF_MASK
; 420 for(i
=0,j
=0; i
< log_size
; i
++) { 421 buf
[j
++] = log_buf
[p
]; 422 p
= (p
+1) & LOG_BUF_MASK
; 423 if(buf
[j
-1] !='\n'&& i
< log_size
-1&& j
<sizeof(buf
)-1) 433 msg_level
= buf
[1] -'0'; 438 msg_level
= default_message_loglevel
; 441 if(msg_level
< console_loglevel
) 442 console
->write(console
, q
, len
); 448 spin_unlock_irqrestore(&console_lock
, flags
); 452 intunregister_console(struct console
* console
) 454 struct console
*a
,*b
; 458 spin_lock_irqsave(&console_lock
, flags
); 459 if(console_drivers
== console
) { 460 console_drivers
=console
->next
; 464 for(a
=console_drivers
->next
, b
=console_drivers
; 474 /* If last console is removed, we re-enable picking the first 475 * one that gets registered. Without that, pmac early boot console 476 * would prevent fbcon from taking over. 478 if(console_drivers
== NULL
) 479 preferred_console
= -1; 482 spin_unlock_irqrestore(&console_lock
, flags
); 487 * Write a message to a certain tty, not just the console. This is used for 488 * messages that need to be redirected to a specific tty. 489 * We don't put it into the syslog queue right now maybe in the future if 492 voidtty_write_message(struct tty_struct
*tty
,char*msg
) 494 if(tty
&& tty
->driver
.write
) 495 tty
->driver
.write(tty
,0, msg
,strlen(msg
));