Patchwork [1/2] UBUNTU: SAUCE: vt -- maintain bootloader screen mode and content until vt switch

login
register
mail settings
Submitter Andy Whitcroft
Date July 29, 2010, 3:36 p.m.
Message ID <1280417791-8989-2-git-send-email-apw@canonical.com>
Download mbox | patch
Permalink /patch/60271/
State Accepted
Delegated to: Leann Ogasawara
Headers show

Comments

Andy Whitcroft - July 29, 2010, 3:36 p.m.
Introduce a new VT mode KD_TRANSPARENT which endevours to leave the current
content of the framebuffer untouched.  This allows the bootloader to insert
a graphical splash and have the kernel maintain it until the OS splash
can take over.  When we finally switch away (either through programs like
plymouth or manually) the content is lost and the VT reverts to text mode.

Signed-off-by: Andy Whitcroft <apw@canonical.com>
---
 drivers/char/vt.c       |   36 +++++++++++++++++++++++++++++++-----
 drivers/char/vt_ioctl.c |   10 +++++-----
 include/linux/kd.h      |    1 +
 include/linux/vt_kern.h |    2 +-
 4 files changed, 38 insertions(+), 11 deletions(-)
Stefan Bader - July 29, 2010, 3:59 p.m.
Was confused a bit by the number of duplication in con_init but makes sense in
the light of vt_handoff possibly being above the minimum number of vt's.

Acked-by: Stefan Bader <stefan.bader@canonical.com>

On 07/29/2010 05:36 PM, Andy Whitcroft wrote:
> Introduce a new VT mode KD_TRANSPARENT which endevours to leave the current
> content of the framebuffer untouched.  This allows the bootloader to insert
> a graphical splash and have the kernel maintain it until the OS splash
> can take over.  When we finally switch away (either through programs like
> plymouth or manually) the content is lost and the VT reverts to text mode.
> 
> Signed-off-by: Andy Whitcroft <apw@canonical.com>
> ---
>  drivers/char/vt.c       |   36 +++++++++++++++++++++++++++++++-----
>  drivers/char/vt_ioctl.c |   10 +++++-----
>  include/linux/kd.h      |    1 +
>  include/linux/vt_kern.h |    2 +-
>  4 files changed, 38 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/char/vt.c b/drivers/char/vt.c
> index 7cdb6ee..2c64292 100644
> --- a/drivers/char/vt.c
> +++ b/drivers/char/vt.c
> @@ -104,6 +104,7 @@
>  #include <linux/io.h>
>  #include <asm/system.h>
>  #include <linux/uaccess.h>
> +#include <linux/screen_info.h>
>  
>  #define MAX_NR_CON_DRIVER 16
>  
> @@ -146,7 +147,7 @@ static const struct consw *con_driver_map[MAX_NR_CONSOLES];
>  
>  static int con_open(struct tty_struct *, struct file *);
>  static void vc_init(struct vc_data *vc, unsigned int rows,
> -		    unsigned int cols, int do_clear);
> +		    unsigned int cols, int do_clear, int mode);
>  static void gotoxy(struct vc_data *vc, int new_x, int new_y);
>  static void save_cur(struct vc_data *vc);
>  static void reset_terminal(struct vc_data *vc, int do_clear);
> @@ -167,6 +168,9 @@ module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);
>  static int cur_default = CUR_DEFAULT;
>  module_param(cur_default, int, S_IRUGO | S_IWUSR);
>  
> +int vt_handoff = -1;
> +module_param_named(handoff, vt_handoff, int, S_IRUGO | S_IWUSR);
> +
>  /*
>   * ignore_poke: don't unblank the screen when things are typed.  This is
>   * mainly for the privacy of braille terminal users.
> @@ -676,6 +680,13 @@ void redraw_screen(struct vc_data *vc, int is_switch)
>  			save_screen(old_vc);
>  			set_origin(old_vc);
>  		}
> +		/*
> +		 * If we are switching away from a transparent VT the contents
> +		 * will be lost, convert it into a blank text console then
> +		 * it will be repainted blank if we ever switch back.
> +		 */
> +		if (old_vc->vc_mode == KD_TRANSPARENT)
> +			old_vc->vc_mode = KD_TEXT;
>  	} else {
>  		hide_cursor(vc);
>  		redraw = 1;
> @@ -784,7 +795,7 @@ int vc_allocate(unsigned int currcons)	/* return 0 on success */
>  	    if (global_cursor_default == -1)
>  		    global_cursor_default = 1;
>  
> -	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
> +	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1, KD_TEXT);
>  	    vcs_make_sysfs(currcons);
>  	    atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
>  	}
> @@ -2837,7 +2848,7 @@ module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR);
>  module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR);
>  
>  static void vc_init(struct vc_data *vc, unsigned int rows,
> -		    unsigned int cols, int do_clear)
> +		    unsigned int cols, int do_clear, int mode)
>  {
>  	int j, k ;
>  
> @@ -2848,7 +2859,7 @@ static void vc_init(struct vc_data *vc, unsigned int rows,
>  
>  	set_origin(vc);
>  	vc->vc_pos = vc->vc_origin;
> -	reset_vc(vc);
> +	reset_vc(vc, mode);
>  	for (j=k=0; j<16; j++) {
>  		vc->vc_palette[k++] = default_red[j] ;
>  		vc->vc_palette[k++] = default_grn[j] ;
> @@ -2905,15 +2916,30 @@ static int __init con_init(void)
>  		mod_timer(&console_timer, jiffies + (blankinterval * HZ));
>  	}
>  
> +	if (vt_handoff >= 0) {
> +		currcons = vt_handoff;
> +		vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
> +		INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
> +		visual_init(vc, currcons, 1);
> +		vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
> +		vc_init(vc, vc->vc_rows, vc->vc_cols, 0, KD_TRANSPARENT);
> +	}
>  	for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
> +		if (currcons == vt_handoff)
> +			continue;
>  		vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
>  		INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
>  		visual_init(vc, currcons, 1);
>  		vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
>  		vc_init(vc, vc->vc_rows, vc->vc_cols,
> -			currcons || !vc->vc_sw->con_save_screen);
> +			currcons || !vc->vc_sw->con_save_screen, KD_TEXT);
>  	}
>  	currcons = fg_console = 0;
> +	if (vt_handoff >= 0) {
> +		printk(KERN_INFO "vt handoff: transparent VT on %d\n",
> +								vt_handoff);
> +		currcons = fg_console = vt_handoff;
> +	}
>  	master_display_fg = vc = vc_cons[currcons].d;
>  	set_origin(vc);
>  	save_screen(vc);
> diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
> index 39c7e70..cb5c150 100644
> --- a/drivers/char/vt_ioctl.c
> +++ b/drivers/char/vt_ioctl.c
> @@ -1345,9 +1345,9 @@ eperm:
>  	goto out;
>  }
>  
> -void reset_vc(struct vc_data *vc)
> +void reset_vc(struct vc_data *vc, int mode)
>  {
> -	vc->vc_mode = KD_TEXT;
> +	vc->vc_mode = mode;
>  	kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
>  	vc->vt_mode.mode = VT_AUTO;
>  	vc->vt_mode.waitv = 0;
> @@ -1378,7 +1378,7 @@ void vc_SAK(struct work_struct *work)
>  		 */
>  		if (tty)
>  			__do_SAK(tty);
> -		reset_vc(vc);
> +		reset_vc(vc, KD_TEXT);
>  	}
>  	release_console_sem();
>  }
> @@ -1665,7 +1665,7 @@ static void complete_change_console(struct vc_data *vc)
>  		 * this outside of VT_PROCESS but there is no single process
>  		 * to account for and tracking tty count may be undesirable.
>  		 */
> -			reset_vc(vc);
> +			reset_vc(vc, KD_TEXT);
>  
>  			if (old_vc_mode != vc->vc_mode) {
>  				if (vc->vc_mode == KD_TEXT)
> @@ -1737,7 +1737,7 @@ void change_console(struct vc_data *new_vc)
>  		 * this outside of VT_PROCESS but there is no single process
>  		 * to account for and tracking tty count may be undesirable.
>  		 */
> -		reset_vc(vc);
> +		reset_vc(vc, KD_TEXT);
>  
>  		/*
>  		 * Fall through to normal (VT_AUTO) handling of the switch...
> diff --git a/include/linux/kd.h b/include/linux/kd.h
> index 15f2853..abe298f 100644
> --- a/include/linux/kd.h
> +++ b/include/linux/kd.h
> @@ -45,6 +45,7 @@ struct consolefontdesc {
>  #define		KD_GRAPHICS	0x01
>  #define		KD_TEXT0	0x02	/* obsolete */
>  #define		KD_TEXT1	0x03	/* obsolete */
> +#define		KD_TRANSPARENT	0x04
>  #define KDGETMODE	0x4B3B	/* get current mode */
>  
>  #define KDMAPDISP	0x4B3C	/* map display into address space */
> diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
> index 7f56db4..b0a6148 100644
> --- a/include/linux/vt_kern.h
> +++ b/include/linux/vt_kern.h
> @@ -95,7 +95,7 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
>  void vt_event_post(unsigned int event, unsigned int old, unsigned int new);
>  int vt_waitactive(int n);
>  void change_console(struct vc_data *new_vc);
> -void reset_vc(struct vc_data *vc);
> +void reset_vc(struct vc_data *vc, int mode);
>  extern int unbind_con_driver(const struct consw *csw, int first, int last,
>  			     int deflt);
>  int vty_init(const struct file_operations *console_fops);

Patch

diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 7cdb6ee..2c64292 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -104,6 +104,7 @@ 
 #include <linux/io.h>
 #include <asm/system.h>
 #include <linux/uaccess.h>
+#include <linux/screen_info.h>
 
 #define MAX_NR_CON_DRIVER 16
 
@@ -146,7 +147,7 @@  static const struct consw *con_driver_map[MAX_NR_CONSOLES];
 
 static int con_open(struct tty_struct *, struct file *);
 static void vc_init(struct vc_data *vc, unsigned int rows,
-		    unsigned int cols, int do_clear);
+		    unsigned int cols, int do_clear, int mode);
 static void gotoxy(struct vc_data *vc, int new_x, int new_y);
 static void save_cur(struct vc_data *vc);
 static void reset_terminal(struct vc_data *vc, int do_clear);
@@ -167,6 +168,9 @@  module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);
 static int cur_default = CUR_DEFAULT;
 module_param(cur_default, int, S_IRUGO | S_IWUSR);
 
+int vt_handoff = -1;
+module_param_named(handoff, vt_handoff, int, S_IRUGO | S_IWUSR);
+
 /*
  * ignore_poke: don't unblank the screen when things are typed.  This is
  * mainly for the privacy of braille terminal users.
@@ -676,6 +680,13 @@  void redraw_screen(struct vc_data *vc, int is_switch)
 			save_screen(old_vc);
 			set_origin(old_vc);
 		}
+		/*
+		 * If we are switching away from a transparent VT the contents
+		 * will be lost, convert it into a blank text console then
+		 * it will be repainted blank if we ever switch back.
+		 */
+		if (old_vc->vc_mode == KD_TRANSPARENT)
+			old_vc->vc_mode = KD_TEXT;
 	} else {
 		hide_cursor(vc);
 		redraw = 1;
@@ -784,7 +795,7 @@  int vc_allocate(unsigned int currcons)	/* return 0 on success */
 	    if (global_cursor_default == -1)
 		    global_cursor_default = 1;
 
-	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
+	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1, KD_TEXT);
 	    vcs_make_sysfs(currcons);
 	    atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
 	}
@@ -2837,7 +2848,7 @@  module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR);
 module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR);
 
 static void vc_init(struct vc_data *vc, unsigned int rows,
-		    unsigned int cols, int do_clear)
+		    unsigned int cols, int do_clear, int mode)
 {
 	int j, k ;
 
@@ -2848,7 +2859,7 @@  static void vc_init(struct vc_data *vc, unsigned int rows,
 
 	set_origin(vc);
 	vc->vc_pos = vc->vc_origin;
-	reset_vc(vc);
+	reset_vc(vc, mode);
 	for (j=k=0; j<16; j++) {
 		vc->vc_palette[k++] = default_red[j] ;
 		vc->vc_palette[k++] = default_grn[j] ;
@@ -2905,15 +2916,30 @@  static int __init con_init(void)
 		mod_timer(&console_timer, jiffies + (blankinterval * HZ));
 	}
 
+	if (vt_handoff >= 0) {
+		currcons = vt_handoff;
+		vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
+		INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
+		visual_init(vc, currcons, 1);
+		vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
+		vc_init(vc, vc->vc_rows, vc->vc_cols, 0, KD_TRANSPARENT);
+	}
 	for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
+		if (currcons == vt_handoff)
+			continue;
 		vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
 		INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
 		visual_init(vc, currcons, 1);
 		vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
 		vc_init(vc, vc->vc_rows, vc->vc_cols,
-			currcons || !vc->vc_sw->con_save_screen);
+			currcons || !vc->vc_sw->con_save_screen, KD_TEXT);
 	}
 	currcons = fg_console = 0;
+	if (vt_handoff >= 0) {
+		printk(KERN_INFO "vt handoff: transparent VT on %d\n",
+								vt_handoff);
+		currcons = fg_console = vt_handoff;
+	}
 	master_display_fg = vc = vc_cons[currcons].d;
 	set_origin(vc);
 	save_screen(vc);
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 39c7e70..cb5c150 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -1345,9 +1345,9 @@  eperm:
 	goto out;
 }
 
-void reset_vc(struct vc_data *vc)
+void reset_vc(struct vc_data *vc, int mode)
 {
-	vc->vc_mode = KD_TEXT;
+	vc->vc_mode = mode;
 	kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE;
 	vc->vt_mode.mode = VT_AUTO;
 	vc->vt_mode.waitv = 0;
@@ -1378,7 +1378,7 @@  void vc_SAK(struct work_struct *work)
 		 */
 		if (tty)
 			__do_SAK(tty);
-		reset_vc(vc);
+		reset_vc(vc, KD_TEXT);
 	}
 	release_console_sem();
 }
@@ -1665,7 +1665,7 @@  static void complete_change_console(struct vc_data *vc)
 		 * this outside of VT_PROCESS but there is no single process
 		 * to account for and tracking tty count may be undesirable.
 		 */
-			reset_vc(vc);
+			reset_vc(vc, KD_TEXT);
 
 			if (old_vc_mode != vc->vc_mode) {
 				if (vc->vc_mode == KD_TEXT)
@@ -1737,7 +1737,7 @@  void change_console(struct vc_data *new_vc)
 		 * this outside of VT_PROCESS but there is no single process
 		 * to account for and tracking tty count may be undesirable.
 		 */
-		reset_vc(vc);
+		reset_vc(vc, KD_TEXT);
 
 		/*
 		 * Fall through to normal (VT_AUTO) handling of the switch...
diff --git a/include/linux/kd.h b/include/linux/kd.h
index 15f2853..abe298f 100644
--- a/include/linux/kd.h
+++ b/include/linux/kd.h
@@ -45,6 +45,7 @@  struct consolefontdesc {
 #define		KD_GRAPHICS	0x01
 #define		KD_TEXT0	0x02	/* obsolete */
 #define		KD_TEXT1	0x03	/* obsolete */
+#define		KD_TRANSPARENT	0x04
 #define KDGETMODE	0x4B3B	/* get current mode */
 
 #define KDMAPDISP	0x4B3C	/* map display into address space */
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 7f56db4..b0a6148 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -95,7 +95,7 @@  int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
 void vt_event_post(unsigned int event, unsigned int old, unsigned int new);
 int vt_waitactive(int n);
 void change_console(struct vc_data *new_vc);
-void reset_vc(struct vc_data *vc);
+void reset_vc(struct vc_data *vc, int mode);
 extern int unbind_con_driver(const struct consw *csw, int first, int last,
 			     int deflt);
 int vty_init(const struct file_operations *console_fops);