LCOV - code coverage report
Current view: top level - drivers/tty/vt - vt.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 178 1826 9.7 %
Date: 2014-02-18 Functions: 16 114 14.0 %
Branches: 48 1473 3.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  Copyright (C) 1991, 1992  Linus Torvalds
       3                 :            :  */
       4                 :            : 
       5                 :            : /*
       6                 :            :  * Hopefully this will be a rather complete VT102 implementation.
       7                 :            :  *
       8                 :            :  * Beeping thanks to John T Kohl.
       9                 :            :  *
      10                 :            :  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
      11                 :            :  *   Chars, and VT100 enhancements by Peter MacDonald.
      12                 :            :  *
      13                 :            :  * Copy and paste function by Andrew Haylett,
      14                 :            :  *   some enhancements by Alessandro Rubini.
      15                 :            :  *
      16                 :            :  * Code to check for different video-cards mostly by Galen Hunt,
      17                 :            :  * <g-hunt@ee.utah.edu>
      18                 :            :  *
      19                 :            :  * Rudimentary ISO 10646/Unicode/UTF-8 character set support by
      20                 :            :  * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
      21                 :            :  *
      22                 :            :  * Dynamic allocation of consoles, aeb@cwi.nl, May 1994
      23                 :            :  * Resizing of consoles, aeb, 940926
      24                 :            :  *
      25                 :            :  * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
      26                 :            :  * <poe@daimi.aau.dk>
      27                 :            :  *
      28                 :            :  * User-defined bell sound, new setterm control sequences and printk
      29                 :            :  * redirection by Martin Mares <mj@k332.feld.cvut.cz> 19-Nov-95
      30                 :            :  *
      31                 :            :  * APM screenblank bug fixed Takashi Manabe <manabe@roy.dsl.tutics.tut.jp>
      32                 :            :  *
      33                 :            :  * Merge with the abstract console driver by Geert Uytterhoeven
      34                 :            :  * <geert@linux-m68k.org>, Jan 1997.
      35                 :            :  *
      36                 :            :  *   Original m68k console driver modifications by
      37                 :            :  *
      38                 :            :  *     - Arno Griffioen <arno@usn.nl>
      39                 :            :  *     - David Carter <carter@cs.bris.ac.uk>
      40                 :            :  * 
      41                 :            :  *   The abstract console driver provides a generic interface for a text
      42                 :            :  *   console. It supports VGA text mode, frame buffer based graphical consoles
      43                 :            :  *   and special graphics processors that are only accessible through some
      44                 :            :  *   registers (e.g. a TMS340x0 GSP).
      45                 :            :  *
      46                 :            :  *   The interface to the hardware is specified using a special structure
      47                 :            :  *   (struct consw) which contains function pointers to console operations
      48                 :            :  *   (see <linux/console.h> for more information).
      49                 :            :  *
      50                 :            :  * Support for changeable cursor shape
      51                 :            :  * by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>, August 1997
      52                 :            :  *
      53                 :            :  * Ported to i386 and con_scrolldelta fixed
      54                 :            :  * by Emmanuel Marty <core@ggi-project.org>, April 1998
      55                 :            :  *
      56                 :            :  * Resurrected character buffers in videoram plus lots of other trickery
      57                 :            :  * by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998
      58                 :            :  *
      59                 :            :  * Removed old-style timers, introduced console_timer, made timer
      60                 :            :  * deletion SMP-safe.  17Jun00, Andrew Morton
      61                 :            :  *
      62                 :            :  * Removed console_lock, enabled interrupts across all console operations
      63                 :            :  * 13 March 2001, Andrew Morton
      64                 :            :  *
      65                 :            :  * Fixed UTF-8 mode so alternate charset modes always work according
      66                 :            :  * to control sequences interpreted in do_con_trol function
      67                 :            :  * preserving backward VT100 semigraphics compatibility,
      68                 :            :  * malformed UTF sequences represented as sequences of replacement glyphs,
      69                 :            :  * original codes or '?' as a last resort if replacement glyph is undefined
      70                 :            :  * by Adam Tla/lka <atlka@pg.gda.pl>, Aug 2006
      71                 :            :  */
      72                 :            : 
      73                 :            : #include <linux/module.h>
      74                 :            : #include <linux/types.h>
      75                 :            : #include <linux/sched.h>
      76                 :            : #include <linux/tty.h>
      77                 :            : #include <linux/tty_flip.h>
      78                 :            : #include <linux/kernel.h>
      79                 :            : #include <linux/string.h>
      80                 :            : #include <linux/errno.h>
      81                 :            : #include <linux/kd.h>
      82                 :            : #include <linux/slab.h>
      83                 :            : #include <linux/major.h>
      84                 :            : #include <linux/mm.h>
      85                 :            : #include <linux/console.h>
      86                 :            : #include <linux/init.h>
      87                 :            : #include <linux/mutex.h>
      88                 :            : #include <linux/vt_kern.h>
      89                 :            : #include <linux/selection.h>
      90                 :            : #include <linux/tiocl.h>
      91                 :            : #include <linux/kbd_kern.h>
      92                 :            : #include <linux/consolemap.h>
      93                 :            : #include <linux/timer.h>
      94                 :            : #include <linux/interrupt.h>
      95                 :            : #include <linux/workqueue.h>
      96                 :            : #include <linux/pm.h>
      97                 :            : #include <linux/font.h>
      98                 :            : #include <linux/bitops.h>
      99                 :            : #include <linux/notifier.h>
     100                 :            : #include <linux/device.h>
     101                 :            : #include <linux/io.h>
     102                 :            : #include <linux/uaccess.h>
     103                 :            : #include <linux/kdb.h>
     104                 :            : #include <linux/ctype.h>
     105                 :            : 
     106                 :            : #define MAX_NR_CON_DRIVER 16
     107                 :            : 
     108                 :            : #define CON_DRIVER_FLAG_MODULE 1
     109                 :            : #define CON_DRIVER_FLAG_INIT   2
     110                 :            : #define CON_DRIVER_FLAG_ATTR   4
     111                 :            : 
     112                 :            : struct con_driver {
     113                 :            :         const struct consw *con;
     114                 :            :         const char *desc;
     115                 :            :         struct device *dev;
     116                 :            :         int node;
     117                 :            :         int first;
     118                 :            :         int last;
     119                 :            :         int flag;
     120                 :            : };
     121                 :            : 
     122                 :            : static struct con_driver registered_con_driver[MAX_NR_CON_DRIVER];
     123                 :            : const struct consw *conswitchp;
     124                 :            : 
     125                 :            : /* A bitmap for codes <32. A bit of 1 indicates that the code
     126                 :            :  * corresponding to that bit number invokes some special action
     127                 :            :  * (such as cursor movement) and should not be displayed as a
     128                 :            :  * glyph unless the disp_ctrl mode is explicitly enabled.
     129                 :            :  */
     130                 :            : #define CTRL_ACTION 0x0d00ff81
     131                 :            : #define CTRL_ALWAYS 0x0800f501  /* Cannot be overridden by disp_ctrl */
     132                 :            : 
     133                 :            : /*
     134                 :            :  * Here is the default bell parameters: 750HZ, 1/8th of a second
     135                 :            :  */
     136                 :            : #define DEFAULT_BELL_PITCH      750
     137                 :            : #define DEFAULT_BELL_DURATION   (HZ/8)
     138                 :            : 
     139                 :            : struct vc vc_cons [MAX_NR_CONSOLES];
     140                 :            : 
     141                 :            : #ifndef VT_SINGLE_DRIVER
     142                 :            : static const struct consw *con_driver_map[MAX_NR_CONSOLES];
     143                 :            : #endif
     144                 :            : 
     145                 :            : static int con_open(struct tty_struct *, struct file *);
     146                 :            : static void vc_init(struct vc_data *vc, unsigned int rows,
     147                 :            :                     unsigned int cols, int do_clear);
     148                 :            : static void gotoxy(struct vc_data *vc, int new_x, int new_y);
     149                 :            : static void save_cur(struct vc_data *vc);
     150                 :            : static void reset_terminal(struct vc_data *vc, int do_clear);
     151                 :            : static void con_flush_chars(struct tty_struct *tty);
     152                 :            : static int set_vesa_blanking(char __user *p);
     153                 :            : static void set_cursor(struct vc_data *vc);
     154                 :            : static void hide_cursor(struct vc_data *vc);
     155                 :            : static void console_callback(struct work_struct *ignored);
     156                 :            : static void blank_screen_t(unsigned long dummy);
     157                 :            : static void set_palette(struct vc_data *vc);
     158                 :            : 
     159                 :            : static int printable;           /* Is console ready for printing? */
     160                 :            : int default_utf8 = true;
     161                 :            : module_param(default_utf8, int, S_IRUGO | S_IWUSR);
     162                 :            : int global_cursor_default = -1;
     163                 :            : module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);
     164                 :            : 
     165                 :            : static int cur_default = CUR_DEFAULT;
     166                 :            : module_param(cur_default, int, S_IRUGO | S_IWUSR);
     167                 :            : 
     168                 :            : /*
     169                 :            :  * ignore_poke: don't unblank the screen when things are typed.  This is
     170                 :            :  * mainly for the privacy of braille terminal users.
     171                 :            :  */
     172                 :            : static int ignore_poke;
     173                 :            : 
     174                 :            : int do_poke_blanked_console;
     175                 :            : int console_blanked;
     176                 :            : 
     177                 :            : static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
     178                 :            : static int vesa_off_interval;
     179                 :            : static int blankinterval = 10*60;
     180                 :            : core_param(consoleblank, blankinterval, int, 0444);
     181                 :            : 
     182                 :            : static DECLARE_WORK(console_work, console_callback);
     183                 :            : 
     184                 :            : /*
     185                 :            :  * fg_console is the current virtual console,
     186                 :            :  * last_console is the last used one,
     187                 :            :  * want_console is the console we want to switch to,
     188                 :            :  * saved_* variants are for save/restore around kernel debugger enter/leave
     189                 :            :  */
     190                 :            : int fg_console;
     191                 :            : int last_console;
     192                 :            : int want_console = -1;
     193                 :            : static int saved_fg_console;
     194                 :            : static int saved_last_console;
     195                 :            : static int saved_want_console;
     196                 :            : static int saved_vc_mode;
     197                 :            : static int saved_console_blanked;
     198                 :            : 
     199                 :            : /*
     200                 :            :  * For each existing display, we have a pointer to console currently visible
     201                 :            :  * on that display, allowing consoles other than fg_console to be refreshed
     202                 :            :  * appropriately. Unless the low-level driver supplies its own display_fg
     203                 :            :  * variable, we use this one for the "master display".
     204                 :            :  */
     205                 :            : static struct vc_data *master_display_fg;
     206                 :            : 
     207                 :            : /*
     208                 :            :  * Unfortunately, we need to delay tty echo when we're currently writing to the
     209                 :            :  * console since the code is (and always was) not re-entrant, so we schedule
     210                 :            :  * all flip requests to process context with schedule-task() and run it from
     211                 :            :  * console_callback().
     212                 :            :  */
     213                 :            : 
     214                 :            : /*
     215                 :            :  * For the same reason, we defer scrollback to the console callback.
     216                 :            :  */
     217                 :            : static int scrollback_delta;
     218                 :            : 
     219                 :            : /*
     220                 :            :  * Hook so that the power management routines can (un)blank
     221                 :            :  * the console on our behalf.
     222                 :            :  */
     223                 :            : int (*console_blank_hook)(int);
     224                 :            : 
     225                 :            : static DEFINE_TIMER(console_timer, blank_screen_t, 0, 0);
     226                 :            : static int blank_state;
     227                 :            : static int blank_timer_expired;
     228                 :            : enum {
     229                 :            :         blank_off = 0,
     230                 :            :         blank_normal_wait,
     231                 :            :         blank_vesa_wait,
     232                 :            : };
     233                 :            : 
     234                 :            : /*
     235                 :            :  * /sys/class/tty/tty0/
     236                 :            :  *
     237                 :            :  * the attribute 'active' contains the name of the current vc
     238                 :            :  * console and it supports poll() to detect vc switches
     239                 :            :  */
     240                 :            : static struct device *tty0dev;
     241                 :            : 
     242                 :            : /*
     243                 :            :  * Notifier list for console events.
     244                 :            :  */
     245                 :            : static ATOMIC_NOTIFIER_HEAD(vt_notifier_list);
     246                 :            : 
     247                 :          0 : int register_vt_notifier(struct notifier_block *nb)
     248                 :            : {
     249                 :          0 :         return atomic_notifier_chain_register(&vt_notifier_list, nb);
     250                 :            : }
     251                 :            : EXPORT_SYMBOL_GPL(register_vt_notifier);
     252                 :            : 
     253                 :          0 : int unregister_vt_notifier(struct notifier_block *nb)
     254                 :            : {
     255                 :          0 :         return atomic_notifier_chain_unregister(&vt_notifier_list, nb);
     256                 :            : }
     257                 :            : EXPORT_SYMBOL_GPL(unregister_vt_notifier);
     258                 :            : 
     259                 :          0 : static void notify_write(struct vc_data *vc, unsigned int unicode)
     260                 :            : {
     261                 :          0 :         struct vt_notifier_param param = { .vc = vc, .c = unicode };
     262                 :          0 :         atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, &param);
     263                 :          0 : }
     264                 :            : 
     265                 :            : static void notify_update(struct vc_data *vc)
     266                 :            : {
     267                 :          0 :         struct vt_notifier_param param = { .vc = vc };
     268                 :          0 :         atomic_notifier_call_chain(&vt_notifier_list, VT_UPDATE, &param);
     269                 :            : }
     270                 :            : /*
     271                 :            :  *      Low-Level Functions
     272                 :            :  */
     273                 :            : 
     274                 :            : #define IS_FG(vc)       ((vc)->vc_num == fg_console)
     275                 :            : 
     276                 :            : #ifdef VT_BUF_VRAM_ONLY
     277                 :            : #define DO_UPDATE(vc)   0
     278                 :            : #else
     279                 :            : #define DO_UPDATE(vc)   (CON_IS_VISIBLE(vc) && !console_blanked)
     280                 :            : #endif
     281                 :            : 
     282                 :            : static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
     283                 :            : {
     284                 :            :         unsigned short *p;
     285                 :            :         
     286 [ #  # ][ #  # ]:          0 :         if (!viewed)
     287                 :          0 :                 p = (unsigned short *)(vc->vc_origin + offset);
     288 [ #  # ][ #  # ]:          0 :         else if (!vc->vc_sw->con_screen_pos)
         [ #  # ][ #  # ]
                 [ #  # ]
     289                 :          0 :                 p = (unsigned short *)(vc->vc_visible_origin + offset);
     290                 :            :         else
     291                 :          0 :                 p = vc->vc_sw->con_screen_pos(vc, offset);
     292                 :            :         return p;
     293                 :            : }
     294                 :            : 
     295                 :            : /* Called  from the keyboard irq path.. */
     296                 :            : static inline void scrolldelta(int lines)
     297                 :            : {
     298                 :            :         /* FIXME */
     299                 :            :         /* scrolldelta needs some kind of consistency lock, but the BKL was
     300                 :            :            and still is not protecting versus the scheduled back end */
     301                 :          0 :         scrollback_delta += lines;
     302                 :          0 :         schedule_console_callback();
     303                 :            : }
     304                 :            : 
     305                 :          0 : void schedule_console_callback(void)
     306                 :            : {
     307                 :            :         schedule_work(&console_work);
     308                 :          0 : }
     309                 :            : 
     310                 :          0 : static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
     311                 :            : {
     312                 :            :         unsigned short *d, *s;
     313                 :            : 
     314         [ #  # ]:          0 :         if (t+nr >= b)
     315                 :          0 :                 nr = b - t - 1;
     316 [ #  # ][ #  # ]:          0 :         if (b > vc->vc_rows || t >= b || nr < 1)
     317                 :            :                 return;
     318 [ #  # ][ #  # ]:          0 :         if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
     319                 :            :                 return;
     320                 :          0 :         d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
     321                 :          0 :         s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
     322                 :          0 :         scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
     323                 :          0 :         scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
     324                 :          0 :                     vc->vc_size_row * nr);
     325                 :            : }
     326                 :            : 
     327                 :          0 : static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
     328                 :            : {
     329                 :            :         unsigned short *s;
     330                 :            :         unsigned int step;
     331                 :            : 
     332         [ #  # ]:          0 :         if (t+nr >= b)
     333                 :          0 :                 nr = b - t - 1;
     334 [ #  # ][ #  # ]:          0 :         if (b > vc->vc_rows || t >= b || nr < 1)
     335                 :            :                 return;
     336 [ #  # ][ #  # ]:          0 :         if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
     337                 :            :                 return;
     338                 :          0 :         s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
     339                 :          0 :         step = vc->vc_cols * nr;
     340                 :          0 :         scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
     341                 :          0 :         scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
     342                 :            : }
     343                 :            : 
     344                 :          0 : static void do_update_region(struct vc_data *vc, unsigned long start, int count)
     345                 :            : {
     346                 :            : #ifndef VT_BUF_VRAM_ONLY
     347                 :            :         unsigned int xx, yy, offset;
     348                 :            :         u16 *p;
     349                 :            : 
     350                 :          0 :         p = (u16 *) start;
     351         [ #  # ]:          0 :         if (!vc->vc_sw->con_getxy) {
     352                 :          0 :                 offset = (start - vc->vc_origin) / 2;
     353                 :          0 :                 xx = offset % vc->vc_cols;
     354                 :          0 :                 yy = offset / vc->vc_cols;
     355                 :            :         } else {
     356                 :            :                 int nxx, nyy;
     357                 :          0 :                 start = vc->vc_sw->con_getxy(vc, start, &nxx, &nyy);
     358                 :          0 :                 xx = nxx; yy = nyy;
     359                 :            :         }
     360                 :            :         for(;;) {
     361                 :          0 :                 u16 attrib = scr_readw(p) & 0xff00;
     362                 :          0 :                 int startx = xx;
     363                 :            :                 u16 *q = p;
     364 [ #  # ][ #  # ]:          0 :                 while (xx < vc->vc_cols && count) {
     365         [ #  # ]:          0 :                         if (attrib != (scr_readw(p) & 0xff00)) {
     366         [ #  # ]:          0 :                                 if (p > q)
     367                 :          0 :                                         vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
     368                 :          0 :                                 startx = xx;
     369                 :            :                                 q = p;
     370                 :          0 :                                 attrib = scr_readw(p) & 0xff00;
     371                 :            :                         }
     372                 :          0 :                         p++;
     373                 :          0 :                         xx++;
     374                 :          0 :                         count--;
     375                 :            :                 }
     376         [ #  # ]:          0 :                 if (p > q)
     377                 :          0 :                         vc->vc_sw->con_putcs(vc, q, p-q, yy, startx);
     378         [ #  # ]:          0 :                 if (!count)
     379                 :            :                         break;
     380                 :            :                 xx = 0;
     381                 :          0 :                 yy++;
     382         [ #  # ]:          0 :                 if (vc->vc_sw->con_getxy) {
     383                 :          0 :                         p = (u16 *)start;
     384                 :          0 :                         start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
     385                 :            :                 }
     386                 :            :         }
     387                 :            : #endif
     388                 :          0 : }
     389                 :            : 
     390                 :          0 : void update_region(struct vc_data *vc, unsigned long start, int count)
     391                 :            : {
     392 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
     393                 :            : 
     394 [ #  # ][ #  # ]:          0 :         if (DO_UPDATE(vc)) {
     395                 :          0 :                 hide_cursor(vc);
     396                 :          0 :                 do_update_region(vc, start, count);
     397                 :          0 :                 set_cursor(vc);
     398                 :            :         }
     399                 :          0 : }
     400                 :            : 
     401                 :            : /* Structure of attributes is hardware-dependent */
     402                 :            : 
     403                 :          0 : static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
     404                 :            :     u8 _underline, u8 _reverse, u8 _italic)
     405                 :            : {
     406         [ -  + ]:        112 :         if (vc->vc_sw->con_build_attr)
     407                 :          0 :                 return vc->vc_sw->con_build_attr(vc, _color, _intensity,
     408                 :            :                        _blink, _underline, _reverse, _italic);
     409                 :            : 
     410                 :            : #ifndef VT_BUF_VRAM_ONLY
     411                 :            : /*
     412                 :            :  * ++roman: I completely changed the attribute format for monochrome
     413                 :            :  * mode (!can_do_color). The formerly used MDA (monochrome display
     414                 :            :  * adapter) format didn't allow the combination of certain effects.
     415                 :            :  * Now the attribute is just a bit vector:
     416                 :            :  *  Bit 0..1: intensity (0..2)
     417                 :            :  *  Bit 2   : underline
     418                 :            :  *  Bit 3   : reverse
     419                 :            :  *  Bit 7   : blink
     420                 :            :  */
     421                 :            :         {
     422                 :            :         u8 a = _color;
     423         [ -  + ]:        112 :         if (!vc->vc_can_do_color)
     424 [ #  # ][ #  # ]:          0 :                 return _intensity |
         [ #  # ][ #  # ]
     425                 :            :                        (_italic ? 2 : 0) |
     426                 :            :                        (_underline ? 4 : 0) |
     427                 :            :                        (_reverse ? 8 : 0) |
     428                 :            :                        (_blink ? 0x80 : 0);
     429         [ -  + ]:        112 :         if (_italic)
     430                 :          0 :                 a = (a & 0xF0) | vc->vc_itcolor;
     431         [ -  + ]:        112 :         else if (_underline)
     432                 :          0 :                 a = (a & 0xf0) | vc->vc_ulcolor;
     433         [ -  + ]:        112 :         else if (_intensity == 0)
     434                 :          0 :                 a = (a & 0xf0) | vc->vc_ulcolor;
     435         [ -  + ]:        112 :         if (_reverse)
     436                 :          0 :                 a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);
     437         [ -  + ]:        112 :         if (_blink)
     438                 :          0 :                 a ^= 0x80;
     439         [ -  + ]:        112 :         if (_intensity == 2)
     440                 :          0 :                 a ^= 0x08;
     441         [ +  - ]:        112 :         if (vc->vc_hi_font_mask == 0x100)
     442                 :        112 :                 a <<= 1;
     443                 :        112 :         return a;
     444                 :            :         }
     445                 :            : #else
     446                 :            :         return 0;
     447                 :            : #endif
     448                 :            : }
     449                 :            : 
     450                 :          0 : static void update_attr(struct vc_data *vc)
     451                 :            : {
     452                 :         56 :         vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity,
     453                 :        112 :                       vc->vc_blink, vc->vc_underline,
     454                 :        112 :                       vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);
     455                 :         56 :         vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';
     456                 :         56 : }
     457                 :            : 
     458                 :            : /* Note: inverting the screen twice should revert to the original state */
     459                 :          0 : void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
     460                 :            : {
     461                 :            :         unsigned short *p;
     462                 :            : 
     463 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
     464                 :            : 
     465                 :          0 :         count /= 2;
     466                 :            :         p = screenpos(vc, offset, viewed);
     467         [ #  # ]:          0 :         if (vc->vc_sw->con_invert_region)
     468                 :          0 :                 vc->vc_sw->con_invert_region(vc, p, count);
     469                 :            : #ifndef VT_BUF_VRAM_ONLY
     470                 :            :         else {
     471                 :            :                 u16 *q = p;
     472                 :            :                 int cnt = count;
     473                 :            :                 u16 a;
     474                 :            : 
     475         [ #  # ]:          0 :                 if (!vc->vc_can_do_color) {
     476         [ #  # ]:          0 :                         while (cnt--) {
     477                 :          0 :                             a = scr_readw(q);
     478                 :          0 :                             a ^= 0x0800;
     479                 :          0 :                             scr_writew(a, q);
     480                 :          0 :                             q++;
     481                 :            :                         }
     482         [ #  # ]:          0 :                 } else if (vc->vc_hi_font_mask == 0x100) {
     483         [ #  # ]:          0 :                         while (cnt--) {
     484                 :          0 :                                 a = scr_readw(q);
     485                 :          0 :                                 a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
     486                 :          0 :                                 scr_writew(a, q);
     487                 :          0 :                                 q++;
     488                 :            :                         }
     489                 :            :                 } else {
     490         [ #  # ]:          0 :                         while (cnt--) {
     491                 :          0 :                                 a = scr_readw(q);
     492                 :          0 :                                 a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
     493                 :          0 :                                 scr_writew(a, q);
     494                 :          0 :                                 q++;
     495                 :            :                         }
     496                 :            :                 }
     497                 :            :         }
     498                 :            : #endif
     499 [ #  # ][ #  # ]:          0 :         if (DO_UPDATE(vc))
     500                 :          0 :                 do_update_region(vc, (unsigned long) p, count);
     501                 :          0 : }
     502                 :            : 
     503                 :            : /* used by selection: complement pointer position */
     504                 :          0 : void complement_pos(struct vc_data *vc, int offset)
     505                 :            : {
     506                 :            :         static int old_offset = -1;
     507                 :            :         static unsigned short old;
     508                 :            :         static unsigned short oldx, oldy;
     509                 :            : 
     510 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
     511                 :            : 
     512 [ #  # ][ #  # ]:          0 :         if (old_offset != -1 && old_offset >= 0 &&
     513                 :          0 :             old_offset < vc->vc_screenbuf_size) {
     514                 :          0 :                 scr_writew(old, screenpos(vc, old_offset, 1));
     515 [ #  # ][ #  # ]:          0 :                 if (DO_UPDATE(vc))
     516                 :          0 :                         vc->vc_sw->con_putc(vc, old, oldy, oldx);
     517                 :            :         }
     518                 :            : 
     519                 :          0 :         old_offset = offset;
     520                 :            : 
     521 [ #  # ][ #  # ]:          0 :         if (offset != -1 && offset >= 0 &&
     522                 :          0 :             offset < vc->vc_screenbuf_size) {
     523                 :            :                 unsigned short new;
     524                 :            :                 unsigned short *p;
     525                 :            :                 p = screenpos(vc, offset, 1);
     526                 :          0 :                 old = scr_readw(p);
     527                 :          0 :                 new = old ^ vc->vc_complement_mask;
     528                 :          0 :                 scr_writew(new, p);
     529 [ #  # ][ #  # ]:          0 :                 if (DO_UPDATE(vc)) {
     530                 :          0 :                         oldx = (offset >> 1) % vc->vc_cols;
     531                 :          0 :                         oldy = (offset >> 1) / vc->vc_cols;
     532                 :          0 :                         vc->vc_sw->con_putc(vc, new, oldy, oldx);
     533                 :            :                 }
     534                 :            :         }
     535                 :            : 
     536                 :          0 : }
     537                 :            : 
     538                 :          0 : static void insert_char(struct vc_data *vc, unsigned int nr)
     539                 :            : {
     540                 :          0 :         unsigned short *p = (unsigned short *) vc->vc_pos;
     541                 :            : 
     542                 :          0 :         scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2);
     543                 :          0 :         scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
     544                 :          0 :         vc->vc_need_wrap = 0;
     545 [ #  # ][ #  # ]:          0 :         if (DO_UPDATE(vc))
     546                 :          0 :                 do_update_region(vc, (unsigned long) p,
     547                 :          0 :                         vc->vc_cols - vc->vc_x);
     548                 :          0 : }
     549                 :            : 
     550                 :          0 : static void delete_char(struct vc_data *vc, unsigned int nr)
     551                 :            : {
     552                 :          0 :         unsigned short *p = (unsigned short *) vc->vc_pos;
     553                 :            : 
     554                 :          0 :         scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2);
     555                 :          0 :         scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
     556                 :            :                         nr * 2);
     557                 :          0 :         vc->vc_need_wrap = 0;
     558 [ #  # ][ #  # ]:          0 :         if (DO_UPDATE(vc))
     559                 :          0 :                 do_update_region(vc, (unsigned long) p,
     560                 :          0 :                         vc->vc_cols - vc->vc_x);
     561                 :          0 : }
     562                 :            : 
     563                 :            : static int softcursor_original;
     564                 :            : 
     565                 :          0 : static void add_softcursor(struct vc_data *vc)
     566                 :            : {
     567                 :          0 :         int i = scr_readw((u16 *) vc->vc_pos);
     568                 :          0 :         u32 type = vc->vc_cursor_type;
     569                 :            : 
     570         [ #  # ]:          0 :         if (! (type & 0x10)) return;
     571         [ #  # ]:          0 :         if (softcursor_original != -1) return;
     572                 :          0 :         softcursor_original = i;
     573                 :          0 :         i |= ((type >> 8) & 0xff00 );
     574                 :          0 :         i ^= ((type) & 0xff00 );
     575 [ #  # ][ #  # ]:          0 :         if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
     576 [ #  # ][ #  # ]:          0 :         if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
     577                 :          0 :         scr_writew(i, (u16 *) vc->vc_pos);
     578 [ #  # ][ #  # ]:          0 :         if (DO_UPDATE(vc))
     579                 :          0 :                 vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
     580                 :            : }
     581                 :            : 
     582                 :          0 : static void hide_softcursor(struct vc_data *vc)
     583                 :            : {
     584         [ #  # ]:          0 :         if (softcursor_original != -1) {
     585                 :          0 :                 scr_writew(softcursor_original, (u16 *)vc->vc_pos);
     586 [ #  # ][ #  # ]:          0 :                 if (DO_UPDATE(vc))
     587                 :          0 :                         vc->vc_sw->con_putc(vc, softcursor_original,
     588                 :          0 :                                         vc->vc_y, vc->vc_x);
     589                 :          0 :                 softcursor_original = -1;
     590                 :            :         }
     591                 :          0 : }
     592                 :            : 
     593                 :          0 : static void hide_cursor(struct vc_data *vc)
     594                 :            : {
     595         [ #  # ]:          0 :         if (vc == sel_cons)
     596                 :          0 :                 clear_selection();
     597                 :          0 :         vc->vc_sw->con_cursor(vc, CM_ERASE);
     598                 :          0 :         hide_softcursor(vc);
     599                 :          0 : }
     600                 :            : 
     601                 :          0 : static void set_cursor(struct vc_data *vc)
     602                 :            : {
     603 [ #  # ][ #  # ]:          0 :         if (!IS_FG(vc) || console_blanked ||
                 [ #  # ]
     604                 :          0 :             vc->vc_mode == KD_GRAPHICS)
     605                 :          0 :                 return;
     606         [ #  # ]:          0 :         if (vc->vc_deccm) {
     607         [ #  # ]:          0 :                 if (vc == sel_cons)
     608                 :          0 :                         clear_selection();
     609                 :          0 :                 add_softcursor(vc);
     610         [ #  # ]:          0 :                 if ((vc->vc_cursor_type & 0x0f) != 1)
     611                 :          0 :                         vc->vc_sw->con_cursor(vc, CM_DRAW);
     612                 :            :         } else
     613                 :          0 :                 hide_cursor(vc);
     614                 :            : }
     615                 :            : 
     616                 :          0 : static void set_origin(struct vc_data *vc)
     617                 :            : {
     618 [ -  + ][ #  # ]:         56 :         WARN_CONSOLE_UNLOCKED();
                 [ -  + ]
     619                 :            : 
     620 [ -  + ][ #  # ]:        112 :         if (!CON_IS_VISIBLE(vc) ||
     621         [ #  # ]:          0 :             !vc->vc_sw->con_set_origin ||
     622                 :          0 :             !vc->vc_sw->con_set_origin(vc))
     623                 :         56 :                 vc->vc_origin = (unsigned long)vc->vc_screenbuf;
     624                 :         56 :         vc->vc_visible_origin = vc->vc_origin;
     625                 :         56 :         vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
     626                 :         56 :         vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
     627                 :         56 : }
     628                 :            : 
     629                 :            : static inline void save_screen(struct vc_data *vc)
     630                 :            : {
     631 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     632                 :            : 
     633 [ #  # ][ #  # ]:          0 :         if (vc->vc_sw->con_save_screen)
         [ #  # ][ #  # ]
                 [ #  # ]
     634                 :          0 :                 vc->vc_sw->con_save_screen(vc);
     635                 :            : }
     636                 :            : 
     637                 :            : /*
     638                 :            :  *      Redrawing of screen
     639                 :            :  */
     640                 :            : 
     641                 :          0 : void clear_buffer_attributes(struct vc_data *vc)
     642                 :            : {
     643                 :          0 :         unsigned short *p = (unsigned short *)vc->vc_origin;
     644                 :          0 :         int count = vc->vc_screenbuf_size / 2;
     645                 :          0 :         int mask = vc->vc_hi_font_mask | 0xff;
     646                 :            : 
     647         [ #  # ]:          0 :         for (; count > 0; count--, p++) {
     648                 :          0 :                 scr_writew((scr_readw(p)&mask) | (vc->vc_video_erase_char & ~mask), p);
     649                 :            :         }
     650                 :          0 : }
     651                 :            : 
     652                 :          0 : void redraw_screen(struct vc_data *vc, int is_switch)
     653                 :            : {
     654                 :            :         int redraw = 0;
     655                 :            : 
     656 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
     657                 :            : 
     658         [ #  # ]:          0 :         if (!vc) {
     659                 :            :                 /* strange ... */
     660                 :            :                 /* printk("redraw_screen: tty %d not allocated ??\n", new_console+1); */
     661                 :            :                 return;
     662                 :            :         }
     663                 :            : 
     664         [ #  # ]:          0 :         if (is_switch) {
     665                 :          0 :                 struct vc_data *old_vc = vc_cons[fg_console].d;
     666         [ #  # ]:          0 :                 if (old_vc == vc)
     667                 :            :                         return;
     668         [ #  # ]:          0 :                 if (!CON_IS_VISIBLE(vc))
     669                 :            :                         redraw = 1;
     670                 :          0 :                 *vc->vc_display_fg = vc;
     671                 :          0 :                 fg_console = vc->vc_num;
     672                 :          0 :                 hide_cursor(old_vc);
     673         [ #  # ]:          0 :                 if (!CON_IS_VISIBLE(old_vc)) {
     674                 :            :                         save_screen(old_vc);
     675                 :          0 :                         set_origin(old_vc);
     676                 :            :                 }
     677         [ #  # ]:          0 :                 if (tty0dev)
     678                 :          0 :                         sysfs_notify(&tty0dev->kobj, NULL, "active");
     679                 :            :         } else {
     680                 :          0 :                 hide_cursor(vc);
     681                 :            :                 redraw = 1;
     682                 :            :         }
     683                 :            : 
     684         [ #  # ]:          0 :         if (redraw) {
     685                 :            :                 int update;
     686                 :          0 :                 int old_was_color = vc->vc_can_do_color;
     687                 :            : 
     688                 :          0 :                 set_origin(vc);
     689                 :          0 :                 update = vc->vc_sw->con_switch(vc);
     690                 :          0 :                 set_palette(vc);
     691                 :            :                 /*
     692                 :            :                  * If console changed from mono<->color, the best we can do
     693                 :            :                  * is to clear the buffer attributes. As it currently stands,
     694                 :            :                  * rebuilding new attributes from the old buffer is not doable
     695                 :            :                  * without overly complex code.
     696                 :            :                  */
     697         [ #  # ]:          0 :                 if (old_was_color != vc->vc_can_do_color) {
     698                 :          0 :                         update_attr(vc);
     699                 :          0 :                         clear_buffer_attributes(vc);
     700                 :            :                 }
     701                 :            : 
     702                 :            :                 /* Forcibly update if we're panicing */
     703 [ #  # ][ #  # ]:          0 :                 if ((update && vc->vc_mode != KD_GRAPHICS) ||
                 [ #  # ]
     704                 :            :                     vt_force_oops_output(vc))
     705                 :          0 :                         do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
     706                 :            :         }
     707                 :          0 :         set_cursor(vc);
     708         [ #  # ]:          0 :         if (is_switch) {
     709                 :            :                 set_leds();
     710                 :          0 :                 compute_shiftstate();
     711                 :            :                 notify_update(vc);
     712                 :            :         }
     713                 :            : }
     714                 :            : 
     715                 :            : /*
     716                 :            :  *      Allocation, freeing and resizing of VTs.
     717                 :            :  */
     718                 :            : 
     719                 :          0 : int vc_cons_allocated(unsigned int i)
     720                 :            : {
     721 [ #  # ][ #  # ]:        704 :         return (i < MAX_NR_CONSOLES && vc_cons[i].d);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
     722                 :            : }
     723                 :            : 
     724                 :          0 : static void visual_init(struct vc_data *vc, int num, int init)
     725                 :            : {
     726                 :            :         /* ++Geert: vc->vc_sw->con_init determines console size */
     727         [ -  + ]:         56 :         if (vc->vc_sw)
     728                 :          0 :                 module_put(vc->vc_sw->owner);
     729                 :         56 :         vc->vc_sw = conswitchp;
     730                 :            : #ifndef VT_SINGLE_DRIVER
     731         [ +  - ]:         56 :         if (con_driver_map[num])
     732                 :         56 :                 vc->vc_sw = con_driver_map[num];
     733                 :            : #endif
     734                 :         56 :         __module_get(vc->vc_sw->owner);
     735                 :         56 :         vc->vc_num = num;
     736                 :         56 :         vc->vc_display_fg = &master_display_fg;
     737                 :         56 :         vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir;
     738                 :         56 :         vc->vc_uni_pagedir = 0;
     739                 :         56 :         vc->vc_hi_font_mask = 0;
     740                 :         56 :         vc->vc_complement_mask = 0;
     741                 :         56 :         vc->vc_can_do_color = 0;
     742                 :         56 :         vc->vc_panic_force_write = false;
     743                 :         56 :         vc->vc_sw->con_init(vc, init);
     744         [ -  + ]:         56 :         if (!vc->vc_complement_mask)
     745         [ #  # ]:          0 :                 vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
     746                 :          0 :         vc->vc_s_complement_mask = vc->vc_complement_mask;
     747                 :          0 :         vc->vc_size_row = vc->vc_cols << 1;
     748                 :          0 :         vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
     749                 :          0 : }
     750                 :            : 
     751                 :          0 : int vc_allocate(unsigned int currcons)  /* return 0 on success */
     752                 :            : {
     753 [ -  + ][ #  # ]:        285 :         WARN_CONSOLE_UNLOCKED();
                 [ -  + ]
     754                 :            : 
     755         [ +  - ]:        285 :         if (currcons >= MAX_NR_CONSOLES)
     756                 :            :                 return -ENXIO;
     757         [ +  + ]:        285 :         if (!vc_cons[currcons].d) {
     758                 :            :             struct vc_data *vc;
     759                 :            :             struct vt_notifier_param param;
     760                 :            : 
     761                 :            :             /* prevent users from taking too much memory */
     762 [ -  + ][ #  # ]:         56 :             if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
     763                 :          0 :               return -EPERM;
     764                 :            : 
     765                 :            :             /* due to the granularity of kmalloc, we waste some memory here */
     766                 :            :             /* the alloc is done in two steps, to optimize the common situation
     767                 :            :                of a 25x80 console (structsize=216, screenbuf_size=4000) */
     768                 :            :             /* although the numbers above are not valid since long ago, the
     769                 :            :                point is still up-to-date and the comment still has its value
     770                 :            :                even if only as a historical artifact.  --mj, July 1998 */
     771                 :         56 :             param.vc = vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL);
     772         [ +  - ]:         56 :             if (!vc)
     773                 :            :                 return -ENOMEM;
     774                 :         56 :             vc_cons[currcons].d = vc;
     775                 :         56 :             tty_port_init(&vc->port);
     776                 :        112 :             INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
     777                 :         56 :             visual_init(vc, currcons, 1);
     778         [ -  + ]:         56 :             if (!*vc->vc_uni_pagedir_loc)
     779                 :          0 :                 con_set_default_unimap(vc);
     780                 :        112 :             vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
     781         [ -  + ]:         56 :             if (!vc->vc_screenbuf) {
     782                 :          0 :                 kfree(vc);
     783                 :          0 :                 vc_cons[currcons].d = NULL;
     784                 :          0 :                 return -ENOMEM;
     785                 :            :             }
     786                 :            : 
     787                 :            :             /* If no drivers have overridden us and the user didn't pass a
     788                 :            :                boot option, default to displaying the cursor */
     789         [ -  + ]:         56 :             if (global_cursor_default == -1)
     790                 :          0 :                     global_cursor_default = 1;
     791                 :            : 
     792                 :         56 :             vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
     793                 :         56 :             vcs_make_sysfs(currcons);
     794                 :         56 :             atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, &param);
     795                 :            :         }
     796                 :            :         return 0;
     797                 :            : }
     798                 :            : 
     799                 :            : static inline int resize_screen(struct vc_data *vc, int width, int height,
     800                 :            :                                 int user)
     801                 :            : {
     802                 :            :         /* Resizes the resolution of the display adapater */
     803                 :            :         int err = 0;
     804                 :            : 
     805 [ #  # ][ #  # ]:          0 :         if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_resize)
     806                 :          0 :                 err = vc->vc_sw->con_resize(vc, width, height, user);
     807                 :            : 
     808                 :            :         return err;
     809                 :            : }
     810                 :            : 
     811                 :            : /*
     812                 :            :  * Change # of rows and columns (0 means unchanged/the size of fg_console)
     813                 :            :  * [this is to be used together with some user program
     814                 :            :  * like resize that changes the hardware videomode]
     815                 :            :  */
     816                 :            : #define VC_RESIZE_MAXCOL (32767)
     817                 :            : #define VC_RESIZE_MAXROW (32767)
     818                 :            : 
     819                 :            : /**
     820                 :            :  *      vc_do_resize    -       resizing method for the tty
     821                 :            :  *      @tty: tty being resized
     822                 :            :  *      @real_tty: real tty (different to tty if a pty/tty pair)
     823                 :            :  *      @vc: virtual console private data
     824                 :            :  *      @cols: columns
     825                 :            :  *      @lines: lines
     826                 :            :  *
     827                 :            :  *      Resize a virtual console, clipping according to the actual constraints.
     828                 :            :  *      If the caller passes a tty structure then update the termios winsize
     829                 :            :  *      information and perform any necessary signal handling.
     830                 :            :  *
     831                 :            :  *      Caller must hold the console semaphore. Takes the termios rwsem and
     832                 :            :  *      ctrl_lock of the tty IFF a tty is passed.
     833                 :            :  */
     834                 :            : 
     835                 :          0 : static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
     836                 :            :                                 unsigned int cols, unsigned int lines)
     837                 :            : {
     838                 :            :         unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
     839                 :            :         unsigned long end;
     840                 :            :         unsigned int old_rows, old_row_size;
     841                 :            :         unsigned int new_cols, new_rows, new_row_size, new_screen_size;
     842                 :            :         unsigned int user;
     843                 :            :         unsigned short *newscreen;
     844                 :            : 
     845 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
     846                 :            : 
     847         [ #  # ]:          0 :         if (!vc)
     848                 :            :                 return -ENXIO;
     849                 :            : 
     850                 :          0 :         user = vc->vc_resize_user;
     851                 :          0 :         vc->vc_resize_user = 0;
     852                 :            : 
     853         [ #  # ]:          0 :         if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
     854                 :            :                 return -EINVAL;
     855                 :            : 
     856         [ #  # ]:          0 :         new_cols = (cols ? cols : vc->vc_cols);
     857         [ #  # ]:          0 :         new_rows = (lines ? lines : vc->vc_rows);
     858                 :          0 :         new_row_size = new_cols << 1;
     859                 :          0 :         new_screen_size = new_row_size * new_rows;
     860                 :            : 
     861 [ #  # ][ #  # ]:          0 :         if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
     862                 :            :                 return 0;
     863                 :            : 
     864                 :            :         newscreen = kmalloc(new_screen_size, GFP_USER);
     865         [ #  # ]:          0 :         if (!newscreen)
     866                 :            :                 return -ENOMEM;
     867                 :            : 
     868                 :          0 :         old_rows = vc->vc_rows;
     869                 :          0 :         old_row_size = vc->vc_size_row;
     870                 :            : 
     871                 :          0 :         err = resize_screen(vc, new_cols, new_rows, user);
     872         [ #  # ]:          0 :         if (err) {
     873                 :          0 :                 kfree(newscreen);
     874                 :          0 :                 return err;
     875                 :            :         }
     876                 :            : 
     877                 :          0 :         vc->vc_rows = new_rows;
     878                 :          0 :         vc->vc_cols = new_cols;
     879                 :          0 :         vc->vc_size_row = new_row_size;
     880                 :          0 :         vc->vc_screenbuf_size = new_screen_size;
     881                 :            : 
     882                 :          0 :         rlth = min(old_row_size, new_row_size);
     883                 :          0 :         rrem = new_row_size - rlth;
     884                 :          0 :         old_origin = vc->vc_origin;
     885                 :          0 :         new_origin = (long) newscreen;
     886                 :          0 :         new_scr_end = new_origin + new_screen_size;
     887                 :            : 
     888         [ #  # ]:          0 :         if (vc->vc_y > new_rows) {
     889         [ #  # ]:          0 :                 if (old_rows - vc->vc_y < new_rows) {
     890                 :            :                         /*
     891                 :            :                          * Cursor near the bottom, copy contents from the
     892                 :            :                          * bottom of buffer
     893                 :            :                          */
     894                 :          0 :                         old_origin += (old_rows - new_rows) * old_row_size;
     895                 :            :                 } else {
     896                 :            :                         /*
     897                 :            :                          * Cursor is in no man's land, copy 1/2 screenful
     898                 :            :                          * from the top and bottom of cursor position
     899                 :            :                          */
     900                 :          0 :                         old_origin += (vc->vc_y - new_rows/2) * old_row_size;
     901                 :            :                 }
     902                 :            :         }
     903                 :            : 
     904                 :          0 :         end = old_origin + old_row_size * min(old_rows, new_rows);
     905                 :            : 
     906                 :          0 :         update_attr(vc);
     907                 :            : 
     908         [ #  # ]:          0 :         while (old_origin < end) {
     909                 :          0 :                 scr_memcpyw((unsigned short *) new_origin,
     910                 :            :                             (unsigned short *) old_origin, rlth);
     911         [ #  # ]:          0 :                 if (rrem)
     912                 :          0 :                         scr_memsetw((void *)(new_origin + rlth),
     913                 :            :                                     vc->vc_video_erase_char, rrem);
     914                 :          0 :                 old_origin += old_row_size;
     915                 :          0 :                 new_origin += new_row_size;
     916                 :            :         }
     917         [ #  # ]:          0 :         if (new_scr_end > new_origin)
     918                 :          0 :                 scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
     919                 :          0 :                             new_scr_end - new_origin);
     920                 :          0 :         kfree(vc->vc_screenbuf);
     921                 :          0 :         vc->vc_screenbuf = newscreen;
     922                 :          0 :         vc->vc_screenbuf_size = new_screen_size;
     923                 :          0 :         set_origin(vc);
     924                 :            : 
     925                 :            :         /* do part of a reset_terminal() */
     926                 :          0 :         vc->vc_top = 0;
     927                 :          0 :         vc->vc_bottom = vc->vc_rows;
     928                 :          0 :         gotoxy(vc, vc->vc_x, vc->vc_y);
     929                 :            :         save_cur(vc);
     930                 :            : 
     931         [ #  # ]:          0 :         if (tty) {
     932                 :            :                 /* Rewrite the requested winsize data with the actual
     933                 :            :                    resulting sizes */
     934                 :            :                 struct winsize ws;
     935                 :          0 :                 memset(&ws, 0, sizeof(ws));
     936                 :          0 :                 ws.ws_row = vc->vc_rows;
     937                 :          0 :                 ws.ws_col = vc->vc_cols;
     938                 :          0 :                 ws.ws_ypixel = vc->vc_scan_lines;
     939                 :          0 :                 tty_do_resize(tty, &ws);
     940                 :            :         }
     941                 :            : 
     942         [ #  # ]:          0 :         if (CON_IS_VISIBLE(vc))
     943                 :          0 :                 update_screen(vc);
     944                 :          0 :         vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
     945                 :          0 :         return err;
     946                 :            : }
     947                 :            : 
     948                 :            : /**
     949                 :            :  *      vc_resize               -       resize a VT
     950                 :            :  *      @vc: virtual console
     951                 :            :  *      @cols: columns
     952                 :            :  *      @rows: rows
     953                 :            :  *
     954                 :            :  *      Resize a virtual console as seen from the console end of things. We
     955                 :            :  *      use the common vc_do_resize methods to update the structures. The
     956                 :            :  *      caller must hold the console sem to protect console internals and
     957                 :            :  *      vc->port.tty
     958                 :            :  */
     959                 :            : 
     960                 :          0 : int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows)
     961                 :            : {
     962                 :          0 :         return vc_do_resize(vc->port.tty, vc, cols, rows);
     963                 :            : }
     964                 :            : 
     965                 :            : /**
     966                 :            :  *      vt_resize               -       resize a VT
     967                 :            :  *      @tty: tty to resize
     968                 :            :  *      @ws: winsize attributes
     969                 :            :  *
     970                 :            :  *      Resize a virtual terminal. This is called by the tty layer as we
     971                 :            :  *      register our own handler for resizing. The mutual helper does all
     972                 :            :  *      the actual work.
     973                 :            :  *
     974                 :            :  *      Takes the console sem and the called methods then take the tty
     975                 :            :  *      termios_rwsem and the tty ctrl_lock in that order.
     976                 :            :  */
     977                 :          0 : static int vt_resize(struct tty_struct *tty, struct winsize *ws)
     978                 :            : {
     979                 :          0 :         struct vc_data *vc = tty->driver_data;
     980                 :            :         int ret;
     981                 :            : 
     982                 :          0 :         console_lock();
     983                 :          0 :         ret = vc_do_resize(tty, vc, ws->ws_col, ws->ws_row);
     984                 :          0 :         console_unlock();
     985                 :          0 :         return ret;
     986                 :            : }
     987                 :            : 
     988                 :          0 : struct vc_data *vc_deallocate(unsigned int currcons)
     989                 :            : {
     990                 :            :         struct vc_data *vc = NULL;
     991                 :            : 
     992 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
     993                 :            : 
     994         [ #  # ]:          0 :         if (vc_cons_allocated(currcons)) {
     995                 :            :                 struct vt_notifier_param param;
     996                 :            : 
     997                 :          0 :                 param.vc = vc = vc_cons[currcons].d;
     998                 :          0 :                 atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
     999                 :          0 :                 vcs_remove_sysfs(currcons);
    1000                 :          0 :                 vc->vc_sw->con_deinit(vc);
    1001                 :          0 :                 put_pid(vc->vt_pid);
    1002                 :          0 :                 module_put(vc->vc_sw->owner);
    1003                 :          0 :                 kfree(vc->vc_screenbuf);
    1004                 :          0 :                 vc_cons[currcons].d = NULL;
    1005                 :            :         }
    1006                 :          0 :         return vc;
    1007                 :            : }
    1008                 :            : 
    1009                 :            : /*
    1010                 :            :  *      VT102 emulator
    1011                 :            :  */
    1012                 :            : 
    1013                 :            : #define set_kbd(vc, x)  vt_set_kbd_mode_bit((vc)->vc_num, (x))
    1014                 :            : #define clr_kbd(vc, x)  vt_clr_kbd_mode_bit((vc)->vc_num, (x))
    1015                 :            : #define is_kbd(vc, x)   vt_get_kbd_mode_bit((vc)->vc_num, (x))
    1016                 :            : 
    1017                 :            : #define decarm          VC_REPEAT
    1018                 :            : #define decckm          VC_CKMODE
    1019                 :            : #define kbdapplic       VC_APPLIC
    1020                 :            : #define lnm             VC_CRLF
    1021                 :            : 
    1022                 :            : /*
    1023                 :            :  * this is what the terminal answers to a ESC-Z or csi0c query.
    1024                 :            :  */
    1025                 :            : #define VT100ID "\033[?1;2c"
    1026                 :            : #define VT102ID "\033[?6c"
    1027                 :            : 
    1028                 :            : unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
    1029                 :            :                                        8,12,10,14, 9,13,11,15 };
    1030                 :            : 
    1031                 :            : /* the default colour table, for VGA+ colour systems */
    1032                 :            : int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
    1033                 :            :     0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
    1034                 :            : int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
    1035                 :            :     0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
    1036                 :            : int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
    1037                 :            :     0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
    1038                 :            : 
    1039                 :            : module_param_array(default_red, int, NULL, S_IRUGO | S_IWUSR);
    1040                 :            : module_param_array(default_grn, int, NULL, S_IRUGO | S_IWUSR);
    1041                 :            : module_param_array(default_blu, int, NULL, S_IRUGO | S_IWUSR);
    1042                 :            : 
    1043                 :            : /*
    1044                 :            :  * gotoxy() must verify all boundaries, because the arguments
    1045                 :            :  * might also be negative. If the given position is out of
    1046                 :            :  * bounds, the cursor is placed at the nearest margin.
    1047                 :            :  */
    1048                 :          0 : static void gotoxy(struct vc_data *vc, int new_x, int new_y)
    1049                 :            : {
    1050                 :            :         int min_y, max_y;
    1051                 :            : 
    1052         [ -  + ]:         56 :         if (new_x < 0)
    1053                 :          0 :                 vc->vc_x = 0;
    1054                 :            :         else {
    1055         [ -  + ]:         56 :                 if (new_x >= vc->vc_cols)
    1056                 :          0 :                         vc->vc_x = vc->vc_cols - 1;
    1057                 :            :                 else
    1058                 :         56 :                         vc->vc_x = new_x;
    1059                 :            :         }
    1060                 :            : 
    1061         [ -  + ]:         56 :         if (vc->vc_decom) {
    1062                 :          0 :                 min_y = vc->vc_top;
    1063                 :          0 :                 max_y = vc->vc_bottom;
    1064                 :            :         } else {
    1065                 :            :                 min_y = 0;
    1066                 :         56 :                 max_y = vc->vc_rows;
    1067                 :            :         }
    1068         [ -  + ]:         56 :         if (new_y < min_y)
    1069                 :          0 :                 vc->vc_y = min_y;
    1070         [ -  + ]:         56 :         else if (new_y >= max_y)
    1071                 :          0 :                 vc->vc_y = max_y - 1;
    1072                 :            :         else
    1073                 :         56 :                 vc->vc_y = new_y;
    1074                 :         56 :         vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x<<1);
    1075                 :         56 :         vc->vc_need_wrap = 0;
    1076                 :         56 : }
    1077                 :            : 
    1078                 :            : /* for absolute user moves, when decom is set */
    1079                 :            : static void gotoxay(struct vc_data *vc, int new_x, int new_y)
    1080                 :            : {
    1081 [ #  # ][ #  # ]:          0 :         gotoxy(vc, new_x, vc->vc_decom ? (vc->vc_top + new_y) : new_y);
         [ #  # ][ #  # ]
    1082                 :            : }
    1083                 :            : 
    1084                 :          0 : void scrollback(struct vc_data *vc, int lines)
    1085                 :            : {
    1086         [ #  # ]:          0 :         if (!lines)
    1087                 :          0 :                 lines = vc->vc_rows / 2;
    1088                 :            :         scrolldelta(-lines);
    1089                 :          0 : }
    1090                 :            : 
    1091                 :          0 : void scrollfront(struct vc_data *vc, int lines)
    1092                 :            : {
    1093 [ #  # ][ #  # ]:          0 :         if (!lines)
    1094                 :          0 :                 lines = vc->vc_rows / 2;
    1095                 :            :         scrolldelta(lines);
    1096                 :          0 : }
    1097                 :            : 
    1098                 :          0 : static void lf(struct vc_data *vc)
    1099                 :            : {
    1100                 :            :         /* don't scroll if above bottom of scrolling region, or
    1101                 :            :          * if below scrolling region
    1102                 :            :          */
    1103         [ #  # ]:          0 :         if (vc->vc_y + 1 == vc->vc_bottom)
    1104                 :          0 :                 scrup(vc, vc->vc_top, vc->vc_bottom, 1);
    1105         [ #  # ]:          0 :         else if (vc->vc_y < vc->vc_rows - 1) {
    1106                 :          0 :                 vc->vc_y++;
    1107                 :          0 :                 vc->vc_pos += vc->vc_size_row;
    1108                 :            :         }
    1109                 :          0 :         vc->vc_need_wrap = 0;
    1110                 :            :         notify_write(vc, '\n');
    1111                 :          0 : }
    1112                 :            : 
    1113                 :          0 : static void ri(struct vc_data *vc)
    1114                 :            : {
    1115                 :            :         /* don't scroll if below top of scrolling region, or
    1116                 :            :          * if above scrolling region
    1117                 :            :          */
    1118         [ #  # ]:          0 :         if (vc->vc_y == vc->vc_top)
    1119                 :          0 :                 scrdown(vc, vc->vc_top, vc->vc_bottom, 1);
    1120         [ #  # ]:          0 :         else if (vc->vc_y > 0) {
    1121                 :          0 :                 vc->vc_y--;
    1122                 :          0 :                 vc->vc_pos -= vc->vc_size_row;
    1123                 :            :         }
    1124                 :          0 :         vc->vc_need_wrap = 0;
    1125                 :          0 : }
    1126                 :            : 
    1127                 :            : static inline void cr(struct vc_data *vc)
    1128                 :            : {
    1129                 :          0 :         vc->vc_pos -= vc->vc_x << 1;
    1130                 :          0 :         vc->vc_need_wrap = vc->vc_x = 0;
    1131                 :          0 :         notify_write(vc, '\r');
    1132                 :            : }
    1133                 :            : 
    1134                 :            : static inline void bs(struct vc_data *vc)
    1135                 :            : {
    1136 [ #  # ][ #  # ]:          0 :         if (vc->vc_x) {
    1137                 :          0 :                 vc->vc_pos -= 2;
    1138                 :          0 :                 vc->vc_x--;
    1139                 :          0 :                 vc->vc_need_wrap = 0;
    1140                 :          0 :                 notify_write(vc, '\b');
    1141                 :            :         }
    1142                 :            : }
    1143                 :            : 
    1144                 :            : static inline void del(struct vc_data *vc)
    1145                 :            : {
    1146                 :            :         /* ignored */
    1147                 :            : }
    1148                 :            : 
    1149                 :          0 : static void csi_J(struct vc_data *vc, int vpar)
    1150                 :            : {
    1151                 :            :         unsigned int count;
    1152                 :            :         unsigned short * start;
    1153                 :            : 
    1154   [ +  -  -  + ]:         56 :         switch (vpar) {
    1155                 :            :                 case 0: /* erase from cursor to end of display */
    1156                 :          0 :                         count = (vc->vc_scr_end - vc->vc_pos) >> 1;
    1157                 :          0 :                         start = (unsigned short *)vc->vc_pos;
    1158                 :         56 :                         break;
    1159                 :            :                 case 1: /* erase from start to cursor */
    1160                 :          0 :                         count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
    1161                 :          0 :                         start = (unsigned short *)vc->vc_origin;
    1162                 :          0 :                         break;
    1163                 :            :                 case 3: /* erase scroll-back buffer (and whole display) */
    1164                 :          0 :                         scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
    1165                 :          0 :                                     vc->vc_screenbuf_size >> 1);
    1166                 :          0 :                         set_origin(vc);
    1167                 :            :                         /* fall through */
    1168                 :            :                 case 2: /* erase whole display */
    1169                 :         56 :                         count = vc->vc_cols * vc->vc_rows;
    1170                 :         56 :                         start = (unsigned short *)vc->vc_origin;
    1171                 :         56 :                         break;
    1172                 :            :                 default:
    1173                 :          0 :                         return;
    1174                 :            :         }
    1175                 :         56 :         scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
    1176 [ -  + ][ #  # ]:         56 :         if (DO_UPDATE(vc))
    1177                 :          0 :                 do_update_region(vc, (unsigned long) start, count);
    1178                 :         56 :         vc->vc_need_wrap = 0;
    1179                 :            : }
    1180                 :            : 
    1181                 :          0 : static void csi_K(struct vc_data *vc, int vpar)
    1182                 :            : {
    1183                 :            :         unsigned int count;
    1184                 :            :         unsigned short * start;
    1185                 :            : 
    1186   [ #  #  #  # ]:          0 :         switch (vpar) {
    1187                 :            :                 case 0: /* erase from cursor to end of line */
    1188                 :          0 :                         count = vc->vc_cols - vc->vc_x;
    1189                 :          0 :                         start = (unsigned short *)vc->vc_pos;
    1190                 :          0 :                         break;
    1191                 :            :                 case 1: /* erase from start of line to cursor */
    1192                 :          0 :                         start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
    1193                 :          0 :                         count = vc->vc_x + 1;
    1194                 :          0 :                         break;
    1195                 :            :                 case 2: /* erase whole line */
    1196                 :          0 :                         start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
    1197                 :          0 :                         count = vc->vc_cols;
    1198                 :          0 :                         break;
    1199                 :            :                 default:
    1200                 :          0 :                         return;
    1201                 :            :         }
    1202                 :          0 :         scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
    1203                 :          0 :         vc->vc_need_wrap = 0;
    1204 [ #  # ][ #  # ]:          0 :         if (DO_UPDATE(vc))
    1205                 :          0 :                 do_update_region(vc, (unsigned long) start, count);
    1206                 :            : }
    1207                 :            : 
    1208                 :          0 : static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */
    1209                 :            : {                                         /* not vt100? */
    1210                 :            :         int count;
    1211                 :            : 
    1212         [ #  # ]:          0 :         if (!vpar)
    1213                 :          0 :                 vpar++;
    1214                 :          0 :         count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;
    1215                 :            : 
    1216                 :          0 :         scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
    1217 [ #  # ][ #  # ]:          0 :         if (DO_UPDATE(vc))
    1218                 :          0 :                 vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);
    1219                 :          0 :         vc->vc_need_wrap = 0;
    1220                 :          0 : }
    1221                 :            : 
    1222                 :            : static void default_attr(struct vc_data *vc)
    1223                 :            : {
    1224                 :         56 :         vc->vc_intensity = 1;
    1225                 :         56 :         vc->vc_italic = 0;
    1226                 :         56 :         vc->vc_underline = 0;
    1227                 :         56 :         vc->vc_reverse = 0;
    1228                 :         56 :         vc->vc_blink = 0;
    1229                 :          0 :         vc->vc_color = vc->vc_def_color;
    1230                 :            : }
    1231                 :            : 
    1232                 :            : /* console_lock is held */
    1233                 :          0 : static void csi_m(struct vc_data *vc)
    1234                 :            : {
    1235                 :            :         int i;
    1236                 :            : 
    1237         [ #  # ]:          0 :         for (i = 0; i <= vc->vc_npar; i++)
    1238   [ #  #  #  #  :          0 :                 switch (vc->vc_par[i]) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1239                 :            :                         case 0: /* all attributes off */
    1240                 :            :                                 default_attr(vc);
    1241                 :            :                                 break;
    1242                 :            :                         case 1:
    1243                 :          0 :                                 vc->vc_intensity = 2;
    1244                 :          0 :                                 break;
    1245                 :            :                         case 2:
    1246                 :          0 :                                 vc->vc_intensity = 0;
    1247                 :          0 :                                 break;
    1248                 :            :                         case 3:
    1249                 :          0 :                                 vc->vc_italic = 1;
    1250                 :          0 :                                 break;
    1251                 :            :                         case 4:
    1252                 :          0 :                                 vc->vc_underline = 1;
    1253                 :          0 :                                 break;
    1254                 :            :                         case 5:
    1255                 :          0 :                                 vc->vc_blink = 1;
    1256                 :          0 :                                 break;
    1257                 :            :                         case 7:
    1258                 :          0 :                                 vc->vc_reverse = 1;
    1259                 :          0 :                                 break;
    1260                 :            :                         case 10: /* ANSI X3.64-1979 (SCO-ish?)
    1261                 :            :                                   * Select primary font, don't display
    1262                 :            :                                   * control chars if defined, don't set
    1263                 :            :                                   * bit 8 on output.
    1264                 :            :                                   */
    1265         [ #  # ]:          0 :                                 vc->vc_translate = set_translate(vc->vc_charset == 0
    1266                 :          0 :                                                 ? vc->vc_G0_charset
    1267                 :          0 :                                                 : vc->vc_G1_charset, vc);
    1268                 :          0 :                                 vc->vc_disp_ctrl = 0;
    1269                 :          0 :                                 vc->vc_toggle_meta = 0;
    1270                 :          0 :                                 break;
    1271                 :            :                         case 11: /* ANSI X3.64-1979 (SCO-ish?)
    1272                 :            :                                   * Select first alternate font, lets
    1273                 :            :                                   * chars < 32 be displayed as ROM chars.
    1274                 :            :                                   */
    1275                 :          0 :                                 vc->vc_translate = set_translate(IBMPC_MAP, vc);
    1276                 :          0 :                                 vc->vc_disp_ctrl = 1;
    1277                 :          0 :                                 vc->vc_toggle_meta = 0;
    1278                 :          0 :                                 break;
    1279                 :            :                         case 12: /* ANSI X3.64-1979 (SCO-ish?)
    1280                 :            :                                   * Select second alternate font, toggle
    1281                 :            :                                   * high bit before displaying as ROM char.
    1282                 :            :                                   */
    1283                 :          0 :                                 vc->vc_translate = set_translate(IBMPC_MAP, vc);
    1284                 :          0 :                                 vc->vc_disp_ctrl = 1;
    1285                 :          0 :                                 vc->vc_toggle_meta = 1;
    1286                 :          0 :                                 break;
    1287                 :            :                         case 21:
    1288                 :            :                         case 22:
    1289                 :          0 :                                 vc->vc_intensity = 1;
    1290                 :          0 :                                 break;
    1291                 :            :                         case 23:
    1292                 :          0 :                                 vc->vc_italic = 0;
    1293                 :          0 :                                 break;
    1294                 :            :                         case 24:
    1295                 :          0 :                                 vc->vc_underline = 0;
    1296                 :          0 :                                 break;
    1297                 :            :                         case 25:
    1298                 :          0 :                                 vc->vc_blink = 0;
    1299                 :          0 :                                 break;
    1300                 :            :                         case 27:
    1301                 :          0 :                                 vc->vc_reverse = 0;
    1302                 :          0 :                                 break;
    1303                 :            :                         case 38:
    1304                 :            :                         case 48: /* ITU T.416
    1305                 :            :                                   * Higher colour modes.
    1306                 :            :                                   * They break the usual properties of SGR codes
    1307                 :            :                                   * and thus need to be detected and ignored by
    1308                 :            :                                   * hand.  Strictly speaking, that standard also
    1309                 :            :                                   * wants : rather than ; as separators, contrary
    1310                 :            :                                   * to ECMA-48, but no one produces such codes
    1311                 :            :                                   * and almost no one accepts them.
    1312                 :            :                                   */
    1313                 :          0 :                                 i++;
    1314         [ #  # ]:          0 :                                 if (i > vc->vc_npar)
    1315                 :            :                                         break;
    1316         [ #  # ]:          0 :                                 if (vc->vc_par[i] == 5)      /* 256 colours */
    1317                 :          0 :                                         i++;                 /* ubiquitous */
    1318         [ #  # ]:          0 :                                 else if (vc->vc_par[i] == 2) /* 24 bit colours */
    1319                 :          0 :                                         i += 3;              /* extremely rare */
    1320                 :            :                                 /* Subcommands 3 (CMY) and 4 (CMYK) are so insane
    1321                 :            :                                  * that detecting them is not worth the few extra
    1322                 :            :                                  * bytes of kernel's size.
    1323                 :            :                                  */
    1324                 :            :                                 break;
    1325                 :            :                         case 39:
    1326                 :          0 :                                 vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
    1327                 :          0 :                                 break;
    1328                 :            :                         case 49:
    1329                 :          0 :                                 vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
    1330                 :          0 :                                 break;
    1331                 :            :                         default:
    1332         [ #  # ]:          0 :                                 if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
    1333                 :          0 :                                         vc->vc_color = color_table[vc->vc_par[i] - 30]
    1334                 :          0 :                                                 | (vc->vc_color & 0xf0);
    1335         [ #  # ]:          0 :                                 else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
    1336                 :          0 :                                         vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
    1337                 :          0 :                                                 | (vc->vc_color & 0x0f);
    1338                 :            :                                 break;
    1339                 :            :                 }
    1340                 :          0 :         update_attr(vc);
    1341                 :          0 : }
    1342                 :            : 
    1343                 :          0 : static void respond_string(const char *p, struct tty_port *port)
    1344                 :            : {
    1345         [ #  # ]:          0 :         while (*p) {
    1346                 :            :                 tty_insert_flip_char(port, *p, 0);
    1347                 :          0 :                 p++;
    1348                 :            :         }
    1349                 :          0 :         tty_schedule_flip(port);
    1350                 :          0 : }
    1351                 :            : 
    1352                 :          0 : static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
    1353                 :            : {
    1354                 :            :         char buf[40];
    1355                 :            : 
    1356         [ #  # ]:          0 :         sprintf(buf, "\033[%d;%dR", vc->vc_y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->vc_x + 1);
    1357                 :          0 :         respond_string(buf, tty->port);
    1358                 :          0 : }
    1359                 :            : 
    1360                 :            : static inline void status_report(struct tty_struct *tty)
    1361                 :            : {
    1362                 :          0 :         respond_string("\033[0n", tty->port);      /* Terminal ok */
    1363                 :            : }
    1364                 :            : 
    1365                 :            : static inline void respond_ID(struct tty_struct *tty)
    1366                 :            : {
    1367                 :          0 :         respond_string(VT102ID, tty->port);
    1368                 :            : }
    1369                 :            : 
    1370                 :          0 : void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry)
    1371                 :            : {
    1372                 :            :         char buf[8];
    1373                 :            : 
    1374                 :          0 :         sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
    1375                 :          0 :                 (char)('!' + mry));
    1376                 :          0 :         respond_string(buf, tty->port);
    1377                 :          0 : }
    1378                 :            : 
    1379                 :            : /* invoked via ioctl(TIOCLINUX) and through set_selection */
    1380                 :          0 : int mouse_reporting(void)
    1381                 :            : {
    1382                 :          0 :         return vc_cons[fg_console].d->vc_report_mouse;
    1383                 :            : }
    1384                 :            : 
    1385                 :            : /* console_lock is held */
    1386                 :          0 : static void set_mode(struct vc_data *vc, int on_off)
    1387                 :            : {
    1388                 :            :         int i;
    1389                 :            : 
    1390         [ #  # ]:          0 :         for (i = 0; i <= vc->vc_npar; i++)
    1391         [ #  # ]:          0 :                 if (vc->vc_ques) {
    1392   [ #  #  #  #  :          0 :                         switch(vc->vc_par[i]) {      /* DEC private modes set/reset */
          #  #  #  #  #  
                      # ]
    1393                 :            :                         case 1:                 /* Cursor keys send ^[Ox/^[[x */
    1394         [ #  # ]:          0 :                                 if (on_off)
    1395                 :          0 :                                         set_kbd(vc, decckm);
    1396                 :            :                                 else
    1397                 :          0 :                                         clr_kbd(vc, decckm);
    1398                 :            :                                 break;
    1399                 :            :                         case 3: /* 80/132 mode switch unimplemented */
    1400                 :          0 :                                 vc->vc_deccolm = on_off;
    1401                 :            : #if 0
    1402                 :            :                                 vc_resize(deccolm ? 132 : 80, vc->vc_rows);
    1403                 :            :                                 /* this alone does not suffice; some user mode
    1404                 :            :                                    utility has to change the hardware regs */
    1405                 :            : #endif
    1406                 :          0 :                                 break;
    1407                 :            :                         case 5:                 /* Inverted screen on/off */
    1408         [ #  # ]:          0 :                                 if (vc->vc_decscnm != on_off) {
    1409                 :          0 :                                         vc->vc_decscnm = on_off;
    1410                 :          0 :                                         invert_screen(vc, 0, vc->vc_screenbuf_size, 0);
    1411                 :          0 :                                         update_attr(vc);
    1412                 :            :                                 }
    1413                 :            :                                 break;
    1414                 :            :                         case 6:                 /* Origin relative/absolute */
    1415                 :          0 :                                 vc->vc_decom = on_off;
    1416                 :            :                                 gotoxay(vc, 0, 0);
    1417                 :            :                                 break;
    1418                 :            :                         case 7:                 /* Autowrap on/off */
    1419                 :          0 :                                 vc->vc_decawm = on_off;
    1420                 :          0 :                                 break;
    1421                 :            :                         case 8:                 /* Autorepeat on/off */
    1422         [ #  # ]:          0 :                                 if (on_off)
    1423                 :          0 :                                         set_kbd(vc, decarm);
    1424                 :            :                                 else
    1425                 :          0 :                                         clr_kbd(vc, decarm);
    1426                 :            :                                 break;
    1427                 :            :                         case 9:
    1428                 :          0 :                                 vc->vc_report_mouse = on_off ? 1 : 0;
    1429                 :          0 :                                 break;
    1430                 :            :                         case 25:                /* Cursor on/off */
    1431                 :          0 :                                 vc->vc_deccm = on_off;
    1432                 :          0 :                                 break;
    1433                 :            :                         case 1000:
    1434         [ #  # ]:          0 :                                 vc->vc_report_mouse = on_off ? 2 : 0;
    1435                 :          0 :                                 break;
    1436                 :            :                         }
    1437                 :            :                 } else {
    1438   [ #  #  #  # ]:          0 :                         switch(vc->vc_par[i]) {      /* ANSI modes set/reset */
    1439                 :            :                         case 3:                 /* Monitor (display ctrls) */
    1440                 :          0 :                                 vc->vc_disp_ctrl = on_off;
    1441                 :          0 :                                 break;
    1442                 :            :                         case 4:                 /* Insert Mode on/off */
    1443                 :          0 :                                 vc->vc_decim = on_off;
    1444                 :          0 :                                 break;
    1445                 :            :                         case 20:                /* Lf, Enter == CrLf/Lf */
    1446         [ #  # ]:          0 :                                 if (on_off)
    1447                 :          0 :                                         set_kbd(vc, lnm);
    1448                 :            :                                 else
    1449                 :          0 :                                         clr_kbd(vc, lnm);
    1450                 :            :                                 break;
    1451                 :            :                         }
    1452                 :            :                 }
    1453                 :          0 : }
    1454                 :            : 
    1455                 :            : /* console_lock is held */
    1456                 :          0 : static void setterm_command(struct vc_data *vc)
    1457                 :            : {
    1458   [ #  #  #  #  :          0 :         switch(vc->vc_par[0]) {
          #  #  #  #  #  
                   #  # ]
    1459                 :            :                 case 1: /* set color for underline mode */
    1460 [ #  # ][ #  # ]:          0 :                         if (vc->vc_can_do_color &&
    1461                 :          0 :                                         vc->vc_par[1] < 16) {
    1462                 :          0 :                                 vc->vc_ulcolor = color_table[vc->vc_par[1]];
    1463         [ #  # ]:          0 :                                 if (vc->vc_underline)
    1464                 :          0 :                                         update_attr(vc);
    1465                 :            :                         }
    1466                 :            :                         break;
    1467                 :            :                 case 2: /* set color for half intensity mode */
    1468 [ #  # ][ #  # ]:          0 :                         if (vc->vc_can_do_color &&
    1469                 :          0 :                                         vc->vc_par[1] < 16) {
    1470                 :          0 :                                 vc->vc_halfcolor = color_table[vc->vc_par[1]];
    1471         [ #  # ]:          0 :                                 if (vc->vc_intensity == 0)
    1472                 :          0 :                                         update_attr(vc);
    1473                 :            :                         }
    1474                 :            :                         break;
    1475                 :            :                 case 8: /* store colors as defaults */
    1476                 :          0 :                         vc->vc_def_color = vc->vc_attr;
    1477         [ #  # ]:          0 :                         if (vc->vc_hi_font_mask == 0x100)
    1478                 :          0 :                                 vc->vc_def_color >>= 1;
    1479                 :            :                         default_attr(vc);
    1480                 :          0 :                         update_attr(vc);
    1481                 :          0 :                         break;
    1482                 :            :                 case 9: /* set blanking interval */
    1483                 :          0 :                         blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60;
    1484                 :          0 :                         poke_blanked_console();
    1485                 :          0 :                         break;
    1486                 :            :                 case 10: /* set bell frequency in Hz */
    1487         [ #  # ]:          0 :                         if (vc->vc_npar >= 1)
    1488                 :          0 :                                 vc->vc_bell_pitch = vc->vc_par[1];
    1489                 :            :                         else
    1490                 :          0 :                                 vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
    1491                 :            :                         break;
    1492                 :            :                 case 11: /* set bell duration in msec */
    1493         [ #  # ]:          0 :                         if (vc->vc_npar >= 1)
    1494                 :          0 :                                 vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
    1495         [ #  # ]:          0 :                                         vc->vc_par[1] * HZ / 1000 : 0;
    1496                 :            :                         else
    1497                 :          0 :                                 vc->vc_bell_duration = DEFAULT_BELL_DURATION;
    1498                 :            :                         break;
    1499                 :            :                 case 12: /* bring specified console to the front */
    1500 [ #  # ][ #  # ]:          0 :                         if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1))
    1501                 :          0 :                                 set_console(vc->vc_par[1] - 1);
    1502                 :            :                         break;
    1503                 :            :                 case 13: /* unblank the screen */
    1504                 :          0 :                         poke_blanked_console();
    1505                 :          0 :                         break;
    1506                 :            :                 case 14: /* set vesa powerdown interval */
    1507                 :          0 :                         vesa_off_interval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
    1508                 :          0 :                         break;
    1509                 :            :                 case 15: /* activate the previous console */
    1510                 :          0 :                         set_console(last_console);
    1511                 :          0 :                         break;
    1512                 :            :         }
    1513                 :          0 : }
    1514                 :            : 
    1515                 :            : /* console_lock is held */
    1516                 :          0 : static void csi_at(struct vc_data *vc, unsigned int nr)
    1517                 :            : {
    1518         [ #  # ]:          0 :         if (nr > vc->vc_cols - vc->vc_x)
    1519                 :            :                 nr = vc->vc_cols - vc->vc_x;
    1520         [ #  # ]:          0 :         else if (!nr)
    1521                 :            :                 nr = 1;
    1522                 :          0 :         insert_char(vc, nr);
    1523                 :          0 : }
    1524                 :            : 
    1525                 :            : /* console_lock is held */
    1526                 :          0 : static void csi_L(struct vc_data *vc, unsigned int nr)
    1527                 :            : {
    1528         [ #  # ]:          0 :         if (nr > vc->vc_rows - vc->vc_y)
    1529                 :            :                 nr = vc->vc_rows - vc->vc_y;
    1530         [ #  # ]:          0 :         else if (!nr)
    1531                 :            :                 nr = 1;
    1532                 :          0 :         scrdown(vc, vc->vc_y, vc->vc_bottom, nr);
    1533                 :          0 :         vc->vc_need_wrap = 0;
    1534                 :          0 : }
    1535                 :            : 
    1536                 :            : /* console_lock is held */
    1537                 :          0 : static void csi_P(struct vc_data *vc, unsigned int nr)
    1538                 :            : {
    1539         [ #  # ]:          0 :         if (nr > vc->vc_cols - vc->vc_x)
    1540                 :            :                 nr = vc->vc_cols - vc->vc_x;
    1541         [ #  # ]:          0 :         else if (!nr)
    1542                 :            :                 nr = 1;
    1543                 :          0 :         delete_char(vc, nr);
    1544                 :          0 : }
    1545                 :            : 
    1546                 :            : /* console_lock is held */
    1547                 :          0 : static void csi_M(struct vc_data *vc, unsigned int nr)
    1548                 :            : {
    1549         [ #  # ]:          0 :         if (nr > vc->vc_rows - vc->vc_y)
    1550                 :            :                 nr = vc->vc_rows - vc->vc_y;
    1551         [ #  # ]:          0 :         else if (!nr)
    1552                 :            :                 nr=1;
    1553                 :          0 :         scrup(vc, vc->vc_y, vc->vc_bottom, nr);
    1554                 :          0 :         vc->vc_need_wrap = 0;
    1555                 :          0 : }
    1556                 :            : 
    1557                 :            : /* console_lock is held (except via vc_init->reset_terminal */
    1558                 :            : static void save_cur(struct vc_data *vc)
    1559                 :            : {
    1560                 :         56 :         vc->vc_saved_x               = vc->vc_x;
    1561                 :         56 :         vc->vc_saved_y               = vc->vc_y;
    1562                 :         56 :         vc->vc_s_intensity   = vc->vc_intensity;
    1563                 :         56 :         vc->vc_s_italic         = vc->vc_italic;
    1564                 :         56 :         vc->vc_s_underline   = vc->vc_underline;
    1565                 :         56 :         vc->vc_s_blink               = vc->vc_blink;
    1566                 :         56 :         vc->vc_s_reverse     = vc->vc_reverse;
    1567                 :         56 :         vc->vc_s_charset     = vc->vc_charset;
    1568                 :         56 :         vc->vc_s_color               = vc->vc_color;
    1569                 :         56 :         vc->vc_saved_G0              = vc->vc_G0_charset;
    1570                 :          0 :         vc->vc_saved_G1              = vc->vc_G1_charset;
    1571                 :            : }
    1572                 :            : 
    1573                 :            : /* console_lock is held */
    1574                 :          0 : static void restore_cur(struct vc_data *vc)
    1575                 :            : {
    1576                 :          0 :         gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y);
    1577                 :          0 :         vc->vc_intensity     = vc->vc_s_intensity;
    1578                 :          0 :         vc->vc_italic                = vc->vc_s_italic;
    1579                 :          0 :         vc->vc_underline     = vc->vc_s_underline;
    1580                 :          0 :         vc->vc_blink         = vc->vc_s_blink;
    1581                 :          0 :         vc->vc_reverse               = vc->vc_s_reverse;
    1582                 :          0 :         vc->vc_charset               = vc->vc_s_charset;
    1583                 :          0 :         vc->vc_color         = vc->vc_s_color;
    1584                 :          0 :         vc->vc_G0_charset    = vc->vc_saved_G0;
    1585                 :          0 :         vc->vc_G1_charset    = vc->vc_saved_G1;
    1586         [ #  # ]:          0 :         vc->vc_translate     = set_translate(vc->vc_charset ? vc->vc_G1_charset : vc->vc_G0_charset, vc);
    1587                 :          0 :         update_attr(vc);
    1588                 :          0 :         vc->vc_need_wrap = 0;
    1589                 :          0 : }
    1590                 :            : 
    1591                 :            : enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
    1592                 :            :         EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
    1593                 :            :         ESpalette };
    1594                 :            : 
    1595                 :            : /* console_lock is held (except via vc_init()) */
    1596                 :          0 : static void reset_terminal(struct vc_data *vc, int do_clear)
    1597                 :            : {
    1598                 :         56 :         vc->vc_top           = 0;
    1599                 :         56 :         vc->vc_bottom                = vc->vc_rows;
    1600                 :         56 :         vc->vc_state         = ESnormal;
    1601                 :         56 :         vc->vc_ques          = 0;
    1602                 :         56 :         vc->vc_translate     = set_translate(LAT1_MAP, vc);
    1603                 :         56 :         vc->vc_G0_charset    = LAT1_MAP;
    1604                 :         56 :         vc->vc_G1_charset    = GRAF_MAP;
    1605                 :         56 :         vc->vc_charset               = 0;
    1606                 :         56 :         vc->vc_need_wrap     = 0;
    1607                 :         56 :         vc->vc_report_mouse  = 0;
    1608                 :         56 :         vc->vc_utf              = default_utf8;
    1609                 :         56 :         vc->vc_utf_count     = 0;
    1610                 :            : 
    1611                 :         56 :         vc->vc_disp_ctrl     = 0;
    1612                 :         56 :         vc->vc_toggle_meta   = 0;
    1613                 :            : 
    1614                 :         56 :         vc->vc_decscnm               = 0;
    1615                 :         56 :         vc->vc_decom         = 0;
    1616                 :         56 :         vc->vc_decawm                = 1;
    1617                 :         56 :         vc->vc_deccm         = global_cursor_default;
    1618                 :         56 :         vc->vc_decim         = 0;
    1619                 :            : 
    1620                 :         56 :         vt_reset_keyboard(vc->vc_num);
    1621                 :            : 
    1622                 :         56 :         vc->vc_cursor_type = cur_default;
    1623                 :         56 :         vc->vc_complement_mask = vc->vc_s_complement_mask;
    1624                 :            : 
    1625                 :            :         default_attr(vc);
    1626                 :         56 :         update_attr(vc);
    1627                 :            : 
    1628                 :         56 :         vc->vc_tab_stop[0]   = 0x01010100;
    1629                 :         56 :         vc->vc_tab_stop[1]   =
    1630                 :         56 :         vc->vc_tab_stop[2]   =
    1631                 :         56 :         vc->vc_tab_stop[3]   =
    1632                 :         56 :         vc->vc_tab_stop[4]   =
    1633                 :         56 :         vc->vc_tab_stop[5]   =
    1634                 :         56 :         vc->vc_tab_stop[6]   =
    1635                 :         56 :         vc->vc_tab_stop[7]   = 0x01010101;
    1636                 :            : 
    1637                 :         56 :         vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
    1638                 :         56 :         vc->vc_bell_duration = DEFAULT_BELL_DURATION;
    1639                 :            : 
    1640                 :         56 :         gotoxy(vc, 0, 0);
    1641                 :            :         save_cur(vc);
    1642         [ +  - ]:         56 :         if (do_clear)
    1643                 :         56 :             csi_J(vc, 2);
    1644                 :          0 : }
    1645                 :            : 
    1646                 :            : /* console_lock is held */
    1647                 :          0 : static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
    1648                 :            : {
    1649                 :            :         /*
    1650                 :            :          *  Control characters can be used in the _middle_
    1651                 :            :          *  of an escape sequence.
    1652                 :            :          */
    1653   [ #  #  #  #  :          0 :         switch (c) {
          #  #  #  #  #  
                #  #  # ]
    1654                 :            :         case 0:
    1655                 :            :                 return;
    1656                 :            :         case 7:
    1657         [ #  # ]:          0 :                 if (vc->vc_bell_duration)
    1658                 :          0 :                         kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
    1659                 :            :                 return;
    1660                 :            :         case 8:
    1661                 :            :                 bs(vc);
    1662                 :            :                 return;
    1663                 :            :         case 9:
    1664                 :          0 :                 vc->vc_pos -= (vc->vc_x << 1);
    1665         [ #  # ]:          0 :                 while (vc->vc_x < vc->vc_cols - 1) {
    1666                 :          0 :                         vc->vc_x++;
    1667         [ #  # ]:          0 :                         if (vc->vc_tab_stop[vc->vc_x >> 5] & (1 << (vc->vc_x & 31)))
    1668                 :            :                                 break;
    1669                 :            :                 }
    1670                 :          0 :                 vc->vc_pos += (vc->vc_x << 1);
    1671                 :            :                 notify_write(vc, '\t');
    1672                 :            :                 return;
    1673                 :            :         case 10: case 11: case 12:
    1674                 :          0 :                 lf(vc);
    1675         [ #  # ]:          0 :                 if (!is_kbd(vc, lnm))
    1676                 :            :                         return;
    1677                 :            :         case 13:
    1678                 :            :                 cr(vc);
    1679                 :            :                 return;
    1680                 :            :         case 14:
    1681                 :          0 :                 vc->vc_charset = 1;
    1682                 :          0 :                 vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
    1683                 :          0 :                 vc->vc_disp_ctrl = 1;
    1684                 :          0 :                 return;
    1685                 :            :         case 15:
    1686                 :          0 :                 vc->vc_charset = 0;
    1687                 :          0 :                 vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
    1688                 :          0 :                 vc->vc_disp_ctrl = 0;
    1689                 :          0 :                 return;
    1690                 :            :         case 24: case 26:
    1691                 :          0 :                 vc->vc_state = ESnormal;
    1692                 :          0 :                 return;
    1693                 :            :         case 27:
    1694                 :          0 :                 vc->vc_state = ESesc;
    1695                 :          0 :                 return;
    1696                 :            :         case 127:
    1697                 :            :                 del(vc);
    1698                 :            :                 return;
    1699                 :            :         case 128+27:
    1700                 :          0 :                 vc->vc_state = ESsquare;
    1701                 :          0 :                 return;
    1702                 :            :         }
    1703   [ #  #  #  #  :          0 :         switch(vc->vc_state) {
          #  #  #  #  #  
                #  #  # ]
    1704                 :            :         case ESesc:
    1705                 :          0 :                 vc->vc_state = ESnormal;
    1706   [ #  #  #  #  :          0 :                 switch (c) {
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
    1707                 :            :                 case '[':
    1708                 :          0 :                         vc->vc_state = ESsquare;
    1709                 :          0 :                         return;
    1710                 :            :                 case ']':
    1711                 :          0 :                         vc->vc_state = ESnonstd;
    1712                 :          0 :                         return;
    1713                 :            :                 case '%':
    1714                 :          0 :                         vc->vc_state = ESpercent;
    1715                 :          0 :                         return;
    1716                 :            :                 case 'E':
    1717                 :            :                         cr(vc);
    1718                 :          0 :                         lf(vc);
    1719                 :          0 :                         return;
    1720                 :            :                 case 'M':
    1721                 :          0 :                         ri(vc);
    1722                 :          0 :                         return;
    1723                 :            :                 case 'D':
    1724                 :          0 :                         lf(vc);
    1725                 :          0 :                         return;
    1726                 :            :                 case 'H':
    1727                 :          0 :                         vc->vc_tab_stop[vc->vc_x >> 5] |= (1 << (vc->vc_x & 31));
    1728                 :          0 :                         return;
    1729                 :            :                 case 'Z':
    1730                 :            :                         respond_ID(tty);
    1731                 :            :                         return;
    1732                 :            :                 case '7':
    1733                 :            :                         save_cur(vc);
    1734                 :            :                         return;
    1735                 :            :                 case '8':
    1736                 :          0 :                         restore_cur(vc);
    1737                 :          0 :                         return;
    1738                 :            :                 case '(':
    1739                 :          0 :                         vc->vc_state = ESsetG0;
    1740                 :          0 :                         return;
    1741                 :            :                 case ')':
    1742                 :          0 :                         vc->vc_state = ESsetG1;
    1743                 :          0 :                         return;
    1744                 :            :                 case '#':
    1745                 :          0 :                         vc->vc_state = EShash;
    1746                 :          0 :                         return;
    1747                 :            :                 case 'c':
    1748                 :          0 :                         reset_terminal(vc, 1);
    1749                 :          0 :                         return;
    1750                 :            :                 case '>':  /* Numeric keypad */
    1751                 :          0 :                         clr_kbd(vc, kbdapplic);
    1752                 :          0 :                         return;
    1753                 :            :                 case '=':  /* Appl. keypad */
    1754                 :          0 :                         set_kbd(vc, kbdapplic);
    1755                 :          0 :                         return;
    1756                 :            :                 }
    1757                 :            :                 return;
    1758                 :            :         case ESnonstd:
    1759         [ #  # ]:          0 :                 if (c=='P') {   /* palette escape sequence */
    1760         [ #  # ]:          0 :                         for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
    1761                 :          0 :                                 vc->vc_par[vc->vc_npar] = 0;
    1762                 :          0 :                         vc->vc_npar = 0;
    1763                 :          0 :                         vc->vc_state = ESpalette;
    1764                 :          0 :                         return;
    1765         [ #  # ]:          0 :                 } else if (c=='R') {   /* reset palette */
    1766                 :          0 :                         reset_palette(vc);
    1767                 :          0 :                         vc->vc_state = ESnormal;
    1768                 :            :                 } else
    1769                 :          0 :                         vc->vc_state = ESnormal;
    1770                 :            :                 return;
    1771                 :            :         case ESpalette:
    1772         [ #  # ]:          0 :                 if (isxdigit(c)) {
    1773                 :          0 :                         vc->vc_par[vc->vc_npar++] = hex_to_bin(c);
    1774         [ #  # ]:          0 :                         if (vc->vc_npar == 7) {
    1775                 :          0 :                                 int i = vc->vc_par[0] * 3, j = 1;
    1776                 :          0 :                                 vc->vc_palette[i] = 16 * vc->vc_par[j++];
    1777                 :          0 :                                 vc->vc_palette[i++] += vc->vc_par[j++];
    1778                 :          0 :                                 vc->vc_palette[i] = 16 * vc->vc_par[j++];
    1779                 :          0 :                                 vc->vc_palette[i++] += vc->vc_par[j++];
    1780                 :          0 :                                 vc->vc_palette[i] = 16 * vc->vc_par[j++];
    1781                 :          0 :                                 vc->vc_palette[i] += vc->vc_par[j];
    1782                 :          0 :                                 set_palette(vc);
    1783                 :          0 :                                 vc->vc_state = ESnormal;
    1784                 :            :                         }
    1785                 :            :                 } else
    1786                 :          0 :                         vc->vc_state = ESnormal;
    1787                 :            :                 return;
    1788                 :            :         case ESsquare:
    1789         [ #  # ]:          0 :                 for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
    1790                 :          0 :                         vc->vc_par[vc->vc_npar] = 0;
    1791                 :          0 :                 vc->vc_npar = 0;
    1792                 :          0 :                 vc->vc_state = ESgetpars;
    1793         [ #  # ]:          0 :                 if (c == '[') { /* Function key */
    1794                 :          0 :                         vc->vc_state=ESfunckey;
    1795                 :          0 :                         return;
    1796                 :            :                 }
    1797                 :          0 :                 vc->vc_ques = (c == '?');
    1798         [ #  # ]:          0 :                 if (vc->vc_ques)
    1799                 :            :                         return;
    1800                 :            :         case ESgetpars:
    1801 [ #  # ][ #  # ]:          0 :                 if (c == ';' && vc->vc_npar < NPAR - 1) {
    1802                 :          0 :                         vc->vc_npar++;
    1803                 :          0 :                         return;
    1804         [ #  # ]:          0 :                 } else if (c>='0' && c<='9') {
    1805                 :          0 :                         vc->vc_par[vc->vc_npar] *= 10;
    1806                 :          0 :                         vc->vc_par[vc->vc_npar] += c - '0';
    1807                 :          0 :                         return;
    1808                 :            :                 } else
    1809                 :          0 :                         vc->vc_state = ESgotpars;
    1810                 :            :         case ESgotpars:
    1811                 :          0 :                 vc->vc_state = ESnormal;
    1812   [ #  #  #  #  :          0 :                 switch(c) {
                   #  # ]
    1813                 :            :                 case 'h':
    1814                 :          0 :                         set_mode(vc, 1);
    1815                 :          0 :                         return;
    1816                 :            :                 case 'l':
    1817                 :          0 :                         set_mode(vc, 0);
    1818                 :          0 :                         return;
    1819                 :            :                 case 'c':
    1820         [ #  # ]:          0 :                         if (vc->vc_ques) {
    1821         [ #  # ]:          0 :                                 if (vc->vc_par[0])
    1822                 :          0 :                                         vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);
    1823                 :            :                                 else
    1824                 :          0 :                                         vc->vc_cursor_type = cur_default;
    1825                 :            :                                 return;
    1826                 :            :                         }
    1827                 :            :                         break;
    1828                 :            :                 case 'm':
    1829         [ #  # ]:          0 :                         if (vc->vc_ques) {
    1830                 :          0 :                                 clear_selection();
    1831         [ #  # ]:          0 :                                 if (vc->vc_par[0])
    1832                 :          0 :                                         vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1];
    1833                 :            :                                 else
    1834                 :          0 :                                         vc->vc_complement_mask = vc->vc_s_complement_mask;
    1835                 :            :                                 return;
    1836                 :            :                         }
    1837                 :            :                         break;
    1838                 :            :                 case 'n':
    1839         [ #  # ]:          0 :                         if (!vc->vc_ques) {
    1840         [ #  # ]:          0 :                                 if (vc->vc_par[0] == 5)
    1841                 :            :                                         status_report(tty);
    1842         [ #  # ]:          0 :                                 else if (vc->vc_par[0] == 6)
    1843                 :          0 :                                         cursor_report(vc, tty);
    1844                 :            :                         }
    1845                 :            :                         return;
    1846                 :            :                 }
    1847         [ #  # ]:          0 :                 if (vc->vc_ques) {
    1848                 :          0 :                         vc->vc_ques = 0;
    1849                 :          0 :                         return;
    1850                 :            :                 }
    1851   [ #  #  #  #  :          0 :                 switch(c) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
    1852                 :            :                 case 'G': case '`':
    1853         [ #  # ]:          0 :                         if (vc->vc_par[0])
    1854                 :          0 :                                 vc->vc_par[0]--;
    1855                 :          0 :                         gotoxy(vc, vc->vc_par[0], vc->vc_y);
    1856                 :          0 :                         return;
    1857                 :            :                 case 'A':
    1858         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1859                 :          0 :                                 vc->vc_par[0]++;
    1860                 :          0 :                         gotoxy(vc, vc->vc_x, vc->vc_y - vc->vc_par[0]);
    1861                 :          0 :                         return;
    1862                 :            :                 case 'B': case 'e':
    1863         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1864                 :          0 :                                 vc->vc_par[0]++;
    1865                 :          0 :                         gotoxy(vc, vc->vc_x, vc->vc_y + vc->vc_par[0]);
    1866                 :          0 :                         return;
    1867                 :            :                 case 'C': case 'a':
    1868         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1869                 :          0 :                                 vc->vc_par[0]++;
    1870                 :          0 :                         gotoxy(vc, vc->vc_x + vc->vc_par[0], vc->vc_y);
    1871                 :          0 :                         return;
    1872                 :            :                 case 'D':
    1873         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1874                 :          0 :                                 vc->vc_par[0]++;
    1875                 :          0 :                         gotoxy(vc, vc->vc_x - vc->vc_par[0], vc->vc_y);
    1876                 :          0 :                         return;
    1877                 :            :                 case 'E':
    1878         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1879                 :          0 :                                 vc->vc_par[0]++;
    1880                 :          0 :                         gotoxy(vc, 0, vc->vc_y + vc->vc_par[0]);
    1881                 :          0 :                         return;
    1882                 :            :                 case 'F':
    1883         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1884                 :          0 :                                 vc->vc_par[0]++;
    1885                 :          0 :                         gotoxy(vc, 0, vc->vc_y - vc->vc_par[0]);
    1886                 :          0 :                         return;
    1887                 :            :                 case 'd':
    1888         [ #  # ]:          0 :                         if (vc->vc_par[0])
    1889                 :          0 :                                 vc->vc_par[0]--;
    1890                 :          0 :                         gotoxay(vc, vc->vc_x ,vc->vc_par[0]);
    1891                 :            :                         return;
    1892                 :            :                 case 'H': case 'f':
    1893         [ #  # ]:          0 :                         if (vc->vc_par[0])
    1894                 :          0 :                                 vc->vc_par[0]--;
    1895         [ #  # ]:          0 :                         if (vc->vc_par[1])
    1896                 :          0 :                                 vc->vc_par[1]--;
    1897                 :          0 :                         gotoxay(vc, vc->vc_par[1], vc->vc_par[0]);
    1898                 :            :                         return;
    1899                 :            :                 case 'J':
    1900                 :          0 :                         csi_J(vc, vc->vc_par[0]);
    1901                 :          0 :                         return;
    1902                 :            :                 case 'K':
    1903                 :          0 :                         csi_K(vc, vc->vc_par[0]);
    1904                 :          0 :                         return;
    1905                 :            :                 case 'L':
    1906                 :          0 :                         csi_L(vc, vc->vc_par[0]);
    1907                 :          0 :                         return;
    1908                 :            :                 case 'M':
    1909                 :          0 :                         csi_M(vc, vc->vc_par[0]);
    1910                 :          0 :                         return;
    1911                 :            :                 case 'P':
    1912                 :          0 :                         csi_P(vc, vc->vc_par[0]);
    1913                 :          0 :                         return;
    1914                 :            :                 case 'c':
    1915         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1916                 :            :                                 respond_ID(tty);
    1917                 :            :                         return;
    1918                 :            :                 case 'g':
    1919         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1920                 :          0 :                                 vc->vc_tab_stop[vc->vc_x >> 5] &= ~(1 << (vc->vc_x & 31));
    1921         [ #  # ]:          0 :                         else if (vc->vc_par[0] == 3) {
    1922                 :          0 :                                 vc->vc_tab_stop[0] =
    1923                 :          0 :                                         vc->vc_tab_stop[1] =
    1924                 :          0 :                                         vc->vc_tab_stop[2] =
    1925                 :          0 :                                         vc->vc_tab_stop[3] =
    1926                 :          0 :                                         vc->vc_tab_stop[4] =
    1927                 :          0 :                                         vc->vc_tab_stop[5] =
    1928                 :          0 :                                         vc->vc_tab_stop[6] =
    1929                 :          0 :                                         vc->vc_tab_stop[7] = 0;
    1930                 :            :                         }
    1931                 :            :                         return;
    1932                 :            :                 case 'm':
    1933                 :          0 :                         csi_m(vc);
    1934                 :          0 :                         return;
    1935                 :            :                 case 'q': /* DECLL - but only 3 leds */
    1936                 :            :                         /* map 0,1,2,3 to 0,1,2,4 */
    1937         [ #  # ]:          0 :                         if (vc->vc_par[0] < 4)
    1938         [ #  # ]:          0 :                                 vt_set_led_state(vc->vc_num,
    1939                 :            :                                             (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4);
    1940                 :            :                         return;
    1941                 :            :                 case 'r':
    1942         [ #  # ]:          0 :                         if (!vc->vc_par[0])
    1943                 :          0 :                                 vc->vc_par[0]++;
    1944         [ #  # ]:          0 :                         if (!vc->vc_par[1])
    1945                 :          0 :                                 vc->vc_par[1] = vc->vc_rows;
    1946                 :            :                         /* Minimum allowed region is 2 lines */
    1947 [ #  # ][ #  # ]:          0 :                         if (vc->vc_par[0] < vc->vc_par[1] &&
    1948                 :          0 :                             vc->vc_par[1] <= vc->vc_rows) {
    1949                 :          0 :                                 vc->vc_top = vc->vc_par[0] - 1;
    1950                 :          0 :                                 vc->vc_bottom = vc->vc_par[1];
    1951                 :            :                                 gotoxay(vc, 0, 0);
    1952                 :            :                         }
    1953                 :            :                         return;
    1954                 :            :                 case 's':
    1955                 :            :                         save_cur(vc);
    1956                 :            :                         return;
    1957                 :            :                 case 'u':
    1958                 :          0 :                         restore_cur(vc);
    1959                 :          0 :                         return;
    1960                 :            :                 case 'X':
    1961                 :          0 :                         csi_X(vc, vc->vc_par[0]);
    1962                 :          0 :                         return;
    1963                 :            :                 case '@':
    1964                 :          0 :                         csi_at(vc, vc->vc_par[0]);
    1965                 :          0 :                         return;
    1966                 :            :                 case ']': /* setterm functions */
    1967                 :          0 :                         setterm_command(vc);
    1968                 :          0 :                         return;
    1969                 :            :                 }
    1970                 :            :                 return;
    1971                 :            :         case ESpercent:
    1972                 :          0 :                 vc->vc_state = ESnormal;
    1973      [ #  #  # ]:          0 :                 switch (c) {
    1974                 :            :                 case '@':  /* defined in ISO 2022 */
    1975                 :          0 :                         vc->vc_utf = 0;
    1976                 :          0 :                         return;
    1977                 :            :                 case 'G':  /* prelim official escape code */
    1978                 :            :                 case '8':  /* retained for compatibility */
    1979                 :          0 :                         vc->vc_utf = 1;
    1980                 :          0 :                         return;
    1981                 :            :                 }
    1982                 :            :                 return;
    1983                 :            :         case ESfunckey:
    1984                 :          0 :                 vc->vc_state = ESnormal;
    1985                 :          0 :                 return;
    1986                 :            :         case EShash:
    1987                 :          0 :                 vc->vc_state = ESnormal;
    1988         [ #  # ]:          0 :                 if (c == '8') {
    1989                 :            :                         /* DEC screen alignment test. kludge :-) */
    1990                 :          0 :                         vc->vc_video_erase_char =
    1991                 :          0 :                                 (vc->vc_video_erase_char & 0xff00) | 'E';
    1992                 :          0 :                         csi_J(vc, 2);
    1993                 :          0 :                         vc->vc_video_erase_char =
    1994                 :          0 :                                 (vc->vc_video_erase_char & 0xff00) | ' ';
    1995                 :          0 :                         do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
    1996                 :            :                 }
    1997                 :            :                 return;
    1998                 :            :         case ESsetG0:
    1999         [ #  # ]:          0 :                 if (c == '0')
    2000                 :          0 :                         vc->vc_G0_charset = GRAF_MAP;
    2001         [ #  # ]:          0 :                 else if (c == 'B')
    2002                 :          0 :                         vc->vc_G0_charset = LAT1_MAP;
    2003         [ #  # ]:          0 :                 else if (c == 'U')
    2004                 :          0 :                         vc->vc_G0_charset = IBMPC_MAP;
    2005         [ #  # ]:          0 :                 else if (c == 'K')
    2006                 :          0 :                         vc->vc_G0_charset = USER_MAP;
    2007         [ #  # ]:          0 :                 if (vc->vc_charset == 0)
    2008                 :          0 :                         vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
    2009                 :          0 :                 vc->vc_state = ESnormal;
    2010                 :          0 :                 return;
    2011                 :            :         case ESsetG1:
    2012         [ #  # ]:          0 :                 if (c == '0')
    2013                 :          0 :                         vc->vc_G1_charset = GRAF_MAP;
    2014         [ #  # ]:          0 :                 else if (c == 'B')
    2015                 :          0 :                         vc->vc_G1_charset = LAT1_MAP;
    2016         [ #  # ]:          0 :                 else if (c == 'U')
    2017                 :          0 :                         vc->vc_G1_charset = IBMPC_MAP;
    2018         [ #  # ]:          0 :                 else if (c == 'K')
    2019                 :          0 :                         vc->vc_G1_charset = USER_MAP;
    2020         [ #  # ]:          0 :                 if (vc->vc_charset == 1)
    2021                 :          0 :                         vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
    2022                 :          0 :                 vc->vc_state = ESnormal;
    2023                 :          0 :                 return;
    2024                 :            :         default:
    2025                 :          0 :                 vc->vc_state = ESnormal;
    2026                 :            :         }
    2027                 :            : }
    2028                 :            : 
    2029                 :            : /* is_double_width() is based on the wcwidth() implementation by
    2030                 :            :  * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
    2031                 :            :  * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
    2032                 :            :  */
    2033                 :            : struct interval {
    2034                 :            :         uint32_t first;
    2035                 :            :         uint32_t last;
    2036                 :            : };
    2037                 :            : 
    2038                 :          0 : static int bisearch(uint32_t ucs, const struct interval *table, int max)
    2039                 :            : {
    2040                 :            :         int min = 0;
    2041                 :            :         int mid;
    2042                 :            : 
    2043 [ #  # ][ #  # ]:          0 :         if (ucs < table[0].first || ucs > table[max].last)
    2044                 :            :                 return 0;
    2045         [ #  # ]:          0 :         while (max >= min) {
    2046                 :          0 :                 mid = (min + max) / 2;
    2047         [ #  # ]:          0 :                 if (ucs > table[mid].last)
    2048                 :          0 :                         min = mid + 1;
    2049         [ #  # ]:          0 :                 else if (ucs < table[mid].first)
    2050                 :          0 :                         max = mid - 1;
    2051                 :            :                 else
    2052                 :            :                         return 1;
    2053                 :            :         }
    2054                 :            :         return 0;
    2055                 :            : }
    2056                 :            : 
    2057                 :            : static int is_double_width(uint32_t ucs)
    2058                 :            : {
    2059                 :            :         static const struct interval double_width[] = {
    2060                 :            :                 { 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E },
    2061                 :            :                 { 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF },
    2062                 :            :                 { 0xFE10, 0xFE19 }, { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 },
    2063                 :            :                 { 0xFFE0, 0xFFE6 }, { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD }
    2064                 :            :         };
    2065                 :          0 :         return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1);
    2066                 :            : }
    2067                 :            : 
    2068                 :            : /* acquires console_lock */
    2069                 :          0 : static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count)
    2070                 :            : {
    2071                 :            : #ifdef VT_BUF_VRAM_ONLY
    2072                 :            : #define FLUSH do { } while(0);
    2073                 :            : #else
    2074                 :            : #define FLUSH if (draw_x >= 0) { \
    2075                 :            :         vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, draw_x); \
    2076                 :            :         draw_x = -1; \
    2077                 :            :         }
    2078                 :            : #endif
    2079                 :            : 
    2080                 :            :         int c, tc, ok, n = 0, draw_x = -1;
    2081                 :            :         unsigned int currcons;
    2082                 :            :         unsigned long draw_from = 0, draw_to = 0;
    2083                 :            :         struct vc_data *vc;
    2084                 :            :         unsigned char vc_attr;
    2085                 :            :         struct vt_notifier_param param;
    2086                 :            :         uint8_t rescan;
    2087                 :            :         uint8_t inverse;
    2088                 :            :         uint8_t width;
    2089                 :            :         u16 himask, charmask;
    2090                 :            : 
    2091         [ #  # ]:          0 :         if (in_interrupt())
    2092                 :            :                 return count;
    2093                 :            : 
    2094                 :            :         might_sleep();
    2095                 :            : 
    2096                 :          0 :         console_lock();
    2097                 :          0 :         vc = tty->driver_data;
    2098         [ #  # ]:          0 :         if (vc == NULL) {
    2099                 :          0 :                 printk(KERN_ERR "vt: argh, driver_data is NULL !\n");
    2100                 :          0 :                 console_unlock();
    2101                 :          0 :                 return 0;
    2102                 :            :         }
    2103                 :            : 
    2104                 :          0 :         currcons = vc->vc_num;
    2105         [ #  # ]:          0 :         if (!vc_cons_allocated(currcons)) {
    2106                 :            :                 /* could this happen? */
    2107         [ #  # ]:          0 :                 pr_warn_once("con_write: tty %d not allocated\n", currcons+1);
    2108                 :          0 :                 console_unlock();
    2109                 :          0 :                 return 0;
    2110                 :            :         }
    2111                 :            : 
    2112                 :          0 :         himask = vc->vc_hi_font_mask;
    2113         [ #  # ]:          0 :         charmask = himask ? 0x1ff : 0xff;
    2114                 :            : 
    2115                 :            :         /* undraw cursor first */
    2116         [ #  # ]:          0 :         if (IS_FG(vc))
    2117                 :          0 :                 hide_cursor(vc);
    2118                 :            : 
    2119                 :          0 :         param.vc = vc;
    2120                 :            : 
    2121 [ #  # ][ #  # ]:          0 :         while (!tty->stopped && count) {
    2122                 :          0 :                 int orig = *buf;
    2123                 :            :                 c = orig;
    2124                 :          0 :                 buf++;
    2125                 :          0 :                 n++;
    2126                 :          0 :                 count--;
    2127                 :            :                 rescan = 0;
    2128                 :            :                 inverse = 0;
    2129                 :            :                 width = 1;
    2130                 :            : 
    2131                 :            :                 /* Do no translation at all in control states */
    2132         [ #  # ]:          0 :                 if (vc->vc_state != ESnormal) {
    2133                 :            :                         tc = c;
    2134         [ #  # ]:          0 :                 } else if (vc->vc_utf && !vc->vc_disp_ctrl) {
    2135                 :            :                     /* Combine UTF-8 into Unicode in vc_utf_char.
    2136                 :            :                      * vc_utf_count is the number of continuation bytes still
    2137                 :            :                      * expected to arrive.
    2138                 :            :                      * vc_npar is the number of continuation bytes arrived so
    2139                 :            :                      * far
    2140                 :            :                      */
    2141                 :            : rescan_last_byte:
    2142         [ #  # ]:          0 :                     if ((c & 0xc0) == 0x80) {
    2143                 :            :                         /* Continuation byte received */
    2144                 :            :                         static const uint32_t utf8_length_changes[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff };
    2145         [ #  # ]:          0 :                         if (vc->vc_utf_count) {
    2146                 :          0 :                             vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
    2147                 :          0 :                             vc->vc_npar++;
    2148         [ #  # ]:          0 :                             if (--vc->vc_utf_count) {
    2149                 :            :                                 /* Still need some bytes */
    2150                 :          0 :                                 continue;
    2151                 :            :                             }
    2152                 :            :                             /* Got a whole character */
    2153                 :            :                             c = vc->vc_utf_char;
    2154                 :            :                             /* Reject overlong sequences */
    2155 [ #  # ][ #  # ]:          0 :                             if (c <= utf8_length_changes[vc->vc_npar - 1] ||
    2156                 :          0 :                                         c > utf8_length_changes[vc->vc_npar])
    2157                 :            :                                 c = 0xfffd;
    2158                 :            :                         } else {
    2159                 :            :                             /* Unexpected continuation byte */
    2160                 :          0 :                             vc->vc_utf_count = 0;
    2161                 :            :                             c = 0xfffd;
    2162                 :            :                         }
    2163                 :            :                     } else {
    2164                 :            :                         /* Single ASCII byte or first byte of a sequence received */
    2165         [ #  # ]:          0 :                         if (vc->vc_utf_count) {
    2166                 :            :                             /* Continuation byte expected */
    2167                 :            :                             rescan = 1;
    2168                 :          0 :                             vc->vc_utf_count = 0;
    2169                 :            :                             c = 0xfffd;
    2170         [ #  # ]:          0 :                         } else if (c > 0x7f) {
    2171                 :            :                             /* First byte of a multibyte sequence received */
    2172                 :          0 :                             vc->vc_npar = 0;
    2173         [ #  # ]:          0 :                             if ((c & 0xe0) == 0xc0) {
    2174                 :          0 :                                 vc->vc_utf_count = 1;
    2175                 :          0 :                                 vc->vc_utf_char = (c & 0x1f);
    2176         [ #  # ]:          0 :                             } else if ((c & 0xf0) == 0xe0) {
    2177                 :          0 :                                 vc->vc_utf_count = 2;
    2178                 :          0 :                                 vc->vc_utf_char = (c & 0x0f);
    2179         [ #  # ]:          0 :                             } else if ((c & 0xf8) == 0xf0) {
    2180                 :          0 :                                 vc->vc_utf_count = 3;
    2181                 :          0 :                                 vc->vc_utf_char = (c & 0x07);
    2182         [ #  # ]:          0 :                             } else if ((c & 0xfc) == 0xf8) {
    2183                 :          0 :                                 vc->vc_utf_count = 4;
    2184                 :          0 :                                 vc->vc_utf_char = (c & 0x03);
    2185         [ #  # ]:          0 :                             } else if ((c & 0xfe) == 0xfc) {
    2186                 :          0 :                                 vc->vc_utf_count = 5;
    2187                 :          0 :                                 vc->vc_utf_char = (c & 0x01);
    2188                 :            :                             } else {
    2189                 :            :                                 /* 254 and 255 are invalid */
    2190                 :            :                                 c = 0xfffd;
    2191                 :            :                             }
    2192         [ #  # ]:          0 :                             if (vc->vc_utf_count) {
    2193                 :            :                                 /* Still need some bytes */
    2194                 :          0 :                                 continue;
    2195                 :            :                             }
    2196                 :            :                         }
    2197                 :            :                         /* Nothing to do if an ASCII byte was received */
    2198                 :            :                     }
    2199                 :            :                     /* End of UTF-8 decoding. */
    2200                 :            :                     /* c is the received character, or U+FFFD for invalid sequences. */
    2201                 :            :                     /* Replace invalid Unicode code points with U+FFFD too */
    2202 [ #  # ][ #  # ]:          0 :                     if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff)
    2203                 :            :                         c = 0xfffd;
    2204                 :            :                     tc = c;
    2205                 :            :                 } else {        /* no utf or alternate charset mode */
    2206         [ #  # ]:          0 :                     tc = vc_translate(vc, c);
    2207                 :            :                 }
    2208                 :            : 
    2209                 :          0 :                 param.c = tc;
    2210         [ #  # ]:          0 :                 if (atomic_notifier_call_chain(&vt_notifier_list, VT_PREWRITE,
    2211                 :            :                                         &param) == NOTIFY_STOP)
    2212                 :          0 :                         continue;
    2213                 :            : 
    2214                 :            :                 /* If the original code was a control character we
    2215                 :            :                  * only allow a glyph to be displayed if the code is
    2216                 :            :                  * not normally used (such as for cursor movement) or
    2217                 :            :                  * if the disp_ctrl mode has been explicitly enabled.
    2218                 :            :                  * Certain characters (as given by the CTRL_ALWAYS
    2219                 :            :                  * bitmap) are always displayed as control characters,
    2220                 :            :                  * as the console would be pretty useless without
    2221                 :            :                  * them; to display an arbitrary font position use the
    2222                 :            :                  * direct-to-font zone in UTF-8 mode.
    2223                 :            :                  */
    2224 [ #  # ][ #  # ]:          0 :                 ok = tc && (c >= 32 ||
                 [ #  # ]
    2225                 :          0 :                             !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
    2226 [ #  # ][ #  # ]:          0 :                                   vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
    2227 [ #  # ][ #  # ]:          0 :                         && (c != 127 || vc->vc_disp_ctrl)
    2228 [ #  # ][ #  # ]:          0 :                         && (c != 128+27);
                 [ #  # ]
    2229                 :            : 
    2230 [ #  # ][ #  # ]:          0 :                 if (vc->vc_state == ESnormal && ok) {
    2231         [ #  # ]:          0 :                         if (vc->vc_utf && !vc->vc_disp_ctrl) {
    2232         [ #  # ]:          0 :                                 if (is_double_width(c))
    2233                 :            :                                         width = 2;
    2234                 :            :                         }
    2235                 :            :                         /* Now try to find out how to display it */
    2236                 :          0 :                         tc = conv_uni_to_pc(vc, tc);
    2237         [ #  # ]:          0 :                         if (tc & ~charmask) {
    2238         [ #  # ]:          0 :                                 if (tc == -1 || tc == -2) {
    2239                 :          0 :                                     continue; /* nothing to display */
    2240                 :            :                                 }
    2241                 :            :                                 /* Glyph not found */
    2242 [ #  # ][ #  # ]:          0 :                                 if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) {
                 [ #  # ]
    2243                 :            :                                     /* In legacy mode use the glyph we get by a 1:1 mapping.
    2244                 :            :                                        This would make absolutely no sense with Unicode in mind,
    2245                 :            :                                        but do this for ASCII characters since a font may lack
    2246                 :            :                                        Unicode mapping info and we don't want to end up with
    2247                 :            :                                        having question marks only. */
    2248                 :            :                                     tc = c;
    2249                 :            :                                 } else {
    2250                 :            :                                     /* Display U+FFFD. If it's not found, display an inverse question mark. */
    2251                 :          0 :                                     tc = conv_uni_to_pc(vc, 0xfffd);
    2252         [ #  # ]:          0 :                                     if (tc < 0) {
    2253                 :            :                                         inverse = 1;
    2254                 :          0 :                                         tc = conv_uni_to_pc(vc, '?');
    2255         [ #  # ]:          0 :                                         if (tc < 0) tc = '?';
    2256                 :            :                                     }
    2257                 :            :                                 }
    2258                 :            :                         }
    2259                 :            : 
    2260         [ #  # ]:          0 :                         if (!inverse) {
    2261                 :          0 :                                 vc_attr = vc->vc_attr;
    2262                 :            :                         } else {
    2263                 :            :                                 /* invert vc_attr */
    2264         [ #  # ]:          0 :                                 if (!vc->vc_can_do_color) {
    2265                 :          0 :                                         vc_attr = (vc->vc_attr) ^ 0x08;
    2266         [ #  # ]:          0 :                                 } else if (vc->vc_hi_font_mask == 0x100) {
    2267                 :          0 :                                         vc_attr = ((vc->vc_attr) & 0x11) | (((vc->vc_attr) & 0xe0) >> 4) | (((vc->vc_attr) & 0x0e) << 4);
    2268                 :            :                                 } else {
    2269                 :          0 :                                         vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
    2270                 :            :                                 }
    2271         [ #  # ]:          0 :                                 FLUSH
    2272                 :            :                         }
    2273                 :            : 
    2274                 :            :                         while (1) {
    2275         [ #  # ]:          0 :                                 if (vc->vc_need_wrap || vc->vc_decim)
    2276         [ #  # ]:          0 :                                         FLUSH
    2277         [ #  # ]:          0 :                                 if (vc->vc_need_wrap) {
    2278                 :            :                                         cr(vc);
    2279                 :          0 :                                         lf(vc);
    2280                 :            :                                 }
    2281         [ #  # ]:          0 :                                 if (vc->vc_decim)
    2282                 :          0 :                                         insert_char(vc, 1);
    2283 [ #  # ][ #  # ]:          0 :                                 scr_writew(himask ?
    2284                 :            :                                              ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
    2285                 :            :                                              (vc_attr << 8) + tc,
    2286                 :            :                                            (u16 *) vc->vc_pos);
    2287 [ #  # ][ #  # ]:          0 :                                 if (DO_UPDATE(vc) && draw_x < 0) {
                 [ #  # ]
    2288                 :          0 :                                         draw_x = vc->vc_x;
    2289                 :          0 :                                         draw_from = vc->vc_pos;
    2290                 :            :                                 }
    2291         [ #  # ]:          0 :                                 if (vc->vc_x == vc->vc_cols - 1) {
    2292                 :          0 :                                         vc->vc_need_wrap = vc->vc_decawm;
    2293                 :          0 :                                         draw_to = vc->vc_pos + 2;
    2294                 :            :                                 } else {
    2295                 :          0 :                                         vc->vc_x++;
    2296                 :          0 :                                         draw_to = (vc->vc_pos += 2);
    2297                 :            :                                 }
    2298                 :            : 
    2299         [ #  # ]:          0 :                                 if (!--width) break;
    2300                 :            : 
    2301                 :          0 :                                 tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
    2302         [ #  # ]:          0 :                                 if (tc < 0) tc = ' ';
    2303                 :            :                         }
    2304                 :          0 :                         notify_write(vc, c);
    2305                 :            : 
    2306         [ #  # ]:          0 :                         if (inverse) {
    2307         [ #  # ]:          0 :                                 FLUSH
    2308                 :            :                         }
    2309                 :            : 
    2310         [ #  # ]:          0 :                         if (rescan) {
    2311                 :            :                                 rescan = 0;
    2312                 :            :                                 inverse = 0;
    2313                 :            :                                 width = 1;
    2314                 :            :                                 c = orig;
    2315                 :            :                                 goto rescan_last_byte;
    2316                 :            :                         }
    2317                 :          0 :                         continue;
    2318                 :            :                 }
    2319         [ #  # ]:          0 :                 FLUSH
    2320                 :          0 :                 do_con_trol(tty, vc, orig);
    2321                 :            :         }
    2322         [ #  # ]:          0 :         FLUSH
    2323                 :          0 :         console_conditional_schedule();
    2324                 :          0 :         console_unlock();
    2325                 :            :         notify_update(vc);
    2326                 :          0 :         return n;
    2327                 :            : #undef FLUSH
    2328                 :            : }
    2329                 :            : 
    2330                 :            : /*
    2331                 :            :  * This is the console switching callback.
    2332                 :            :  *
    2333                 :            :  * Doing console switching in a process context allows
    2334                 :            :  * us to do the switches asynchronously (needed when we want
    2335                 :            :  * to switch due to a keyboard interrupt).  Synchronization
    2336                 :            :  * with other console code and prevention of re-entrancy is
    2337                 :            :  * ensured with console_lock.
    2338                 :            :  */
    2339                 :          0 : static void console_callback(struct work_struct *ignored)
    2340                 :            : {
    2341                 :          0 :         console_lock();
    2342                 :            : 
    2343         [ #  # ]:          0 :         if (want_console >= 0) {
    2344 [ #  # ][ #  # ]:          0 :                 if (want_console != fg_console &&
    2345                 :          0 :                     vc_cons_allocated(want_console)) {
    2346                 :          0 :                         hide_cursor(vc_cons[fg_console].d);
    2347                 :          0 :                         change_console(vc_cons[want_console].d);
    2348                 :            :                         /* we only changed when the console had already
    2349                 :            :                            been allocated - a new console is not created
    2350                 :            :                            in an interrupt routine */
    2351                 :            :                 }
    2352                 :          0 :                 want_console = -1;
    2353                 :            :         }
    2354         [ #  # ]:          0 :         if (do_poke_blanked_console) { /* do not unblank for a LED change */
    2355                 :          0 :                 do_poke_blanked_console = 0;
    2356                 :          0 :                 poke_blanked_console();
    2357                 :            :         }
    2358         [ #  # ]:          0 :         if (scrollback_delta) {
    2359                 :          0 :                 struct vc_data *vc = vc_cons[fg_console].d;
    2360                 :          0 :                 clear_selection();
    2361         [ #  # ]:          0 :                 if (vc->vc_mode == KD_TEXT)
    2362                 :          0 :                         vc->vc_sw->con_scrolldelta(vc, scrollback_delta);
    2363                 :          0 :                 scrollback_delta = 0;
    2364                 :            :         }
    2365         [ #  # ]:          0 :         if (blank_timer_expired) {
    2366                 :          0 :                 do_blank_screen(0);
    2367                 :          0 :                 blank_timer_expired = 0;
    2368                 :            :         }
    2369                 :          0 :         notify_update(vc_cons[fg_console].d);
    2370                 :            : 
    2371                 :          0 :         console_unlock();
    2372                 :          0 : }
    2373                 :            : 
    2374                 :          0 : int set_console(int nr)
    2375                 :            : {
    2376                 :          0 :         struct vc_data *vc = vc_cons[fg_console].d;
    2377                 :            : 
    2378 [ #  # ][ #  # ]:          0 :         if (!vc_cons_allocated(nr) || vt_dont_switch ||
                 [ #  # ]
    2379         [ #  # ]:          0 :                 (vc->vt_mode.mode == VT_AUTO && vc->vc_mode == KD_GRAPHICS)) {
    2380                 :            : 
    2381                 :            :                 /*
    2382                 :            :                  * Console switch will fail in console_callback() or
    2383                 :            :                  * change_console() so there is no point scheduling
    2384                 :            :                  * the callback
    2385                 :            :                  *
    2386                 :            :                  * Existing set_console() users don't check the return
    2387                 :            :                  * value so this shouldn't break anything
    2388                 :            :                  */
    2389                 :            :                 return -EINVAL;
    2390                 :            :         }
    2391                 :            : 
    2392                 :          0 :         want_console = nr;
    2393                 :            :         schedule_console_callback();
    2394                 :            : 
    2395                 :          0 :         return 0;
    2396                 :            : }
    2397                 :            : 
    2398                 :            : struct tty_driver *console_driver;
    2399                 :            : 
    2400                 :            : #ifdef CONFIG_VT_CONSOLE
    2401                 :            : 
    2402                 :            : /**
    2403                 :            :  * vt_kmsg_redirect() - Sets/gets the kernel message console
    2404                 :            :  * @new:        The new virtual terminal number or -1 if the console should stay
    2405                 :            :  *              unchanged
    2406                 :            :  *
    2407                 :            :  * By default, the kernel messages are always printed on the current virtual
    2408                 :            :  * console. However, the user may modify that default with the
    2409                 :            :  * TIOCL_SETKMSGREDIRECT ioctl call.
    2410                 :            :  *
    2411                 :            :  * This function sets the kernel message console to be @new. It returns the old
    2412                 :            :  * virtual console number. The virtual terminal number 0 (both as parameter and
    2413                 :            :  * return value) means no redirection (i.e. always printed on the currently
    2414                 :            :  * active console).
    2415                 :            :  *
    2416                 :            :  * The parameter -1 means that only the current console is returned, but the
    2417                 :            :  * value is not modified. You may use the macro vt_get_kmsg_redirect() in that
    2418                 :            :  * case to make the code more understandable.
    2419                 :            :  *
    2420                 :            :  * When the kernel is compiled without CONFIG_VT_CONSOLE, this function ignores
    2421                 :            :  * the parameter and always returns 0.
    2422                 :            :  */
    2423                 :          0 : int vt_kmsg_redirect(int new)
    2424                 :            : {
    2425                 :            :         static int kmsg_con;
    2426                 :            : 
    2427 [ #  # ][ #  # ]:          0 :         if (new != -1)
    2428                 :          0 :                 return xchg(&kmsg_con, new);
    2429                 :            :         else
    2430                 :          0 :                 return kmsg_con;
    2431                 :            : }
    2432                 :            : 
    2433                 :            : /*
    2434                 :            :  *      Console on virtual terminal
    2435                 :            :  *
    2436                 :            :  * The console must be locked when we get here.
    2437                 :            :  */
    2438                 :            : 
    2439                 :          0 : static void vt_console_print(struct console *co, const char *b, unsigned count)
    2440                 :            : {
    2441                 :          0 :         struct vc_data *vc = vc_cons[fg_console].d;
    2442                 :            :         unsigned char c;
    2443                 :            :         static DEFINE_SPINLOCK(printing_lock);
    2444                 :            :         const ushort *start;
    2445                 :            :         ushort cnt = 0;
    2446                 :            :         ushort myx;
    2447                 :            :         int kmsg_console;
    2448                 :            : 
    2449                 :            :         /* console busy or not yet initialized */
    2450         [ #  # ]:          0 :         if (!printable)
    2451                 :            :                 return;
    2452         [ #  # ]:          0 :         if (!spin_trylock(&printing_lock))
    2453                 :            :                 return;
    2454                 :            : 
    2455                 :            :         kmsg_console = vt_get_kmsg_redirect();
    2456 [ #  # ][ #  # ]:          0 :         if (kmsg_console && vc_cons_allocated(kmsg_console - 1))
    2457                 :          0 :                 vc = vc_cons[kmsg_console - 1].d;
    2458                 :            : 
    2459                 :            :         /* read `x' only after setting currcons properly (otherwise
    2460                 :            :            the `x' macro will read the x of the foreground console). */
    2461                 :          0 :         myx = vc->vc_x;
    2462                 :            : 
    2463         [ #  # ]:          0 :         if (!vc_cons_allocated(fg_console)) {
    2464                 :            :                 /* impossible */
    2465                 :            :                 /* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
    2466                 :            :                 goto quit;
    2467                 :            :         }
    2468                 :            : 
    2469 [ #  # ][ #  # ]:          0 :         if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
    2470                 :            :                 goto quit;
    2471                 :            : 
    2472                 :            :         /* undraw cursor first */
    2473         [ #  # ]:          0 :         if (IS_FG(vc))
    2474                 :          0 :                 hide_cursor(vc);
    2475                 :            : 
    2476                 :          0 :         start = (ushort *)vc->vc_pos;
    2477                 :            : 
    2478                 :            :         /* Contrived structure to try to emulate original need_wrap behaviour
    2479                 :            :          * Problems caused when we have need_wrap set on '\n' character */
    2480         [ #  # ]:          0 :         while (count--) {
    2481                 :          0 :                 c = *b++;
    2482 [ #  # ][ #  # ]:          0 :                 if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
                 [ #  # ]
    2483         [ #  # ]:          0 :                         if (cnt > 0) {
    2484         [ #  # ]:          0 :                                 if (CON_IS_VISIBLE(vc))
    2485                 :          0 :                                         vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
    2486                 :          0 :                                 vc->vc_x += cnt;
    2487         [ #  # ]:          0 :                                 if (vc->vc_need_wrap)
    2488                 :          0 :                                         vc->vc_x--;
    2489                 :            :                                 cnt = 0;
    2490                 :            :                         }
    2491         [ #  # ]:          0 :                         if (c == 8) {           /* backspace */
    2492                 :            :                                 bs(vc);
    2493                 :          0 :                                 start = (ushort *)vc->vc_pos;
    2494                 :          0 :                                 myx = vc->vc_x;
    2495                 :          0 :                                 continue;
    2496                 :            :                         }
    2497         [ #  # ]:          0 :                         if (c != 13)
    2498                 :          0 :                                 lf(vc);
    2499                 :            :                         cr(vc);
    2500                 :          0 :                         start = (ushort *)vc->vc_pos;
    2501                 :          0 :                         myx = vc->vc_x;
    2502         [ #  # ]:          0 :                         if (c == 10 || c == 13)
    2503                 :          0 :                                 continue;
    2504                 :            :                 }
    2505                 :          0 :                 scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
    2506                 :          0 :                 notify_write(vc, c);
    2507                 :          0 :                 cnt++;
    2508         [ #  # ]:          0 :                 if (myx == vc->vc_cols - 1) {
    2509                 :          0 :                         vc->vc_need_wrap = 1;
    2510                 :          0 :                         continue;
    2511                 :            :                 }
    2512                 :          0 :                 vc->vc_pos += 2;
    2513                 :          0 :                 myx++;
    2514                 :            :         }
    2515         [ #  # ]:          0 :         if (cnt > 0) {
    2516         [ #  # ]:          0 :                 if (CON_IS_VISIBLE(vc))
    2517                 :          0 :                         vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
    2518                 :          0 :                 vc->vc_x += cnt;
    2519         [ #  # ]:          0 :                 if (vc->vc_x == vc->vc_cols) {
    2520                 :          0 :                         vc->vc_x--;
    2521                 :          0 :                         vc->vc_need_wrap = 1;
    2522                 :            :                 }
    2523                 :            :         }
    2524                 :          0 :         set_cursor(vc);
    2525                 :            :         notify_update(vc);
    2526                 :            : 
    2527                 :            : quit:
    2528                 :            :         spin_unlock(&printing_lock);
    2529                 :            : }
    2530                 :            : 
    2531                 :          0 : static struct tty_driver *vt_console_device(struct console *c, int *index)
    2532                 :            : {
    2533         [ #  # ]:          0 :         *index = c->index ? c->index-1 : fg_console;
    2534                 :          0 :         return console_driver;
    2535                 :            : }
    2536                 :            : 
    2537                 :            : static struct console vt_console_driver = {
    2538                 :            :         .name           = "tty",
    2539                 :            :         .write          = vt_console_print,
    2540                 :            :         .device         = vt_console_device,
    2541                 :            :         .unblank        = unblank_screen,
    2542                 :            :         .flags          = CON_PRINTBUFFER,
    2543                 :            :         .index          = -1,
    2544                 :            : };
    2545                 :            : #endif
    2546                 :            : 
    2547                 :            : /*
    2548                 :            :  *      Handling of Linux-specific VC ioctls
    2549                 :            :  */
    2550                 :            : 
    2551                 :            : /*
    2552                 :            :  * Generally a bit racy with respect to console_lock();.
    2553                 :            :  *
    2554                 :            :  * There are some functions which don't need it.
    2555                 :            :  *
    2556                 :            :  * There are some functions which can sleep for arbitrary periods
    2557                 :            :  * (paste_selection) but we don't need the lock there anyway.
    2558                 :            :  *
    2559                 :            :  * set_selection has locking, and definitely needs it
    2560                 :            :  */
    2561                 :            : 
    2562                 :          0 : int tioclinux(struct tty_struct *tty, unsigned long arg)
    2563                 :            : {
    2564                 :            :         char type, data;
    2565                 :          0 :         char __user *p = (char __user *)arg;
    2566                 :            :         int lines;
    2567                 :            :         int ret;
    2568                 :            : 
    2569 [ #  # ][ #  # ]:          0 :         if (current->signal->tty != tty && !capable(CAP_SYS_ADMIN))
    2570                 :            :                 return -EPERM;
    2571         [ #  # ]:          0 :         if (get_user(type, p))
    2572                 :            :                 return -EFAULT;
    2573                 :            :         ret = 0;
    2574                 :            : 
    2575   [ #  #  #  #  :          0 :         switch (type)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2576                 :            :         {
    2577                 :            :                 case TIOCL_SETSEL:
    2578                 :          0 :                         console_lock();
    2579                 :          0 :                         ret = set_selection((struct tiocl_selection __user *)(p+1), tty);
    2580                 :          0 :                         console_unlock();
    2581                 :          0 :                         break;
    2582                 :            :                 case TIOCL_PASTESEL:
    2583                 :          0 :                         ret = paste_selection(tty);
    2584                 :          0 :                         break;
    2585                 :            :                 case TIOCL_UNBLANKSCREEN:
    2586                 :          0 :                         console_lock();
    2587                 :            :                         unblank_screen();
    2588                 :          0 :                         console_unlock();
    2589                 :          0 :                         break;
    2590                 :            :                 case TIOCL_SELLOADLUT:
    2591                 :          0 :                         console_lock();
    2592                 :          0 :                         ret = sel_loadlut(p);
    2593                 :          0 :                         console_unlock();
    2594                 :          0 :                         break;
    2595                 :            :                 case TIOCL_GETSHIFTSTATE:
    2596                 :            : 
    2597                 :            :         /*
    2598                 :            :          * Make it possible to react to Shift+Mousebutton.
    2599                 :            :          * Note that 'shift_state' is an undocumented
    2600                 :            :          * kernel-internal variable; programs not closely
    2601                 :            :          * related to the kernel should not use this.
    2602                 :            :          */
    2603                 :          0 :                         data = vt_get_shift_state();
    2604                 :          0 :                         ret = __put_user(data, p);
    2605                 :          0 :                         break;
    2606                 :            :                 case TIOCL_GETMOUSEREPORTING:
    2607                 :          0 :                         console_lock(); /* May be overkill */
    2608                 :          0 :                         data = mouse_reporting();
    2609                 :          0 :                         console_unlock();
    2610                 :          0 :                         ret = __put_user(data, p);
    2611                 :          0 :                         break;
    2612                 :            :                 case TIOCL_SETVESABLANK:
    2613                 :          0 :                         console_lock();
    2614                 :          0 :                         ret = set_vesa_blanking(p);
    2615                 :          0 :                         console_unlock();
    2616                 :          0 :                         break;
    2617                 :            :                 case TIOCL_GETKMSGREDIRECT:
    2618                 :          0 :                         data = vt_get_kmsg_redirect();
    2619                 :          0 :                         ret = __put_user(data, p);
    2620                 :          0 :                         break;
    2621                 :            :                 case TIOCL_SETKMSGREDIRECT:
    2622         [ #  # ]:          0 :                         if (!capable(CAP_SYS_ADMIN)) {
    2623                 :            :                                 ret = -EPERM;
    2624                 :            :                         } else {
    2625         [ #  # ]:          0 :                                 if (get_user(data, p+1))
    2626                 :            :                                         ret = -EFAULT;
    2627                 :            :                                 else
    2628                 :          0 :                                         vt_kmsg_redirect(data);
    2629                 :            :                         }
    2630                 :            :                         break;
    2631                 :            :                 case TIOCL_GETFGCONSOLE:
    2632                 :            :                         /* No locking needed as this is a transiently
    2633                 :            :                            correct return anyway if the caller hasn't
    2634                 :            :                            disabled switching */
    2635                 :          0 :                         ret = fg_console;
    2636                 :          0 :                         break;
    2637                 :            :                 case TIOCL_SCROLLCONSOLE:
    2638         [ #  # ]:          0 :                         if (get_user(lines, (s32 __user *)(p+4))) {
    2639                 :            :                                 ret = -EFAULT;
    2640                 :            :                         } else {
    2641                 :            :                                 /* Need the console lock here. Note that lots
    2642                 :            :                                    of other calls need fixing before the lock
    2643                 :            :                                    is actually useful ! */
    2644                 :          0 :                                 console_lock();
    2645                 :          0 :                                 scrollfront(vc_cons[fg_console].d, lines);
    2646                 :          0 :                                 console_unlock();
    2647                 :            :                                 ret = 0;
    2648                 :            :                         }
    2649                 :            :                         break;
    2650                 :            :                 case TIOCL_BLANKSCREEN: /* until explicitly unblanked, not only poked */
    2651                 :          0 :                         console_lock();
    2652                 :          0 :                         ignore_poke = 1;
    2653                 :          0 :                         do_blank_screen(0);
    2654                 :          0 :                         console_unlock();
    2655                 :          0 :                         break;
    2656                 :            :                 case TIOCL_BLANKEDSCREEN:
    2657                 :          0 :                         ret = console_blanked;
    2658                 :          0 :                         break;
    2659                 :            :                 default:
    2660                 :            :                         ret = -EINVAL;
    2661                 :            :                         break;
    2662                 :            :         }
    2663                 :          0 :         return ret;
    2664                 :            : }
    2665                 :            : 
    2666                 :            : /*
    2667                 :            :  * /dev/ttyN handling
    2668                 :            :  */
    2669                 :            : 
    2670                 :          0 : static int con_write(struct tty_struct *tty, const unsigned char *buf, int count)
    2671                 :            : {
    2672                 :            :         int     retval;
    2673                 :            : 
    2674                 :          0 :         retval = do_con_write(tty, buf, count);
    2675                 :          0 :         con_flush_chars(tty);
    2676                 :            : 
    2677                 :          0 :         return retval;
    2678                 :            : }
    2679                 :            : 
    2680                 :          0 : static int con_put_char(struct tty_struct *tty, unsigned char ch)
    2681                 :            : {
    2682         [ #  # ]:          0 :         if (in_interrupt())
    2683                 :            :                 return 0;       /* n_r3964 calls put_char() from interrupt context */
    2684                 :          0 :         return do_con_write(tty, &ch, 1);
    2685                 :            : }
    2686                 :            : 
    2687                 :          0 : static int con_write_room(struct tty_struct *tty)
    2688                 :            : {
    2689         [ #  # ]:          0 :         if (tty->stopped)
    2690                 :            :                 return 0;
    2691                 :          0 :         return 32768;           /* No limit, really; we're not buffering */
    2692                 :            : }
    2693                 :            : 
    2694                 :          0 : static int con_chars_in_buffer(struct tty_struct *tty)
    2695                 :            : {
    2696                 :          0 :         return 0;               /* we're not buffering */
    2697                 :            : }
    2698                 :            : 
    2699                 :            : /*
    2700                 :            :  * con_throttle and con_unthrottle are only used for
    2701                 :            :  * paste_selection(), which has to stuff in a large number of
    2702                 :            :  * characters...
    2703                 :            :  */
    2704                 :          0 : static void con_throttle(struct tty_struct *tty)
    2705                 :            : {
    2706                 :          0 : }
    2707                 :            : 
    2708                 :          0 : static void con_unthrottle(struct tty_struct *tty)
    2709                 :            : {
    2710                 :          0 :         struct vc_data *vc = tty->driver_data;
    2711                 :            : 
    2712                 :          0 :         wake_up_interruptible(&vc->paste_wait);
    2713                 :          0 : }
    2714                 :            : 
    2715                 :            : /*
    2716                 :            :  * Turn the Scroll-Lock LED on when the tty is stopped
    2717                 :            :  */
    2718                 :          0 : static void con_stop(struct tty_struct *tty)
    2719                 :            : {
    2720                 :            :         int console_num;
    2721         [ #  # ]:          0 :         if (!tty)
    2722                 :            :                 return;
    2723                 :          0 :         console_num = tty->index;
    2724         [ #  # ]:          0 :         if (!vc_cons_allocated(console_num))
    2725                 :            :                 return;
    2726                 :          0 :         vt_kbd_con_stop(console_num);
    2727                 :            : }
    2728                 :            : 
    2729                 :            : /*
    2730                 :            :  * Turn the Scroll-Lock LED off when the console is started
    2731                 :            :  */
    2732                 :          0 : static void con_start(struct tty_struct *tty)
    2733                 :            : {
    2734                 :            :         int console_num;
    2735         [ #  # ]:          0 :         if (!tty)
    2736                 :            :                 return;
    2737                 :          0 :         console_num = tty->index;
    2738         [ #  # ]:          0 :         if (!vc_cons_allocated(console_num))
    2739                 :            :                 return;
    2740                 :          0 :         vt_kbd_con_start(console_num);
    2741                 :            : }
    2742                 :            : 
    2743                 :          0 : static void con_flush_chars(struct tty_struct *tty)
    2744                 :            : {
    2745                 :            :         struct vc_data *vc;
    2746                 :            : 
    2747         [ #  # ]:          0 :         if (in_interrupt())     /* from flush_to_ldisc */
    2748                 :          0 :                 return;
    2749                 :            : 
    2750                 :            :         /* if we race with con_close(), vt may be null */
    2751                 :          0 :         console_lock();
    2752                 :          0 :         vc = tty->driver_data;
    2753         [ #  # ]:          0 :         if (vc)
    2754                 :          0 :                 set_cursor(vc);
    2755                 :          0 :         console_unlock();
    2756                 :            : }
    2757                 :            : 
    2758                 :            : /*
    2759                 :            :  * Allocate the console screen memory.
    2760                 :            :  */
    2761                 :          0 : static int con_install(struct tty_driver *driver, struct tty_struct *tty)
    2762                 :            : {
    2763                 :        285 :         unsigned int currcons = tty->index;
    2764                 :            :         struct vc_data *vc;
    2765                 :            :         int ret;
    2766                 :            : 
    2767                 :        285 :         console_lock();
    2768                 :        285 :         ret = vc_allocate(currcons);
    2769         [ +  - ]:        285 :         if (ret)
    2770                 :            :                 goto unlock;
    2771                 :            : 
    2772                 :        285 :         vc = vc_cons[currcons].d;
    2773                 :            : 
    2774                 :            :         /* Still being freed */
    2775         [ +  - ]:        285 :         if (vc->port.tty) {
    2776                 :            :                 ret = -ERESTARTSYS;
    2777                 :            :                 goto unlock;
    2778                 :            :         }
    2779                 :            : 
    2780                 :        285 :         ret = tty_port_install(&vc->port, driver, tty);
    2781            [ + ]:        285 :         if (ret)
    2782                 :            :                 goto unlock;
    2783                 :            : 
    2784                 :        285 :         tty->driver_data = vc;
    2785                 :        285 :         vc->port.tty = tty;
    2786                 :            : 
    2787         [ +  - ]:        570 :         if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
    2788                 :        285 :                 tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
    2789                 :        285 :                 tty->winsize.ws_col = vc_cons[currcons].d->vc_cols;
    2790                 :            :         }
    2791         [ +  - ]:        285 :         if (vc->vc_utf)
    2792                 :        285 :                 tty->termios.c_iflag |= IUTF8;
    2793                 :            :         else
    2794                 :          0 :                 tty->termios.c_iflag &= ~IUTF8;
    2795                 :            : unlock:
    2796                 :          0 :         console_unlock();
    2797                 :        285 :         return ret;
    2798                 :            : }
    2799                 :            : 
    2800                 :          0 : static int con_open(struct tty_struct *tty, struct file *filp)
    2801                 :            : {
    2802                 :            :         /* everything done in install */
    2803                 :        384 :         return 0;
    2804                 :            : }
    2805                 :            : 
    2806                 :            : 
    2807                 :          0 : static void con_close(struct tty_struct *tty, struct file *filp)
    2808                 :            : {
    2809                 :            :         /* Nothing to do - we defer to shutdown */
    2810                 :        384 : }
    2811                 :            : 
    2812                 :          0 : static void con_shutdown(struct tty_struct *tty)
    2813                 :            : {
    2814                 :        285 :         struct vc_data *vc = tty->driver_data;
    2815         [ -  + ]:        285 :         BUG_ON(vc == NULL);
    2816                 :        285 :         console_lock();
    2817                 :        285 :         vc->port.tty = NULL;
    2818                 :        285 :         console_unlock();
    2819                 :        285 : }
    2820                 :            : 
    2821                 :            : static int default_color           = 7; /* white */
    2822                 :            : static int default_italic_color    = 2; // green (ASCII)
    2823                 :            : static int default_underline_color = 3; // cyan (ASCII)
    2824                 :            : module_param_named(color, default_color, int, S_IRUGO | S_IWUSR);
    2825                 :            : module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR);
    2826                 :            : module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR);
    2827                 :            : 
    2828                 :          0 : static void vc_init(struct vc_data *vc, unsigned int rows,
    2829                 :            :                     unsigned int cols, int do_clear)
    2830                 :            : {
    2831                 :            :         int j, k ;
    2832                 :            : 
    2833                 :         56 :         vc->vc_cols = cols;
    2834                 :         56 :         vc->vc_rows = rows;
    2835                 :         56 :         vc->vc_size_row = cols << 1;
    2836                 :         56 :         vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
    2837                 :            : 
    2838                 :         56 :         set_origin(vc);
    2839                 :         56 :         vc->vc_pos = vc->vc_origin;
    2840                 :         56 :         reset_vc(vc);
    2841         [ +  + ]:       1008 :         for (j=k=0; j<16; j++) {
    2842                 :        896 :                 vc->vc_palette[k++] = default_red[j] ;
    2843                 :        896 :                 vc->vc_palette[k++] = default_grn[j] ;
    2844                 :        896 :                 vc->vc_palette[k++] = default_blu[j] ;
    2845                 :            :         }
    2846                 :         56 :         vc->vc_def_color       = default_color;
    2847                 :         56 :         vc->vc_ulcolor         = default_underline_color;
    2848                 :         56 :         vc->vc_itcolor         = default_italic_color;
    2849                 :         56 :         vc->vc_halfcolor       = 0x08;   /* grey */
    2850                 :         56 :         init_waitqueue_head(&vc->paste_wait);
    2851                 :         56 :         reset_terminal(vc, do_clear);
    2852                 :         56 : }
    2853                 :            : 
    2854                 :            : /*
    2855                 :            :  * This routine initializes console interrupts, and does nothing
    2856                 :            :  * else. If you want the screen to clear, call tty_write with
    2857                 :            :  * the appropriate escape-sequence.
    2858                 :            :  */
    2859                 :            : 
    2860                 :          0 : static int __init con_init(void)
    2861                 :            : {
    2862                 :            :         const char *display_desc = NULL;
    2863                 :            :         struct vc_data *vc;
    2864                 :            :         unsigned int currcons = 0, i;
    2865                 :            : 
    2866                 :          0 :         console_lock();
    2867                 :            : 
    2868         [ #  # ]:          0 :         if (conswitchp)
    2869                 :          0 :                 display_desc = conswitchp->con_startup();
    2870         [ #  # ]:          0 :         if (!display_desc) {
    2871                 :          0 :                 fg_console = 0;
    2872                 :          0 :                 console_unlock();
    2873                 :          0 :                 return 0;
    2874                 :            :         }
    2875                 :            : 
    2876         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    2877                 :          0 :                 struct con_driver *con_driver = &registered_con_driver[i];
    2878                 :            : 
    2879         [ #  # ]:          0 :                 if (con_driver->con == NULL) {
    2880                 :          0 :                         con_driver->con = conswitchp;
    2881                 :          0 :                         con_driver->desc = display_desc;
    2882                 :          0 :                         con_driver->flag = CON_DRIVER_FLAG_INIT;
    2883                 :          0 :                         con_driver->first = 0;
    2884                 :          0 :                         con_driver->last = MAX_NR_CONSOLES - 1;
    2885                 :          0 :                         break;
    2886                 :            :                 }
    2887                 :            :         }
    2888                 :            : 
    2889         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CONSOLES; i++)
    2890                 :          0 :                 con_driver_map[i] = conswitchp;
    2891                 :            : 
    2892         [ #  # ]:          0 :         if (blankinterval) {
    2893                 :          0 :                 blank_state = blank_normal_wait;
    2894                 :          0 :                 mod_timer(&console_timer, jiffies + (blankinterval * HZ));
    2895                 :            :         }
    2896                 :            : 
    2897         [ #  # ]:          0 :         for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
    2898                 :          0 :                 vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT);
    2899                 :          0 :                 INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
    2900                 :          0 :                 tty_port_init(&vc->port);
    2901                 :          0 :                 visual_init(vc, currcons, 1);
    2902                 :          0 :                 vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
    2903 [ #  # ][ #  # ]:          0 :                 vc_init(vc, vc->vc_rows, vc->vc_cols,
    2904                 :          0 :                         currcons || !vc->vc_sw->con_save_screen);
    2905                 :            :         }
    2906                 :          0 :         currcons = fg_console = 0;
    2907                 :          0 :         master_display_fg = vc = vc_cons[currcons].d;
    2908                 :          0 :         set_origin(vc);
    2909                 :            :         save_screen(vc);
    2910                 :          0 :         gotoxy(vc, vc->vc_x, vc->vc_y);
    2911                 :          0 :         csi_J(vc, 0);
    2912                 :          0 :         update_screen(vc);
    2913         [ #  # ]:          0 :         pr_info("Console: %s %s %dx%d\n",
    2914                 :            :                 vc->vc_can_do_color ? "colour" : "mono",
    2915                 :            :                 display_desc, vc->vc_cols, vc->vc_rows);
    2916                 :          0 :         printable = 1;
    2917                 :            : 
    2918                 :          0 :         console_unlock();
    2919                 :            : 
    2920                 :            : #ifdef CONFIG_VT_CONSOLE
    2921                 :          0 :         register_console(&vt_console_driver);
    2922                 :            : #endif
    2923                 :          0 :         return 0;
    2924                 :            : }
    2925                 :            : console_initcall(con_init);
    2926                 :            : 
    2927                 :            : static const struct tty_operations con_ops = {
    2928                 :            :         .install = con_install,
    2929                 :            :         .open = con_open,
    2930                 :            :         .close = con_close,
    2931                 :            :         .write = con_write,
    2932                 :            :         .write_room = con_write_room,
    2933                 :            :         .put_char = con_put_char,
    2934                 :            :         .flush_chars = con_flush_chars,
    2935                 :            :         .chars_in_buffer = con_chars_in_buffer,
    2936                 :            :         .ioctl = vt_ioctl,
    2937                 :            : #ifdef CONFIG_COMPAT
    2938                 :            :         .compat_ioctl = vt_compat_ioctl,
    2939                 :            : #endif
    2940                 :            :         .stop = con_stop,
    2941                 :            :         .start = con_start,
    2942                 :            :         .throttle = con_throttle,
    2943                 :            :         .unthrottle = con_unthrottle,
    2944                 :            :         .resize = vt_resize,
    2945                 :            :         .shutdown = con_shutdown
    2946                 :            : };
    2947                 :            : 
    2948                 :            : static struct cdev vc0_cdev;
    2949                 :            : 
    2950                 :          0 : static ssize_t show_tty_active(struct device *dev,
    2951                 :            :                                 struct device_attribute *attr, char *buf)
    2952                 :            : {
    2953                 :          0 :         return sprintf(buf, "tty%d\n", fg_console + 1);
    2954                 :            : }
    2955                 :            : static DEVICE_ATTR(active, S_IRUGO, show_tty_active, NULL);
    2956                 :            : 
    2957                 :          0 : int __init vty_init(const struct file_operations *console_fops)
    2958                 :            : {
    2959                 :          0 :         cdev_init(&vc0_cdev, console_fops);
    2960   [ #  #  #  # ]:          0 :         if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
    2961                 :          0 :             register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
    2962                 :          0 :                 panic("Couldn't register /dev/tty0 driver\n");
    2963                 :          0 :         tty0dev = device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
    2964         [ #  # ]:          0 :         if (IS_ERR(tty0dev))
    2965                 :          0 :                 tty0dev = NULL;
    2966                 :            :         else
    2967         [ #  # ]:          0 :                 WARN_ON(device_create_file(tty0dev, &dev_attr_active) < 0);
    2968                 :            : 
    2969                 :          0 :         vcs_init();
    2970                 :            : 
    2971                 :          0 :         console_driver = alloc_tty_driver(MAX_NR_CONSOLES);
    2972         [ #  # ]:          0 :         if (!console_driver)
    2973                 :          0 :                 panic("Couldn't allocate console driver\n");
    2974                 :            : 
    2975                 :          0 :         console_driver->name = "tty";
    2976                 :          0 :         console_driver->name_base = 1;
    2977                 :          0 :         console_driver->major = TTY_MAJOR;
    2978                 :          0 :         console_driver->minor_start = 1;
    2979                 :          0 :         console_driver->type = TTY_DRIVER_TYPE_CONSOLE;
    2980                 :          0 :         console_driver->init_termios = tty_std_termios;
    2981         [ #  # ]:          0 :         if (default_utf8)
    2982                 :          0 :                 console_driver->init_termios.c_iflag |= IUTF8;
    2983                 :          0 :         console_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
    2984                 :          0 :         tty_set_operations(console_driver, &con_ops);
    2985         [ #  # ]:          0 :         if (tty_register_driver(console_driver))
    2986                 :          0 :                 panic("Couldn't register console driver\n");
    2987                 :          0 :         kbd_init();
    2988                 :          0 :         console_map_init();
    2989                 :            : #ifdef CONFIG_MDA_CONSOLE
    2990                 :            :         mda_console_init();
    2991                 :            : #endif
    2992                 :          0 :         return 0;
    2993                 :            : }
    2994                 :            : 
    2995                 :            : #ifndef VT_SINGLE_DRIVER
    2996                 :            : 
    2997                 :            : static struct class *vtconsole_class;
    2998                 :            : 
    2999                 :          0 : static int do_bind_con_driver(const struct consw *csw, int first, int last,
    3000                 :            :                            int deflt)
    3001                 :            : {
    3002                 :          0 :         struct module *owner = csw->owner;
    3003                 :            :         const char *desc = NULL;
    3004                 :            :         struct con_driver *con_driver;
    3005                 :            :         int i, j = -1, k = -1, retval = -ENODEV;
    3006                 :            : 
    3007         [ #  # ]:          0 :         if (!try_module_get(owner))
    3008                 :            :                 return -ENODEV;
    3009                 :            : 
    3010 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
    3011                 :            : 
    3012                 :            :         /* check if driver is registered */
    3013         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    3014                 :          0 :                 con_driver = &registered_con_driver[i];
    3015                 :            : 
    3016         [ #  # ]:          0 :                 if (con_driver->con == csw) {
    3017                 :          0 :                         desc = con_driver->desc;
    3018                 :            :                         retval = 0;
    3019                 :          0 :                         break;
    3020                 :            :                 }
    3021                 :            :         }
    3022                 :            : 
    3023         [ #  # ]:          0 :         if (retval)
    3024                 :            :                 goto err;
    3025                 :            : 
    3026         [ #  # ]:          0 :         if (!(con_driver->flag & CON_DRIVER_FLAG_INIT)) {
    3027                 :          0 :                 csw->con_startup();
    3028                 :          0 :                 con_driver->flag |= CON_DRIVER_FLAG_INIT;
    3029                 :            :         }
    3030                 :            : 
    3031         [ #  # ]:          0 :         if (deflt) {
    3032         [ #  # ]:          0 :                 if (conswitchp)
    3033                 :          0 :                         module_put(conswitchp->owner);
    3034                 :            : 
    3035                 :          0 :                 __module_get(owner);
    3036                 :          0 :                 conswitchp = csw;
    3037                 :            :         }
    3038                 :            : 
    3039                 :          0 :         first = max(first, con_driver->first);
    3040                 :          0 :         last = min(last, con_driver->last);
    3041                 :            : 
    3042         [ #  # ]:          0 :         for (i = first; i <= last; i++) {
    3043                 :            :                 int old_was_color;
    3044                 :          0 :                 struct vc_data *vc = vc_cons[i].d;
    3045                 :            : 
    3046         [ #  # ]:          0 :                 if (con_driver_map[i])
    3047                 :          0 :                         module_put(con_driver_map[i]->owner);
    3048                 :          0 :                 __module_get(owner);
    3049                 :          0 :                 con_driver_map[i] = csw;
    3050                 :            : 
    3051 [ #  # ][ #  # ]:          0 :                 if (!vc || !vc->vc_sw)
    3052                 :          0 :                         continue;
    3053                 :            : 
    3054                 :            :                 j = i;
    3055                 :            : 
    3056         [ #  # ]:          0 :                 if (CON_IS_VISIBLE(vc)) {
    3057                 :            :                         k = i;
    3058                 :            :                         save_screen(vc);
    3059                 :            :                 }
    3060                 :            : 
    3061                 :          0 :                 old_was_color = vc->vc_can_do_color;
    3062                 :          0 :                 vc->vc_sw->con_deinit(vc);
    3063                 :          0 :                 vc->vc_origin = (unsigned long)vc->vc_screenbuf;
    3064                 :          0 :                 visual_init(vc, i, 0);
    3065                 :          0 :                 set_origin(vc);
    3066                 :          0 :                 update_attr(vc);
    3067                 :            : 
    3068                 :            :                 /* If the console changed between mono <-> color, then
    3069                 :            :                  * the attributes in the screenbuf will be wrong.  The
    3070                 :            :                  * following resets all attributes to something sane.
    3071                 :            :                  */
    3072         [ #  # ]:          0 :                 if (old_was_color != vc->vc_can_do_color)
    3073                 :          0 :                         clear_buffer_attributes(vc);
    3074                 :            :         }
    3075                 :            : 
    3076                 :          0 :         pr_info("Console: switching ");
    3077         [ #  # ]:          0 :         if (!deflt)
    3078                 :          0 :                 printk("consoles %d-%d ", first+1, last+1);
    3079         [ #  # ]:          0 :         if (j >= 0) {
    3080                 :          0 :                 struct vc_data *vc = vc_cons[j].d;
    3081                 :            : 
    3082         [ #  # ]:          0 :                 printk("to %s %s %dx%d\n",
    3083                 :          0 :                        vc->vc_can_do_color ? "colour" : "mono",
    3084                 :            :                        desc, vc->vc_cols, vc->vc_rows);
    3085                 :            : 
    3086         [ #  # ]:          0 :                 if (k >= 0) {
    3087                 :          0 :                         vc = vc_cons[k].d;
    3088                 :          0 :                         update_screen(vc);
    3089                 :            :                 }
    3090                 :            :         } else
    3091                 :          0 :                 printk("to %s\n", desc);
    3092                 :            : 
    3093                 :            :         retval = 0;
    3094                 :            : err:
    3095                 :          0 :         module_put(owner);
    3096                 :          0 :         return retval;
    3097                 :            : };
    3098                 :            : 
    3099                 :            : 
    3100                 :            : #ifdef CONFIG_VT_HW_CONSOLE_BINDING
    3101                 :            : static int con_is_graphics(const struct consw *csw, int first, int last)
    3102                 :            : {
    3103                 :            :         int i, retval = 0;
    3104                 :            : 
    3105 [ #  # ][ #  # ]:          0 :         for (i = first; i <= last; i++) {
    3106                 :          0 :                 struct vc_data *vc = vc_cons[i].d;
    3107                 :            : 
    3108 [ #  # ][ #  # ]:          0 :                 if (vc && vc->vc_mode == KD_GRAPHICS) {
         [ #  # ][ #  # ]
    3109                 :            :                         retval = 1;
    3110                 :            :                         break;
    3111                 :            :                 }
    3112                 :            :         }
    3113                 :            : 
    3114                 :            :         return retval;
    3115                 :            : }
    3116                 :            : 
    3117                 :            : /* unlocked version of unbind_con_driver() */
    3118                 :          0 : int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt)
    3119                 :            : {
    3120                 :          0 :         struct module *owner = csw->owner;
    3121                 :            :         const struct consw *defcsw = NULL;
    3122                 :            :         struct con_driver *con_driver = NULL, *con_back = NULL;
    3123                 :            :         int i, retval = -ENODEV;
    3124                 :            : 
    3125         [ #  # ]:          0 :         if (!try_module_get(owner))
    3126                 :            :                 return -ENODEV;
    3127                 :            : 
    3128 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
    3129                 :            : 
    3130                 :            :         /* check if driver is registered and if it is unbindable */
    3131         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    3132                 :          0 :                 con_driver = &registered_con_driver[i];
    3133                 :            : 
    3134 [ #  # ][ #  # ]:          0 :                 if (con_driver->con == csw &&
    3135                 :          0 :                     con_driver->flag & CON_DRIVER_FLAG_MODULE) {
    3136                 :            :                         retval = 0;
    3137                 :            :                         break;
    3138                 :            :                 }
    3139                 :            :         }
    3140                 :            : 
    3141         [ #  # ]:          0 :         if (retval)
    3142                 :            :                 goto err;
    3143                 :            : 
    3144                 :            :         retval = -ENODEV;
    3145                 :            : 
    3146                 :            :         /* check if backup driver exists */
    3147         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    3148                 :          0 :                 con_back = &registered_con_driver[i];
    3149                 :            : 
    3150 [ #  # ][ #  # ]:          0 :                 if (con_back->con &&
    3151                 :          0 :                     !(con_back->flag & CON_DRIVER_FLAG_MODULE)) {
    3152                 :            :                         defcsw = con_back->con;
    3153                 :            :                         retval = 0;
    3154                 :            :                         break;
    3155                 :            :                 }
    3156                 :            :         }
    3157                 :            : 
    3158         [ #  # ]:          0 :         if (retval)
    3159                 :            :                 goto err;
    3160                 :            : 
    3161         [ #  # ]:          0 :         if (!con_is_bound(csw))
    3162                 :            :                 goto err;
    3163                 :            : 
    3164                 :          0 :         first = max(first, con_driver->first);
    3165                 :          0 :         last = min(last, con_driver->last);
    3166                 :            : 
    3167         [ #  # ]:          0 :         for (i = first; i <= last; i++) {
    3168         [ #  # ]:          0 :                 if (con_driver_map[i] == csw) {
    3169                 :          0 :                         module_put(csw->owner);
    3170                 :          0 :                         con_driver_map[i] = NULL;
    3171                 :            :                 }
    3172                 :            :         }
    3173                 :            : 
    3174         [ #  # ]:          0 :         if (!con_is_bound(defcsw)) {
    3175                 :          0 :                 const struct consw *defconsw = conswitchp;
    3176                 :            : 
    3177                 :          0 :                 defcsw->con_startup();
    3178                 :          0 :                 con_back->flag |= CON_DRIVER_FLAG_INIT;
    3179                 :            :                 /*
    3180                 :            :                  * vgacon may change the default driver to point
    3181                 :            :                  * to dummycon, we restore it here...
    3182                 :            :                  */
    3183                 :          0 :                 conswitchp = defconsw;
    3184                 :            :         }
    3185                 :            : 
    3186         [ #  # ]:          0 :         if (!con_is_bound(csw))
    3187                 :          0 :                 con_driver->flag &= ~CON_DRIVER_FLAG_INIT;
    3188                 :            : 
    3189                 :            :         /* ignore return value, binding should not fail */
    3190                 :          0 :         do_bind_con_driver(defcsw, first, last, deflt);
    3191                 :            : err:
    3192                 :          0 :         module_put(owner);
    3193                 :          0 :         return retval;
    3194                 :            : 
    3195                 :            : }
    3196                 :            : EXPORT_SYMBOL_GPL(do_unbind_con_driver);
    3197                 :            : 
    3198                 :          0 : static int vt_bind(struct con_driver *con)
    3199                 :            : {
    3200                 :            :         const struct consw *defcsw = NULL, *csw = NULL;
    3201                 :            :         int i, more = 1, first = -1, last = -1, deflt = 0;
    3202                 :            : 
    3203 [ #  # ][ #  # ]:          0 :         if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
                 [ #  # ]
    3204                 :          0 :             con_is_graphics(con->con, con->first, con->last))
    3205                 :            :                 goto err;
    3206                 :            : 
    3207                 :            :         csw = con->con;
    3208                 :            : 
    3209         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    3210                 :          0 :                 struct con_driver *con = &registered_con_driver[i];
    3211                 :            : 
    3212 [ #  # ][ #  # ]:          0 :                 if (con->con && !(con->flag & CON_DRIVER_FLAG_MODULE)) {
    3213                 :            :                         defcsw = con->con;
    3214                 :            :                         break;
    3215                 :            :                 }
    3216                 :            :         }
    3217                 :            : 
    3218         [ #  # ]:          0 :         if (!defcsw)
    3219                 :            :                 goto err;
    3220                 :            : 
    3221         [ #  # ]:          0 :         while (more) {
    3222                 :            :                 more = 0;
    3223                 :            : 
    3224         [ #  # ]:          0 :                 for (i = con->first; i <= con->last; i++) {
    3225         [ #  # ]:          0 :                         if (con_driver_map[i] == defcsw) {
    3226         [ #  # ]:          0 :                                 if (first == -1)
    3227                 :            :                                         first = i;
    3228                 :            :                                 last = i;
    3229                 :            :                                 more = 1;
    3230         [ #  # ]:          0 :                         } else if (first != -1)
    3231                 :            :                                 break;
    3232                 :            :                 }
    3233                 :            : 
    3234         [ #  # ]:          0 :                 if (first == 0 && last == MAX_NR_CONSOLES -1)
    3235                 :            :                         deflt = 1;
    3236                 :            : 
    3237         [ #  # ]:          0 :                 if (first != -1) {
    3238                 :          0 :                         console_lock();
    3239                 :          0 :                         do_bind_con_driver(csw, first, last, deflt);
    3240                 :          0 :                         console_unlock();
    3241                 :            :                 }
    3242                 :            : 
    3243                 :            :                 first = -1;
    3244                 :            :                 last = -1;
    3245                 :            :                 deflt = 0;
    3246                 :            :         }
    3247                 :            : 
    3248                 :            : err:
    3249                 :          0 :         return 0;
    3250                 :            : }
    3251                 :            : 
    3252                 :          0 : static int vt_unbind(struct con_driver *con)
    3253                 :            : {
    3254                 :            :         const struct consw *csw = NULL;
    3255                 :            :         int i, more = 1, first = -1, last = -1, deflt = 0;
    3256                 :            : 
    3257 [ #  # ][ #  # ]:          0 :         if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
                 [ #  # ]
    3258                 :          0 :             con_is_graphics(con->con, con->first, con->last))
    3259                 :            :                 goto err;
    3260                 :            : 
    3261                 :            :         csw = con->con;
    3262                 :            : 
    3263         [ #  # ]:          0 :         while (more) {
    3264                 :            :                 more = 0;
    3265                 :            : 
    3266         [ #  # ]:          0 :                 for (i = con->first; i <= con->last; i++) {
    3267         [ #  # ]:          0 :                         if (con_driver_map[i] == csw) {
    3268         [ #  # ]:          0 :                                 if (first == -1)
    3269                 :            :                                         first = i;
    3270                 :            :                                 last = i;
    3271                 :            :                                 more = 1;
    3272         [ #  # ]:          0 :                         } else if (first != -1)
    3273                 :            :                                 break;
    3274                 :            :                 }
    3275                 :            : 
    3276         [ #  # ]:          0 :                 if (first == 0 && last == MAX_NR_CONSOLES -1)
    3277                 :            :                         deflt = 1;
    3278                 :            : 
    3279         [ #  # ]:          0 :                 if (first != -1) {
    3280                 :          0 :                         console_lock();
    3281                 :          0 :                         do_unbind_con_driver(csw, first, last, deflt);
    3282                 :          0 :                         console_unlock();
    3283                 :            :                 }
    3284                 :            : 
    3285                 :            :                 first = -1;
    3286                 :            :                 last = -1;
    3287                 :            :                 deflt = 0;
    3288                 :            :         }
    3289                 :            : 
    3290                 :            : err:
    3291                 :          0 :         return 0;
    3292                 :            : }
    3293                 :            : #else
    3294                 :            : static inline int vt_bind(struct con_driver *con)
    3295                 :            : {
    3296                 :            :         return 0;
    3297                 :            : }
    3298                 :            : static inline int vt_unbind(struct con_driver *con)
    3299                 :            : {
    3300                 :            :         return 0;
    3301                 :            : }
    3302                 :            : #endif /* CONFIG_VT_HW_CONSOLE_BINDING */
    3303                 :            : 
    3304                 :          0 : static ssize_t store_bind(struct device *dev, struct device_attribute *attr,
    3305                 :            :                           const char *buf, size_t count)
    3306                 :            : {
    3307                 :          0 :         struct con_driver *con = dev_get_drvdata(dev);
    3308                 :          0 :         int bind = simple_strtoul(buf, NULL, 0);
    3309                 :            : 
    3310         [ #  # ]:          0 :         if (bind)
    3311                 :          0 :                 vt_bind(con);
    3312                 :            :         else
    3313                 :          0 :                 vt_unbind(con);
    3314                 :            : 
    3315                 :          0 :         return count;
    3316                 :            : }
    3317                 :            : 
    3318                 :          0 : static ssize_t show_bind(struct device *dev, struct device_attribute *attr,
    3319                 :            :                          char *buf)
    3320                 :            : {
    3321                 :          0 :         struct con_driver *con = dev_get_drvdata(dev);
    3322                 :          0 :         int bind = con_is_bound(con->con);
    3323                 :            : 
    3324                 :          0 :         return snprintf(buf, PAGE_SIZE, "%i\n", bind);
    3325                 :            : }
    3326                 :            : 
    3327                 :          0 : static ssize_t show_name(struct device *dev, struct device_attribute *attr,
    3328                 :            :                          char *buf)
    3329                 :            : {
    3330                 :          0 :         struct con_driver *con = dev_get_drvdata(dev);
    3331                 :            : 
    3332         [ #  # ]:          0 :         return snprintf(buf, PAGE_SIZE, "%s %s\n",
    3333                 :          0 :                         (con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)",
    3334                 :            :                          con->desc);
    3335                 :            : 
    3336                 :            : }
    3337                 :            : 
    3338                 :            : static struct device_attribute device_attrs[] = {
    3339                 :            :         __ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
    3340                 :            :         __ATTR(name, S_IRUGO, show_name, NULL),
    3341                 :            : };
    3342                 :            : 
    3343                 :          0 : static int vtconsole_init_device(struct con_driver *con)
    3344                 :            : {
    3345                 :            :         int i;
    3346                 :            :         int error = 0;
    3347                 :            : 
    3348                 :          0 :         con->flag |= CON_DRIVER_FLAG_ATTR;
    3349                 :          0 :         dev_set_drvdata(con->dev, con);
    3350         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
    3351                 :          0 :                 error = device_create_file(con->dev, &device_attrs[i]);
    3352         [ #  # ]:          0 :                 if (error)
    3353                 :            :                         break;
    3354                 :            :         }
    3355                 :            : 
    3356         [ #  # ]:          0 :         if (error) {
    3357         [ #  # ]:          0 :                 while (--i >= 0)
    3358                 :          0 :                         device_remove_file(con->dev, &device_attrs[i]);
    3359                 :          0 :                 con->flag &= ~CON_DRIVER_FLAG_ATTR;
    3360                 :            :         }
    3361                 :            : 
    3362                 :          0 :         return error;
    3363                 :            : }
    3364                 :            : 
    3365                 :          0 : static void vtconsole_deinit_device(struct con_driver *con)
    3366                 :            : {
    3367                 :            :         int i;
    3368                 :            : 
    3369         [ #  # ]:          0 :         if (con->flag & CON_DRIVER_FLAG_ATTR) {
    3370         [ #  # ]:          0 :                 for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
    3371                 :          0 :                         device_remove_file(con->dev, &device_attrs[i]);
    3372                 :          0 :                 con->flag &= ~CON_DRIVER_FLAG_ATTR;
    3373                 :            :         }
    3374                 :          0 : }
    3375                 :            : 
    3376                 :            : /**
    3377                 :            :  * con_is_bound - checks if driver is bound to the console
    3378                 :            :  * @csw: console driver
    3379                 :            :  *
    3380                 :            :  * RETURNS: zero if unbound, nonzero if bound
    3381                 :            :  *
    3382                 :            :  * Drivers can call this and if zero, they should release
    3383                 :            :  * all resources allocated on con_startup()
    3384                 :            :  */
    3385                 :          0 : int con_is_bound(const struct consw *csw)
    3386                 :            : {
    3387                 :            :         int i, bound = 0;
    3388                 :            : 
    3389 [ #  # ][ #  # ]:          0 :         for (i = 0; i < MAX_NR_CONSOLES; i++) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    3390 [ #  # ][ #  # ]:          0 :                 if (con_driver_map[i] == csw) {
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    3391                 :            :                         bound = 1;
    3392                 :            :                         break;
    3393                 :            :                 }
    3394                 :            :         }
    3395                 :            : 
    3396                 :          0 :         return bound;
    3397                 :            : }
    3398                 :            : EXPORT_SYMBOL(con_is_bound);
    3399                 :            : 
    3400                 :            : /**
    3401                 :            :  * con_debug_enter - prepare the console for the kernel debugger
    3402                 :            :  * @sw: console driver
    3403                 :            :  *
    3404                 :            :  * Called when the console is taken over by the kernel debugger, this
    3405                 :            :  * function needs to save the current console state, then put the console
    3406                 :            :  * into a state suitable for the kernel debugger.
    3407                 :            :  *
    3408                 :            :  * RETURNS:
    3409                 :            :  * Zero on success, nonzero if a failure occurred when trying to prepare
    3410                 :            :  * the console for the debugger.
    3411                 :            :  */
    3412                 :          0 : int con_debug_enter(struct vc_data *vc)
    3413                 :            : {
    3414                 :            :         int ret = 0;
    3415                 :            : 
    3416                 :          0 :         saved_fg_console = fg_console;
    3417                 :          0 :         saved_last_console = last_console;
    3418                 :          0 :         saved_want_console = want_console;
    3419                 :          0 :         saved_vc_mode = vc->vc_mode;
    3420                 :          0 :         saved_console_blanked = console_blanked;
    3421                 :          0 :         vc->vc_mode = KD_TEXT;
    3422                 :          0 :         console_blanked = 0;
    3423         [ #  # ]:          0 :         if (vc->vc_sw->con_debug_enter)
    3424                 :          0 :                 ret = vc->vc_sw->con_debug_enter(vc);
    3425                 :            : #ifdef CONFIG_KGDB_KDB
    3426                 :            :         /* Set the initial LINES variable if it is not already set */
    3427                 :            :         if (vc->vc_rows < 999) {
    3428                 :            :                 int linecount;
    3429                 :            :                 char lns[4];
    3430                 :            :                 const char *setargs[3] = {
    3431                 :            :                         "set",
    3432                 :            :                         "LINES",
    3433                 :            :                         lns,
    3434                 :            :                 };
    3435                 :            :                 if (kdbgetintenv(setargs[0], &linecount)) {
    3436                 :            :                         snprintf(lns, 4, "%i", vc->vc_rows);
    3437                 :            :                         kdb_set(2, setargs);
    3438                 :            :                 }
    3439                 :            :         }
    3440                 :            :         if (vc->vc_cols < 999) {
    3441                 :            :                 int colcount;
    3442                 :            :                 char cols[4];
    3443                 :            :                 const char *setargs[3] = {
    3444                 :            :                         "set",
    3445                 :            :                         "COLUMNS",
    3446                 :            :                         cols,
    3447                 :            :                 };
    3448                 :            :                 if (kdbgetintenv(setargs[0], &colcount)) {
    3449                 :            :                         snprintf(cols, 4, "%i", vc->vc_cols);
    3450                 :            :                         kdb_set(2, setargs);
    3451                 :            :                 }
    3452                 :            :         }
    3453                 :            : #endif /* CONFIG_KGDB_KDB */
    3454                 :          0 :         return ret;
    3455                 :            : }
    3456                 :            : EXPORT_SYMBOL_GPL(con_debug_enter);
    3457                 :            : 
    3458                 :            : /**
    3459                 :            :  * con_debug_leave - restore console state
    3460                 :            :  * @sw: console driver
    3461                 :            :  *
    3462                 :            :  * Restore the console state to what it was before the kernel debugger
    3463                 :            :  * was invoked.
    3464                 :            :  *
    3465                 :            :  * RETURNS:
    3466                 :            :  * Zero on success, nonzero if a failure occurred when trying to restore
    3467                 :            :  * the console.
    3468                 :            :  */
    3469                 :          0 : int con_debug_leave(void)
    3470                 :            : {
    3471                 :            :         struct vc_data *vc;
    3472                 :            :         int ret = 0;
    3473                 :            : 
    3474                 :          0 :         fg_console = saved_fg_console;
    3475                 :          0 :         last_console = saved_last_console;
    3476                 :          0 :         want_console = saved_want_console;
    3477                 :          0 :         console_blanked = saved_console_blanked;
    3478                 :          0 :         vc_cons[fg_console].d->vc_mode = saved_vc_mode;
    3479                 :            : 
    3480                 :          0 :         vc = vc_cons[fg_console].d;
    3481         [ #  # ]:          0 :         if (vc->vc_sw->con_debug_leave)
    3482                 :          0 :                 ret = vc->vc_sw->con_debug_leave(vc);
    3483                 :          0 :         return ret;
    3484                 :            : }
    3485                 :            : EXPORT_SYMBOL_GPL(con_debug_leave);
    3486                 :            : 
    3487                 :          0 : static int do_register_con_driver(const struct consw *csw, int first, int last)
    3488                 :            : {
    3489                 :          0 :         struct module *owner = csw->owner;
    3490                 :            :         struct con_driver *con_driver;
    3491                 :            :         const char *desc;
    3492                 :            :         int i, retval = 0;
    3493                 :            : 
    3494 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
    3495                 :            : 
    3496         [ #  # ]:          0 :         if (!try_module_get(owner))
    3497                 :            :                 return -ENODEV;
    3498                 :            : 
    3499         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    3500                 :          0 :                 con_driver = &registered_con_driver[i];
    3501                 :            : 
    3502                 :            :                 /* already registered */
    3503         [ #  # ]:          0 :                 if (con_driver->con == csw)
    3504                 :            :                         retval = -EBUSY;
    3505                 :            :         }
    3506                 :            : 
    3507         [ #  # ]:          0 :         if (retval)
    3508                 :            :                 goto err;
    3509                 :            : 
    3510                 :          0 :         desc = csw->con_startup();
    3511                 :            : 
    3512         [ #  # ]:          0 :         if (!desc)
    3513                 :            :                 goto err;
    3514                 :            : 
    3515                 :            :         retval = -EINVAL;
    3516                 :            : 
    3517         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    3518                 :          0 :                 con_driver = &registered_con_driver[i];
    3519                 :            : 
    3520         [ #  # ]:          0 :                 if (con_driver->con == NULL) {
    3521                 :          0 :                         con_driver->con = csw;
    3522                 :          0 :                         con_driver->desc = desc;
    3523                 :          0 :                         con_driver->node = i;
    3524                 :          0 :                         con_driver->flag = CON_DRIVER_FLAG_MODULE |
    3525                 :            :                                            CON_DRIVER_FLAG_INIT;
    3526                 :          0 :                         con_driver->first = first;
    3527                 :          0 :                         con_driver->last = last;
    3528                 :            :                         retval = 0;
    3529                 :          0 :                         break;
    3530                 :            :                 }
    3531                 :            :         }
    3532                 :            : 
    3533         [ #  # ]:          0 :         if (retval)
    3534                 :            :                 goto err;
    3535                 :            : 
    3536                 :          0 :         con_driver->dev = device_create(vtconsole_class, NULL,
    3537                 :          0 :                                                 MKDEV(0, con_driver->node),
    3538                 :            :                                                 NULL, "vtcon%i",
    3539                 :            :                                                 con_driver->node);
    3540                 :            : 
    3541         [ #  # ]:          0 :         if (IS_ERR(con_driver->dev)) {
    3542                 :          0 :                 printk(KERN_WARNING "Unable to create device for %s; "
    3543                 :            :                        "errno = %ld\n", con_driver->desc,
    3544                 :            :                        PTR_ERR(con_driver->dev));
    3545                 :          0 :                 con_driver->dev = NULL;
    3546                 :            :         } else {
    3547                 :          0 :                 vtconsole_init_device(con_driver);
    3548                 :            :         }
    3549                 :            : 
    3550                 :            : err:
    3551                 :          0 :         module_put(owner);
    3552                 :          0 :         return retval;
    3553                 :            : }
    3554                 :            : 
    3555                 :            : 
    3556                 :            : /**
    3557                 :            :  * do_unregister_con_driver - unregister console driver from console layer
    3558                 :            :  * @csw: console driver
    3559                 :            :  *
    3560                 :            :  * DESCRIPTION: All drivers that registers to the console layer must
    3561                 :            :  * call this function upon exit, or if the console driver is in a state
    3562                 :            :  * where it won't be able to handle console services, such as the
    3563                 :            :  * framebuffer console without loaded framebuffer drivers.
    3564                 :            :  *
    3565                 :            :  * The driver must unbind first prior to unregistration.
    3566                 :            :  */
    3567                 :          0 : int do_unregister_con_driver(const struct consw *csw)
    3568                 :            : {
    3569                 :            :         int i, retval = -ENODEV;
    3570                 :            : 
    3571                 :            :         /* cannot unregister a bound driver */
    3572         [ #  # ]:          0 :         if (con_is_bound(csw))
    3573                 :            :                 goto err;
    3574                 :            : 
    3575         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    3576                 :          0 :                 struct con_driver *con_driver = &registered_con_driver[i];
    3577                 :            : 
    3578 [ #  # ][ #  # ]:          0 :                 if (con_driver->con == csw &&
    3579                 :          0 :                     con_driver->flag & CON_DRIVER_FLAG_MODULE) {
    3580                 :          0 :                         vtconsole_deinit_device(con_driver);
    3581                 :          0 :                         device_destroy(vtconsole_class,
    3582                 :          0 :                                        MKDEV(0, con_driver->node));
    3583                 :          0 :                         con_driver->con = NULL;
    3584                 :          0 :                         con_driver->desc = NULL;
    3585                 :          0 :                         con_driver->dev = NULL;
    3586                 :          0 :                         con_driver->node = 0;
    3587                 :          0 :                         con_driver->flag = 0;
    3588                 :          0 :                         con_driver->first = 0;
    3589                 :          0 :                         con_driver->last = 0;
    3590                 :            :                         retval = 0;
    3591                 :          0 :                         break;
    3592                 :            :                 }
    3593                 :            :         }
    3594                 :            : err:
    3595                 :          0 :         return retval;
    3596                 :            : }
    3597                 :            : EXPORT_SYMBOL_GPL(do_unregister_con_driver);
    3598                 :            : 
    3599                 :            : /*
    3600                 :            :  *      If we support more console drivers, this function is used
    3601                 :            :  *      when a driver wants to take over some existing consoles
    3602                 :            :  *      and become default driver for newly opened ones.
    3603                 :            :  *
    3604                 :            :  *      do_take_over_console is basically a register followed by unbind
    3605                 :            :  */
    3606                 :          0 : int do_take_over_console(const struct consw *csw, int first, int last, int deflt)
    3607                 :            : {
    3608                 :            :         int err;
    3609                 :            : 
    3610                 :          0 :         err = do_register_con_driver(csw, first, last);
    3611                 :            :         /*
    3612                 :            :          * If we get an busy error we still want to bind the console driver
    3613                 :            :          * and return success, as we may have unbound the console driver
    3614                 :            :          * but not unregistered it.
    3615                 :            :          */
    3616         [ #  # ]:          0 :         if (err == -EBUSY)
    3617                 :            :                 err = 0;
    3618         [ #  # ]:          0 :         if (!err)
    3619                 :          0 :                 do_bind_con_driver(csw, first, last, deflt);
    3620                 :            : 
    3621                 :          0 :         return err;
    3622                 :            : }
    3623                 :            : EXPORT_SYMBOL_GPL(do_take_over_console);
    3624                 :            : 
    3625                 :            : 
    3626                 :            : /*
    3627                 :            :  * give_up_console is a wrapper to unregister_con_driver. It will only
    3628                 :            :  * work if driver is fully unbound.
    3629                 :            :  */
    3630                 :          0 : void give_up_console(const struct consw *csw)
    3631                 :            : {
    3632                 :          0 :         console_lock();
    3633                 :          0 :         do_unregister_con_driver(csw);
    3634                 :          0 :         console_unlock();
    3635                 :          0 : }
    3636                 :            : 
    3637                 :          0 : static int __init vtconsole_class_init(void)
    3638                 :            : {
    3639                 :            :         int i;
    3640                 :            : 
    3641                 :          0 :         vtconsole_class = class_create(THIS_MODULE, "vtconsole");
    3642         [ #  # ]:          0 :         if (IS_ERR(vtconsole_class)) {
    3643                 :          0 :                 printk(KERN_WARNING "Unable to create vt console class; "
    3644                 :            :                        "errno = %ld\n", PTR_ERR(vtconsole_class));
    3645                 :          0 :                 vtconsole_class = NULL;
    3646                 :            :         }
    3647                 :            : 
    3648                 :            :         /* Add system drivers to sysfs */
    3649         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
    3650                 :          0 :                 struct con_driver *con = &registered_con_driver[i];
    3651                 :            : 
    3652 [ #  # ][ #  # ]:          0 :                 if (con->con && !con->dev) {
    3653                 :          0 :                         con->dev = device_create(vtconsole_class, NULL,
    3654                 :          0 :                                                          MKDEV(0, con->node),
    3655                 :            :                                                          NULL, "vtcon%i",
    3656                 :            :                                                          con->node);
    3657                 :            : 
    3658         [ #  # ]:          0 :                         if (IS_ERR(con->dev)) {
    3659                 :          0 :                                 printk(KERN_WARNING "Unable to create "
    3660                 :            :                                        "device for %s; errno = %ld\n",
    3661                 :            :                                        con->desc, PTR_ERR(con->dev));
    3662                 :          0 :                                 con->dev = NULL;
    3663                 :            :                         } else {
    3664                 :          0 :                                 vtconsole_init_device(con);
    3665                 :            :                         }
    3666                 :            :                 }
    3667                 :            :         }
    3668                 :            : 
    3669                 :          0 :         return 0;
    3670                 :            : }
    3671                 :            : postcore_initcall(vtconsole_class_init);
    3672                 :            : 
    3673                 :            : #endif
    3674                 :            : 
    3675                 :            : /*
    3676                 :            :  *      Screen blanking
    3677                 :            :  */
    3678                 :            : 
    3679                 :          0 : static int set_vesa_blanking(char __user *p)
    3680                 :            : {
    3681                 :            :         unsigned int mode;
    3682                 :            : 
    3683         [ #  # ]:          0 :         if (get_user(mode, p + 1))
    3684                 :            :                 return -EFAULT;
    3685                 :            : 
    3686         [ #  # ]:          0 :         vesa_blank_mode = (mode < 4) ? mode : 0;
    3687                 :          0 :         return 0;
    3688                 :            : }
    3689                 :            : 
    3690                 :          0 : void do_blank_screen(int entering_gfx)
    3691                 :            : {
    3692                 :          0 :         struct vc_data *vc = vc_cons[fg_console].d;
    3693                 :            :         int i;
    3694                 :            : 
    3695 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
    3696                 :            : 
    3697         [ #  # ]:          0 :         if (console_blanked) {
    3698         [ #  # ]:          0 :                 if (blank_state == blank_vesa_wait) {
    3699                 :          0 :                         blank_state = blank_off;
    3700                 :          0 :                         vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
    3701                 :            :                 }
    3702                 :            :                 return;
    3703                 :            :         }
    3704                 :            : 
    3705                 :            :         /* entering graphics mode? */
    3706         [ #  # ]:          0 :         if (entering_gfx) {
    3707                 :          0 :                 hide_cursor(vc);
    3708                 :            :                 save_screen(vc);
    3709                 :          0 :                 vc->vc_sw->con_blank(vc, -1, 1);
    3710                 :          0 :                 console_blanked = fg_console + 1;
    3711                 :          0 :                 blank_state = blank_off;
    3712                 :          0 :                 set_origin(vc);
    3713                 :          0 :                 return;
    3714                 :            :         }
    3715                 :            : 
    3716         [ #  # ]:          0 :         if (blank_state != blank_normal_wait)
    3717                 :            :                 return;
    3718                 :          0 :         blank_state = blank_off;
    3719                 :            : 
    3720                 :            :         /* don't blank graphics */
    3721         [ #  # ]:          0 :         if (vc->vc_mode != KD_TEXT) {
    3722                 :          0 :                 console_blanked = fg_console + 1;
    3723                 :          0 :                 return;
    3724                 :            :         }
    3725                 :            : 
    3726                 :          0 :         hide_cursor(vc);
    3727                 :          0 :         del_timer_sync(&console_timer);
    3728                 :          0 :         blank_timer_expired = 0;
    3729                 :            : 
    3730                 :            :         save_screen(vc);
    3731                 :            :         /* In case we need to reset origin, blanking hook returns 1 */
    3732         [ #  # ]:          0 :         i = vc->vc_sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0);
    3733                 :          0 :         console_blanked = fg_console + 1;
    3734         [ #  # ]:          0 :         if (i)
    3735                 :          0 :                 set_origin(vc);
    3736                 :            : 
    3737 [ #  # ][ #  # ]:          0 :         if (console_blank_hook && console_blank_hook(1))
    3738                 :            :                 return;
    3739                 :            : 
    3740 [ #  # ][ #  # ]:          0 :         if (vesa_off_interval && vesa_blank_mode) {
    3741                 :          0 :                 blank_state = blank_vesa_wait;
    3742                 :          0 :                 mod_timer(&console_timer, jiffies + vesa_off_interval);
    3743                 :            :         }
    3744                 :          0 :         vt_event_post(VT_EVENT_BLANK, vc->vc_num, vc->vc_num);
    3745                 :            : }
    3746                 :            : EXPORT_SYMBOL(do_blank_screen);
    3747                 :            : 
    3748                 :            : /*
    3749                 :            :  * Called by timer as well as from vt_console_driver
    3750                 :            :  */
    3751                 :          0 : void do_unblank_screen(int leaving_gfx)
    3752                 :            : {
    3753                 :            :         struct vc_data *vc;
    3754                 :            : 
    3755                 :            :         /* This should now always be called from a "sane" (read: can schedule)
    3756                 :            :          * context for the sake of the low level drivers, except in the special
    3757                 :            :          * case of oops_in_progress
    3758                 :            :          */
    3759                 :            :         if (!oops_in_progress)
    3760                 :            :                 might_sleep();
    3761                 :            : 
    3762 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
    3763                 :            : 
    3764                 :          0 :         ignore_poke = 0;
    3765         [ #  # ]:          0 :         if (!console_blanked)
    3766                 :            :                 return;
    3767         [ #  # ]:          0 :         if (!vc_cons_allocated(fg_console)) {
    3768                 :            :                 /* impossible */
    3769                 :          0 :                 pr_warning("unblank_screen: tty %d not allocated ??\n",
    3770                 :            :                            fg_console+1);
    3771                 :          0 :                 return;
    3772                 :            :         }
    3773                 :          0 :         vc = vc_cons[fg_console].d;
    3774                 :            :         /* Try to unblank in oops case too */
    3775 [ #  # ][ #  # ]:          0 :         if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
    3776                 :            :                 return; /* but leave console_blanked != 0 */
    3777                 :            : 
    3778         [ #  # ]:          0 :         if (blankinterval) {
    3779                 :          0 :                 mod_timer(&console_timer, jiffies + (blankinterval * HZ));
    3780                 :          0 :                 blank_state = blank_normal_wait;
    3781                 :            :         }
    3782                 :            : 
    3783                 :          0 :         console_blanked = 0;
    3784 [ #  # ][ #  # ]:          0 :         if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc))
    3785                 :            :                 /* Low-level driver cannot restore -> do it ourselves */
    3786                 :          0 :                 update_screen(vc);
    3787         [ #  # ]:          0 :         if (console_blank_hook)
    3788                 :          0 :                 console_blank_hook(0);
    3789                 :          0 :         set_palette(vc);
    3790                 :          0 :         set_cursor(vc);
    3791                 :          0 :         vt_event_post(VT_EVENT_UNBLANK, vc->vc_num, vc->vc_num);
    3792                 :            : }
    3793                 :            : EXPORT_SYMBOL(do_unblank_screen);
    3794                 :            : 
    3795                 :            : /*
    3796                 :            :  * This is called by the outside world to cause a forced unblank, mostly for
    3797                 :            :  * oopses. Currently, I just call do_unblank_screen(0), but we could eventually
    3798                 :            :  * call it with 1 as an argument and so force a mode restore... that may kill
    3799                 :            :  * X or at least garbage the screen but would also make the Oops visible...
    3800                 :            :  */
    3801                 :          0 : void unblank_screen(void)
    3802                 :            : {
    3803                 :          0 :         do_unblank_screen(0);
    3804                 :          0 : }
    3805                 :            : 
    3806                 :            : /*
    3807                 :            :  * We defer the timer blanking to work queue so it can take the console mutex
    3808                 :            :  * (console operations can still happen at irq time, but only from printk which
    3809                 :            :  * has the console mutex. Not perfect yet, but better than no locking
    3810                 :            :  */
    3811                 :          0 : static void blank_screen_t(unsigned long dummy)
    3812                 :            : {
    3813         [ #  # ]:          0 :         if (unlikely(!keventd_up())) {
    3814                 :          0 :                 mod_timer(&console_timer, jiffies + (blankinterval * HZ));
    3815                 :          0 :                 return;
    3816                 :            :         }
    3817                 :          0 :         blank_timer_expired = 1;
    3818                 :            :         schedule_work(&console_work);
    3819                 :            : }
    3820                 :            : 
    3821                 :          0 : void poke_blanked_console(void)
    3822                 :            : {
    3823 [ #  # ][ #  # ]:          0 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
    3824                 :            : 
    3825                 :            :         /* Add this so we quickly catch whoever might call us in a non
    3826                 :            :          * safe context. Nowadays, unblank_screen() isn't to be called in
    3827                 :            :          * atomic contexts and is allowed to schedule (with the special case
    3828                 :            :          * of oops_in_progress, but that isn't of any concern for this
    3829                 :            :          * function. --BenH.
    3830                 :            :          */
    3831                 :            :         might_sleep();
    3832                 :            : 
    3833                 :            :         /* This isn't perfectly race free, but a race here would be mostly harmless,
    3834                 :            :          * at worse, we'll do a spurrious blank and it's unlikely
    3835                 :            :          */
    3836                 :          0 :         del_timer(&console_timer);
    3837                 :          0 :         blank_timer_expired = 0;
    3838                 :            : 
    3839 [ #  # ][ #  # ]:          0 :         if (ignore_poke || !vc_cons[fg_console].d || vc_cons[fg_console].d->vc_mode == KD_GRAPHICS)
                 [ #  # ]
    3840                 :          0 :                 return;
    3841         [ #  # ]:          0 :         if (console_blanked)
    3842                 :            :                 unblank_screen();
    3843         [ #  # ]:          0 :         else if (blankinterval) {
    3844                 :          0 :                 mod_timer(&console_timer, jiffies + (blankinterval * HZ));
    3845                 :          0 :                 blank_state = blank_normal_wait;
    3846                 :            :         }
    3847                 :            : }
    3848                 :            : 
    3849                 :            : /*
    3850                 :            :  *      Palettes
    3851                 :            :  */
    3852                 :            : 
    3853                 :          0 : static void set_palette(struct vc_data *vc)
    3854                 :            : {
    3855 [ -  + ][ #  # ]:         56 :         WARN_CONSOLE_UNLOCKED();
                 [ #  # ]
    3856                 :            : 
    3857         [ +  - ]:         56 :         if (vc->vc_mode != KD_GRAPHICS)
    3858                 :         56 :                 vc->vc_sw->con_set_palette(vc, color_table);
    3859                 :         56 : }
    3860                 :            : 
    3861                 :            : /*
    3862                 :            :  * Load palette into the DAC registers. arg points to a colour
    3863                 :            :  * map, 3 bytes per colour, 16 colours, range from 0 to 255.
    3864                 :            :  */
    3865                 :            : 
    3866                 :          0 : int con_set_cmap(unsigned char __user *arg)
    3867                 :            : {
    3868                 :            :         int i, j, k;
    3869                 :            :         unsigned char colormap[3*16];
    3870                 :            : 
    3871         [ #  # ]:          0 :         if (copy_from_user(colormap, arg, sizeof(colormap)))
    3872                 :            :                 return -EFAULT;
    3873                 :            : 
    3874                 :          0 :         console_lock();
    3875         [ #  # ]:          0 :         for (i = k = 0; i < 16; i++) {
    3876                 :          0 :                 default_red[i] = colormap[k++];
    3877                 :          0 :                 default_grn[i] = colormap[k++];
    3878                 :          0 :                 default_blu[i] = colormap[k++];
    3879                 :            :         }
    3880         [ #  # ]:          0 :         for (i = 0; i < MAX_NR_CONSOLES; i++) {
    3881         [ #  # ]:          0 :                 if (!vc_cons_allocated(i))
    3882                 :          0 :                         continue;
    3883         [ #  # ]:          0 :                 for (j = k = 0; j < 16; j++) {
    3884                 :          0 :                         vc_cons[i].d->vc_palette[k++] = default_red[j];
    3885                 :          0 :                         vc_cons[i].d->vc_palette[k++] = default_grn[j];
    3886                 :          0 :                         vc_cons[i].d->vc_palette[k++] = default_blu[j];
    3887                 :            :                 }
    3888                 :          0 :                 set_palette(vc_cons[i].d);
    3889                 :            :         }
    3890                 :          0 :         console_unlock();
    3891                 :            : 
    3892                 :          0 :         return 0;
    3893                 :            : }
    3894                 :            : 
    3895                 :          0 : int con_get_cmap(unsigned char __user *arg)
    3896                 :            : {
    3897                 :            :         int i, k;
    3898                 :            :         unsigned char colormap[3*16];
    3899                 :            : 
    3900                 :          0 :         console_lock();
    3901         [ #  # ]:          0 :         for (i = k = 0; i < 16; i++) {
    3902                 :          0 :                 colormap[k++] = default_red[i];
    3903                 :          0 :                 colormap[k++] = default_grn[i];
    3904                 :          0 :                 colormap[k++] = default_blu[i];
    3905                 :            :         }
    3906                 :          0 :         console_unlock();
    3907                 :            : 
    3908         [ #  # ]:          0 :         if (copy_to_user(arg, colormap, sizeof(colormap)))
    3909                 :            :                 return -EFAULT;
    3910                 :            : 
    3911                 :          0 :         return 0;
    3912                 :            : }
    3913                 :            : 
    3914                 :          0 : void reset_palette(struct vc_data *vc)
    3915                 :            : {
    3916                 :            :         int j, k;
    3917         [ +  + ]:        952 :         for (j=k=0; j<16; j++) {
    3918                 :        896 :                 vc->vc_palette[k++] = default_red[j];
    3919                 :        896 :                 vc->vc_palette[k++] = default_grn[j];
    3920                 :        896 :                 vc->vc_palette[k++] = default_blu[j];
    3921                 :            :         }
    3922                 :         56 :         set_palette(vc);
    3923                 :         56 : }
    3924                 :            : 
    3925                 :            : /*
    3926                 :            :  *  Font switching
    3927                 :            :  *
    3928                 :            :  *  Currently we only support fonts up to 32 pixels wide, at a maximum height
    3929                 :            :  *  of 32 pixels. Userspace fontdata is stored with 32 bytes (shorts/ints, 
    3930                 :            :  *  depending on width) reserved for each character which is kinda wasty, but 
    3931                 :            :  *  this is done in order to maintain compatibility with the EGA/VGA fonts. It 
    3932                 :            :  *  is up to the actual low-level console-driver convert data into its favorite
    3933                 :            :  *  format (maybe we should add a `fontoffset' field to the `display'
    3934                 :            :  *  structure so we won't have to convert the fontdata all the time.
    3935                 :            :  *  /Jes
    3936                 :            :  */
    3937                 :            : 
    3938                 :            : #define max_font_size 65536
    3939                 :            : 
    3940                 :          0 : static int con_font_get(struct vc_data *vc, struct console_font_op *op)
    3941                 :            : {
    3942                 :            :         struct console_font font;
    3943                 :            :         int rc = -EINVAL;
    3944                 :            :         int c;
    3945                 :            : 
    3946         [ #  # ]:          0 :         if (op->data) {
    3947                 :          0 :                 font.data = kmalloc(max_font_size, GFP_KERNEL);
    3948         [ #  # ]:          0 :                 if (!font.data)
    3949                 :            :                         return -ENOMEM;
    3950                 :            :         } else
    3951                 :          0 :                 font.data = NULL;
    3952                 :            : 
    3953                 :          0 :         console_lock();
    3954         [ #  # ]:          0 :         if (vc->vc_mode != KD_TEXT)
    3955                 :            :                 rc = -EINVAL;
    3956         [ #  # ]:          0 :         else if (vc->vc_sw->con_font_get)
    3957                 :          0 :                 rc = vc->vc_sw->con_font_get(vc, &font);
    3958                 :            :         else
    3959                 :            :                 rc = -ENOSYS;
    3960                 :          0 :         console_unlock();
    3961                 :            : 
    3962         [ #  # ]:          0 :         if (rc)
    3963                 :            :                 goto out;
    3964                 :            : 
    3965                 :          0 :         c = (font.width+7)/8 * 32 * font.charcount;
    3966                 :            : 
    3967 [ #  # ][ #  # ]:          0 :         if (op->data && font.charcount > op->charcount)
    3968                 :            :                 rc = -ENOSPC;
    3969         [ #  # ]:          0 :         if (!(op->flags & KD_FONT_FLAG_OLD)) {
    3970 [ #  # ][ #  # ]:          0 :                 if (font.width > op->width || font.height > op->height) 
    3971                 :            :                         rc = -ENOSPC;
    3972                 :            :         } else {
    3973         [ #  # ]:          0 :                 if (font.width != 8)
    3974                 :            :                         rc = -EIO;
    3975 [ #  # ][ #  # ]:          0 :                 else if ((op->height && font.height > op->height) ||
                 [ #  # ]
    3976                 :          0 :                          font.height > 32)
    3977                 :            :                         rc = -ENOSPC;
    3978                 :            :         }
    3979         [ #  # ]:          0 :         if (rc)
    3980                 :            :                 goto out;
    3981                 :            : 
    3982                 :          0 :         op->height = font.height;
    3983                 :          0 :         op->width = font.width;
    3984                 :          0 :         op->charcount = font.charcount;
    3985                 :            : 
    3986 [ #  # ][ #  # ]:          0 :         if (op->data && copy_to_user(op->data, font.data, c))
    3987                 :            :                 rc = -EFAULT;
    3988                 :            : 
    3989                 :            : out:
    3990                 :          0 :         kfree(font.data);
    3991                 :          0 :         return rc;
    3992                 :            : }
    3993                 :            : 
    3994                 :          0 : static int con_font_set(struct vc_data *vc, struct console_font_op *op)
    3995                 :            : {
    3996                 :            :         struct console_font font;
    3997                 :            :         int rc = -EINVAL;
    3998                 :            :         int size;
    3999                 :            : 
    4000         [ #  # ]:          0 :         if (vc->vc_mode != KD_TEXT)
    4001                 :            :                 return -EINVAL;
    4002         [ #  # ]:          0 :         if (!op->data)
    4003                 :            :                 return -EINVAL;
    4004         [ #  # ]:          0 :         if (op->charcount > 512)
    4005                 :            :                 return -EINVAL;
    4006         [ #  # ]:          0 :         if (!op->height) {           /* Need to guess font height [compat] */
    4007                 :            :                 int h, i;
    4008                 :            :                 u8 __user *charmap = op->data;
    4009                 :            :                 u8 tmp;
    4010                 :            :                 
    4011                 :            :                 /* If from KDFONTOP ioctl, don't allow things which can be done in userland,
    4012                 :            :                    so that we can get rid of this soon */
    4013         [ #  # ]:          0 :                 if (!(op->flags & KD_FONT_FLAG_OLD))
    4014                 :            :                         return -EINVAL;
    4015         [ #  # ]:          0 :                 for (h = 32; h > 0; h--)
    4016         [ #  # ]:          0 :                         for (i = 0; i < op->charcount; i++) {
    4017         [ #  # ]:          0 :                                 if (get_user(tmp, &charmap[32*i+h-1]))
    4018                 :            :                                         return -EFAULT;
    4019         [ #  # ]:          0 :                                 if (tmp)
    4020                 :            :                                         goto nonzero;
    4021                 :            :                         }
    4022                 :            :                 return -EINVAL;
    4023                 :            :         nonzero:
    4024                 :          0 :                 op->height = h;
    4025                 :            :         }
    4026 [ #  # ][ #  # ]:          0 :         if (op->width <= 0 || op->width > 32 || op->height > 32)
    4027                 :            :                 return -EINVAL;
    4028                 :          0 :         size = (op->width+7)/8 * 32 * op->charcount;
    4029         [ #  # ]:          0 :         if (size > max_font_size)
    4030                 :            :                 return -ENOSPC;
    4031                 :          0 :         font.charcount = op->charcount;
    4032                 :          0 :         font.height = op->height;
    4033                 :          0 :         font.width = op->width;
    4034                 :          0 :         font.data = memdup_user(op->data, size);
    4035         [ #  # ]:          0 :         if (IS_ERR(font.data))
    4036                 :          0 :                 return PTR_ERR(font.data);
    4037                 :          0 :         console_lock();
    4038         [ #  # ]:          0 :         if (vc->vc_mode != KD_TEXT)
    4039                 :            :                 rc = -EINVAL;
    4040         [ #  # ]:          0 :         else if (vc->vc_sw->con_font_set)
    4041                 :          0 :                 rc = vc->vc_sw->con_font_set(vc, &font, op->flags);
    4042                 :            :         else
    4043                 :            :                 rc = -ENOSYS;
    4044                 :          0 :         console_unlock();
    4045                 :          0 :         kfree(font.data);
    4046                 :          0 :         return rc;
    4047                 :            : }
    4048                 :            : 
    4049                 :          0 : static int con_font_default(struct vc_data *vc, struct console_font_op *op)
    4050                 :            : {
    4051                 :          0 :         struct console_font font = {.width = op->width, .height = op->height};
    4052                 :            :         char name[MAX_FONT_NAME];
    4053                 :            :         char *s = name;
    4054                 :            :         int rc;
    4055                 :            : 
    4056                 :            : 
    4057         [ #  # ]:          0 :         if (!op->data)
    4058                 :            :                 s = NULL;
    4059         [ #  # ]:          0 :         else if (strncpy_from_user(name, op->data, MAX_FONT_NAME - 1) < 0)
    4060                 :            :                 return -EFAULT;
    4061                 :            :         else
    4062                 :          0 :                 name[MAX_FONT_NAME - 1] = 0;
    4063                 :            : 
    4064                 :          0 :         console_lock();
    4065         [ #  # ]:          0 :         if (vc->vc_mode != KD_TEXT) {
    4066                 :          0 :                 console_unlock();
    4067                 :          0 :                 return -EINVAL;
    4068                 :            :         }
    4069         [ #  # ]:          0 :         if (vc->vc_sw->con_font_default)
    4070                 :          0 :                 rc = vc->vc_sw->con_font_default(vc, &font, s);
    4071                 :            :         else
    4072                 :            :                 rc = -ENOSYS;
    4073                 :          0 :         console_unlock();
    4074         [ #  # ]:          0 :         if (!rc) {
    4075                 :          0 :                 op->width = font.width;
    4076                 :          0 :                 op->height = font.height;
    4077                 :            :         }
    4078                 :          0 :         return rc;
    4079                 :            : }
    4080                 :            : 
    4081                 :          0 : static int con_font_copy(struct vc_data *vc, struct console_font_op *op)
    4082                 :            : {
    4083                 :          0 :         int con = op->height;
    4084                 :            :         int rc;
    4085                 :            : 
    4086                 :            : 
    4087                 :          0 :         console_lock();
    4088         [ #  # ]:          0 :         if (vc->vc_mode != KD_TEXT)
    4089                 :            :                 rc = -EINVAL;
    4090         [ #  # ]:          0 :         else if (!vc->vc_sw->con_font_copy)
    4091                 :            :                 rc = -ENOSYS;
    4092 [ #  # ][ #  # ]:          0 :         else if (con < 0 || !vc_cons_allocated(con))
    4093                 :            :                 rc = -ENOTTY;
    4094         [ #  # ]:          0 :         else if (con == vc->vc_num)  /* nothing to do */
    4095                 :            :                 rc = 0;
    4096                 :            :         else
    4097                 :          0 :                 rc = vc->vc_sw->con_font_copy(vc, con);
    4098                 :          0 :         console_unlock();
    4099                 :          0 :         return rc;
    4100                 :            : }
    4101                 :            : 
    4102                 :          0 : int con_font_op(struct vc_data *vc, struct console_font_op *op)
    4103                 :            : {
    4104   [ #  #  #  #  :          0 :         switch (op->op) {
                      # ]
    4105                 :            :         case KD_FONT_OP_SET:
    4106                 :          0 :                 return con_font_set(vc, op);
    4107                 :            :         case KD_FONT_OP_GET:
    4108                 :          0 :                 return con_font_get(vc, op);
    4109                 :            :         case KD_FONT_OP_SET_DEFAULT:
    4110                 :          0 :                 return con_font_default(vc, op);
    4111                 :            :         case KD_FONT_OP_COPY:
    4112                 :          0 :                 return con_font_copy(vc, op);
    4113                 :            :         }
    4114                 :            :         return -ENOSYS;
    4115                 :            : }
    4116                 :            : 
    4117                 :            : /*
    4118                 :            :  *      Interface exported to selection and vcs.
    4119                 :            :  */
    4120                 :            : 
    4121                 :            : /* used by selection */
    4122                 :          0 : u16 screen_glyph(struct vc_data *vc, int offset)
    4123                 :            : {
    4124                 :          0 :         u16 w = scr_readw(screenpos(vc, offset, 1));
    4125                 :          0 :         u16 c = w & 0xff;
    4126                 :            : 
    4127         [ #  # ]:          0 :         if (w & vc->vc_hi_font_mask)
    4128                 :          0 :                 c |= 0x100;
    4129                 :          0 :         return c;
    4130                 :            : }
    4131                 :            : EXPORT_SYMBOL_GPL(screen_glyph);
    4132                 :            : 
    4133                 :            : /* used by vcs - note the word offset */
    4134                 :          0 : unsigned short *screen_pos(struct vc_data *vc, int w_offset, int viewed)
    4135                 :            : {
    4136                 :          0 :         return screenpos(vc, 2 * w_offset, viewed);
    4137                 :            : }
    4138                 :            : 
    4139                 :          0 : void getconsxy(struct vc_data *vc, unsigned char *p)
    4140                 :            : {
    4141                 :          0 :         p[0] = vc->vc_x;
    4142                 :          0 :         p[1] = vc->vc_y;
    4143                 :          0 : }
    4144                 :            : 
    4145                 :          0 : void putconsxy(struct vc_data *vc, unsigned char *p)
    4146                 :            : {
    4147                 :          0 :         hide_cursor(vc);
    4148                 :          0 :         gotoxy(vc, p[0], p[1]);
    4149                 :          0 :         set_cursor(vc);
    4150                 :          0 : }
    4151                 :            : 
    4152                 :          0 : u16 vcs_scr_readw(struct vc_data *vc, const u16 *org)
    4153                 :            : {
    4154 [ #  # ][ #  # ]:          0 :         if ((unsigned long)org == vc->vc_pos && softcursor_original != -1)
    4155                 :          0 :                 return softcursor_original;
    4156                 :          0 :         return scr_readw(org);
    4157                 :            : }
    4158                 :            : 
    4159                 :          0 : void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
    4160                 :            : {
    4161                 :          0 :         scr_writew(val, org);
    4162         [ #  # ]:          0 :         if ((unsigned long)org == vc->vc_pos) {
    4163                 :          0 :                 softcursor_original = -1;
    4164                 :          0 :                 add_softcursor(vc);
    4165                 :            :         }
    4166                 :          0 : }
    4167                 :            : 
    4168                 :          0 : void vcs_scr_updated(struct vc_data *vc)
    4169                 :            : {
    4170                 :            :         notify_update(vc);
    4171                 :          0 : }
    4172                 :            : 
    4173                 :            : /*
    4174                 :            :  *      Visible symbols for modules
    4175                 :            :  */
    4176                 :            : 
    4177                 :            : EXPORT_SYMBOL(color_table);
    4178                 :            : EXPORT_SYMBOL(default_red);
    4179                 :            : EXPORT_SYMBOL(default_grn);
    4180                 :            : EXPORT_SYMBOL(default_blu);
    4181                 :            : EXPORT_SYMBOL(update_region);
    4182                 :            : EXPORT_SYMBOL(redraw_screen);
    4183                 :            : EXPORT_SYMBOL(vc_resize);
    4184                 :            : EXPORT_SYMBOL(fg_console);
    4185                 :            : EXPORT_SYMBOL(console_blank_hook);
    4186                 :            : EXPORT_SYMBOL(console_blanked);
    4187                 :            : EXPORT_SYMBOL(vc_cons);
    4188                 :            : EXPORT_SYMBOL(global_cursor_default);
    4189                 :            : #ifndef VT_SINGLE_DRIVER
    4190                 :            : EXPORT_SYMBOL(give_up_console);
    4191                 :            : #endif

Generated by: LCOV version 1.9