Merge tag 'tty-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
[linux-2.6-microblaze.git] / drivers / tty / vt / vt.c
index ef981d3..7359c3e 100644 (file)
@@ -1219,8 +1219,25 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        new_row_size = new_cols << 1;
        new_screen_size = new_row_size * new_rows;
 
-       if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
-               return 0;
+       if (new_cols == vc->vc_cols && new_rows == vc->vc_rows) {
+               /*
+                * This function is being called here to cover the case
+                * where the userspace calls the FBIOPUT_VSCREENINFO twice,
+                * passing the same fb_var_screeninfo containing the fields
+                * yres/xres equal to a number non-multiple of vc_font.height
+                * and yres_virtual/xres_virtual equal to number lesser than the
+                * vc_font.height and yres/xres.
+                * In the second call, the struct fb_var_screeninfo isn't
+                * being modified by the underlying driver because of the
+                * if above, and this causes the fbcon_display->vrows to become
+                * negative and it eventually leads to out-of-bound
+                * access by the imageblit function.
+                * To give the correct values to the struct and to not have
+                * to deal with possible errors from the code below, we call
+                * the resize_screen here as well.
+                */
+               return resize_screen(vc, new_cols, new_rows, user);
+       }
 
        if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size)
                return -EINVAL;
@@ -2059,7 +2076,7 @@ static void restore_cur(struct vc_data *vc)
 
 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey,
        EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd,
-       ESpalette, ESosc };
+       ESpalette, ESosc, ESapc, ESpm, ESdcs };
 
 /* console_lock is held (except via vc_init()) */
 static void reset_terminal(struct vc_data *vc, int do_clear)
@@ -2133,20 +2150,28 @@ static void vc_setGx(struct vc_data *vc, unsigned int which, int c)
                vc->vc_translate = set_translate(*charset, vc);
 }
 
+/* is this state an ANSI control string? */
+static bool ansi_control_string(unsigned int state)
+{
+       if (state == ESosc || state == ESapc || state == ESpm || state == ESdcs)
+               return true;
+       return false;
+}
+
 /* console_lock is held */
 static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 {
        /*
         *  Control characters can be used in the _middle_
-        *  of an escape sequence.
+        *  of an escape sequence, aside from ANSI control strings.
         */
-       if (vc->vc_state == ESosc && c>=8 && c<=13) /* ... except for OSC */
+       if (ansi_control_string(vc->vc_state) && c >= 8 && c <= 13)
                return;
        switch (c) {
        case 0:
                return;
        case 7:
-               if (vc->vc_state == ESosc)
+               if (ansi_control_string(vc->vc_state))
                        vc->vc_state = ESnormal;
                else if (vc->vc_bell_duration)
                        kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
@@ -2207,6 +2232,12 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                case ']':
                        vc->vc_state = ESnonstd;
                        return;
+               case '_':
+                       vc->vc_state = ESapc;
+                       return;
+               case '^':
+                       vc->vc_state = ESpm;
+                       return;
                case '%':
                        vc->vc_state = ESpercent;
                        return;
@@ -2224,6 +2255,9 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                        if (vc->state.x < VC_TABSTOPS_COUNT)
                                set_bit(vc->state.x, vc->vc_tab_stop);
                        return;
+               case 'P':
+                       vc->vc_state = ESdcs;
+                       return;
                case 'Z':
                        respond_ID(tty);
                        return;
@@ -2520,8 +2554,14 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                vc_setGx(vc, 1, c);
                vc->vc_state = ESnormal;
                return;
+       case ESapc:
+               return;
        case ESosc:
                return;
+       case ESpm:
+               return;
+       case ESdcs:
+               return;
        default:
                vc->vc_state = ESnormal;
        }
@@ -3559,8 +3599,9 @@ int __init vty_init(const struct file_operations *console_fops)
 
        vcs_init();
 
-       console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
-       if (!console_driver)
+       console_driver = tty_alloc_driver(MAX_NR_CONSOLES, TTY_DRIVER_REAL_RAW |
+                       TTY_DRIVER_RESET_TERMIOS);
+       if (IS_ERR(console_driver))
                panic("Couldn't allocate console driver\n");
 
        console_driver->name = "tty";
@@ -3571,7 +3612,6 @@ int __init vty_init(const struct file_operations *console_fops)
        console_driver->init_termios = tty_std_termios;
        if (default_utf8)
                console_driver->init_termios.c_iflag |= IUTF8;
-       console_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
        tty_set_operations(console_driver, &con_ops);
        if (tty_register_driver(console_driver))
                panic("Couldn't register console driver\n");