--- 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, ¶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); @@ -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 - and 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 @@ ¶m) == 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,