Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

vgacon: unconfuse vc_origin when using soft scrollback

When CONFIG_VGACON_SOFT_SCROLLBACK is selected, the VGA display memory
index and vc_visible_origin don't change when scrollback is activated.
The actual screen content is saved away and the scrollbackdata is copied
over it. However the vt code, and /dev/vcs devices in particular, still
expect vc_origin to always point at the actual screen content not the
displayed scrollback content.

So adjust vc_origin to point at the saved screen content when scrollback
is active and set it back to vc_visible_origin when restoring the screen.

This fixes /dev/vcsa<n> that return scrollback content when they
shouldn't (onli /dev/vcsa without a number should), and also fixes
/dev/vcsu that should return scrollback content when scrollback is
active but currently doesn't.

An unnecessary call to vga_set_mem_top() is also removed.

Signed-off-by: Nicolas Pitre <nico@linaro.org>
Cc: stable@vger.kernel.org # v4.19+
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Nicolas Pitre and committed by
Greg Kroah-Hartman
bfd8d8fe 0c9b1965

+4 -3
+4 -3
drivers/video/console/vgacon.c
··· 271 271 272 272 static void vgacon_restore_screen(struct vc_data *c) 273 273 { 274 + c->vc_origin = c->vc_visible_origin; 274 275 vgacon_scrollback_cur->save = 0; 275 276 276 277 if (!vga_is_gfx && !vgacon_scrollback_cur->restore) { ··· 288 287 int start, end, count, soff; 289 288 290 289 if (!lines) { 291 - c->vc_visible_origin = c->vc_origin; 292 - vga_set_mem_top(c); 290 + vgacon_restore_screen(c); 293 291 return; 294 292 } 295 293 ··· 298 298 if (!vgacon_scrollback_cur->save) { 299 299 vgacon_cursor(c, CM_ERASE); 300 300 vgacon_save_screen(c); 301 + c->vc_origin = (unsigned long)c->vc_screenbuf; 301 302 vgacon_scrollback_cur->save = 1; 302 303 } 303 304 ··· 336 335 int copysize; 337 336 338 337 int diff = c->vc_rows - count; 339 - void *d = (void *) c->vc_origin; 338 + void *d = (void *) c->vc_visible_origin; 340 339 void *s = (void *) c->vc_screenbuf; 341 340 342 341 count *= c->vc_size_row;