lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 31 Jul 2009 10:07:08 -0500
From:	Jason Wessel <jason.wessel@...driver.com>
To:	gregkh@...e.de
Cc:	linux-usb@...r.kernel.org, linux-kernel@...r.kernel.org,
	Jason Wessel <jason.wessel@...driver.com>,
	Ingo Molnar <mingo@...e.hu>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Yinghai Lu <yinghai@...nel.org>,
	"Eric W. Biederman" <ebiederm@...ssion.com>,
	Randy Dunlap <randy.dunlap@...cle.com>
Subject: [PATCH 05/10] printk,early_printk,console: Allow more than one early console

It is very nice to be able to use one early boot device to debug
another or to have multiple places you can see the early boot
diagnostics, such as the vga screen or serial device.

This patch changes the early_printk console device registration to
allow more than one early printk device to get registered via
register_console().

A corresponding change is required to the console registration code
such that it will properly unregister any console marked with the
CON_BOOT flag via a simple loop during a console handover or at late
init time.

Signed-off-by: Jason Wessel <jason.wessel@...driver.com>
Cc: Greg KH <gregkh@...e.de>
Cc: Ingo Molnar <mingo@...e.hu>
Cc: Andrew Morton <akpm@...ux-foundation.org>
Cc: Yinghai Lu <yinghai@...nel.org>
Cc: "Eric W. Biederman" <ebiederm@...ssion.com>
Cc: Randy Dunlap <randy.dunlap@...cle.com>
---
 arch/x86/kernel/early_printk.c |   65 ++++++++++++++++++++-------------------
 kernel/printk.c                |   41 ++++++++++++++++---------
 2 files changed, 59 insertions(+), 47 deletions(-)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 519a5e1..2acfd3f 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -176,10 +176,19 @@ asmlinkage void early_printk(const char *fmt, ...)
 	va_end(ap);
 }
 
+static inline void early_console_register(struct console *con, int keep_early)
+{
+	early_console = con;
+	if (keep_early)
+		early_console->flags &= ~CON_BOOT;
+	else
+		early_console->flags |= CON_BOOT;
+	register_console(early_console);
+}
 
 static int __init setup_early_printk(char *buf)
 {
-	int keep_early;
+	int keep;
 
 	if (!buf)
 		return 0;
@@ -188,42 +197,34 @@ static int __init setup_early_printk(char *buf)
 		return 0;
 	early_console_initialized = 1;
 
-	keep_early = (strstr(buf, "keep") != NULL);
-
-	if (!strncmp(buf, "serial", 6)) {
-		early_serial_init(buf + 6);
-		early_console = &early_serial_console;
-	} else if (!strncmp(buf, "ttyS", 4)) {
-		early_serial_init(buf);
-		early_console = &early_serial_console;
-	} else if (!strncmp(buf, "vga", 3)
-		&& boot_params.screen_info.orig_video_isVGA == 1) {
-		max_xpos = boot_params.screen_info.orig_video_cols;
-		max_ypos = boot_params.screen_info.orig_video_lines;
-		current_ypos = boot_params.screen_info.orig_y;
-		early_console = &early_vga_console;
+	keep = (strstr(buf, "keep") != NULL);
+
+	while (*buf != '\0') {
+		if (!strncmp(buf, "serial", 6)) {
+			early_serial_init(buf + 6);
+			early_console_register(&early_serial_console, keep);
+		}
+		if (!strncmp(buf, "ttyS", 4)) {
+			early_serial_init(buf + 4);
+			early_console_register(&early_serial_console, keep);
+		}
+		if (!strncmp(buf, "vga", 3) &&
+		    boot_params.screen_info.orig_video_isVGA == 1) {
+			max_xpos = boot_params.screen_info.orig_video_cols;
+			max_ypos = boot_params.screen_info.orig_video_lines;
+			current_ypos = boot_params.screen_info.orig_y;
+			early_console_register(&early_vga_console, keep);
+		}
 #ifdef CONFIG_EARLY_PRINTK_DBGP
-	} else if (!strncmp(buf, "dbgp", 4)) {
-		if (early_dbgp_init(buf+4) < 0)
-			return 0;
-		early_console = &early_dbgp_console;
-		/*
-		 * usb subsys will reset ehci controller, so don't keep
-		 * that early console
-		 */
-		keep_early = 0;
+		if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4))
+			early_console_register(&early_dbgp_console, keep);
 #endif
 #ifdef CONFIG_HVC_XEN
-	} else if (!strncmp(buf, "xen", 3)) {
-		early_console = &xenboot_console;
+		if (!strncmp(buf, "xen", 3))
+			early_console_register(&xenboot_console, keep);
 #endif
+		buf++;
 	}
-
-	if (keep_early)
-		early_console->flags &= ~CON_BOOT;
-	else
-		early_console->flags |= CON_BOOT;
-	register_console(early_console);
 	return 0;
 }
 
diff --git a/kernel/printk.c b/kernel/printk.c
index b4d97b5..45e0cec 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1129,6 +1129,28 @@ void console_start(struct console *console)
 }
 EXPORT_SYMBOL(console_start);
 
+static int disable_boot_consoles(void)
+{
+	struct console *bootconsole = console_drivers;
+	struct console *nextcon;
+	if (!bootconsole)
+		return 0;
+	while (bootconsole) {
+		nextcon = bootconsole->next;
+		if (bootconsole->flags & CON_BOOT) {
+			printk(KERN_INFO "turn off boot console %s%d\n",
+			       console_drivers->name, console_drivers->index);
+			if (unregister_console(bootconsole) != 0)
+				printk(KERN_ERR "ERROR unregistering %s%d\n",
+				       console_drivers->name,
+				       console_drivers->index);
+		}
+		bootconsole = nextcon;
+	}
+	return 0;
+}
+late_initcall(disable_boot_consoles);
+
 /*
  * The console driver calls this routine during kernel initialization
  * to register the console printing procedure with printk() and to
@@ -1142,8 +1164,7 @@ void register_console(struct console *console)
 	struct console *bootconsole = NULL;
 
 	if (console_drivers) {
-		if (console->flags & CON_BOOT)
-			return;
+
 		if (console_drivers->flags & CON_BOOT)
 			bootconsole = console_drivers;
 	}
@@ -1216,6 +1237,7 @@ void register_console(struct console *console)
 		       console->name, console->index);
 		unregister_console(bootconsole);
 		console->flags &= ~CON_PRINTBUFFER;
+		disable_boot_consoles();
 	} else {
 		printk(KERN_INFO "console [%s%d] enabled\n",
 		       console->name, console->index);
@@ -1280,24 +1302,13 @@ int unregister_console(struct console *console)
 	if (console_drivers != NULL && console->flags & CON_CONSDEV)
 		console_drivers->flags |= CON_CONSDEV;
 
+	if (!res)
+		console->index = -1;
 	release_console_sem();
 	return res;
 }
 EXPORT_SYMBOL(unregister_console);
 
-static int __init disable_boot_consoles(void)
-{
-	if (console_drivers != NULL) {
-		if (console_drivers->flags & CON_BOOT) {
-			printk(KERN_INFO "turn off boot console %s%d\n",
-				console_drivers->name, console_drivers->index);
-			return unregister_console(console_drivers);
-		}
-	}
-	return 0;
-}
-late_initcall(disable_boot_consoles);
-
 #if defined CONFIG_PRINTK
 
 /*
-- 
1.6.0.3.523.g304d0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ