Skip to content

Commit

Permalink
drivers/char/vt.c: fix vc->vc_origin on take_over_console()
Browse files Browse the repository at this point in the history
kernel will die on some platform when switch from vga mode to framebuffer
mode.  The reason of this bug is that bind_con_driver reset vc->vc_origin
to (unsigned long)vc->vc_screenbuf.

On vgacon vc->vc_origin is not releated to vc->vc_screenbuf,if set
vc->vc_origin to vc->vc_screenbuf,kernel will die on vc_do_resize.

static int vc_do_resize(struct tty_struct *tty, struct tty_struct *real_tty,
        struct vc_data *vc, unsigned int cols, unsigned int lines)
{
    unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
    unsigned int old_cols, old_rows, old_row_size, old_screen_size;
    unsigned int new_cols, new_rows, new_row_size, new_screen_size;
    unsigned int end, user;
...
        end = (old_rows > new_rows) ? old_origin +
            (old_row_size * new_rows) :
            vc->vc_scr_end;

...
/*
here for a test from vgacon to framebuffer:
old_origin=0x810814a0,end=0xb00b8fa0,vc->vc_origin=0x810814a0
the code bellow will copy memory from 0x810814a0 to 0xb00b8fa0,
this will cover kernel code,kernel died here.
*/

    while (old_origin < end) {

        scr_memcpyw((unsigned short *) new_origin,
                (unsigned short *) old_origin, rlth);
        if (rrem)
            scr_memsetw((void *)(new_origin + rlth),
                    vc->vc_video_erase_char, rrem);
        old_origin += old_row_size;
        new_origin += new_row_size;
    }

...
}

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: qiaochong <qiaochong@loongson.cn>
Cc: Greg KH <greg@kroah.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
qiaochong authored and Linus Torvalds committed Aug 10, 2010
1 parent a8618a0 commit 02f0777
Showing 1 changed file with 2 additions and 1 deletion.
3 changes: 2 additions & 1 deletion drivers/char/vt.c
Original file line number Diff line number Diff line change
Expand Up @@ -3065,7 +3065,8 @@ static int bind_con_driver(const struct consw *csw, int first, int last,

old_was_color = vc->vc_can_do_color;
vc->vc_sw->con_deinit(vc);
vc->vc_origin = (unsigned long)vc->vc_screenbuf;
if (!vc->vc_origin)
vc->vc_origin = (unsigned long)vc->vc_screenbuf;
visual_init(vc, i, 0);
set_origin(vc);
update_attr(vc);
Expand Down

0 comments on commit 02f0777

Please sign in to comment.