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
= NULL
;
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"))
78 strcpy(name
, "ttyS0");
79 if (!strcmp(str
, "ttyb"))
80 strcpy(name
, "ttyS1");
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 up to the last 4k of messages in the ring buffer.
117 * 4 -- Read and clear last 4k of messages 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 int do_syslog(int type
, char * buf
, int len
)
125 unsigned long i
, j
, limit
, count
;
132 case 0: /* Close log */
134 case 1: /* Open log */
136 case 2: /* 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 case 4: /* Read/clear last kernel messages */
167 case 3: /* 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 case 5: /* Clear ring buffer */
214 spin_lock_irq(&console_lock
);
216 spin_unlock_irq(&console_lock
);
218 case 6: /* Disable logging to console */
219 spin_lock_irq(&console_lock
);
220 console_loglevel
= minimum_console_loglevel
;
221 spin_unlock_irq(&console_lock
);
223 case 7: /* Enable logging to console */
224 spin_lock_irq(&console_lock
);
225 console_loglevel
= default_console_loglevel
;
226 spin_unlock_irq(&console_lock
);
230 if (len
< 1 || len
> 8)
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
long sys_syslog(int type
, char * buf
, int len
)
249 if ((type
!= 3) && !capable(CAP_SYS_ADMIN
))
251 return do_syslog(type
, buf
, len
);
254 asmlinkage
int printk(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 */
266 buf_end
= buf
+ 3 + i
;
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 void console_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 void unblank_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 void register_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
;
388 if (console
->setup
&&
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
);
443 if (buf
[j
-1] == '\n')
448 spin_unlock_irqrestore(&console_lock
, flags
);
452 int unregister_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 void tty_write_message(struct tty_struct
*tty
, char *msg
)
494 if (tty
&& tty
->driver
.write
)
495 tty
->driver
.write(tty
, 0, msg
, strlen(msg
));