diff options
Diffstat (limited to 'drivers/tty/vt')
-rw-r--r-- | drivers/tty/vt/keyboard.c | 5 | ||||
-rw-r--r-- | drivers/tty/vt/vc_screen.c | 110 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 27 | ||||
-rw-r--r-- | drivers/tty/vt/vt_ioctl.c | 12 |
4 files changed, 86 insertions, 68 deletions
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index e95d7876ca6b..6dd3c68c13ad 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c | |||
@@ -654,7 +654,8 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag) | |||
654 | if (value >= ARRAY_SIZE(fn_handler)) | 654 | if (value >= ARRAY_SIZE(fn_handler)) |
655 | return; | 655 | return; |
656 | if ((kbd->kbdmode == VC_RAW || | 656 | if ((kbd->kbdmode == VC_RAW || |
657 | kbd->kbdmode == VC_MEDIUMRAW) && | 657 | kbd->kbdmode == VC_MEDIUMRAW || |
658 | kbd->kbdmode == VC_OFF) && | ||
658 | value != KVAL(K_SAK)) | 659 | value != KVAL(K_SAK)) |
659 | return; /* SAK is allowed even in raw mode */ | 660 | return; /* SAK is allowed even in raw mode */ |
660 | fn_handler[value](vc); | 661 | fn_handler[value](vc); |
@@ -1295,7 +1296,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw) | |||
1295 | if (rc == NOTIFY_STOP) | 1296 | if (rc == NOTIFY_STOP) |
1296 | return; | 1297 | return; |
1297 | 1298 | ||
1298 | if (raw_mode && type != KT_SPEC && type != KT_SHIFT) | 1299 | if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT) |
1299 | return; | 1300 | return; |
1300 | 1301 | ||
1301 | (*k_handler[type])(vc, keysym & 0xff, !down); | 1302 | (*k_handler[type])(vc, keysym & 0xff, !down); |
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 95e05dfc437c..1564261e80c8 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/mutex.h> | ||
32 | #include <linux/vt_kern.h> | 31 | #include <linux/vt_kern.h> |
33 | #include <linux/selection.h> | 32 | #include <linux/selection.h> |
34 | #include <linux/kbd_kern.h> | 33 | #include <linux/kbd_kern.h> |
@@ -50,6 +49,8 @@ | |||
50 | #undef addr | 49 | #undef addr |
51 | #define HEADER_SIZE 4 | 50 | #define HEADER_SIZE 4 |
52 | 51 | ||
52 | #define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE) | ||
53 | |||
53 | struct vcs_poll_data { | 54 | struct vcs_poll_data { |
54 | struct notifier_block notifier; | 55 | struct notifier_block notifier; |
55 | unsigned int cons_num; | 56 | unsigned int cons_num; |
@@ -130,21 +131,45 @@ vcs_poll_data_get(struct file *file) | |||
130 | return poll; | 131 | return poll; |
131 | } | 132 | } |
132 | 133 | ||
134 | /* | ||
135 | * Returns VC for inode. | ||
136 | * Must be called with console_lock. | ||
137 | */ | ||
138 | static struct vc_data* | ||
139 | vcs_vc(struct inode *inode, int *viewed) | ||
140 | { | ||
141 | unsigned int currcons = iminor(inode) & 127; | ||
142 | |||
143 | WARN_CONSOLE_UNLOCKED(); | ||
144 | |||
145 | if (currcons == 0) { | ||
146 | currcons = fg_console; | ||
147 | if (viewed) | ||
148 | *viewed = 1; | ||
149 | } else { | ||
150 | currcons--; | ||
151 | if (viewed) | ||
152 | *viewed = 0; | ||
153 | } | ||
154 | return vc_cons[currcons].d; | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * Returns size for VC carried by inode. | ||
159 | * Must be called with console_lock. | ||
160 | */ | ||
133 | static int | 161 | static int |
134 | vcs_size(struct inode *inode) | 162 | vcs_size(struct inode *inode) |
135 | { | 163 | { |
136 | int size; | 164 | int size; |
137 | int minor = iminor(inode); | 165 | int minor = iminor(inode); |
138 | int currcons = minor & 127; | ||
139 | struct vc_data *vc; | 166 | struct vc_data *vc; |
140 | 167 | ||
141 | if (currcons == 0) | 168 | WARN_CONSOLE_UNLOCKED(); |
142 | currcons = fg_console; | 169 | |
143 | else | 170 | vc = vcs_vc(inode, NULL); |
144 | currcons--; | 171 | if (!vc) |
145 | if (!vc_cons_allocated(currcons)) | ||
146 | return -ENXIO; | 172 | return -ENXIO; |
147 | vc = vc_cons[currcons].d; | ||
148 | 173 | ||
149 | size = vc->vc_rows * vc->vc_cols; | 174 | size = vc->vc_rows * vc->vc_cols; |
150 | 175 | ||
@@ -157,11 +182,13 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) | |||
157 | { | 182 | { |
158 | int size; | 183 | int size; |
159 | 184 | ||
160 | mutex_lock(&con_buf_mtx); | 185 | console_lock(); |
161 | size = vcs_size(file->f_path.dentry->d_inode); | 186 | size = vcs_size(file->f_path.dentry->d_inode); |
187 | console_unlock(); | ||
188 | if (size < 0) | ||
189 | return size; | ||
162 | switch (orig) { | 190 | switch (orig) { |
163 | default: | 191 | default: |
164 | mutex_unlock(&con_buf_mtx); | ||
165 | return -EINVAL; | 192 | return -EINVAL; |
166 | case 2: | 193 | case 2: |
167 | offset += size; | 194 | offset += size; |
@@ -172,11 +199,9 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) | |||
172 | break; | 199 | break; |
173 | } | 200 | } |
174 | if (offset < 0 || offset > size) { | 201 | if (offset < 0 || offset > size) { |
175 | mutex_unlock(&con_buf_mtx); | ||
176 | return -EINVAL; | 202 | return -EINVAL; |
177 | } | 203 | } |
178 | file->f_pos = offset; | 204 | file->f_pos = offset; |
179 | mutex_unlock(&con_buf_mtx); | ||
180 | return file->f_pos; | 205 | return file->f_pos; |
181 | } | 206 | } |
182 | 207 | ||
@@ -189,12 +214,15 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
189 | struct vc_data *vc; | 214 | struct vc_data *vc; |
190 | struct vcs_poll_data *poll; | 215 | struct vcs_poll_data *poll; |
191 | long pos; | 216 | long pos; |
192 | long viewed, attr, read; | 217 | long attr, read; |
193 | int col, maxcol; | 218 | int col, maxcol, viewed; |
194 | unsigned short *org = NULL; | 219 | unsigned short *org = NULL; |
195 | ssize_t ret; | 220 | ssize_t ret; |
221 | char *con_buf; | ||
196 | 222 | ||
197 | mutex_lock(&con_buf_mtx); | 223 | con_buf = (char *) __get_free_page(GFP_KERNEL); |
224 | if (!con_buf) | ||
225 | return -ENOMEM; | ||
198 | 226 | ||
199 | pos = *ppos; | 227 | pos = *ppos; |
200 | 228 | ||
@@ -204,18 +232,10 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
204 | console_lock(); | 232 | console_lock(); |
205 | 233 | ||
206 | attr = (currcons & 128); | 234 | attr = (currcons & 128); |
207 | currcons = (currcons & 127); | ||
208 | if (currcons == 0) { | ||
209 | currcons = fg_console; | ||
210 | viewed = 1; | ||
211 | } else { | ||
212 | currcons--; | ||
213 | viewed = 0; | ||
214 | } | ||
215 | ret = -ENXIO; | 235 | ret = -ENXIO; |
216 | if (!vc_cons_allocated(currcons)) | 236 | vc = vcs_vc(inode, &viewed); |
237 | if (!vc) | ||
217 | goto unlock_out; | 238 | goto unlock_out; |
218 | vc = vc_cons[currcons].d; | ||
219 | 239 | ||
220 | ret = -EINVAL; | 240 | ret = -EINVAL; |
221 | if (pos < 0) | 241 | if (pos < 0) |
@@ -236,6 +256,12 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
236 | * could sleep. | 256 | * could sleep. |
237 | */ | 257 | */ |
238 | size = vcs_size(inode); | 258 | size = vcs_size(inode); |
259 | if (size < 0) { | ||
260 | if (read) | ||
261 | break; | ||
262 | ret = size; | ||
263 | goto unlock_out; | ||
264 | } | ||
239 | if (pos >= size) | 265 | if (pos >= size) |
240 | break; | 266 | break; |
241 | if (count > size - pos) | 267 | if (count > size - pos) |
@@ -354,7 +380,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | |||
354 | ret = read; | 380 | ret = read; |
355 | unlock_out: | 381 | unlock_out: |
356 | console_unlock(); | 382 | console_unlock(); |
357 | mutex_unlock(&con_buf_mtx); | 383 | free_page((unsigned long) con_buf); |
358 | return ret; | 384 | return ret; |
359 | } | 385 | } |
360 | 386 | ||
@@ -365,13 +391,16 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
365 | unsigned int currcons = iminor(inode); | 391 | unsigned int currcons = iminor(inode); |
366 | struct vc_data *vc; | 392 | struct vc_data *vc; |
367 | long pos; | 393 | long pos; |
368 | long viewed, attr, size, written; | 394 | long attr, size, written; |
369 | char *con_buf0; | 395 | char *con_buf0; |
370 | int col, maxcol; | 396 | int col, maxcol, viewed; |
371 | u16 *org0 = NULL, *org = NULL; | 397 | u16 *org0 = NULL, *org = NULL; |
372 | size_t ret; | 398 | size_t ret; |
399 | char *con_buf; | ||
373 | 400 | ||
374 | mutex_lock(&con_buf_mtx); | 401 | con_buf = (char *) __get_free_page(GFP_KERNEL); |
402 | if (!con_buf) | ||
403 | return -ENOMEM; | ||
375 | 404 | ||
376 | pos = *ppos; | 405 | pos = *ppos; |
377 | 406 | ||
@@ -381,19 +410,10 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
381 | console_lock(); | 410 | console_lock(); |
382 | 411 | ||
383 | attr = (currcons & 128); | 412 | attr = (currcons & 128); |
384 | currcons = (currcons & 127); | ||
385 | |||
386 | if (currcons == 0) { | ||
387 | currcons = fg_console; | ||
388 | viewed = 1; | ||
389 | } else { | ||
390 | currcons--; | ||
391 | viewed = 0; | ||
392 | } | ||
393 | ret = -ENXIO; | 413 | ret = -ENXIO; |
394 | if (!vc_cons_allocated(currcons)) | 414 | vc = vcs_vc(inode, &viewed); |
415 | if (!vc) | ||
395 | goto unlock_out; | 416 | goto unlock_out; |
396 | vc = vc_cons[currcons].d; | ||
397 | 417 | ||
398 | size = vcs_size(inode); | 418 | size = vcs_size(inode); |
399 | ret = -EINVAL; | 419 | ret = -EINVAL; |
@@ -435,6 +455,12 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
435 | * Return data written up to now on failure. | 455 | * Return data written up to now on failure. |
436 | */ | 456 | */ |
437 | size = vcs_size(inode); | 457 | size = vcs_size(inode); |
458 | if (size < 0) { | ||
459 | if (written) | ||
460 | break; | ||
461 | ret = size; | ||
462 | goto unlock_out; | ||
463 | } | ||
438 | if (pos >= size) | 464 | if (pos >= size) |
439 | break; | 465 | break; |
440 | if (this_round > size - pos) | 466 | if (this_round > size - pos) |
@@ -542,9 +568,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
542 | 568 | ||
543 | unlock_out: | 569 | unlock_out: |
544 | console_unlock(); | 570 | console_unlock(); |
545 | 571 | free_page((unsigned long) con_buf); | |
546 | mutex_unlock(&con_buf_mtx); | ||
547 | |||
548 | return ret; | 572 | return ret; |
549 | } | 573 | } |
550 | 574 | ||
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2178efcec1b5..c83cdfb56fcc 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c | |||
@@ -2067,18 +2067,6 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | |||
2067 | } | 2067 | } |
2068 | } | 2068 | } |
2069 | 2069 | ||
2070 | /* This is a temporary buffer used to prepare a tty console write | ||
2071 | * so that we can easily avoid touching user space while holding the | ||
2072 | * console spinlock. It is allocated in con_init and is shared by | ||
2073 | * this code and the vc_screen read/write tty calls. | ||
2074 | * | ||
2075 | * We have to allocate this statically in the kernel data section | ||
2076 | * since console_init (and thus con_init) are called before any | ||
2077 | * kernel memory allocation is available. | ||
2078 | */ | ||
2079 | char con_buf[CON_BUF_SIZE]; | ||
2080 | DEFINE_MUTEX(con_buf_mtx); | ||
2081 | |||
2082 | /* is_double_width() is based on the wcwidth() implementation by | 2070 | /* is_double_width() is based on the wcwidth() implementation by |
2083 | * Markus Kuhn -- 2007-05-26 (Unicode 5.0) | 2071 | * Markus Kuhn -- 2007-05-26 (Unicode 5.0) |
2084 | * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c | 2072 | * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c |
@@ -2156,10 +2144,10 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co | |||
2156 | 2144 | ||
2157 | currcons = vc->vc_num; | 2145 | currcons = vc->vc_num; |
2158 | if (!vc_cons_allocated(currcons)) { | 2146 | if (!vc_cons_allocated(currcons)) { |
2159 | /* could this happen? */ | 2147 | /* could this happen? */ |
2160 | printk_once("con_write: tty %d not allocated\n", currcons+1); | 2148 | pr_warn_once("con_write: tty %d not allocated\n", currcons+1); |
2161 | console_unlock(); | 2149 | console_unlock(); |
2162 | return 0; | 2150 | return 0; |
2163 | } | 2151 | } |
2164 | 2152 | ||
2165 | himask = vc->vc_hi_font_mask; | 2153 | himask = vc->vc_hi_font_mask; |
@@ -2939,7 +2927,7 @@ static int __init con_init(void) | |||
2939 | gotoxy(vc, vc->vc_x, vc->vc_y); | 2927 | gotoxy(vc, vc->vc_x, vc->vc_y); |
2940 | csi_J(vc, 0); | 2928 | csi_J(vc, 0); |
2941 | update_screen(vc); | 2929 | update_screen(vc); |
2942 | printk("Console: %s %s %dx%d", | 2930 | pr_info("Console: %s %s %dx%d", |
2943 | vc->vc_can_do_color ? "colour" : "mono", | 2931 | vc->vc_can_do_color ? "colour" : "mono", |
2944 | display_desc, vc->vc_cols, vc->vc_rows); | 2932 | display_desc, vc->vc_cols, vc->vc_rows); |
2945 | printable = 1; | 2933 | printable = 1; |
@@ -3102,7 +3090,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last, | |||
3102 | clear_buffer_attributes(vc); | 3090 | clear_buffer_attributes(vc); |
3103 | } | 3091 | } |
3104 | 3092 | ||
3105 | printk("Console: switching "); | 3093 | pr_info("Console: switching "); |
3106 | if (!deflt) | 3094 | if (!deflt) |
3107 | printk("consoles %d-%d ", first+1, last+1); | 3095 | printk("consoles %d-%d ", first+1, last+1); |
3108 | if (j >= 0) { | 3096 | if (j >= 0) { |
@@ -3808,7 +3796,8 @@ void do_unblank_screen(int leaving_gfx) | |||
3808 | return; | 3796 | return; |
3809 | if (!vc_cons_allocated(fg_console)) { | 3797 | if (!vc_cons_allocated(fg_console)) { |
3810 | /* impossible */ | 3798 | /* impossible */ |
3811 | printk("unblank_screen: tty %d not allocated ??\n", fg_console+1); | 3799 | pr_warning("unblank_screen: tty %d not allocated ??\n", |
3800 | fg_console+1); | ||
3812 | return; | 3801 | return; |
3813 | } | 3802 | } |
3814 | vc = vc_cons[fg_console].d; | 3803 | vc = vc_cons[fg_console].d; |
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index fd4c9376f875..937d17219984 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c | |||
@@ -494,7 +494,7 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_ | |||
494 | * We handle the console-specific ioctl's here. We allow the | 494 | * We handle the console-specific ioctl's here. We allow the |
495 | * capability to modify any console, not just the fg_console. | 495 | * capability to modify any console, not just the fg_console. |
496 | */ | 496 | */ |
497 | int vt_ioctl(struct tty_struct *tty, struct file * file, | 497 | int vt_ioctl(struct tty_struct *tty, |
498 | unsigned int cmd, unsigned long arg) | 498 | unsigned int cmd, unsigned long arg) |
499 | { | 499 | { |
500 | struct vc_data *vc = tty->driver_data; | 500 | struct vc_data *vc = tty->driver_data; |
@@ -687,6 +687,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
687 | kbd->kbdmode = VC_UNICODE; | 687 | kbd->kbdmode = VC_UNICODE; |
688 | compute_shiftstate(); | 688 | compute_shiftstate(); |
689 | break; | 689 | break; |
690 | case K_OFF: | ||
691 | kbd->kbdmode = VC_OFF; | ||
692 | break; | ||
690 | default: | 693 | default: |
691 | ret = -EINVAL; | 694 | ret = -EINVAL; |
692 | goto out; | 695 | goto out; |
@@ -1006,8 +1009,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
1006 | if (ret) | 1009 | if (ret) |
1007 | break; | 1010 | break; |
1008 | /* Commence switch and lock */ | 1011 | /* Commence switch and lock */ |
1009 | set_console(arg); | 1012 | set_console(vsa.console); |
1010 | } | 1013 | } |
1014 | break; | ||
1011 | } | 1015 | } |
1012 | 1016 | ||
1013 | /* | 1017 | /* |
@@ -1490,7 +1494,7 @@ compat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud, | |||
1490 | return 0; | 1494 | return 0; |
1491 | } | 1495 | } |
1492 | 1496 | ||
1493 | long vt_compat_ioctl(struct tty_struct *tty, struct file * file, | 1497 | long vt_compat_ioctl(struct tty_struct *tty, |
1494 | unsigned int cmd, unsigned long arg) | 1498 | unsigned int cmd, unsigned long arg) |
1495 | { | 1499 | { |
1496 | struct vc_data *vc = tty->driver_data; | 1500 | struct vc_data *vc = tty->driver_data; |
@@ -1576,7 +1580,7 @@ out: | |||
1576 | 1580 | ||
1577 | fallback: | 1581 | fallback: |
1578 | tty_unlock(); | 1582 | tty_unlock(); |
1579 | return vt_ioctl(tty, file, cmd, arg); | 1583 | return vt_ioctl(tty, cmd, arg); |
1580 | } | 1584 | } |
1581 | 1585 | ||
1582 | 1586 | ||