From: Alan Mackenzie <acm@muc.de>
To: gentoo-user@lists.gentoo.org
Subject: Re: [gentoo-user] Console scrollback
Date: Fri, 2 Apr 2021 20:49:34 +0000 [thread overview]
Message-ID: <YGeDXlb6eSgb7IW1@ACM> (raw)
In-Reply-To: <20210402193204.749098246B59@turkos.aspodata.se>
[-- Attachment #1: Type: text/plain, Size: 2376 bytes --]
Hello, Karl.
Thanks for the reply.
On Fri, Apr 02, 2021 at 21:32:04 +0200, karl@aspodata.se wrote:
> Alan Mackenzie:
> ...
> > I've now cobbled together a working console scroll on Linux
> > 5.4.80-gentoo-r1. In the end, I reused much of the old machinery which
> > was still present in 4.19.97. Once I've tidied it up, I hope that the
> > resulting patch file will apply cleanly also to later versions than
> > 5.4.80-r1.
> ...
> Nice, where is the patch so I can try ?
I've attached a patch to this post. To apply it, the following seems to
work from the top directory of a kernel source tree, e.g. 5.4.80-r1:
$ patch -p0 < diff.20210402.diff
.. Then you'll need to run make menuconfig (or whatever), going down to
Device Drivers/Graphic support/Console display driver support and there
accepting the defaults for the new config variables. (This is assuming
you've got FRAMEBUFFER support enabled in a neighbouring page.)
Then build the kernel as normal, and put the new version into whatever
boot loader you use. It should (??) run, with a scrollback buffer on
each virtual terminal.
Just a word about the current state of the source - it is rough, with
things unfinished. The "word" STOUGH (pronounced "stuff") is just a
word I use which appears nowhere else and enables me to find changes
quickly and unambiguously.
As I said, I'm not finished with the changes, and swapping from and back
to a scrolled tty isn't completely satisfactory. Nevertheless, I hope
it works for you and you have fun with it.
> > (i) The scrolling doesn't work on /dev/tty1 aka the console.
> > (ii) When, e.g., /dev/tty6 has been scrolled upwards a bit, and then
> > <Alt><F2> pressed to go to /dev/tty2, on returning to /dev/tty6, the
> > scrolling has been cancelled and the cursor is no longer visible.
> > However, the scrollback buffer is still present.
> >
> > I think I'm fairly likely to be able to solve (ii). However, (i), the
> > problem with /dev/tty1, has me baffled. I don't know where to start
> > looking for the problem. If anybody with some kernel knowledge could
> > make any suggestions, I'd be very grateful.
> What happens if you set /dev/console to be /dev/ttyS0, i.e. make sure
> that tty1 is the only one using the first virtual console.
I will try than. Thanks!
> Regards,
> /Karl Hammar
--
Alan Mackenzie (Nuremberg, Germany).
[-- Attachment #2: diff.20210402.diff --]
[-- Type: text/plain, Size: 15009 bytes --]
--- drivers/video/console/Kconfig.orig 2021-03-31 19:14:48.186140856 +0000
+++ drivers/video/console/Kconfig 2021-03-31 12:39:08.090301096 +0000
@@ -79,6 +79,52 @@
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
+ 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 scrollback buffers of
+ framebuffer consoles. 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
+
+ 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-02 15:28:53.094607272 +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
@@ -623,6 +630,205 @@
}
}
+/* 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;
+ 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;
+
+ 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;
+ 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);
+ 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);
+ 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 +839,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;
@@ -900,6 +1112,10 @@
clear_selection();
vc->vc_sw->con_cursor(vc, CM_ERASE);
+ /* NEW STOUGH, 2021-04-01 */
+ /* if (vc->vc_softback_lines) */
+ /* concon_set_origin (vc); */
+ /* END OF NEW STOUGH */
hide_softcursor(vc);
}
@@ -912,7 +1128,15 @@
clear_selection();
add_softcursor(vc);
if ((vc->vc_cursor_type & 0x0f) != 1)
- vc->vc_sw->con_cursor(vc, CM_DRAW);
+ /* NEW STOUGH, 2021-04-01 */
+ {
+ /* if (vc->vc_softback_lines) */
+ /* concon_set_origin (vc); */
+ /* END OF NEW STOUGH */
+ vc->vc_sw->con_cursor(vc, CM_DRAW);
+ /* NEW STOUGH, 2021-04-01 */
+ }
+ /* END OF NEW STOUGH */
} else
hide_cursor(vc);
}
@@ -922,8 +1146,19 @@
WARN_CONSOLE_UNLOCKED();
if (!con_is_visible(vc) ||
- !vc->vc_sw->con_set_origin ||
- !vc->vc_sw->con_set_origin(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)
+#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 +1233,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 +1248,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);
/*
@@ -1152,6 +1391,20 @@
vcs_make_sysfs(currcons);
atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m);
+ /* 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);
--- include/linux/console_struct.h.orig 2021-04-02 19:55:52.696177657 +0000
+++ include/linux/console_struct.h 2021-04-02 14:30:20.792800814 +0000
@@ -70,6 +70,18 @@
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. */
+#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-02 00:11:10.090444550 +0000
@@ -1337,6 +1337,11 @@
else
fbcon_add_cursor_timer(info);
+ /* NEW STOUGH, 2021-04-01 */
+ if (vc->vc_softback_lines)
+ mode = CM_ERASE;
+ /* END OF NEW STOUGH */
+
ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
ops->cursor(vc, info, mode, get_color(vc, info, c, 1),
@@ -3115,6 +3120,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,
prev parent reply other threads:[~2021-04-02 20:49 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-13 10:30 [gentoo-user] Console scrollback Peter Humphrey
2021-01-13 10:38 ` Michael
2021-01-13 10:55 ` Peter Humphrey
2021-01-13 11:21 ` Andreas Fink
2021-01-13 11:46 ` Peter Humphrey
2021-01-13 18:14 ` Alan Mackenzie
2021-01-13 18:44 ` Neil Bothwick
2021-01-14 16:00 ` Alan Mackenzie
2021-01-13 19:14 ` Peter Humphrey
2021-01-13 19:32 ` Grant Taylor
2021-01-13 21:56 ` Alan Mackenzie
2021-01-13 22:14 ` Grant Taylor
2021-01-14 16:39 ` karl
2021-01-13 22:15 ` [gentoo-user] " Grant Edwards
2021-01-13 23:01 ` Neil Bothwick
2021-01-13 23:06 ` Grant Edwards
2021-01-14 0:00 ` Grant Taylor
2021-01-14 1:25 ` Grant Edwards
2021-01-14 17:10 ` Grant Taylor
2021-01-14 0:12 ` Neil Bothwick
2021-01-14 16:06 ` Alan Mackenzie
2021-01-16 12:01 ` Alan Mackenzie
2021-01-17 5:17 ` [gentoo-user] " Thomas Mueller
[not found] ` <20210117051748.E3239E0869@pigeon.gentoo.org>
2021-01-17 9:16 ` Philip Webb
[not found] ` <20210117051748.B8178E0863@pigeon.gentoo.org>
2021-01-19 17:09 ` Laurence Perkins
2021-01-20 19:59 ` Alan Mackenzie
2021-01-21 9:32 ` Wols Lists
2021-01-21 8:58 ` Jorge Almeida
2021-01-21 12:40 ` Remco Rijnders
2021-01-21 13:00 ` Jorge Almeida
2021-01-25 12:42 ` Alan Mackenzie
2021-04-02 18:30 ` Alan Mackenzie
2021-04-02 19:32 ` karl
2021-04-02 20:49 ` Alan Mackenzie [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YGeDXlb6eSgb7IW1@ACM \
--to=acm@muc.de \
--cc=gentoo-user@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox