|
@@ -51,6 +51,9 @@
|
|
|
#define CREATE_TRACE_POINTS
|
|
|
#include <trace/events/printk.h>
|
|
|
|
|
|
+#include "console_cmdline.h"
|
|
|
+#include "braille.h"
|
|
|
+
|
|
|
/* printk's without a loglevel use this.. */
|
|
|
#define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
|
|
|
|
|
@@ -105,19 +108,11 @@ static struct console *exclusive_console;
|
|
|
/*
|
|
|
* Array of consoles built from command line options (console=)
|
|
|
*/
|
|
|
-struct console_cmdline
|
|
|
-{
|
|
|
- char name[8]; /* Name of the driver */
|
|
|
- int index; /* Minor dev. to use */
|
|
|
- char *options; /* Options for the driver */
|
|
|
-#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
|
|
|
- char *brl_options; /* Options for braille driver */
|
|
|
-#endif
|
|
|
-};
|
|
|
|
|
|
#define MAX_CMDLINECONSOLES 8
|
|
|
|
|
|
static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
|
|
|
+
|
|
|
static int selected_console = -1;
|
|
|
static int preferred_console = -1;
|
|
|
int console_set_on_cmdline;
|
|
@@ -178,7 +173,7 @@ static int console_may_schedule;
|
|
|
* 67 "g"
|
|
|
* 0032 00 00 00 padding to next message header
|
|
|
*
|
|
|
- * The 'struct log' buffer header must never be directly exported to
|
|
|
+ * The 'struct printk_log' buffer header must never be directly exported to
|
|
|
* userspace, it is a kernel-private implementation detail that might
|
|
|
* need to be changed in the future, when the requirements change.
|
|
|
*
|
|
@@ -200,7 +195,7 @@ enum log_flags {
|
|
|
LOG_CONT = 8, /* text is a fragment of a continuation line */
|
|
|
};
|
|
|
|
|
|
-struct log {
|
|
|
+struct printk_log {
|
|
|
u64 ts_nsec; /* timestamp in nanoseconds */
|
|
|
u16 len; /* length of entire record */
|
|
|
u16 text_len; /* length of text buffer */
|
|
@@ -248,7 +243,7 @@ static u32 clear_idx;
|
|
|
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
|
|
#define LOG_ALIGN 4
|
|
|
#else
|
|
|
-#define LOG_ALIGN __alignof__(struct log)
|
|
|
+#define LOG_ALIGN __alignof__(struct printk_log)
|
|
|
#endif
|
|
|
#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
|
|
|
static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
|
|
@@ -259,35 +254,35 @@ static u32 log_buf_len = __LOG_BUF_LEN;
|
|
|
static volatile unsigned int logbuf_cpu = UINT_MAX;
|
|
|
|
|
|
/* human readable text of the record */
|
|
|
-static char *log_text(const struct log *msg)
|
|
|
+static char *log_text(const struct printk_log *msg)
|
|
|
{
|
|
|
- return (char *)msg + sizeof(struct log);
|
|
|
+ return (char *)msg + sizeof(struct printk_log);
|
|
|
}
|
|
|
|
|
|
/* optional key/value pair dictionary attached to the record */
|
|
|
-static char *log_dict(const struct log *msg)
|
|
|
+static char *log_dict(const struct printk_log *msg)
|
|
|
{
|
|
|
- return (char *)msg + sizeof(struct log) + msg->text_len;
|
|
|
+ return (char *)msg + sizeof(struct printk_log) + msg->text_len;
|
|
|
}
|
|
|
|
|
|
/* get record by index; idx must point to valid msg */
|
|
|
-static struct log *log_from_idx(u32 idx)
|
|
|
+static struct printk_log *log_from_idx(u32 idx)
|
|
|
{
|
|
|
- struct log *msg = (struct log *)(log_buf + idx);
|
|
|
+ struct printk_log *msg = (struct printk_log *)(log_buf + idx);
|
|
|
|
|
|
/*
|
|
|
* A length == 0 record is the end of buffer marker. Wrap around and
|
|
|
* read the message at the start of the buffer.
|
|
|
*/
|
|
|
if (!msg->len)
|
|
|
- return (struct log *)log_buf;
|
|
|
+ return (struct printk_log *)log_buf;
|
|
|
return msg;
|
|
|
}
|
|
|
|
|
|
/* get next record; idx must point to valid msg */
|
|
|
static u32 log_next(u32 idx)
|
|
|
{
|
|
|
- struct log *msg = (struct log *)(log_buf + idx);
|
|
|
+ struct printk_log *msg = (struct printk_log *)(log_buf + idx);
|
|
|
|
|
|
/* length == 0 indicates the end of the buffer; wrap */
|
|
|
/*
|
|
@@ -296,7 +291,7 @@ static u32 log_next(u32 idx)
|
|
|
* return the one after that.
|
|
|
*/
|
|
|
if (!msg->len) {
|
|
|
- msg = (struct log *)log_buf;
|
|
|
+ msg = (struct printk_log *)log_buf;
|
|
|
return msg->len;
|
|
|
}
|
|
|
return idx + msg->len;
|
|
@@ -308,11 +303,11 @@ static void log_store(int facility, int level,
|
|
|
const char *dict, u16 dict_len,
|
|
|
const char *text, u16 text_len)
|
|
|
{
|
|
|
- struct log *msg;
|
|
|
+ struct printk_log *msg;
|
|
|
u32 size, pad_len;
|
|
|
|
|
|
/* number of '\0' padding bytes to next message */
|
|
|
- size = sizeof(struct log) + text_len + dict_len;
|
|
|
+ size = sizeof(struct printk_log) + text_len + dict_len;
|
|
|
pad_len = (-size) & (LOG_ALIGN - 1);
|
|
|
size += pad_len;
|
|
|
|
|
@@ -324,7 +319,7 @@ static void log_store(int facility, int level,
|
|
|
else
|
|
|
free = log_first_idx - log_next_idx;
|
|
|
|
|
|
- if (free > size + sizeof(struct log))
|
|
|
+ if (free > size + sizeof(struct printk_log))
|
|
|
break;
|
|
|
|
|
|
/* drop old messages until we have enough contiuous space */
|
|
@@ -332,18 +327,18 @@ static void log_store(int facility, int level,
|
|
|
log_first_seq++;
|
|
|
}
|
|
|
|
|
|
- if (log_next_idx + size + sizeof(struct log) >= log_buf_len) {
|
|
|
+ if (log_next_idx + size + sizeof(struct printk_log) >= log_buf_len) {
|
|
|
/*
|
|
|
* This message + an additional empty header does not fit
|
|
|
* at the end of the buffer. Add an empty header with len == 0
|
|
|
* to signify a wrap around.
|
|
|
*/
|
|
|
- memset(log_buf + log_next_idx, 0, sizeof(struct log));
|
|
|
+ memset(log_buf + log_next_idx, 0, sizeof(struct printk_log));
|
|
|
log_next_idx = 0;
|
|
|
}
|
|
|
|
|
|
/* fill message */
|
|
|
- msg = (struct log *)(log_buf + log_next_idx);
|
|
|
+ msg = (struct printk_log *)(log_buf + log_next_idx);
|
|
|
memcpy(log_text(msg), text, text_len);
|
|
|
msg->text_len = text_len;
|
|
|
memcpy(log_dict(msg), dict, dict_len);
|
|
@@ -356,7 +351,7 @@ static void log_store(int facility, int level,
|
|
|
else
|
|
|
msg->ts_nsec = local_clock();
|
|
|
memset(log_dict(msg) + dict_len, 0, pad_len);
|
|
|
- msg->len = sizeof(struct log) + text_len + dict_len + pad_len;
|
|
|
+ msg->len = sizeof(struct printk_log) + text_len + dict_len + pad_len;
|
|
|
|
|
|
/* insert message */
|
|
|
log_next_idx += msg->len;
|
|
@@ -479,7 +474,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
|
|
|
size_t count, loff_t *ppos)
|
|
|
{
|
|
|
struct devkmsg_user *user = file->private_data;
|
|
|
- struct log *msg;
|
|
|
+ struct printk_log *msg;
|
|
|
u64 ts_usec;
|
|
|
size_t i;
|
|
|
char cont = '-';
|
|
@@ -724,14 +719,14 @@ void log_buf_kexec_setup(void)
|
|
|
VMCOREINFO_SYMBOL(log_first_idx);
|
|
|
VMCOREINFO_SYMBOL(log_next_idx);
|
|
|
/*
|
|
|
- * Export struct log size and field offsets. User space tools can
|
|
|
+ * Export struct printk_log size and field offsets. User space tools can
|
|
|
* parse it and detect any changes to structure down the line.
|
|
|
*/
|
|
|
- VMCOREINFO_STRUCT_SIZE(log);
|
|
|
- VMCOREINFO_OFFSET(log, ts_nsec);
|
|
|
- VMCOREINFO_OFFSET(log, len);
|
|
|
- VMCOREINFO_OFFSET(log, text_len);
|
|
|
- VMCOREINFO_OFFSET(log, dict_len);
|
|
|
+ VMCOREINFO_STRUCT_SIZE(printk_log);
|
|
|
+ VMCOREINFO_OFFSET(printk_log, ts_nsec);
|
|
|
+ VMCOREINFO_OFFSET(printk_log, len);
|
|
|
+ VMCOREINFO_OFFSET(printk_log, text_len);
|
|
|
+ VMCOREINFO_OFFSET(printk_log, dict_len);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -884,7 +879,7 @@ static size_t print_time(u64 ts, char *buf)
|
|
|
(unsigned long)ts, rem_nsec / 1000);
|
|
|
}
|
|
|
|
|
|
-static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
|
|
|
+static size_t print_prefix(const struct printk_log *msg, bool syslog, char *buf)
|
|
|
{
|
|
|
size_t len = 0;
|
|
|
unsigned int prefix = (msg->facility << 3) | msg->level;
|
|
@@ -907,7 +902,7 @@ static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
|
|
|
return len;
|
|
|
}
|
|
|
|
|
|
-static size_t msg_print_text(const struct log *msg, enum log_flags prev,
|
|
|
+static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev,
|
|
|
bool syslog, char *buf, size_t size)
|
|
|
{
|
|
|
const char *text = log_text(msg);
|
|
@@ -969,7 +964,7 @@ static size_t msg_print_text(const struct log *msg, enum log_flags prev,
|
|
|
static int syslog_print(char __user *buf, int size)
|
|
|
{
|
|
|
char *text;
|
|
|
- struct log *msg;
|
|
|
+ struct printk_log *msg;
|
|
|
int len = 0;
|
|
|
|
|
|
text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
|
|
@@ -1060,7 +1055,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
|
|
|
idx = clear_idx;
|
|
|
prev = 0;
|
|
|
while (seq < log_next_seq) {
|
|
|
- struct log *msg = log_from_idx(idx);
|
|
|
+ struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
len += msg_print_text(msg, prev, true, NULL, 0);
|
|
|
prev = msg->flags;
|
|
@@ -1073,7 +1068,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
|
|
|
idx = clear_idx;
|
|
|
prev = 0;
|
|
|
while (len > size && seq < log_next_seq) {
|
|
|
- struct log *msg = log_from_idx(idx);
|
|
|
+ struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
len -= msg_print_text(msg, prev, true, NULL, 0);
|
|
|
prev = msg->flags;
|
|
@@ -1087,7 +1082,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
|
|
|
len = 0;
|
|
|
prev = 0;
|
|
|
while (len >= 0 && seq < next_seq) {
|
|
|
- struct log *msg = log_from_idx(idx);
|
|
|
+ struct printk_log *msg = log_from_idx(idx);
|
|
|
int textlen;
|
|
|
|
|
|
textlen = msg_print_text(msg, prev, true, text,
|
|
@@ -1233,7 +1228,7 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
|
|
|
|
|
|
error = 0;
|
|
|
while (seq < log_next_seq) {
|
|
|
- struct log *msg = log_from_idx(idx);
|
|
|
+ struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
error += msg_print_text(msg, prev, true, NULL, 0);
|
|
|
idx = log_next(idx);
|
|
@@ -1719,10 +1714,10 @@ static struct cont {
|
|
|
u8 level;
|
|
|
bool flushed:1;
|
|
|
} cont;
|
|
|
-static struct log *log_from_idx(u32 idx) { return NULL; }
|
|
|
+static struct printk_log *log_from_idx(u32 idx) { return NULL; }
|
|
|
static u32 log_next(u32 idx) { return 0; }
|
|
|
static void call_console_drivers(int level, const char *text, size_t len) {}
|
|
|
-static size_t msg_print_text(const struct log *msg, enum log_flags prev,
|
|
|
+static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev,
|
|
|
bool syslog, char *buf, size_t size) { return 0; }
|
|
|
static size_t cont_print_text(char *text, size_t size) { return 0; }
|
|
|
|
|
@@ -1761,23 +1756,23 @@ static int __add_preferred_console(char *name, int idx, char *options,
|
|
|
* See if this tty is not yet registered, and
|
|
|
* if we have a slot free.
|
|
|
*/
|
|
|
- for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
|
|
|
- if (strcmp(console_cmdline[i].name, name) == 0 &&
|
|
|
- console_cmdline[i].index == idx) {
|
|
|
- if (!brl_options)
|
|
|
- selected_console = i;
|
|
|
- return 0;
|
|
|
+ for (i = 0, c = console_cmdline;
|
|
|
+ i < MAX_CMDLINECONSOLES && c->name[0];
|
|
|
+ i++, c++) {
|
|
|
+ if (strcmp(c->name, name) == 0 && c->index == idx) {
|
|
|
+ if (!brl_options)
|
|
|
+ selected_console = i;
|
|
|
+ return 0;
|
|
|
}
|
|
|
+ }
|
|
|
if (i == MAX_CMDLINECONSOLES)
|
|
|
return -E2BIG;
|
|
|
if (!brl_options)
|
|
|
selected_console = i;
|
|
|
- c = &console_cmdline[i];
|
|
|
strlcpy(c->name, name, sizeof(c->name));
|
|
|
c->options = options;
|
|
|
-#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
|
|
|
- c->brl_options = brl_options;
|
|
|
-#endif
|
|
|
+ braille_set_options(c, brl_options);
|
|
|
+
|
|
|
c->index = idx;
|
|
|
return 0;
|
|
|
}
|
|
@@ -1790,20 +1785,8 @@ static int __init console_setup(char *str)
|
|
|
char *s, *options, *brl_options = NULL;
|
|
|
int idx;
|
|
|
|
|
|
-#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
|
|
|
- if (!memcmp(str, "brl,", 4)) {
|
|
|
- brl_options = "";
|
|
|
- str += 4;
|
|
|
- } else if (!memcmp(str, "brl=", 4)) {
|
|
|
- brl_options = str + 4;
|
|
|
- str = strchr(brl_options, ',');
|
|
|
- if (!str) {
|
|
|
- printk(KERN_ERR "need port name after brl=\n");
|
|
|
- return 1;
|
|
|
- }
|
|
|
- *(str++) = 0;
|
|
|
- }
|
|
|
-#endif
|
|
|
+ if (_braille_console_setup(&str, &brl_options))
|
|
|
+ return 1;
|
|
|
|
|
|
/*
|
|
|
* Decode str into name, index, options.
|
|
@@ -1858,15 +1841,15 @@ int update_console_cmdline(char *name, int idx, char *name_new, int idx_new, cha
|
|
|
struct console_cmdline *c;
|
|
|
int i;
|
|
|
|
|
|
- for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
|
|
|
- if (strcmp(console_cmdline[i].name, name) == 0 &&
|
|
|
- console_cmdline[i].index == idx) {
|
|
|
- c = &console_cmdline[i];
|
|
|
- strlcpy(c->name, name_new, sizeof(c->name));
|
|
|
- c->name[sizeof(c->name) - 1] = 0;
|
|
|
- c->options = options;
|
|
|
- c->index = idx_new;
|
|
|
- return i;
|
|
|
+ for (i = 0, c = console_cmdline;
|
|
|
+ i < MAX_CMDLINECONSOLES && c->name[0];
|
|
|
+ i++, c++)
|
|
|
+ if (strcmp(c->name, name) == 0 && c->index == idx) {
|
|
|
+ strlcpy(c->name, name_new, sizeof(c->name));
|
|
|
+ c->name[sizeof(c->name) - 1] = 0;
|
|
|
+ c->options = options;
|
|
|
+ c->index = idx_new;
|
|
|
+ return i;
|
|
|
}
|
|
|
/* not found */
|
|
|
return -1;
|
|
@@ -2046,7 +2029,7 @@ void console_unlock(void)
|
|
|
console_cont_flush(text, sizeof(text));
|
|
|
again:
|
|
|
for (;;) {
|
|
|
- struct log *msg;
|
|
|
+ struct printk_log *msg;
|
|
|
size_t len;
|
|
|
int level;
|
|
|
|
|
@@ -2241,6 +2224,7 @@ void register_console(struct console *newcon)
|
|
|
int i;
|
|
|
unsigned long flags;
|
|
|
struct console *bcon = NULL;
|
|
|
+ struct console_cmdline *c;
|
|
|
|
|
|
/*
|
|
|
* before we register a new CON_BOOT console, make sure we don't
|
|
@@ -2288,30 +2272,25 @@ void register_console(struct console *newcon)
|
|
|
* See if this console matches one we selected on
|
|
|
* the command line.
|
|
|
*/
|
|
|
- for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
|
|
|
- i++) {
|
|
|
- if (strcmp(console_cmdline[i].name, newcon->name) != 0)
|
|
|
+ for (i = 0, c = console_cmdline;
|
|
|
+ i < MAX_CMDLINECONSOLES && c->name[0];
|
|
|
+ i++, c++) {
|
|
|
+ if (strcmp(c->name, newcon->name) != 0)
|
|
|
continue;
|
|
|
if (newcon->index >= 0 &&
|
|
|
- newcon->index != console_cmdline[i].index)
|
|
|
+ newcon->index != c->index)
|
|
|
continue;
|
|
|
if (newcon->index < 0)
|
|
|
- newcon->index = console_cmdline[i].index;
|
|
|
-#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
|
|
|
- if (console_cmdline[i].brl_options) {
|
|
|
- newcon->flags |= CON_BRL;
|
|
|
- braille_register_console(newcon,
|
|
|
- console_cmdline[i].index,
|
|
|
- console_cmdline[i].options,
|
|
|
- console_cmdline[i].brl_options);
|
|
|
+ newcon->index = c->index;
|
|
|
+
|
|
|
+ if (_braille_register_console(newcon, c))
|
|
|
return;
|
|
|
- }
|
|
|
-#endif
|
|
|
+
|
|
|
if (newcon->setup &&
|
|
|
newcon->setup(newcon, console_cmdline[i].options) != 0)
|
|
|
break;
|
|
|
newcon->flags |= CON_ENABLED;
|
|
|
- newcon->index = console_cmdline[i].index;
|
|
|
+ newcon->index = c->index;
|
|
|
if (i == selected_console) {
|
|
|
newcon->flags |= CON_CONSDEV;
|
|
|
preferred_console = selected_console;
|
|
@@ -2394,13 +2373,13 @@ EXPORT_SYMBOL(register_console);
|
|
|
int unregister_console(struct console *console)
|
|
|
{
|
|
|
struct console *a, *b;
|
|
|
- int res = 1;
|
|
|
+ int res;
|
|
|
|
|
|
-#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
|
|
|
- if (console->flags & CON_BRL)
|
|
|
- return braille_unregister_console(console);
|
|
|
-#endif
|
|
|
+ res = _braille_unregister_console(console);
|
|
|
+ if (res)
|
|
|
+ return res;
|
|
|
|
|
|
+ res = 1;
|
|
|
console_lock();
|
|
|
if (console_drivers == console) {
|
|
|
console_drivers=console->next;
|
|
@@ -2666,7 +2645,7 @@ void kmsg_dump(enum kmsg_dump_reason reason)
|
|
|
bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
|
|
|
char *line, size_t size, size_t *len)
|
|
|
{
|
|
|
- struct log *msg;
|
|
|
+ struct printk_log *msg;
|
|
|
size_t l = 0;
|
|
|
bool ret = false;
|
|
|
|
|
@@ -2778,7 +2757,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
|
|
|
idx = dumper->cur_idx;
|
|
|
prev = 0;
|
|
|
while (seq < dumper->next_seq) {
|
|
|
- struct log *msg = log_from_idx(idx);
|
|
|
+ struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
l += msg_print_text(msg, prev, true, NULL, 0);
|
|
|
idx = log_next(idx);
|
|
@@ -2791,7 +2770,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
|
|
|
idx = dumper->cur_idx;
|
|
|
prev = 0;
|
|
|
while (l > size && seq < dumper->next_seq) {
|
|
|
- struct log *msg = log_from_idx(idx);
|
|
|
+ struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
l -= msg_print_text(msg, prev, true, NULL, 0);
|
|
|
idx = log_next(idx);
|
|
@@ -2806,7 +2785,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
|
|
|
l = 0;
|
|
|
prev = 0;
|
|
|
while (seq < dumper->next_seq) {
|
|
|
- struct log *msg = log_from_idx(idx);
|
|
|
+ struct printk_log *msg = log_from_idx(idx);
|
|
|
|
|
|
l += msg_print_text(msg, prev, syslog, buf + l, size - l);
|
|
|
idx = log_next(idx);
|