public inbox for gentoo-user@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-user] Console scrollback is back again!
@ 2021-04-05 17:12 Alan Mackenzie
  2021-04-05 17:44 ` antlists
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Alan Mackenzie @ 2021-04-05 17:12 UTC (permalink / raw
  To: gentoo-user

[-- Attachment #1: Type: text/plain, Size: 1817 bytes --]

Hello, Gentoo.

Yes, console soft scrolling is back!  That essential feature that was
stripped out of the kernel at around 5.4.x has returned!

Only this time, it's even better!  Instead of one scrollback buffer
shared between all tty's, there's now a buffer for each tty.

How to get it working:
(i) Extract the enclosed patch file to your /usr/src/linux-5.10.27-gentoo
directory (or probably any 5.10 kernel's).
(ii) From that directory run $ patch -p0 < diff.20210405.diff.
(iii)(a) If you've already got a working 5.10.27, do a $ make oldconfig.
  That should bring up the new configuration items, for which you can
  accept the defaults.  These two items are a flag to enable the
  scrollback, and a buffer size defaulting to 128kB.
(iii)(b) If you haven't yet got a 5.10.27, just configure your kernel in
  the usual way.  The two new items are under Device Drivers/Graphics
  support/Console display driver support.
(iv) Build the kernel.
(v) Put the new kernel into your usual boot manager.
(vi) Reboot and enjoy!

Admittedly, the exercise isn't quite finished - the patched source files
still have my personal change markings in them, to make debugging easier.
But the problems I reported here a few days ago are now solved.  One or
two features haven't (yet) been implemented - having a single scroll
buffer shared amongst all tty's isn't there, and there're no kernel
command line parameters to control the feature.

Also, you may wonder about how safe the patch is.  All I can say is that
there is nothing malicious in it, and I am known on this list, but of
course if it breaks I won't be to blame.

Bug reports and other comments are welcome, of course.

If anybody would like the corresponding patch which works on 5.4.n, for n
>= 80, that is available, too.

-- 
Alan Mackenzie (Nuremberg, Germany).


[-- Attachment #2: diff.20210405.diff --]
[-- Type: text/plain, Size: 21448 bytes --]

--- ./include/linux/vt_kern.h.orig	2020-12-13 22:41:30.000000000 +0000
+++ ./include/linux/vt_kern.h	2021-04-05 15:22:28.445755234 +0000
@@ -127,6 +127,11 @@
 /* vt.c */
 void vt_event_post(unsigned int event, unsigned int old, unsigned int new);
 int vt_waitactive(int n);
+/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+void concon_scrolldelta(struct vc_data *vc, int lines);
+#endif
+/* END OF NEW STOUGH */
 void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
 int do_unbind_con_driver(const struct consw *csw, int first, int last,
--- ./include/linux/console_struct.h.orig	2020-12-13 22:41:30.000000000 +0000
+++ ./include/linux/console_struct.h	2021-04-05 15:22:28.432755234 +0000
@@ -109,6 +109,21 @@
 	unsigned short	*vc_screenbuf;		/* In-memory character/attribute buffer */
 	unsigned int	vc_screenbuf_size;
 	unsigned char	vc_mode;		/* KD_TEXT, ... */
+	/* NEW STOUGH, 2021-03-31 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	unsigned int    vc_softback_size;	/* Size in bytes of scrollback buffer. */
+	unsigned long   vc_softback_buf;	/* Address of scrollback buffer. */
+	unsigned long   vc_softback_end;	/* (Just past) end of buffer. */
+	unsigned long   vc_softback_in;		/* Head pointer into circular buffer. */
+	unsigned long   vc_softback_top;	/* Tail pointer into circular buffer. */
+	unsigned long   vc_softback_curr;	/* Pos in vc_screenbuf or vc_softback_buf
+						   corresponding to visible screen. */
+	int             vc_softback_lines;	/* Number of lines currently scrolled. */
+	/* NEW STOUGH, 2021-04-04 */
+	unsigned short  vc_char_at_pos;		/* Char at vc_pos when no soft scroll */
+	/* END OF NEW STOUGH. */
+#endif
+	/* END OF NEW STOUGH */
 	/* attributes for all characters on screen */
 	unsigned char	vc_attr;		/* Current attributes */
 	unsigned char	vc_def_color;		/* Default colors */
--- ./drivers/video/fbdev/core/fbcon.c.orig	2021-04-05 15:22:28.434755234 +0000
+++ ./drivers/video/fbdev/core/fbcon.c	2021-04-05 15:56:00.836644342 +0000
@@ -3084,6 +3084,11 @@
 	.con_font_default	= fbcon_set_def_font,
 	.con_font_copy 		= fbcon_copy_font,
 	.con_set_palette 	= fbcon_set_palette,
+	/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	.con_scrolldelta	= concon_scrolldelta,
+#endif
+	/* END OF NEW STOUGH */
 	.con_invert_region 	= fbcon_invert_region,
 	.con_screen_pos 	= fbcon_screen_pos,
 	.con_getxy 		= fbcon_getxy,
--- ./drivers/video/console/Kconfig.orig	2020-12-13 22:41:30.000000000 +0000
+++ ./drivers/video/console/Kconfig	2021-04-05 15:22:28.414755235 +0000
@@ -78,6 +78,55 @@
 	help
 	  Low-level framebuffer-based console driver.
 
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	bool "Enable Scrollback Buffer in System RAM"
+	depends on FB=y && FRAMEBUFFER_CONSOLE
+	default y
+	select FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+	help
+	  This option creates scrollback buffers for each framebuffer console,
+	  or one buffer for them all.  These buffers are allocated dynamically
+	  during initialisation.
+
+	  If you want this feature, say 'Y' here and enter the amount of
+	  RAM to allocate for this buffer.  If unsure, say 'N'.
+
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_SIZE
+       int "Scrollback Buffer Size (in KB)"
+       depends on FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+       range 1 1024
+       default "128"
+       help
+       	  Enter the amount of System RAM to allocate for each scrollback
+	  buffer of framebuffer consoles in kilobytes.  Each character
+	  position on the video takes 2 bytes of storage.  128k will give you
+	  approximately 4 240x67 screenfuls of scrollback buffer.
+
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+	bool "Persistent Scrollback History for each framebuffer console by default"
+	depends on FB=y && FRAMEBUFFER_CONSOLE && FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	default y
+	help
+
+	  Note: this option's value N has not (?yet) been implemented (2021-04).
+
+	  Say Y here if the scrollback history should persist by default when
+	  switching between consoles. Otherwise, the scrollback history will
+	  be flushed the first time a scroll-up operation occurs on the new
+	  console after the console is switched. STOUGH!!!  FIXME!!! This
+	  feature can also be enabled using the boot command line parameter
+	  'vgacon.scrollback_persistent=1'.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
+
 config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
        bool "Map the console to the primary display device"
        depends on FRAMEBUFFER_CONSOLE
--- ./drivers/tty/vt/vt.c.orig	2020-12-13 22:41:30.000000000 +0000
+++ ./drivers/tty/vt/vt.c	2021-04-05 16:20:32.624563241 +0000
@@ -134,6 +134,13 @@
 #define DEFAULT_BELL_DURATION	(HZ/8)
 #define DEFAULT_CURSOR_BLINK_MS	200
 
+/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+static unsigned int console_soft_scrollback_size =
+	1024 * CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_SIZE;
+#endif
+/* END OF NEW STOUGH */
+
 struct vc vc_cons [MAX_NR_CONSOLES];
 
 #ifndef VT_SINGLE_DRIVER
@@ -287,7 +294,7 @@
 		bool viewed)
 {
 	unsigned short *p;
-	
+
 	if (!viewed)
 		p = (unsigned short *)(vc->vc_origin + offset);
 	else if (!vc->vc_sw->con_screen_pos)
@@ -616,6 +623,232 @@
 	}
 }
 
+/* NEW STOUGH, 2021-03-31 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+/* NEW STOUGH, 2021-04-01 */
+static void con_update_softback(struct vc_data *vc)
+{
+	int l = vc->vc_softback_size / vc->vc_size_row;
+	if (l > 5)
+	{
+		vc->vc_softback_end = vc->vc_softback_buf + l * vc->vc_size_row;
+		vc->vc_softback_top = vc->vc_softback_buf; /* STOUGH, 2021-04-04 */
+	}
+	else
+		/* Smaller scrollback makes no sense, and 0 would screw
+		   the operation totally */
+		vc->vc_softback_top = 0;
+}
+
+static int concon_set_origin(struct vc_data *vc)
+{
+	if (vc->vc_softback_lines)
+		concon_scrolldelta(vc, vc->vc_softback_lines);
+	return 0;
+}
+/* END OF NEW STOUGH */
+
+#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
+
+static void con_redraw_softback(struct vc_data *vc, /* struct display *p, */
+				long delta)
+{
+	int count = vc->vc_rows;
+	unsigned short *d, *s;
+	unsigned long n;
+	int line = 0;
+
+	/* NEW STOUGH, 2021-04-04 */
+	if (!vc->vc_softback_lines)
+		vc->vc_char_at_pos = scr_readw((u16 *)vc->vc_pos);
+	/* END OF NEW STOUGH */
+
+	d = (u16 *) vc->vc_softback_curr;
+	if (d == (u16 *) vc->vc_softback_in)
+		d = (u16 *) vc->vc_origin;
+	n = vc->vc_softback_curr + delta * vc->vc_size_row;
+	vc->vc_softback_lines -= delta;
+	if (delta < 0) {
+		if (vc->vc_softback_curr < vc->vc_softback_top
+		    && n < vc->vc_softback_buf) {
+			n += vc->vc_softback_end - vc->vc_softback_buf;
+			if (n < vc->vc_softback_top) {
+				vc->vc_softback_lines -=
+				    (vc->vc_softback_top - n) / vc->vc_size_row;
+				n = vc->vc_softback_top;
+			}
+		} else if (vc->vc_softback_curr >= vc->vc_softback_top
+			   && n < vc->vc_softback_top) {
+			vc->vc_softback_lines -=
+			    (vc->vc_softback_top - n) / vc->vc_size_row;
+			n = vc->vc_softback_top;
+		}
+	} else {
+		if (vc->vc_softback_curr > vc->vc_softback_in
+		    && n >= vc->vc_softback_end) {
+			n += vc->vc_softback_buf - vc->vc_softback_end;
+			if (n > vc->vc_softback_in) {
+				n = vc->vc_softback_in;
+				vc->vc_softback_lines = 0;
+			}
+		} else if (vc->vc_softback_curr <= vc->vc_softback_in
+			   && n > vc->vc_softback_in) {
+			n = vc->vc_softback_in;
+			vc->vc_softback_lines = 0;
+		}
+	}
+	if (n == vc->vc_softback_curr)
+		return;
+	vc->vc_softback_curr = n;
+	/* NEW STOUGH, 2021-04-04 */
+	/* If we're not scrolled any more, restore the character to the cursor
+	 * position */
+	if (!vc->vc_softback_lines)
+		scr_writew(vc->vc_char_at_pos, (u16 *)vc->vc_pos);
+	/* END OF NEW STOUGH */
+	s = (u16 *) vc->vc_softback_curr;
+	if (s == (u16 *) vc->vc_softback_in)
+		s = (u16 *) vc->vc_origin;
+	while (count--) {
+		unsigned short *start;
+		unsigned short *le;
+		unsigned short c;
+		int x = 0;
+		unsigned short attr = 1;
+
+		start = s;
+		le = advance_row(s, 1);
+		/* NEW STOUGH, 2021-04-04 */
+		/* Temporarily overwrite the character at the cursor position
+		 * with the one we actually want to see on the screen.  */
+		if (count == vc->vc_rows - vc->state.y - 1)
+		{
+			c = scr_readw((u16 *)(s + vc->state.x));
+			scr_writew(c, (u16 *)vc->vc_pos);
+			vc->vc_sw->con_putcs
+				(vc, (u16 *)vc->vc_pos, 1, line, vc->state.x);
+		}
+		/* END OF NEW STOUGH */
+		do {
+			c = scr_readw(s);
+			if (attr != (c & 0xff00)) {
+				attr = c & 0xff00;
+				if (s > start) {
+					vc->vc_sw->con_putcs(
+						vc, start, s - start,
+						line, x);
+					x += s - start;
+					start = s;
+				}
+			}
+			if (c == scr_readw(d)) {
+				if (s > start) {
+					vc->vc_sw->con_putcs(
+						vc, start, s - start,
+						line, x);
+					x += s - start + 1;
+					start = s + 1;
+				} else {
+					x++;
+					start++;
+				}
+			}
+			s++;
+			d++;
+		} while (s < le);
+		if (s > start)
+			vc->vc_sw->con_putcs(vc, start, s - start, line, x);
+		line++;
+		if (d == (u16 *) vc->vc_softback_end)
+			d = (u16 *) vc->vc_softback_buf;
+		if (d == (u16 *) vc->vc_softback_in)
+			d = (u16 *) vc->vc_origin;
+		if (s == (u16 *) vc->vc_softback_end)
+			s = (u16 *) vc->vc_softback_buf;
+		if (s == (u16 *) vc->vc_softback_in)
+			s = (u16 *) vc->vc_origin;
+	}
+}
+/* END OF NEW STOUGH */
+
+/* NEW STOUGH, 2021-04-01 */
+static inline void con_softback_note(struct vc_data *vc, int t,
+				     int count)
+{
+	unsigned short *p;
+
+	if (vc->vc_num != fg_console)
+		return;
+	p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
+
+	while (count) {
+		scr_memcpyw((u16 *) vc->vc_softback_in, p, vc->vc_size_row);
+		count--;
+		p = advance_row(p, 1);
+		vc->vc_softback_in += vc->vc_size_row;
+		if (vc->vc_softback_in == vc->vc_softback_end)
+			vc->vc_softback_in = vc->vc_softback_buf;
+		if (vc->vc_softback_in == vc->vc_softback_top) {
+			vc->vc_softback_top += vc->vc_size_row;
+			if (vc->vc_softback_top == vc->vc_softback_end)
+				vc->vc_softback_top = vc->vc_softback_buf;
+		}
+	}
+	vc->vc_softback_curr = vc->vc_softback_in;
+}
+
+void concon_scrolldelta(struct vc_data *vc, int lines)
+{
+	/* struct display *disp = &fb_display[fg_console]; */
+	/* int offset, limit, scrollback_old; */
+
+	if (vc->vc_softback_top) {
+		if (vc->vc_num != fg_console)
+			return;
+		if (vc->vc_mode != KD_TEXT || !lines)
+			return;
+#if 0
+		if (logo_shown >= 0) {
+			struct vc_data *conp2 = vc_cons[logo_shown].d;
+
+			if (conp2->vc_top == logo_lines
+			    && conp2->vc_bottom == conp2->vc_rows)
+				conp2->vc_top = 0;
+			if (logo_shown == vc->vc_num) {
+				unsigned long p, q;
+				int i;
+
+				p = vc->vc_softback_in;
+				q = vc->vc_origin +
+				    logo_lines * vc->vc_size_row;
+				for (i = 0; i < logo_lines; i++) {
+					if (p == vc->vc_softback_top)
+						break;
+					if (p == vc->vc_softback_buf)
+						p = vc->vc_softback_end;
+					p -= vc->vc_size_row;
+					q -= vc->vc_size_row;
+					scr_memcpyw((u16 *) q, (u16 *) p,
+						    vc->vc_size_row);
+				}
+				vc->vc_softback_in = vc->vc_softback_curr = p;
+				update_region(vc, vc->vc_origin,
+					      logo_lines * vc->vc_cols);
+			}
+			logo_shown = FBCON_LOGO_CANSHOW;
+		}
+#endif
+		vc->vc_sw->con_cursor(vc, CM_ERASE /* | CM_SOFTBACK */);
+		con_redraw_softback(vc, /* disp, */ lines);
+		/* NEW STOUGH, 2021-04-04 */
+		if (!vc->vc_softback_lines)
+			/* END OF NEW STOUGH */
+			vc->vc_sw->con_cursor(vc, CM_DRAW /* | CM_SOFTBACK */);
+	}
+}
+
+/* END OF NEW STOUGH */
+#endif  /* CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK */
 
 static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
 		enum con_scroll dir, unsigned int nr)
@@ -626,6 +859,12 @@
 		nr = b - t - 1;
 	if (b > vc->vc_rows || t >= b || nr < 1)
 		return;
+	/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (dir == SM_UP && vc->vc_softback_top)
+		con_softback_note (vc, t, nr);
+#endif
+	/* END OF NEW STOUGH */
 	vc_uniscr_scroll(vc, t, b, dir, nr);
 	if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, dir, nr))
 		return;
@@ -641,6 +880,72 @@
 	scr_memsetw(clear, vc->vc_video_erase_char, vc->vc_size_row * nr);
 }
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+static void do_update_region(struct vc_data *vc, unsigned long start, int count)
+{
+	unsigned int xx, yy, offset;
+	u16 *p;
+
+	/* NEW STOUGH, 2021-04-03 */
+	unsigned long origin =
+		(start >= vc->vc_softback_buf && start < vc->vc_softback_end)
+		? start >= vc->vc_softback_curr
+		  ? vc->vc_softback_curr
+		  : vc->vc_softback_curr
+		    - (vc->vc_softback_end - vc->vc_softback_buf)
+		: vc->vc_origin;
+	/* END OF NEW STOUGH */
+	p = (u16 *) start;
+	/* OLD STOUGH, 2021-04-03 */
+	/* if (!vc->vc_sw->con_getxy) { */
+		/* END OF OLD STOUGH */
+		offset = (start - origin) / 2; /* STOUGH, 2021-04-03 */
+		xx = offset % vc->vc_cols;
+		yy = offset / vc->vc_cols;
+		/* OLD STOUGH, 2021-04-03 */
+	/* } else { */
+	/* 	int nxx, nyy; */
+	/* 	start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy); */
+	/* 	xx = nxx; yy = nyy; */
+	/* } */
+		/* END OF OLD STOUGH */
+	for(;;) {
+		u16 attrib = scr_readw(p) & 0xff00;
+		int startx = xx;
+		u16 *q = p;
+		while (xx < vc->vc_cols && count) {
+			if (attrib != (scr_readw(p) & 0xff00)) {
+				if (p > q)
+					vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
+				startx = xx;
+				q = p;
+				attrib = scr_readw(p) & 0xff00;
+			}
+			p++;
+			xx++;
+			count--;
+		}
+		if (p > q)
+			vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
+		/* NEW STOUGH, 2021-04-03 */
+		if (p == (u16 *) vc->vc_softback_end)
+			p = (u16 *)vc->vc_softback_buf;
+		if (p == (u16 *) vc->vc_softback_in)
+			p = (u16 *)vc->vc_origin;
+		/* END OF NEW STOUGH */
+		if (!count)
+			break;
+		xx = 0;
+		yy++;
+		/* OLD STOUGH, 2021-04-03 */
+		/* if (vc->vc_sw->con_getxy) { */
+		/* 	p = (u16 *)start; */
+		/* 	start = vc->vc_sw->con_getxy(vc, start, NULL, NULL); */
+		/* } */
+		/* END OF OLD STOUGH */
+	}
+}
+#else
 static void do_update_region(struct vc_data *vc, unsigned long start, int count)
 {
 	unsigned int xx, yy, offset;
@@ -684,6 +989,7 @@
 		}
 	}
 }
+#endif
 
 void update_region(struct vc_data *vc, unsigned long start, int count)
 {
@@ -692,7 +998,12 @@
 	if (con_should_update(vc)) {
 		hide_cursor(vc);
 		do_update_region(vc, start, count);
-		set_cursor(vc);
+		/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		if (!vc->vc_softback_lines)
+#endif
+			/* END OF NEW STOUGH */
+			set_cursor(vc);
 	}
 }
 
@@ -927,8 +1238,19 @@
 	WARN_CONSOLE_UNLOCKED();
 
 	if (!con_is_visible(vc) ||
+	    /* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	    (
+	     !concon_set_origin (vc) &&
+	     (
+#endif
+	    /* END OF NEW STOUGH */
 	    !vc->vc_sw->con_set_origin ||
-	    !vc->vc_sw->con_set_origin(vc))
+	    !vc->vc_sw->con_set_origin(vc)
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		     ))
+#endif
+					  )
 		vc->vc_origin = (unsigned long)vc->vc_screenbuf;
 	vc->vc_visible_origin = vc->vc_origin;
 	vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
@@ -1004,7 +1326,9 @@
 		hide_cursor(old_vc);
 		if (!con_is_visible(old_vc)) {
 			save_screen(old_vc);
-			set_origin(old_vc);
+			/* OLD STOUGH, 2021-04-02 */
+			/* set_origin(old_vc); */
+			/* END OF OLD STOUGH */
 		}
 		if (tty0dev)
 			sysfs_notify(&tty0dev->kobj, NULL, "active");
@@ -1017,7 +1341,9 @@
 		int update;
 		int old_was_color = vc->vc_can_do_color;
 
-		set_origin(vc);
+		/* OLD STOUGH, 2021-04-02 */
+		/* set_origin(vc); */
+		/* END OF OLD STOUGH */
 		update = vc->vc_sw->con_switch(vc);
 		set_palette(vc);
 		/*
@@ -1032,9 +1358,25 @@
 		}
 
 		if (update && vc->vc_mode != KD_GRAPHICS)
-			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
-	}
-	set_cursor(vc);
+			/* OLD STOUGH, 2021-04-03 */
+			/* do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); */
+			/* NEW STOUGH, 2021-04-03 */
+			do_update_region(vc,
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+					 vc->vc_softback_lines
+					 ? vc->vc_softback_curr
+					 :
+#endif
+					   vc->vc_origin,
+					 vc->vc_screenbuf_size / 2);
+			/* END OF NEW STOUGH */
+	}
+	/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		/* END OF NEW STOUGH */
+		set_cursor(vc);
 	if (is_switch) {
 		set_leds();
 		compute_shiftstate();
@@ -1113,12 +1455,32 @@
 	int err;
 
 	WARN_CONSOLE_UNLOCKED();
-
 	if (currcons >= MAX_NR_CONSOLES)
 		return -ENXIO;
 
 	if (vc_cons[currcons].d)
+		/* NEW STOUGH, 2021-04-05 */
+	{
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		vc = vc_cons[currcons].d;
+		if (!vc->vc_softback_size) {
+			/* vc was partially initialized by __init. */
+			vc->vc_softback_size = console_soft_scrollback_size;
+			vc->vc_softback_buf =
+				(unsigned long)kzalloc(vc->vc_softback_size, GFP_KERNEL);
+			if (vc->vc_softback_buf) {
+				vc->vc_softback_in = vc->vc_softback_top =
+					vc->vc_softback_curr = vc->vc_softback_buf;
+				vc->vc_softback_lines = 0;
+				con_update_softback(vc);
+			}
+		}
+#endif
+		/* END OF NEW STOUGH */
 		return 0;
+		/* NEW STOUGH, 2021-04-05 */
+	}
+	/* END OF NEW STOUGH */
 
 	/* due to the granularity of kmalloc, we waste some memory here */
 	/* the alloc is done in two steps, to optimize the common situation
@@ -1158,6 +1520,20 @@
 	vcs_make_sysfs(currcons);
 	atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
 
+	/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	vc->vc_softback_size = console_soft_scrollback_size;
+	err = -ENOMEM;
+	vc->vc_softback_buf =
+		(unsigned long)kzalloc(vc->vc_softback_size, GFP_KERNEL);
+	if (!vc->vc_softback_buf)
+		goto err_free;
+	vc->vc_softback_in = vc->vc_softback_top = vc->vc_softback_curr =
+		vc->vc_softback_buf;
+	vc->vc_softback_lines = 0;
+	con_update_softback(vc);
+#endif
+	/* END OF NEW STOUGH */
 	return 0;
 err_free:
 	visual_deinit(vc);
@@ -1629,7 +2005,7 @@
 
 static void rgb_from_256(int i, struct rgb *c)
 {
-	if (i < 8) {            /* Standard colours. */
+	if (i < 8) {	    /* Standard colours. */
 		c->r = i&1 ? 0xaa : 0x00;
 		c->g = i&2 ? 0xaa : 0x00;
 		c->b = i&4 ? 0xaa : 0x00;
@@ -1641,7 +2017,7 @@
 		c->r = (i - 16) / 36 * 85 / 2;
 		c->g = (i - 16) / 6 % 6 * 85 / 2;
 		c->b = (i - 16) % 6 * 85 / 2;
-	} else                  /* Grayscale ramp. */
+	} else		  /* Grayscale ramp. */
 		c->r = c->g = c->b = i * 10 - 2312;
 }
 
@@ -2888,6 +3264,14 @@
 
 	param.vc = vc;
 
+	/* NEW STOUGH, 2021-04-03 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	/* Undo any soft scrolling - <Alt><Fn> and <Shift><PgUp/Down> do
+	   not pass through this function.  */
+	concon_set_origin (vc);
+#endif
+	/* END OF NEW STOUGH */
+
 	while (!tty->stopped && count) {
 		int orig = *buf;
 		buf++;
@@ -3103,7 +3487,16 @@
 	}
 	if (cnt && con_is_visible(vc))
 		vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x);
-	set_cursor(vc);
+	/* OLD STOUGH, 2021-04-05 */
+	/* set_cursor(vc); */
+	/* NEW STOUGH, 2021-04-05 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		/* END OF NEW STOUGH */
+		set_cursor(vc);
+
+	/* END OF NEW STOUGH */
 	notify_update(vc);
 
 quit:
@@ -3331,7 +3724,13 @@
 	/* if we race with con_close(), vt may be null */
 	console_lock();
 	vc = tty->driver_data;
-	if (vc)
+	if (vc
+	    /* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	    && !vc->vc_softback_lines
+#endif
+	    /* END OF NEW STOUGH */
+	      )
 		set_cursor(vc);
 	console_unlock();
 }
@@ -3352,6 +3751,12 @@
 
 	vc = vc_cons[currcons].d;
 
+	/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	con_update_softback(vc);
+#endif
+	/* END OF NEW STOUGH */
+
 	/* Still being freed */
 	if (vc->port.tty) {
 		ret = -ERESTARTSYS;
@@ -3407,7 +3812,7 @@
 	tty_port_put(&vc->port);
 }
 
-static int default_color           = 7; /* white */
+static int default_color	   = 7; /* white */
 static int default_italic_color    = 2; // green (ASCII)
 static int default_underline_color = 3; // cyan (ASCII)
 module_param_named(color, default_color, int, S_IRUGO | S_IWUSR);
@@ -4108,7 +4513,7 @@
 			con_driver->desc = desc;
 			con_driver->node = i;
 			con_driver->flag = CON_DRIVER_FLAG_MODULE |
-			                   CON_DRIVER_FLAG_INIT;
+					   CON_DRIVER_FLAG_INIT;
 			con_driver->first = first;
 			con_driver->last = last;
 			retval = 0;
@@ -4409,7 +4814,12 @@
 	if (console_blank_hook)
 		console_blank_hook(0);
 	set_palette(vc);
-	set_cursor(vc);
+	/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		/* END OF NEW STOUGH */
+		set_cursor(vc);
 	vt_event_post(VT_EVENT_UNBLANK, vc->vc_num, vc->vc_num);
 }
 EXPORT_SYMBOL(do_unblank_screen);

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 17:12 [gentoo-user] Console scrollback is back again! Alan Mackenzie
@ 2021-04-05 17:44 ` antlists
  2021-04-05 18:13   ` Alan Mackenzie
  2021-04-05 18:38 ` Jorge Almeida
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: antlists @ 2021-04-05 17:44 UTC (permalink / raw
  To: gentoo-user

On 05/04/2021 18:12, Alan Mackenzie wrote:
> Bug reports and other comments are welcome, of course.
> 
> If anybody would like the corresponding patch which works on 5.4.n, for n
>> = 80, that is available, too.

Why did it get removed from the kernel?

If you want to get it back in, couldn't you ping Greg KH and get some 
help - or even just advice - getting it accepted?

Cheers,
Wol


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 17:44 ` antlists
@ 2021-04-05 18:13   ` Alan Mackenzie
  2021-04-05 23:08     ` Michael Jones
  2021-04-06 13:14     ` Peter Humphrey
  0 siblings, 2 replies; 18+ messages in thread
From: Alan Mackenzie @ 2021-04-05 18:13 UTC (permalink / raw
  To: gentoo-user

Hello, Wol.

On Mon, Apr 05, 2021 at 18:44:15 +0100, antlists wrote:
> On 05/04/2021 18:12, Alan Mackenzie wrote:
> > Bug reports and other comments are welcome, of course.
> > 
> > If anybody would like the corresponding patch which works on 5.4.n, for n
> >> = 80, that is available, too.

> Why did it get removed from the kernel?

Allegedly, there were security problems with it.  I think the kernel
people had a program which fired random inputs at lots of components,
and noted when things went wrong; and things went wrong in the scroll
back component.  And they couldn't find anybody to look into these
problems.

That's the official position.  I'm a bit more cynical about it.

> If you want to get it back in, couldn't you ping Greg KH and get some 
> help - or even just advice - getting it accepted?

I have no reason to believe all the "security problems" will have been
resolved by my hacking.  I took the algorithmic bits from 4.19.97
basically unchanged.

Maybe there's not much enthusiasm for this feature, in which case I will
keep it working for myself.  Linux is basically unusable to me without
it.  There are probably quite a few patches to restore the scrollback
floating around the web by now: the changes were not particularly
difficult to anybody who knows the code, but getting to know the code
was unusually difficult.

We'll see how people react to it here, first.

> Cheers,
> Wol

-- 
Alan Mackenzie (Nuremberg, Germany).


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 17:12 [gentoo-user] Console scrollback is back again! Alan Mackenzie
  2021-04-05 17:44 ` antlists
@ 2021-04-05 18:38 ` Jorge Almeida
  2021-04-06  9:55   ` Alan Mackenzie
  2021-04-05 19:58 ` karl
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Jorge Almeida @ 2021-04-05 18:38 UTC (permalink / raw
  To: gentoo-user

On Mon, Apr 5, 2021 at 6:12 PM Alan Mackenzie <acm@muc.de> wrote:
>
> Hello, Gentoo.
>
> Yes, console soft scrolling is back!  That essential feature that was
> stripped out of the kernel at around 5.4.x has returned!
>
> Only this time, it's even better!  Instead of one scrollback buffer
> shared between all tty's, there's now a buffer for each tty.
>

I just tested it with kernel 5.11.11. Seems fine.

Jorge Almeida


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 17:12 [gentoo-user] Console scrollback is back again! Alan Mackenzie
  2021-04-05 17:44 ` antlists
  2021-04-05 18:38 ` Jorge Almeida
@ 2021-04-05 19:58 ` karl
  2021-04-06 11:04   ` Alan Mackenzie
  2021-04-06  0:10 ` konsolebox
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: karl @ 2021-04-05 19:58 UTC (permalink / raw
  To: gentoo-user

Alan Mackenzie:
> Yes, console soft scrolling is back!  That essential feature that was
> stripped out of the kernel at around 5.4.x has returned!

It is commit 087b6cb17df5834d395ab72da3f937380470ba15,
between v5.4.65 and 66.
Perhaps also 0d123a8c64fde433a, cf5a7ded53652c3d63d72, and possible
other stuff.

> Only this time, it's even better!  Instead of one scrollback buffer
> shared between all tty's, there's now a buffer for each tty.

Great, no more missing data when switching vts.

Btw, wasn't that added in commit aabd31c421ddc730edf6d89c4ed3885e4fca5e30
but turned off by default.

...
> One ord two features haven't (yet) been implemented - having a
> single scroll buffer shared amongst all tty's isn't there,
...

Is there any reason to share the buffer ?

> Bug reports and other comments are welcome, of course.

git log drivers/video/console/vgacon.c etc. can give some ideas
what one is up against.

Regards,
/Karl Hammar




^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 18:13   ` Alan Mackenzie
@ 2021-04-05 23:08     ` Michael Jones
  2021-04-06  9:54       ` Alan Mackenzie
  2021-04-06 13:14     ` Peter Humphrey
  1 sibling, 1 reply; 18+ messages in thread
From: Michael Jones @ 2021-04-05 23:08 UTC (permalink / raw
  To: gentoo-user

[-- Attachment #1: Type: text/plain, Size: 1834 bytes --]

On Mon, Apr 5, 2021, 13:13 Alan Mackenzie <acm@muc.de> wrote:

> Hello, Wol.
>
> On Mon, Apr 05, 2021 at 18:44:15 +0100, antlists wrote:
> > On 05/04/2021 18:12, Alan Mackenzie wrote:
> > > Bug reports and other comments are welcome, of course.
> > >
> > > If anybody would like the corresponding patch which works on 5.4.n,
> for n
> > >> = 80, that is available, too.
>
> > Why did it get removed from the kernel?
>
> Allegedly, there were security problems with it.  I think the kernel
> people had a program which fired random inputs at lots of components,
> and noted when things went wrong; and things went wrong in the scroll
> back component.  And they couldn't find anybody to look into these
> problems.
>
> That's the official position.  I'm a bit more cynical about it.
>
> > If you want to get it back in, couldn't you ping Greg KH and get some
> > help - or even just advice - getting it accepted?
>
> I have no reason to believe all the "security problems" will have been
> resolved by my hacking.  I took the algorithmic bits from 4.19.97
> basically unchanged.
>
> Maybe there's not much enthusiasm for this feature, in which case I will
> keep it working for myself.  Linux is basically unusable to me without
> it.  There are probably quite a few patches to restore the scrollback
> floating around the web by now: the changes were not particularly
> difficult to anybody who knows the code, but getting to know the code
> was unusually difficult.
>
> We'll see how people react to it here, first.
>
> > Cheers,
> > Wol
>
> --
> Alan Mackenzie (Nuremberg, Germany).


Without looking at the patch itself:

Have you considered something like kmscon as a userland alternative?

I installed it on my laptop, and aside from not working with gpmd or
consolation for mouse support, it's a perfectly functional local tty.

[-- Attachment #2: Type: text/html, Size: 2476 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 17:12 [gentoo-user] Console scrollback is back again! Alan Mackenzie
                   ` (2 preceding siblings ...)
  2021-04-05 19:58 ` karl
@ 2021-04-06  0:10 ` konsolebox
  2021-04-06 12:50 ` J. Roeleveld
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: konsolebox @ 2021-04-06  0:10 UTC (permalink / raw
  To: gentoo-user

On Tue, Apr 6, 2021 at 1:12 AM Alan Mackenzie <acm@muc.de> wrote:
>
> Hello, Gentoo.
>
> Yes, console soft scrolling is back!  That essential feature that was
> stripped out of the kernel at around 5.4.x has returned!

Thank you. I'll try to make this work in 5.10.28 once it's released.

-- 
konsolebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 23:08     ` Michael Jones
@ 2021-04-06  9:54       ` Alan Mackenzie
  2021-04-06 15:30         ` Michael Jones
  0 siblings, 1 reply; 18+ messages in thread
From: Alan Mackenzie @ 2021-04-06  9:54 UTC (permalink / raw
  To: gentoo-user

Hello, Michael.

On Mon, Apr 05, 2021 at 18:08:58 -0500, Michael Jones wrote:

[ .... ]

> Without looking at the patch itself:

> Have you considered something like kmscon as a userland alternative?

To be honest, no.  I wasn't really aware of it when I starting working on
the Linux console.

According to Wikipedia, the last release was in 2013, and development
stopped altogether in 2015.  The Gentoo package for it is masked.

> I installed it on my laptop, and aside from not working with gpmd or
> consolation for mouse support, it's a perfectly functional local tty.

I suppose it's one of these programs that once working, pretty much
carries on working for ever.

-- 
Alan Mackenzie (Nuremberg, Germany).


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 18:38 ` Jorge Almeida
@ 2021-04-06  9:55   ` Alan Mackenzie
  2021-04-06 10:36     ` Jorge Almeida
  0 siblings, 1 reply; 18+ messages in thread
From: Alan Mackenzie @ 2021-04-06  9:55 UTC (permalink / raw
  To: gentoo-user

Hello, Jorge.

On Mon, Apr 05, 2021 at 19:38:57 +0100, Jorge Almeida wrote:
> On Mon, Apr 5, 2021 at 6:12 PM Alan Mackenzie <acm@muc.de> wrote:

> > Hello, Gentoo.

> > Yes, console soft scrolling is back!  That essential feature that was
> > stripped out of the kernel at around 5.4.x has returned!

> > Only this time, it's even better!  Instead of one scrollback buffer
> > shared between all tty's, there's now a buffer for each tty.


> I just tested it with kernel 5.11.11. Seems fine.

Thanks!

> Jorge Almeida

-- 
Alan Mackenzie (Nuremberg, Germany).


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-06  9:55   ` Alan Mackenzie
@ 2021-04-06 10:36     ` Jorge Almeida
  0 siblings, 0 replies; 18+ messages in thread
From: Jorge Almeida @ 2021-04-06 10:36 UTC (permalink / raw
  To: gentoo-user

On Tue, Apr 6, 2021 at 10:56 AM Alan Mackenzie <acm@muc.de> wrote:
>

>
>
> > I just tested it with kernel 5.11.11. Seems fine.
>
> Thanks!
>
Thank _you_!

It is regrettable that console scrolling is out of the kernel. Even if
one doesn't use the console that much, it is used once in a while, and
those occasions tend to be  precisely the ones back scrolling will be
most missed.

Jorge Almeida


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 19:58 ` karl
@ 2021-04-06 11:04   ` Alan Mackenzie
  0 siblings, 0 replies; 18+ messages in thread
From: Alan Mackenzie @ 2021-04-06 11:04 UTC (permalink / raw
  To: gentoo-user

Hello, Karl.

On Mon, Apr 05, 2021 at 21:58:37 +0200, karl@aspodata.se wrote:
> Alan Mackenzie:
> > Yes, console soft scrolling is back!  That essential feature that was
> > stripped out of the kernel at around 5.4.x has returned!

> It is commit 087b6cb17df5834d395ab72da3f937380470ba15,
> between v5.4.65 and 66.
> Perhaps also 0d123a8c64fde433a, cf5a7ded53652c3d63d72, and possible
> other stuff.

I will confess that I don't actually have a git repository of Linux on
my machine.  I'd have to back it up, somehow.  It would be a fair amount
of work to write an efficient back-up procedure - the one I have at the
moment for git repos backs up the entire repository, which would
probably be excessive for Linux.

Currently, I've changed a mere five files, for which I'm getting by with
symbolic links in the kernel tree pointing into my home directory.

> > Only this time, it's even better!  Instead of one scrollback buffer
> > shared between all tty's, there's now a buffer for each tty.

> Great, no more missing data when switching vts.

> Btw, wasn't that added in commit aabd31c421ddc730edf6d89c4ed3885e4fca5e30
> but turned off by default.

There was no capability at all for one buffer per tty in framebuffer
consoles.  It was there for VGA consoles, and, I think, one or two
others.  The configuration page for it was confusing - the option for
"persistent scrollback" was purely for VGAcon, though that wasn't
obvious.  I spent time in the past trying to get multiple buffers
working, and was even considering reporting a bug.

> ...
> > One or two features haven't (yet) been implemented - having a
> > single scroll buffer shared amongst all tty's isn't there,
> ...

> Is there any reason to share the buffer ?

Not that I can think of.  The only reason might be if somebody wanted a
very large scrollback buffer, but didn't have a lot of RAM.  But even
so, the current default takes a total of less than 1 MB of RAM with the
standard 7 tty's.  Even increasing the buffer size to 10 MB, that would
only come to 70 MB.  Such a size of buffer would really need more
sophisticated handling, with search facilities, some marking of
positions, and so on.  That would be a large project.

> > Bug reports and other comments are welcome, of course.

> git log drivers/video/console/vgacon.c etc. can give some ideas
> what one is up against.

Once I find some way to read it.  ;-(

Anyhow, the patch I have is working software, and is not going away any
time soon.  It means I can carry on using Linux.

Just in case you're interested, the problem I had with no scrolling on
tty1 was due to the way the console was initialised early on in the boot
process.  Its structures were initialised in a separate place from the
normal init function, thus bypassing the scrollbuffer's init.  When it
came to re-initialising it for scrollbuffer, this partial initialisation
acted as a flag not to carry on with the init.  At least it caused me to
learn about printk.  ;-)

> Regards,
> /Karl Hammar

-- 
Alan Mackenzie (Nuremberg, Germany).


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 17:12 [gentoo-user] Console scrollback is back again! Alan Mackenzie
                   ` (3 preceding siblings ...)
  2021-04-06  0:10 ` konsolebox
@ 2021-04-06 12:50 ` J. Roeleveld
  2021-04-08 18:16 ` konsolebox
  2021-07-15 19:19 ` Alan Mackenzie
  6 siblings, 0 replies; 18+ messages in thread
From: J. Roeleveld @ 2021-04-06 12:50 UTC (permalink / raw
  To: gentoo-user

On Monday, April 5, 2021 7:12:07 PM CEST Alan Mackenzie wrote:
> Hello, Gentoo.
> 
> Yes, console soft scrolling is back!  That essential feature that was
> stripped out of the kernel at around 5.4.x has returned!
> 
> Only this time, it's even better!  Instead of one scrollback buffer
> shared between all tty's, there's now a buffer for each tty.
> 
> How to get it working:
> (i) Extract the enclosed patch file to your /usr/src/linux-5.10.27-gentoo
> directory (or probably any 5.10 kernel's).
> (ii) From that directory run $ patch -p0 < diff.20210405.diff.
> (iii)(a) If you've already got a working 5.10.27, do a $ make oldconfig.
>   That should bring up the new configuration items, for which you can
>   accept the defaults.  These two items are a flag to enable the
>   scrollback, and a buffer size defaulting to 128kB.
> (iii)(b) If you haven't yet got a 5.10.27, just configure your kernel in
>   the usual way.  The two new items are under Device Drivers/Graphics
>   support/Console display driver support.
> (iv) Build the kernel.
> (v) Put the new kernel into your usual boot manager.
> (vi) Reboot and enjoy!
> 

Thank you!

I will add this to my "/etc/portage/patches/sys-kernel/gentoo-sources" 
directory. Right next to the gpl-defang patch.







^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 18:13   ` Alan Mackenzie
  2021-04-05 23:08     ` Michael Jones
@ 2021-04-06 13:14     ` Peter Humphrey
  2021-04-06 14:13       ` John Covici
  1 sibling, 1 reply; 18+ messages in thread
From: Peter Humphrey @ 2021-04-06 13:14 UTC (permalink / raw
  To: gentoo-user

On Monday, 5 April 2021 19:13:18 BST Alan Mackenzie wrote:

> We'll see how people react to it here, first.

You're my hero!

-- 
Regards,
Peter.





^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-06 13:14     ` Peter Humphrey
@ 2021-04-06 14:13       ` John Covici
  2021-04-06 14:32         ` Alan Mackenzie
  0 siblings, 1 reply; 18+ messages in thread
From: John Covici @ 2021-04-06 14:13 UTC (permalink / raw
  To: gentoo-user


On Tue, 06 Apr 2021 09:14:23 -0400,
Peter Humphrey wrote:
> 
> On Monday, 5 April 2021 19:13:18 BST Alan Mackenzie wrote:
> 
> > We'll see how people react to it here, first.
> 
> You're my hero!

Would this patch work on 5.4.96 and following?

-- 
Your life is like a penny.  You're going to lose it.  The question is:
How do
you spend it?

         John Covici wb2una
         covici@ccs.covici.com


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-06 14:13       ` John Covici
@ 2021-04-06 14:32         ` Alan Mackenzie
  0 siblings, 0 replies; 18+ messages in thread
From: Alan Mackenzie @ 2021-04-06 14:32 UTC (permalink / raw
  To: gentoo-user

[-- Attachment #1: Type: text/plain, Size: 723 bytes --]

Hello, John

On Tue, Apr 06, 2021 at 10:13:39 -0400, John Covici wrote:

> On Tue, 06 Apr 2021 09:14:23 -0400,
> Peter Humphrey wrote:

> > On Monday, 5 April 2021 19:13:18 BST Alan Mackenzie wrote:

> > > We'll see how people react to it here, first.

> > You're my hero!

> Would this patch work on 5.4.96 and following?

No, there is a slight difference (two struct fields moved and renamed)
between 5.4 and 5.10.

For 5.4, please use the attached patch instead.  It has been tested on
5.4.80-r1 and 5.4.97.

> -- 
> Your life is like a penny.  You're going to lose it.  The question is:
> How do
> you spend it?

>          John Covici wb2una
>          covici@ccs.covici.com

-- 
Alan Mackenzie (Nuremberg, Germany).


[-- Attachment #2: diff.20210405b.diff --]
[-- Type: text/plain, Size: 23284 bytes --]

--- drivers/video/console/Kconfig.orig	2021-03-31 19:14:48.186140856 +0000
+++ drivers/video/console/Kconfig	2021-04-05 13:41:20.967713154 +0000
@@ -79,6 +79,55 @@
 	help
 	  Low-level framebuffer-based console driver.
 
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	bool "Enable Scrollback Buffer in System RAM"
+	depends on FB=y && FRAMEBUFFER_CONSOLE
+	default y
+	select FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+	help
+	  This option creates scrollback buffers for each framebuffer console,
+	  or one buffer for them all.  These buffers are allocated dynamically
+	  during initialisation.
+
+	  If you want this feature, say 'Y' here and enter the amount of
+	  RAM to allocate for this buffer.  If unsure, say 'N'.
+
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_SIZE
+       int "Scrollback Buffer Size (in KB)"
+       depends on FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+       range 1 1024
+       default "128"
+       help
+       	  Enter the amount of System RAM to allocate for each scrollback
+	  buffer of framebuffer consoles in kilobytes.  Each character
+	  position on the video takes 2 bytes of storage.  128k will give you
+	  approximately 4 240x67 screenfuls of scrollback buffer.
+
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+	bool "Persistent Scrollback History for each framebuffer console by default"
+	depends on FB=y && FRAMEBUFFER_CONSOLE && FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	default y
+	help
+
+	  Note: this option's value N has not (?yet) been implemented (2021-04).
+
+	  Say Y here if the scrollback history should persist by default when
+	  switching between consoles. Otherwise, the scrollback history will
+	  be flushed the first time a scroll-up operation occurs on the new
+	  console after the console is switched. STOUGH!!!  FIXME!!! This
+	  feature can also be enabled using the boot command line parameter
+	  'vgacon.scrollback_persistent=1'.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
+
 config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
        bool "Map the console to the primary display device"
        depends on FRAMEBUFFER_CONSOLE
--- drivers/tty/vt/vt.orig.c	2020-11-28 17:14:38.523649992 +0000
+++ drivers/tty/vt/vt.c	2021-04-05 14:33:47.743786578 +0000
@@ -142,6 +142,13 @@
 #define DEFAULT_BELL_DURATION	(HZ/8)
 #define DEFAULT_CURSOR_BLINK_MS	200
 
+/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+static unsigned int console_soft_scrollback_size =
+	1024 * CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_SIZE;
+#endif
+/* END OF NEW STOUGH */
+
 struct vc vc_cons [MAX_NR_CONSOLES];
 
 #ifndef VT_SINGLE_DRIVER
@@ -294,7 +301,7 @@
 static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
 {
 	unsigned short *p;
-	
+
 	if (!viewed)
 		p = (unsigned short *)(vc->vc_origin + offset);
 	else if (!vc->vc_sw->con_screen_pos)
@@ -623,6 +630,232 @@
 	}
 }
 
+/* NEW STOUGH, 2021-03-31 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+/* NEW STOUGH, 2021-04-01 */
+static void con_update_softback(struct vc_data *vc)
+{
+	int l = vc->vc_softback_size / vc->vc_size_row;
+	if (l > 5)
+	{
+		vc->vc_softback_end = vc->vc_softback_buf + l * vc->vc_size_row;
+		vc->vc_softback_top = vc->vc_softback_buf; /* STOUGH, 2021-04-04 */
+	}
+	else
+		/* Smaller scrollback makes no sense, and 0 would screw
+		   the operation totally */
+		vc->vc_softback_top = 0;
+}
+
+static int concon_set_origin(struct vc_data *vc)
+{
+	if (vc->vc_softback_lines)
+		concon_scrolldelta(vc, vc->vc_softback_lines);
+	return 0;
+}
+/* END OF NEW STOUGH */
+
+#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
+
+static void con_redraw_softback(struct vc_data *vc, /* struct display *p, */
+				long delta)
+{
+	int count = vc->vc_rows;
+	unsigned short *d, *s;
+	unsigned long n;
+	int line = 0;
+
+	/* NEW STOUGH, 2021-04-04 */
+	if (!vc->vc_softback_lines)
+		vc->vc_char_at_pos = scr_readw((u16 *)vc->vc_pos);
+	/* END OF NEW STOUGH */
+
+	d = (u16 *) vc->vc_softback_curr;
+	if (d == (u16 *) vc->vc_softback_in)
+		d = (u16 *) vc->vc_origin;
+	n = vc->vc_softback_curr + delta * vc->vc_size_row;
+	vc->vc_softback_lines -= delta;
+	if (delta < 0) {
+		if (vc->vc_softback_curr < vc->vc_softback_top
+		    && n < vc->vc_softback_buf) {
+			n += vc->vc_softback_end - vc->vc_softback_buf;
+			if (n < vc->vc_softback_top) {
+				vc->vc_softback_lines -=
+				    (vc->vc_softback_top - n) / vc->vc_size_row;
+				n = vc->vc_softback_top;
+			}
+		} else if (vc->vc_softback_curr >= vc->vc_softback_top
+			   && n < vc->vc_softback_top) {
+			vc->vc_softback_lines -=
+			    (vc->vc_softback_top - n) / vc->vc_size_row;
+			n = vc->vc_softback_top;
+		}
+	} else {
+		if (vc->vc_softback_curr > vc->vc_softback_in
+		    && n >= vc->vc_softback_end) {
+			n += vc->vc_softback_buf - vc->vc_softback_end;
+			if (n > vc->vc_softback_in) {
+				n = vc->vc_softback_in;
+				vc->vc_softback_lines = 0;
+			}
+		} else if (vc->vc_softback_curr <= vc->vc_softback_in
+			   && n > vc->vc_softback_in) {
+			n = vc->vc_softback_in;
+			vc->vc_softback_lines = 0;
+		}
+	}
+	if (n == vc->vc_softback_curr)
+		return;
+	vc->vc_softback_curr = n;
+	/* NEW STOUGH, 2021-04-04 */
+	/* If we're not scrolled any more, restore the character to the cursor
+	 * position */
+	if (!vc->vc_softback_lines)
+		scr_writew(vc->vc_char_at_pos, (u16 *)vc->vc_pos);
+	/* END OF NEW STOUGH */
+	s = (u16 *) vc->vc_softback_curr;
+	if (s == (u16 *) vc->vc_softback_in)
+		s = (u16 *) vc->vc_origin;
+	while (count--) {
+		unsigned short *start;
+		unsigned short *le;
+		unsigned short c;
+		int x = 0;
+		unsigned short attr = 1;
+
+		start = s;
+		le = advance_row(s, 1);
+		/* NEW STOUGH, 2021-04-04 */
+		/* Temporarily overwrite the character at the cursor position
+		 * with the one we actually want to see on the screen.  */
+		if (count == vc->vc_rows - vc->vc_y - 1)
+		{
+			c = scr_readw((u16 *)(s + vc->vc_x));
+			scr_writew(c, (u16 *)vc->vc_pos);
+			vc->vc_sw->con_putcs
+				(vc, (u16 *)vc->vc_pos, 1, line, vc->vc_x);
+		}
+		/* END OF NEW STOUGH */
+		do {
+			c = scr_readw(s);
+			if (attr != (c & 0xff00)) {
+				attr = c & 0xff00;
+				if (s > start) {
+					vc->vc_sw->con_putcs(
+						vc, start, s - start,
+						line, x);
+					x += s - start;
+					start = s;
+				}
+			}
+			if (c == scr_readw(d)) {
+				if (s > start) {
+					vc->vc_sw->con_putcs(
+						vc, start, s - start,
+						line, x);
+					x += s - start + 1;
+					start = s + 1;
+				} else {
+					x++;
+					start++;
+				}
+			}
+			s++;
+			d++;
+		} while (s < le);
+		if (s > start)
+			vc->vc_sw->con_putcs(vc, start, s - start, line, x);
+		line++;
+		if (d == (u16 *) vc->vc_softback_end)
+			d = (u16 *) vc->vc_softback_buf;
+		if (d == (u16 *) vc->vc_softback_in)
+			d = (u16 *) vc->vc_origin;
+		if (s == (u16 *) vc->vc_softback_end)
+			s = (u16 *) vc->vc_softback_buf;
+		if (s == (u16 *) vc->vc_softback_in)
+			s = (u16 *) vc->vc_origin;
+	}
+}
+/* END OF NEW STOUGH */
+
+/* NEW STOUGH, 2021-04-01 */
+static inline void con_softback_note(struct vc_data *vc, int t,
+				     int count)
+{
+	unsigned short *p;
+
+	if (vc->vc_num != fg_console)
+		return;
+	p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
+
+	while (count) {
+		scr_memcpyw((u16 *) vc->vc_softback_in, p, vc->vc_size_row);
+		count--;
+		p = advance_row(p, 1);
+		vc->vc_softback_in += vc->vc_size_row;
+		if (vc->vc_softback_in == vc->vc_softback_end)
+			vc->vc_softback_in = vc->vc_softback_buf;
+		if (vc->vc_softback_in == vc->vc_softback_top) {
+			vc->vc_softback_top += vc->vc_size_row;
+			if (vc->vc_softback_top == vc->vc_softback_end)
+				vc->vc_softback_top = vc->vc_softback_buf;
+		}
+	}
+	vc->vc_softback_curr = vc->vc_softback_in;
+}
+
+void concon_scrolldelta(struct vc_data *vc, int lines)
+{
+	/* struct display *disp = &fb_display[fg_console]; */
+	/* int offset, limit, scrollback_old; */
+
+	if (vc->vc_softback_top) {
+		if (vc->vc_num != fg_console)
+			return;
+		if (vc->vc_mode != KD_TEXT || !lines)
+			return;
+#if 0
+		if (logo_shown >= 0) {
+			struct vc_data *conp2 = vc_cons[logo_shown].d;
+
+			if (conp2->vc_top == logo_lines
+			    && conp2->vc_bottom == conp2->vc_rows)
+				conp2->vc_top = 0;
+			if (logo_shown == vc->vc_num) {
+				unsigned long p, q;
+				int i;
+
+				p = vc->vc_softback_in;
+				q = vc->vc_origin +
+				    logo_lines * vc->vc_size_row;
+				for (i = 0; i < logo_lines; i++) {
+					if (p == vc->vc_softback_top)
+						break;
+					if (p == vc->vc_softback_buf)
+						p = vc->vc_softback_end;
+					p -= vc->vc_size_row;
+					q -= vc->vc_size_row;
+					scr_memcpyw((u16 *) q, (u16 *) p,
+						    vc->vc_size_row);
+				}
+				vc->vc_softback_in = vc->vc_softback_curr = p;
+				update_region(vc, vc->vc_origin,
+					      logo_lines * vc->vc_cols);
+			}
+			logo_shown = FBCON_LOGO_CANSHOW;
+		}
+#endif
+		vc->vc_sw->con_cursor(vc, CM_ERASE /* | CM_SOFTBACK */);
+		con_redraw_softback(vc, /* disp, */ lines);
+		/* NEW STOUGH, 2021-04-04 */
+		if (!vc->vc_softback_lines)
+			/* END OF NEW STOUGH */
+			vc->vc_sw->con_cursor(vc, CM_DRAW /* | CM_SOFTBACK */);
+	}
+}
+
+/* END OF NEW STOUGH */
+#endif  /* CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK */
 
 static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
 		enum con_scroll dir, unsigned int nr)
@@ -633,6 +866,12 @@
 		nr = b - t - 1;
 	if (b > vc->vc_rows || t >= b || nr < 1)
 		return;
+	/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (dir == SM_UP && vc->vc_softback_top)
+		con_softback_note (vc, t, nr);
+#endif
+	/* END OF NEW STOUGH */
 	vc_uniscr_scroll(vc, t, b, dir, nr);
 	if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, dir, nr))
 		return;
@@ -648,6 +887,72 @@
 	scr_memsetw(clear, vc->vc_video_erase_char, vc->vc_size_row * nr);
 }
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+static void do_update_region(struct vc_data *vc, unsigned long start, int count)
+{
+	unsigned int xx, yy, offset;
+	u16 *p;
+
+	/* NEW STOUGH, 2021-04-03 */
+	unsigned long origin =
+		(start >= vc->vc_softback_buf && start < vc->vc_softback_end)
+		? start >= vc->vc_softback_curr
+		  ? vc->vc_softback_curr
+		  : vc->vc_softback_curr
+		    - (vc->vc_softback_end - vc->vc_softback_buf)
+		: vc->vc_origin;
+	/* END OF NEW STOUGH */
+	p = (u16 *) start;
+	/* OLD STOUGH, 2021-04-03 */
+	/* if (!vc->vc_sw->con_getxy) { */
+		/* END OF OLD STOUGH */
+		offset = (start - origin) / 2; /* STOUGH, 2021-04-03 */
+		xx = offset % vc->vc_cols;
+		yy = offset / vc->vc_cols;
+		/* OLD STOUGH, 2021-04-03 */
+	/* } else { */
+	/* 	int nxx, nyy; */
+	/* 	start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy); */
+	/* 	xx = nxx; yy = nyy; */
+	/* } */
+		/* END OF OLD STOUGH */
+	for(;;) {
+		u16 attrib = scr_readw(p) & 0xff00;
+		int startx = xx;
+		u16 *q = p;
+		while (xx < vc->vc_cols && count) {
+			if (attrib != (scr_readw(p) & 0xff00)) {
+				if (p > q)
+					vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
+				startx = xx;
+				q = p;
+				attrib = scr_readw(p) & 0xff00;
+			}
+			p++;
+			xx++;
+			count--;
+		}
+		if (p > q)
+			vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
+		/* NEW STOUGH, 2021-04-03 */
+		if (p == (u16 *) vc->vc_softback_end)
+			p = (u16 *)vc->vc_softback_buf;
+		if (p == (u16 *) vc->vc_softback_in)
+			p = (u16 *)vc->vc_origin;
+		/* END OF NEW STOUGH */
+		if (!count)
+			break;
+		xx = 0;
+		yy++;
+		/* OLD STOUGH, 2021-04-03 */
+		/* if (vc->vc_sw->con_getxy) { */
+		/* 	p = (u16 *)start; */
+		/* 	start = vc->vc_sw->con_getxy(vc, start, NULL, NULL); */
+		/* } */
+		/* END OF OLD STOUGH */
+	}
+}
+#else
 static void do_update_region(struct vc_data *vc, unsigned long start, int count)
 {
 	unsigned int xx, yy, offset;
@@ -691,6 +996,7 @@
 		}
 	}
 }
+#endif
 
 void update_region(struct vc_data *vc, unsigned long start, int count)
 {
@@ -699,7 +1005,12 @@
 	if (con_should_update(vc)) {
 		hide_cursor(vc);
 		do_update_region(vc, start, count);
-		set_cursor(vc);
+		/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		if (!vc->vc_softback_lines)
+#endif
+			/* END OF NEW STOUGH */
+			set_cursor(vc);
 	}
 }
 
@@ -751,8 +1062,8 @@
 static void update_attr(struct vc_data *vc)
 {
 	vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity,
-	              vc->vc_blink, vc->vc_underline,
-	              vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
+		      vc->vc_blink, vc->vc_underline,
+		      vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
 	vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
 }
 
@@ -922,8 +1233,19 @@
 	WARN_CONSOLE_UNLOCKED();
 
 	if (!con_is_visible(vc) ||
+	    /* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	    (
+	     !concon_set_origin (vc) &&
+	     (
+#endif
+	    /* END OF NEW STOUGH */
 	    !vc->vc_sw->con_set_origin ||
-	    !vc->vc_sw->con_set_origin(vc))
+	    !vc->vc_sw->con_set_origin(vc)
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		     ))
+#endif
+					  )
 		vc->vc_origin = (unsigned long)vc->vc_screenbuf;
 	vc->vc_visible_origin = vc->vc_origin;
 	vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
@@ -998,7 +1320,9 @@
 		hide_cursor(old_vc);
 		if (!con_is_visible(old_vc)) {
 			save_screen(old_vc);
-			set_origin(old_vc);
+			/* OLD STOUGH, 2021-04-02 */
+			/* set_origin(old_vc); */
+			/* END OF OLD STOUGH */
 		}
 		if (tty0dev)
 			sysfs_notify(&tty0dev->kobj, NULL, "active");
@@ -1011,7 +1335,9 @@
 		int update;
 		int old_was_color = vc->vc_can_do_color;
 
-		set_origin(vc);
+		/* OLD STOUGH, 2021-04-02 */
+		/* set_origin(vc); */
+		/* END OF OLD STOUGH */
 		update = vc->vc_sw->con_switch(vc);
 		set_palette(vc);
 		/*
@@ -1026,9 +1352,25 @@
 		}
 
 		if (update && vc->vc_mode != KD_GRAPHICS)
-			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
-	}
-	set_cursor(vc);
+			/* OLD STOUGH, 2021-04-03 */
+			/* do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2); */
+			/* NEW STOUGH, 2021-04-03 */
+			do_update_region(vc,
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+					 vc->vc_softback_lines
+					 ? vc->vc_softback_curr
+					 :
+#endif
+					   vc->vc_origin,
+					 vc->vc_screenbuf_size / 2);
+			/* END OF NEW STOUGH */
+	}
+	/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		/* END OF NEW STOUGH */
+		set_cursor(vc);
 	if (is_switch) {
 		set_leds();
 		compute_shiftstate();
@@ -1107,12 +1449,32 @@
 	int err;
 
 	WARN_CONSOLE_UNLOCKED();
-
 	if (currcons >= MAX_NR_CONSOLES)
 		return -ENXIO;
 
 	if (vc_cons[currcons].d)
+		/* NEW STOUGH, 2021-04-05 */
+	{
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		vc = vc_cons[currcons].d;
+		if (!vc->vc_softback_size) {
+			/* vc was partially initialized by __init. */
+			vc->vc_softback_size = console_soft_scrollback_size;
+			vc->vc_softback_buf =
+				(unsigned long)kzalloc(vc->vc_softback_size, GFP_KERNEL);
+			if (vc->vc_softback_buf) {
+				vc->vc_softback_in = vc->vc_softback_top =
+					vc->vc_softback_curr = vc->vc_softback_buf;
+				vc->vc_softback_lines = 0;
+				con_update_softback(vc);
+			}
+		}
+#endif
+		/* END OF NEW STOUGH */
 		return 0;
+		/* NEW STOUGH, 2021-04-05 */
+	}
+	/* END OF NEW STOUGH */
 
 	/* due to the granularity of kmalloc, we waste some memory here */
 	/* the alloc is done in two steps, to optimize the common situation
@@ -1152,6 +1514,20 @@
 	vcs_make_sysfs(currcons);
 	atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
 
+	/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	vc->vc_softback_size = console_soft_scrollback_size;
+	err = -ENOMEM;
+	vc->vc_softback_buf =
+		(unsigned long)kzalloc(vc->vc_softback_size, GFP_KERNEL);
+	if (!vc->vc_softback_buf)
+		goto err_free;
+	vc->vc_softback_in = vc->vc_softback_top = vc->vc_softback_curr =
+		vc->vc_softback_buf;
+	vc->vc_softback_lines = 0;
+	con_update_softback(vc);
+#endif
+	/* END OF NEW STOUGH */
 	return 0;
 err_free:
 	visual_deinit(vc);
@@ -1627,7 +2003,7 @@
 
 static void rgb_from_256(int i, struct rgb *c)
 {
-	if (i < 8) {            /* Standard colours. */
+	if (i < 8) {	    /* Standard colours. */
 		c->r = i&1 ? 0xaa : 0x00;
 		c->g = i&2 ? 0xaa : 0x00;
 		c->b = i&4 ? 0xaa : 0x00;
@@ -1639,7 +2015,7 @@
 		c->r = (i - 16) / 36 * 85 / 2;
 		c->g = (i - 16) / 6 % 6 * 85 / 2;
 		c->b = (i - 16) % 6 * 85 / 2;
-	} else                  /* Grayscale ramp. */
+	} else		  /* Grayscale ramp. */
 		c->r = c->g = c->b = i * 10 - 2312;
 }
 
@@ -2629,6 +3005,14 @@
 
 	param.vc = vc;
 
+	/* NEW STOUGH, 2021-04-03 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	/* Undo any soft scrolling - <Alt><Fn> and <Shift><PgUp/Down> do
+	   not pass through this function.  */
+	concon_set_origin (vc);
+#endif
+	/* END OF NEW STOUGH */
+
 	while (!tty->stopped && count) {
 		int orig = *buf;
 		c = orig;
@@ -2722,17 +3106,17 @@
 					&param) == NOTIFY_STOP)
 			continue;
 
-                /* If the original code was a control character we
-                 * only allow a glyph to be displayed if the code is
-                 * not normally used (such as for cursor movement) or
-                 * if the disp_ctrl mode has been explicitly enabled.
-                 * Certain characters (as given by the CTRL_ALWAYS
-                 * bitmap) are always displayed as control characters,
-                 * as the console would be pretty useless without
-                 * them; to display an arbitrary font position use the
-                 * direct-to-font zone in UTF-8 mode.
-                 */
-                ok = tc && (c >= 32 ||
+		/* If the original code was a control character we
+		 * only allow a glyph to be displayed if the code is
+		 * not normally used (such as for cursor movement) or
+		 * if the disp_ctrl mode has been explicitly enabled.
+		 * Certain characters (as given by the CTRL_ALWAYS
+		 * bitmap) are always displayed as control characters,
+		 * as the console would be pretty useless without
+		 * them; to display an arbitrary font position use the
+		 * direct-to-font zone in UTF-8 mode.
+		 */
+		ok = tc && (c >= 32 ||
 			    !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
 				  vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
 			&& (c != 127 || vc->vc_disp_ctrl)
@@ -3018,7 +3402,12 @@
 	}
 	if (cnt && con_is_visible(vc))
 		vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
-	set_cursor(vc);
+	/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		/* END OF NEW STOUGH */
+		set_cursor(vc);
 	notify_update(vc);
 
 quit:
@@ -3246,7 +3635,13 @@
 	/* if we race with con_close(), vt may be null */
 	console_lock();
 	vc = tty->driver_data;
-	if (vc)
+	if (vc
+	    /* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	    && !vc->vc_softback_lines
+#endif
+	    /* END OF NEW STOUGH */
+	      )
 		set_cursor(vc);
 	console_unlock();
 }
@@ -3267,6 +3662,12 @@
 
 	vc = vc_cons[currcons].d;
 
+	/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	con_update_softback(vc);
+#endif
+	/* END OF NEW STOUGH */
+
 	/* Still being freed */
 	if (vc->port.tty) {
 		ret = -ERESTARTSYS;
@@ -3322,7 +3723,7 @@
 	tty_port_put(&vc->port);
 }
 
-static int default_color           = 7; /* white */
+static int default_color	   = 7; /* white */
 static int default_italic_color    = 2; // green (ASCII)
 static int default_underline_color = 3; // cyan (ASCII)
 module_param_named(color, default_color, int, S_IRUGO | S_IWUSR);
@@ -4024,7 +4425,7 @@
 			con_driver->desc = desc;
 			con_driver->node = i;
 			con_driver->flag = CON_DRIVER_FLAG_MODULE |
-			                   CON_DRIVER_FLAG_INIT;
+					   CON_DRIVER_FLAG_INIT;
 			con_driver->first = first;
 			con_driver->last = last;
 			retval = 0;
@@ -4325,7 +4726,12 @@
 	if (console_blank_hook)
 		console_blank_hook(0);
 	set_palette(vc);
-	set_cursor(vc);
+	/* NEW STOUGH, 2021-04-04 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		/* END OF NEW STOUGH */
+		set_cursor(vc);
 	vt_event_post(VT_EVENT_UNBLANK, vc->vc_num, vc->vc_num);
 }
 EXPORT_SYMBOL(do_unblank_screen);
--- include/linux/console_struct.h.orig	2021-04-02 19:55:52.696177657 +0000
+++ include/linux/console_struct.h	2021-04-05 14:39:24.531805027 +0000
@@ -70,6 +70,21 @@
 	unsigned short	*vc_screenbuf;		/* In-memory character/attribute buffer */
 	unsigned int	vc_screenbuf_size;
 	unsigned char	vc_mode;		/* KD_TEXT, ... */
+	/* NEW STOUGH, 2021-03-31 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	unsigned int    vc_softback_size;	/* Size in bytes of scrollback buffer. */
+	unsigned long   vc_softback_buf;	/* Address of scrollback buffer. */
+	unsigned long   vc_softback_end;	/* (Just past) end of buffer. */
+	unsigned long   vc_softback_in;		/* Head pointer into circular buffer. */
+	unsigned long   vc_softback_top;	/* Tail pointer into circular buffer. */
+	unsigned long   vc_softback_curr;	/* Pos in vc_screenbuf or vc_softback_buf
+						   corresponding to visible screen. */
+	int             vc_softback_lines;	/* Number of lines currently scrolled. */
+	/* NEW STOUGH, 2021-04-04 */
+	unsigned short  vc_char_at_pos;		/* Char at vc_pos when no soft scroll */
+	/* END OF NEW STOUGH. */
+#endif
+	/* END OF NEW STOUGH */
 	/* attributes for all characters on screen */
 	unsigned char	vc_attr;		/* Current attributes */
 	unsigned char	vc_def_color;		/* Default colors */
--- drivers/video/fbdev/core/fbcon.c.orig	2021-04-02 19:58:46.332168089 +0000
+++ drivers/video/fbdev/core/fbcon.c	2021-04-05 14:41:32.128812016 +0000
@@ -3115,6 +3115,11 @@
 	.con_font_default	= fbcon_set_def_font,
 	.con_font_copy 		= fbcon_copy_font,
 	.con_set_palette 	= fbcon_set_palette,
+	/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	.con_scrolldelta	= concon_scrolldelta,
+#endif
+	/* END OF NEW STOUGH */
 	.con_set_origin 	= fbcon_set_origin,
 	.con_invert_region 	= fbcon_invert_region,
 	.con_screen_pos 	= fbcon_screen_pos,
--- include/linux/vt_kern.h.orig	2021-04-02 20:01:19.552159645 +0000
+++ include/linux/vt_kern.h	2021-04-01 17:31:45.125471834 +0000
@@ -129,6 +129,11 @@
 /* vt.c */
 void vt_event_post(unsigned int event, unsigned int old, unsigned int new);
 int vt_waitactive(int n);
+/* NEW STOUGH, 2021-04-01 */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+void concon_scrolldelta(struct vc_data *vc, int lines);
+#endif
+/* END OF NEW STOUGH */
 void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
 extern int do_unbind_con_driver(const struct consw *csw, int first, int last,

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-06  9:54       ` Alan Mackenzie
@ 2021-04-06 15:30         ` Michael Jones
  0 siblings, 0 replies; 18+ messages in thread
From: Michael Jones @ 2021-04-06 15:30 UTC (permalink / raw
  To: gentoo-user

[-- Attachment #1: Type: text/plain, Size: 1287 bytes --]

On Tue, Apr 6, 2021 at 4:54 AM Alan Mackenzie <acm@muc.de> wrote:

> Hello, Michael.
>
> On Mon, Apr 05, 2021 at 18:08:58 -0500, Michael Jones wrote:
>
> [ .... ]
>
> > Without looking at the patch itself:
>
> > Have you considered something like kmscon as a userland alternative?
>
> To be honest, no.  I wasn't really aware of it when I starting working on
> the Linux console.
>
> According to Wikipedia, the last release was in 2013, and development
> stopped altogether in 2015.  The Gentoo package for it is masked.
>

Good points, and I can't speak to the code cleanliness of kmscon, or
potential security problems.

That being said, even though I was annoyed when the scrollback was removed
from the kernel, I do understand the reason for it being removed. It does
seem like the kind of functionality that would be better provided by
userspace.


> > I installed it on my laptop, and aside from not working with gpmd or
> > consolation for mouse support, it's a perfectly functional local tty.
>
> I suppose it's one of these programs that once working, pretty much
> carries on working for ever.
>

That's entirely possible :-)
Maybe someone (not necessarily you) will find the removal of the scrollback
buffer to be enough motivation to bring kmscon back to life as a project.

[-- Attachment #2: Type: text/html, Size: 1923 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 17:12 [gentoo-user] Console scrollback is back again! Alan Mackenzie
                   ` (4 preceding siblings ...)
  2021-04-06 12:50 ` J. Roeleveld
@ 2021-04-08 18:16 ` konsolebox
  2021-07-15 19:19 ` Alan Mackenzie
  6 siblings, 0 replies; 18+ messages in thread
From: konsolebox @ 2021-04-08 18:16 UTC (permalink / raw
  To: gentoo-user

On Tue, Apr 6, 2021 at 1:12 AM Alan Mackenzie <acm@muc.de> wrote:
> How to get it working:
> (i) Extract the enclosed patch file to your /usr/src/linux-5.10.27-gentoo
> directory (or probably any 5.10 kernel's).

Works with 5.10.28-gentoo. Thanks again.

I finally can uninstall my 5.8.6 which still has the old scrollback.

-- 
konsolebox


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [gentoo-user] Console scrollback is back again!
  2021-04-05 17:12 [gentoo-user] Console scrollback is back again! Alan Mackenzie
                   ` (5 preceding siblings ...)
  2021-04-08 18:16 ` konsolebox
@ 2021-07-15 19:19 ` Alan Mackenzie
  6 siblings, 0 replies; 18+ messages in thread
From: Alan Mackenzie @ 2021-07-15 19:19 UTC (permalink / raw
  To: gentoo-user

[-- Attachment #1: Type: text/plain, Size: 3295 bytes --]

Hello, Gentoo.

A new kernel, gentoo-sources-5.10.49-r1 has become current.

For those who wish to have console soft scrolling, the patch which worked
with 5.10.27 actually still works in 5.10.49-r1.  But I've tidied that
patch up somewhat for 5.10.49-r1 and have attached the patch file to this
post.

The instructions for using it are basically unchanged, apart from file
names, etc.  Updating those instructions gives us:
(i) Extract the attached patch file to your
  /usr/src/linux-5.10.49-gentoo-r1 directory (or probably any 5.10
  kernel's).
(ii) From that directory run $ patch -p0 < 5.10.49-scroll.20210715.diff.
(iii)(a) If you've already got a working 5.10.49-r1, do a $ make oldconfig.
  That should bring up the new configuration items, for which you can
  accept the defaults.  These two items are a flag to enable the
  scrollback, and a buffer size defaulting to 128kB.
(iii)(b) If you haven't yet got a 5.10.49-r1, just configure your kernel
  in the usual way.  The two new items are under Device Drivers/Graphics
  support/Console display driver support.
(iv) Build the kernel.
(v) Put the new kernel into your usual boot manager.
(vi) Reboot and enjoy!

As before, it works for me, and there's nothing malicious in it, but if
it breaks for you, I'm sorry but I won't be responsible.

-- 
Alan Mackenzie (Nuremberg, Germany).



On Mon, Apr 05, 2021 at 17:12:07 +0000, Alan Mackenzie wrote:
> Hello, Gentoo.

> Yes, console soft scrolling is back!  That essential feature that was
> stripped out of the kernel at around 5.4.x has returned!

> Only this time, it's even better!  Instead of one scrollback buffer
> shared between all tty's, there's now a buffer for each tty.

> How to get it working:
> (i) Extract the enclosed patch file to your /usr/src/linux-5.10.27-gentoo
> directory (or probably any 5.10 kernel's).
> (ii) From that directory run $ patch -p0 < diff.20210405.diff.
> (iii)(a) If you've already got a working 5.10.27, do a $ make oldconfig.
>   That should bring up the new configuration items, for which you can
>   accept the defaults.  These two items are a flag to enable the
>   scrollback, and a buffer size defaulting to 128kB.
> (iii)(b) If you haven't yet got a 5.10.27, just configure your kernel in
>   the usual way.  The two new items are under Device Drivers/Graphics
>   support/Console display driver support.
> (iv) Build the kernel.
> (v) Put the new kernel into your usual boot manager.
> (vi) Reboot and enjoy!

> Admittedly, the exercise isn't quite finished - the patched source files
> still have my personal change markings in them, to make debugging easier.
> But the problems I reported here a few days ago are now solved.  One or
> two features haven't (yet) been implemented - having a single scroll
> buffer shared amongst all tty's isn't there, and there're no kernel
> command line parameters to control the feature.

> Also, you may wonder about how safe the patch is.  All I can say is that
> there is nothing malicious in it, and I am known on this list, but of
> course if it breaks I won't be to blame.

> Bug reports and other comments are welcome, of course.

> If anybody would like the corresponding patch which works on 5.4.n, for n
> >= 80, that is available, too.

> -- 
> Alan Mackenzie (Nuremberg, Germany).




[-- Attachment #2: 5.10.49-scroll.20210715.diff --]
[-- Type: text/plain, Size: 19113 bytes --]

--- ./include/linux/vt_kern.h.orig	2020-12-13 22:41:30.000000000 +0000
+++ ./include/linux/vt_kern.h	2021-04-05 15:22:28.445755234 +0000
@@ -127,6 +127,9 @@
 /* vt.c */
 void vt_event_post(unsigned int event, unsigned int old, unsigned int new);
 int vt_waitactive(int n);
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+void concon_scrolldelta(struct vc_data *vc, int lines);
+#endif
 void change_console(struct vc_data *new_vc);
 void reset_vc(struct vc_data *vc);
 int do_unbind_con_driver(const struct consw *csw, int first, int last,
--- ./include/linux/console_struct.h.orig	2020-12-13 22:41:30.000000000 +0000
+++ ./include/linux/console_struct.h	2021-04-05 15:22:28.432755234 +0000
@@ -109,6 +109,17 @@
 	unsigned short	*vc_screenbuf;		/* In-memory character/attribute buffer */
 	unsigned int	vc_screenbuf_size;
 	unsigned char	vc_mode;		/* KD_TEXT, ... */
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	unsigned int    vc_softback_size;	/* Size in bytes of scrollback buffer. */
+	unsigned long   vc_softback_buf;	/* Address of scrollback buffer. */
+	unsigned long   vc_softback_end;	/* (Just past) end of buffer. */
+	unsigned long   vc_softback_in;		/* Head pointer into circular buffer. */
+	unsigned long   vc_softback_top;	/* Tail pointer into circular buffer. */
+	unsigned long   vc_softback_curr;	/* Pos in vc_screenbuf or vc_softback_buf
+						   corresponding to visible screen. */
+	int             vc_softback_lines;	/* Number of lines currently scrolled. */
+	unsigned short  vc_char_at_pos;		/* Char at vc_pos when no soft scroll */
+#endif
 	/* attributes for all characters on screen */
 	unsigned char	vc_attr;		/* Current attributes */
 	unsigned char	vc_def_color;		/* Default colors */
--- ./drivers/video/fbdev/core/fbcon.c.orig	2021-04-05 15:22:28.434755234 +0000
+++ ./drivers/video/fbdev/core/fbcon.c	2021-04-05 15:56:00.836644342 +0000
@@ -3084,6 +3084,9 @@
 	.con_font_default	= fbcon_set_def_font,
 	.con_font_copy 		= fbcon_copy_font,
 	.con_set_palette 	= fbcon_set_palette,
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	.con_scrolldelta	= concon_scrolldelta,
+#endif
 	.con_invert_region 	= fbcon_invert_region,
 	.con_screen_pos 	= fbcon_screen_pos,
 	.con_getxy 		= fbcon_getxy,
--- ./drivers/video/console/Kconfig.orig	2020-12-13 22:41:30.000000000 +0000
+++ ./drivers/video/console/Kconfig	2021-04-05 15:22:28.414755235 +0000
@@ -78,6 +78,55 @@
 	help
 	  Low-level framebuffer-based console driver.
 
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	bool "Enable Scrollback Buffer in System RAM"
+	depends on FB=y && FRAMEBUFFER_CONSOLE
+	default y
+	select FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+	help
+	  This option creates scrollback buffers for each framebuffer console,
+	  or one buffer for them all.  These buffers are allocated dynamically
+	  during initialisation.
+
+	  If you want this feature, say 'Y' here and enter the amount of
+	  RAM to allocate for this buffer.  If unsure, say 'N'.
+
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_SIZE
+       int "Scrollback Buffer Size (in KB)"
+       depends on FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+       range 1 1024
+       default "128"
+       help
+       	  Enter the amount of System RAM to allocate for each scrollback
+	  buffer of framebuffer consoles in kilobytes.  Each character
+	  position on the video takes 2 bytes of storage.  128k will give you
+	  approximately 4 240x67 screenfuls of scrollback buffer.
+
+config FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_PERSISTENT_ENABLE_BY_DEFAULT
+	bool "Persistent Scrollback History for each framebuffer console by default"
+	depends on FB=y && FRAMEBUFFER_CONSOLE && FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	default y
+	help
+
+	  Note: this option's value N has not (?yet) been implemented (2021-04).
+
+	  Say Y here if the scrollback history should persist by default when
+	  switching between consoles. Otherwise, the scrollback history will
+	  be flushed the first time a scroll-up operation occurs on the new
+	  console after the console is switched. STOUGH!!!  FIXME!!! This
+	  feature can also be enabled using the boot command line parameter
+	  'vgacon.scrollback_persistent=1'.
+
+	  This feature might break your tool of choice to flush the scrollback
+	  buffer, e.g. clear(1) will work fine but Debian's clear_console(1)
+	  will be broken, which might cause security issues.
+	  You can use the escape sequence \e[3J instead if this feature is
+	  activated.
+
+	  Note that a buffer of VGACON_SOFT_SCROLLBACK_SIZE is taken for each
+	  created tty device.
+	  So if you use a RAM-constrained system, say N here.
+
 config FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
        bool "Map the console to the primary display device"
        depends on FRAMEBUFFER_CONSOLE
--- ./drivers/tty/vt/vt.c.orig	2020-12-13 22:41:30.000000000 +0000
+++ ./drivers/tty/vt/vt.c	2021-04-05 16:20:32.624563241 +0000
@@ -134,6 +134,11 @@
 #define DEFAULT_BELL_DURATION	(HZ/8)
 #define DEFAULT_CURSOR_BLINK_MS	200
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+static unsigned int console_soft_scrollback_size =
+	1024 * CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK_SIZE;
+#endif
+
 struct vc vc_cons [MAX_NR_CONSOLES];
 
 #ifndef VT_SINGLE_DRIVER
@@ -287,7 +294,7 @@
 		bool viewed)
 {
 	unsigned short *p;
-	
+
 	if (!viewed)
 		p = (unsigned short *)(vc->vc_origin + offset);
 	else if (!vc->vc_sw->con_screen_pos)
@@ -616,6 +623,218 @@
 	}
 }
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+static void con_update_softback(struct vc_data *vc)
+{
+	int l = vc->vc_softback_size / vc->vc_size_row;
+	if (l > 5)
+	{
+		vc->vc_softback_end = vc->vc_softback_buf + l * vc->vc_size_row;
+		vc->vc_softback_top = vc->vc_softback_buf;
+	}
+	else
+		/* Smaller scrollback makes no sense, and 0 would screw
+		   the operation totally */
+		vc->vc_softback_top = 0;
+}
+
+static int concon_set_origin(struct vc_data *vc)
+{
+	if (vc->vc_softback_lines)
+		concon_scrolldelta(vc, vc->vc_softback_lines);
+	return 0;
+}
+
+#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
+
+static void con_redraw_softback(struct vc_data *vc, /* struct display *p, */
+				long delta)
+{
+	int count = vc->vc_rows;
+	unsigned short *d, *s;
+	unsigned long n;
+	int line = 0;
+
+	if (!vc->vc_softback_lines)
+		vc->vc_char_at_pos = scr_readw((u16 *)vc->vc_pos);
+
+	d = (u16 *) vc->vc_softback_curr;
+	if (d == (u16 *) vc->vc_softback_in)
+		d = (u16 *) vc->vc_origin;
+	n = vc->vc_softback_curr + delta * vc->vc_size_row;
+	vc->vc_softback_lines -= delta;
+	if (delta < 0) {
+		if (vc->vc_softback_curr < vc->vc_softback_top
+		    && n < vc->vc_softback_buf) {
+			n += vc->vc_softback_end - vc->vc_softback_buf;
+			if (n < vc->vc_softback_top) {
+				vc->vc_softback_lines -=
+				    (vc->vc_softback_top - n) / vc->vc_size_row;
+				n = vc->vc_softback_top;
+			}
+		} else if (vc->vc_softback_curr >= vc->vc_softback_top
+			   && n < vc->vc_softback_top) {
+			vc->vc_softback_lines -=
+			    (vc->vc_softback_top - n) / vc->vc_size_row;
+			n = vc->vc_softback_top;
+		}
+	} else {
+		if (vc->vc_softback_curr > vc->vc_softback_in
+		    && n >= vc->vc_softback_end) {
+			n += vc->vc_softback_buf - vc->vc_softback_end;
+			if (n > vc->vc_softback_in) {
+				n = vc->vc_softback_in;
+				vc->vc_softback_lines = 0;
+			}
+		} else if (vc->vc_softback_curr <= vc->vc_softback_in
+			   && n > vc->vc_softback_in) {
+			n = vc->vc_softback_in;
+			vc->vc_softback_lines = 0;
+		}
+	}
+	if (n == vc->vc_softback_curr)
+		return;
+	vc->vc_softback_curr = n;
+	/* If we're not scrolled any more, restore the character to the cursor
+	 * position */
+	if (!vc->vc_softback_lines)
+		scr_writew(vc->vc_char_at_pos, (u16 *)vc->vc_pos);
+	s = (u16 *) vc->vc_softback_curr;
+	if (s == (u16 *) vc->vc_softback_in)
+		s = (u16 *) vc->vc_origin;
+	while (count--) {
+		unsigned short *start;
+		unsigned short *le;
+		unsigned short c;
+		int x = 0;
+		unsigned short attr = 1;
+
+		start = s;
+		le = advance_row(s, 1);
+		/* Temporarily overwrite the character at the cursor position
+		 * with the one we actually want to see on the screen.  */
+		if (count == vc->vc_rows - vc->state.y - 1)
+		{
+			c = scr_readw((u16 *)(s + vc->state.x));
+			scr_writew(c, (u16 *)vc->vc_pos);
+			vc->vc_sw->con_putcs
+				(vc, (u16 *)vc->vc_pos, 1, line, vc->state.x);
+		}
+		do {
+			c = scr_readw(s);
+			if (attr != (c & 0xff00)) {
+				attr = c & 0xff00;
+				if (s > start) {
+					vc->vc_sw->con_putcs(
+						vc, start, s - start,
+						line, x);
+					x += s - start;
+					start = s;
+				}
+			}
+			if (c == scr_readw(d)) {
+				if (s > start) {
+					vc->vc_sw->con_putcs(
+						vc, start, s - start,
+						line, x);
+					x += s - start + 1;
+					start = s + 1;
+				} else {
+					x++;
+					start++;
+				}
+			}
+			s++;
+			d++;
+		} while (s < le);
+		if (s > start)
+			vc->vc_sw->con_putcs(vc, start, s - start, line, x);
+		line++;
+		if (d == (u16 *) vc->vc_softback_end)
+			d = (u16 *) vc->vc_softback_buf;
+		if (d == (u16 *) vc->vc_softback_in)
+			d = (u16 *) vc->vc_origin;
+		if (s == (u16 *) vc->vc_softback_end)
+			s = (u16 *) vc->vc_softback_buf;
+		if (s == (u16 *) vc->vc_softback_in)
+			s = (u16 *) vc->vc_origin;
+	}
+}
+
+static inline void con_softback_note(struct vc_data *vc, int t,
+				     int count)
+{
+	unsigned short *p;
+
+	if (vc->vc_num != fg_console)
+		return;
+	p = (unsigned short *) (vc->vc_origin + t * vc->vc_size_row);
+
+	while (count) {
+		scr_memcpyw((u16 *) vc->vc_softback_in, p, vc->vc_size_row);
+		count--;
+		p = advance_row(p, 1);
+		vc->vc_softback_in += vc->vc_size_row;
+		if (vc->vc_softback_in == vc->vc_softback_end)
+			vc->vc_softback_in = vc->vc_softback_buf;
+		if (vc->vc_softback_in == vc->vc_softback_top) {
+			vc->vc_softback_top += vc->vc_size_row;
+			if (vc->vc_softback_top == vc->vc_softback_end)
+				vc->vc_softback_top = vc->vc_softback_buf;
+		}
+	}
+	vc->vc_softback_curr = vc->vc_softback_in;
+}
+
+void concon_scrolldelta(struct vc_data *vc, int lines)
+{
+	/* struct display *disp = &fb_display[fg_console]; */
+	/* int offset, limit, scrollback_old; */
+
+	if (vc->vc_softback_top) {
+		if (vc->vc_num != fg_console)
+			return;
+		if (vc->vc_mode != KD_TEXT || !lines)
+			return;
+#if 0
+		if (logo_shown >= 0) {
+			struct vc_data *conp2 = vc_cons[logo_shown].d;
+
+			if (conp2->vc_top == logo_lines
+			    && conp2->vc_bottom == conp2->vc_rows)
+				conp2->vc_top = 0;
+			if (logo_shown == vc->vc_num) {
+				unsigned long p, q;
+				int i;
+
+				p = vc->vc_softback_in;
+				q = vc->vc_origin +
+				    logo_lines * vc->vc_size_row;
+				for (i = 0; i < logo_lines; i++) {
+					if (p == vc->vc_softback_top)
+						break;
+					if (p == vc->vc_softback_buf)
+						p = vc->vc_softback_end;
+					p -= vc->vc_size_row;
+					q -= vc->vc_size_row;
+					scr_memcpyw((u16 *) q, (u16 *) p,
+						    vc->vc_size_row);
+				}
+				vc->vc_softback_in = vc->vc_softback_curr = p;
+				update_region(vc, vc->vc_origin,
+					      logo_lines * vc->vc_cols);
+			}
+			logo_shown = FBCON_LOGO_CANSHOW;
+		}
+#endif
+		vc->vc_sw->con_cursor(vc, CM_ERASE /* | CM_SOFTBACK */);
+		con_redraw_softback(vc, /* disp, */ lines);
+		if (!vc->vc_softback_lines)
+			vc->vc_sw->con_cursor(vc, CM_DRAW /* | CM_SOFTBACK */);
+	}
+}
+
+#endif  /* CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK */
 
 static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
 		enum con_scroll dir, unsigned int nr)
@@ -626,6 +859,10 @@
 		nr = b - t - 1;
 	if (b > vc->vc_rows || t >= b || nr < 1)
 		return;
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (dir == SM_UP && vc->vc_softback_top)
+		con_softback_note (vc, t, nr);
+#endif
 	vc_uniscr_scroll(vc, t, b, dir, nr);
 	if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, dir, nr))
 		return;
@@ -641,6 +880,56 @@
 	scr_memsetw(clear, vc->vc_video_erase_char, vc->vc_size_row * nr);
 }
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+static void do_update_region(struct vc_data *vc, unsigned long start, int count)
+{
+	unsigned int xx, yy, offset;
+	u16 *p;
+
+	unsigned long origin =
+		(start >= vc->vc_softback_buf && start < vc->vc_softback_end)
+		? start >= vc->vc_softback_curr
+		  ? vc->vc_softback_curr
+		  : vc->vc_softback_curr
+		    - (vc->vc_softback_end - vc->vc_softback_buf)
+		: vc->vc_origin;
+	p = (u16 *) start;
+		offset = (start - origin) / 2;
+		xx = offset % vc->vc_cols;
+		yy = offset / vc->vc_cols;
+	for(;;) {
+		u16 attrib = scr_readw(p) & 0xff00;
+		int startx = xx;
+		u16 *q = p;
+		while (xx < vc->vc_cols && count) {
+			if (attrib != (scr_readw(p) & 0xff00)) {
+				if (p > q)
+					vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
+				startx = xx;
+				q = p;
+				attrib = scr_readw(p) & 0xff00;
+			}
+			p++;
+			xx++;
+			count--;
+		}
+		if (p > q)
+			vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
+		if (p == (u16 *) vc->vc_softback_end)
+			p = (u16 *)vc->vc_softback_buf;
+		if (p == (u16 *) vc->vc_softback_in)
+			p = (u16 *)vc->vc_origin;
+		if (!count)
+			break;
+		xx = 0;
+		yy++;
+		/* if (vc->vc_sw->con_getxy) { */
+		/* 	p = (u16 *)start; */
+		/* 	start = vc->vc_sw->con_getxy(vc, start, NULL, NULL); */
+		/* } */
+	}
+}
+#else
 static void do_update_region(struct vc_data *vc, unsigned long start, int count)
 {
 	unsigned int xx, yy, offset;
@@ -684,6 +989,7 @@
 		}
 	}
 }
+#endif
 
 void update_region(struct vc_data *vc, unsigned long start, int count)
 {
@@ -692,7 +998,10 @@
 	if (con_should_update(vc)) {
 		hide_cursor(vc);
 		do_update_region(vc, start, count);
-		set_cursor(vc);
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		if (!vc->vc_softback_lines)
+#endif
+			set_cursor(vc);
 	}
 }
 
@@ -927,8 +1238,17 @@
 	WARN_CONSOLE_UNLOCKED();
 
 	if (!con_is_visible(vc) ||
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	    (
+	     !concon_set_origin (vc) &&
+	     (
+#endif
 	    !vc->vc_sw->con_set_origin ||
-	    !vc->vc_sw->con_set_origin(vc))
+	    !vc->vc_sw->con_set_origin(vc)
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		     ))
+#endif
+					  )
 		vc->vc_origin = (unsigned long)vc->vc_screenbuf;
 	vc->vc_visible_origin = vc->vc_origin;
 	vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
@@ -1004,7 +1326,6 @@
 		hide_cursor(old_vc);
 		if (!con_is_visible(old_vc)) {
 			save_screen(old_vc);
-			set_origin(old_vc);
 		}
 		if (tty0dev)
 			sysfs_notify(&tty0dev->kobj, NULL, "active");
@@ -1017,7 +1341,6 @@
 		int update;
 		int old_was_color = vc->vc_can_do_color;
 
-		set_origin(vc);
 		update = vc->vc_sw->con_switch(vc);
 		set_palette(vc);
 		/*
@@ -1032,9 +1358,19 @@
 		}
 
 		if (update && vc->vc_mode != KD_GRAPHICS)
-			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
-	}
-	set_cursor(vc);
+			do_update_region(vc,
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+					 vc->vc_softback_lines
+					 ? vc->vc_softback_curr
+					 :
+#endif
+					   vc->vc_origin,
+					 vc->vc_screenbuf_size / 2);
+	}
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		set_cursor(vc);
 	if (is_switch) {
 		set_leds();
 		compute_shiftstate();
@@ -1113,12 +1455,28 @@
 	int err;
 
 	WARN_CONSOLE_UNLOCKED();
-
 	if (currcons >= MAX_NR_CONSOLES)
 		return -ENXIO;
 
 	if (vc_cons[currcons].d)
+	{
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+		vc = vc_cons[currcons].d;
+		if (!vc->vc_softback_size) {
+			/* vc was partially initialized by __init. */
+			vc->vc_softback_size = console_soft_scrollback_size;
+			vc->vc_softback_buf =
+				(unsigned long)kzalloc(vc->vc_softback_size, GFP_KERNEL);
+			if (vc->vc_softback_buf) {
+				vc->vc_softback_in = vc->vc_softback_top =
+					vc->vc_softback_curr = vc->vc_softback_buf;
+				vc->vc_softback_lines = 0;
+				con_update_softback(vc);
+			}
+		}
+#endif
 		return 0;
+	}
 
 	/* due to the granularity of kmalloc, we waste some memory here */
 	/* the alloc is done in two steps, to optimize the common situation
@@ -1158,6 +1520,18 @@
 	vcs_make_sysfs(currcons);
 	atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	vc->vc_softback_size = console_soft_scrollback_size;
+	err = -ENOMEM;
+	vc->vc_softback_buf =
+		(unsigned long)kzalloc(vc->vc_softback_size, GFP_KERNEL);
+	if (!vc->vc_softback_buf)
+		goto err_free;
+	vc->vc_softback_in = vc->vc_softback_top = vc->vc_softback_curr =
+		vc->vc_softback_buf;
+	vc->vc_softback_lines = 0;
+	con_update_softback(vc);
+#endif
 	return 0;
 err_free:
 	visual_deinit(vc);
@@ -1629,7 +2005,7 @@
 
 static void rgb_from_256(int i, struct rgb *c)
 {
-	if (i < 8) {            /* Standard colours. */
+	if (i < 8) {	    /* Standard colours. */
 		c->r = i&1 ? 0xaa : 0x00;
 		c->g = i&2 ? 0xaa : 0x00;
 		c->b = i&4 ? 0xaa : 0x00;
@@ -1641,7 +2017,7 @@
 		c->r = (i - 16) / 36 * 85 / 2;
 		c->g = (i - 16) / 6 % 6 * 85 / 2;
 		c->b = (i - 16) % 6 * 85 / 2;
-	} else                  /* Grayscale ramp. */
+	} else		  /* Grayscale ramp. */
 		c->r = c->g = c->b = i * 10 - 2312;
 }
 
@@ -2888,6 +3264,12 @@
 
 	param.vc = vc;
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	/* Undo any soft scrolling - <Alt><Fn> and <Shift><PgUp/Down> do
+	   not pass through this function.  */
+	concon_set_origin (vc);
+#endif
+
 	while (!tty->stopped && count) {
 		int orig = *buf;
 		buf++;
@@ -3103,7 +3487,11 @@
 	}
 	if (cnt && con_is_visible(vc))
 		vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x);
-	set_cursor(vc);
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		set_cursor(vc);
+
 	notify_update(vc);
 
 quit:
@@ -3331,7 +3724,11 @@
 	/* if we race with con_close(), vt may be null */
 	console_lock();
 	vc = tty->driver_data;
-	if (vc)
+	if (vc
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	    && !vc->vc_softback_lines
+#endif
+	      )
 		set_cursor(vc);
 	console_unlock();
 }
@@ -3352,6 +3751,10 @@
 
 	vc = vc_cons[currcons].d;
 
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	con_update_softback(vc);
+#endif
+
 	/* Still being freed */
 	if (vc->port.tty) {
 		ret = -ERESTARTSYS;
@@ -3407,7 +3812,7 @@
 	tty_port_put(&vc->port);
 }
 
-static int default_color           = 7; /* white */
+static int default_color	   = 7; /* white */
 static int default_italic_color    = 2; // green (ASCII)
 static int default_underline_color = 3; // cyan (ASCII)
 module_param_named(color, default_color, int, S_IRUGO | S_IWUSR);
@@ -4108,7 +4513,7 @@
 			con_driver->desc = desc;
 			con_driver->node = i;
 			con_driver->flag = CON_DRIVER_FLAG_MODULE |
-			                   CON_DRIVER_FLAG_INIT;
+					   CON_DRIVER_FLAG_INIT;
 			con_driver->first = first;
 			con_driver->last = last;
 			retval = 0;
@@ -4409,7 +4814,10 @@
 	if (console_blank_hook)
 		console_blank_hook(0);
 	set_palette(vc);
-	set_cursor(vc);
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_SOFT_SCROLLBACK
+	if (!vc->vc_softback_lines)
+#endif
+		set_cursor(vc);
 	vt_event_post(VT_EVENT_UNBLANK, vc->vc_num, vc->vc_num);
 }
 EXPORT_SYMBOL(do_unblank_screen);

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2021-07-15 19:19 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-04-05 17:12 [gentoo-user] Console scrollback is back again! Alan Mackenzie
2021-04-05 17:44 ` antlists
2021-04-05 18:13   ` Alan Mackenzie
2021-04-05 23:08     ` Michael Jones
2021-04-06  9:54       ` Alan Mackenzie
2021-04-06 15:30         ` Michael Jones
2021-04-06 13:14     ` Peter Humphrey
2021-04-06 14:13       ` John Covici
2021-04-06 14:32         ` Alan Mackenzie
2021-04-05 18:38 ` Jorge Almeida
2021-04-06  9:55   ` Alan Mackenzie
2021-04-06 10:36     ` Jorge Almeida
2021-04-05 19:58 ` karl
2021-04-06 11:04   ` Alan Mackenzie
2021-04-06  0:10 ` konsolebox
2021-04-06 12:50 ` J. Roeleveld
2021-04-08 18:16 ` konsolebox
2021-07-15 19:19 ` Alan Mackenzie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox