aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/vt/consolemap.c123
-rw-r--r--drivers/tty/vt/vt_ioctl.c25
-rw-r--r--include/linux/vt_kern.h1
3 files changed, 96 insertions, 53 deletions
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 8308fc7cdc26..2aaa0c228409 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -19,6 +19,7 @@
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/tty.h> 20#include <linux/tty.h>
21#include <asm/uaccess.h> 21#include <asm/uaccess.h>
22#include <linux/console.h>
22#include <linux/consolemap.h> 23#include <linux/consolemap.h>
23#include <linux/vt_kern.h> 24#include <linux/vt_kern.h>
24 25
@@ -312,6 +313,7 @@ int con_set_trans_old(unsigned char __user * arg)
312 if (!access_ok(VERIFY_READ, arg, E_TABSZ)) 313 if (!access_ok(VERIFY_READ, arg, E_TABSZ))
313 return -EFAULT; 314 return -EFAULT;
314 315
316 console_lock();
315 for (i=0; i<E_TABSZ ; i++) { 317 for (i=0; i<E_TABSZ ; i++) {
316 unsigned char uc; 318 unsigned char uc;
317 __get_user(uc, arg+i); 319 __get_user(uc, arg+i);
@@ -319,6 +321,7 @@ int con_set_trans_old(unsigned char __user * arg)
319 } 321 }
320 322
321 update_user_maps(); 323 update_user_maps();
324 console_unlock();
322 return 0; 325 return 0;
323} 326}
324 327
@@ -330,11 +333,13 @@ int con_get_trans_old(unsigned char __user * arg)
330 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ)) 333 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
331 return -EFAULT; 334 return -EFAULT;
332 335
336 console_lock();
333 for (i=0; i<E_TABSZ ; i++) 337 for (i=0; i<E_TABSZ ; i++)
334 { 338 {
335 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]); 339 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
336 __put_user((ch & ~0xff) ? 0 : ch, arg+i); 340 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
337 } 341 }
342 console_unlock();
338 return 0; 343 return 0;
339} 344}
340 345
@@ -346,6 +351,7 @@ int con_set_trans_new(ushort __user * arg)
346 if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short))) 351 if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
347 return -EFAULT; 352 return -EFAULT;
348 353
354 console_lock();
349 for (i=0; i<E_TABSZ ; i++) { 355 for (i=0; i<E_TABSZ ; i++) {
350 unsigned short us; 356 unsigned short us;
351 __get_user(us, arg+i); 357 __get_user(us, arg+i);
@@ -353,6 +359,7 @@ int con_set_trans_new(ushort __user * arg)
353 } 359 }
354 360
355 update_user_maps(); 361 update_user_maps();
362 console_unlock();
356 return 0; 363 return 0;
357} 364}
358 365
@@ -364,8 +371,10 @@ int con_get_trans_new(ushort __user * arg)
364 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short))) 371 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
365 return -EFAULT; 372 return -EFAULT;
366 373
374 console_lock();
367 for (i=0; i<E_TABSZ ; i++) 375 for (i=0; i<E_TABSZ ; i++)
368 __put_user(p[i], arg+i); 376 __put_user(p[i], arg+i);
377 console_unlock();
369 378
370 return 0; 379 return 0;
371} 380}
@@ -407,6 +416,7 @@ static void con_release_unimap(struct uni_pagedir *p)
407 } 416 }
408} 417}
409 418
419/* Caller must hold the console lock */
410void con_free_unimap(struct vc_data *vc) 420void con_free_unimap(struct vc_data *vc)
411{ 421{
412 struct uni_pagedir *p; 422 struct uni_pagedir *p;
@@ -487,17 +497,21 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
487 return 0; 497 return 0;
488} 498}
489 499
490/* ui is a leftover from using a hashtable, but might be used again */ 500/* ui is a leftover from using a hashtable, but might be used again
491int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui) 501 Caller must hold the lock */
502static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
492{ 503{
493 struct uni_pagedir *p, *q; 504 struct uni_pagedir *p, *q;
494 505
495 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; 506 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
496 if (p && p->readonly) return -EIO; 507 if (p && p->readonly)
508 return -EIO;
509
497 if (!p || --p->refcount) { 510 if (!p || --p->refcount) {
498 q = kzalloc(sizeof(*p), GFP_KERNEL); 511 q = kzalloc(sizeof(*p), GFP_KERNEL);
499 if (!q) { 512 if (!q) {
500 if (p) p->refcount++; 513 if (p)
514 p->refcount++;
501 return -ENOMEM; 515 return -ENOMEM;
502 } 516 }
503 q->refcount=1; 517 q->refcount=1;
@@ -511,23 +525,43 @@ int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
511 return 0; 525 return 0;
512} 526}
513 527
528int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
529{
530 int ret;
531 console_lock();
532 ret = con_do_clear_unimap(vc, ui);
533 console_unlock();
534 return ret;
535}
536
514int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) 537int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
515{ 538{
516 int err = 0, err1, i; 539 int err = 0, err1, i;
517 struct uni_pagedir *p, *q; 540 struct uni_pagedir *p, *q;
518 541
542 console_lock();
543
519 /* Save original vc_unipagdir_loc in case we allocate a new one */ 544 /* Save original vc_unipagdir_loc in case we allocate a new one */
520 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; 545 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
521 if (p->readonly) return -EIO; 546 if (p->readonly) {
547 console_unlock();
548 return -EIO;
549 }
522 550
523 if (!ct) return 0; 551 if (!ct) {
552 console_unlock();
553 return 0;
554 }
524 555
525 if (p->refcount > 1) { 556 if (p->refcount > 1) {
526 int j, k; 557 int j, k;
527 u16 **p1, *p2, l; 558 u16 **p1, *p2, l;
528 559
529 err1 = con_clear_unimap(vc, NULL); 560 err1 = con_do_clear_unimap(vc, NULL);
530 if (err1) return err1; 561 if (err1) {
562 console_unlock();
563 return err1;
564 }
531 565
532 /* 566 /*
533 * Since refcount was > 1, con_clear_unimap() allocated a 567 * Since refcount was > 1, con_clear_unimap() allocated a
@@ -558,7 +592,8 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
558 *vc->vc_uni_pagedir_loc = (unsigned long)p; 592 *vc->vc_uni_pagedir_loc = (unsigned long)p;
559 con_release_unimap(q); 593 con_release_unimap(q);
560 kfree(q); 594 kfree(q);
561 return err1; 595 console_unlock();
596 return err1;
562 } 597 }
563 } 598 }
564 } else { 599 } else {
@@ -592,21 +627,30 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
592 /* 627 /*
593 * Merge with fontmaps of any other virtual consoles. 628 * Merge with fontmaps of any other virtual consoles.
594 */ 629 */
595 if (con_unify_unimap(vc, p)) 630 if (con_unify_unimap(vc, p)) {
631 console_unlock();
596 return err; 632 return err;
633 }
597 634
598 for (i = 0; i <= 3; i++) 635 for (i = 0; i <= 3; i++)
599 set_inverse_transl(vc, p, i); /* Update inverse translations */ 636 set_inverse_transl(vc, p, i); /* Update inverse translations */
600 set_inverse_trans_unicode(vc, p); 637 set_inverse_trans_unicode(vc, p);
601 638
639 console_unlock();
602 return err; 640 return err;
603} 641}
604 642
605/* Loads the unimap for the hardware font, as defined in uni_hash.tbl. 643/**
606 The representation used was the most compact I could come up 644 * con_set_default_unimap - set default unicode map
607 with. This routine is executed at sys_setup time, and when the 645 * @vc: the console we are updating
608 PIO_FONTRESET ioctl is called. */ 646 *
609 647 * Loads the unimap for the hardware font, as defined in uni_hash.tbl.
648 * The representation used was the most compact I could come up
649 * with. This routine is executed at video setup, and when the
650 * PIO_FONTRESET ioctl is called.
651 *
652 * The caller must hold the console lock
653 */
610int con_set_default_unimap(struct vc_data *vc) 654int con_set_default_unimap(struct vc_data *vc)
611{ 655{
612 int i, j, err = 0, err1; 656 int i, j, err = 0, err1;
@@ -617,6 +661,7 @@ int con_set_default_unimap(struct vc_data *vc)
617 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; 661 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
618 if (p == dflt) 662 if (p == dflt)
619 return 0; 663 return 0;
664
620 dflt->refcount++; 665 dflt->refcount++;
621 *vc->vc_uni_pagedir_loc = (unsigned long)dflt; 666 *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
622 if (p && !--p->refcount) { 667 if (p && !--p->refcount) {
@@ -628,8 +673,9 @@ int con_set_default_unimap(struct vc_data *vc)
628 673
629 /* The default font is always 256 characters */ 674 /* The default font is always 256 characters */
630 675
631 err = con_clear_unimap(vc, NULL); 676 err = con_do_clear_unimap(vc, NULL);
632 if (err) return err; 677 if (err)
678 return err;
633 679
634 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; 680 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
635 q = dfont_unitable; 681 q = dfont_unitable;
@@ -654,6 +700,13 @@ int con_set_default_unimap(struct vc_data *vc)
654} 700}
655EXPORT_SYMBOL(con_set_default_unimap); 701EXPORT_SYMBOL(con_set_default_unimap);
656 702
703/**
704 * con_copy_unimap - copy unimap between two vts
705 * @dst_vc: target
706 * @src_vt: source
707 *
708 * The caller must hold the console lock when invoking this method
709 */
657int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc) 710int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
658{ 711{
659 struct uni_pagedir *q; 712 struct uni_pagedir *q;
@@ -668,13 +721,23 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
668 *dst_vc->vc_uni_pagedir_loc = (long)q; 721 *dst_vc->vc_uni_pagedir_loc = (long)q;
669 return 0; 722 return 0;
670} 723}
724EXPORT_SYMBOL(con_copy_unimap);
671 725
726/**
727 * con_get_unimap - get the unicode map
728 * @vc: the console to read from
729 *
730 * Read the console unicode data for this console. Called from the ioctl
731 * handlers.
732 */
672int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list) 733int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
673{ 734{
674 int i, j, k, ect; 735 int i, j, k, ect;
675 u16 **p1, *p2; 736 u16 **p1, *p2;
676 struct uni_pagedir *p; 737 struct uni_pagedir *p;
677 738
739 console_lock();
740
678 ect = 0; 741 ect = 0;
679 if (*vc->vc_uni_pagedir_loc) { 742 if (*vc->vc_uni_pagedir_loc) {
680 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; 743 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
@@ -694,22 +757,19 @@ int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct uni
694 } 757 }
695 } 758 }
696 __put_user(ect, uct); 759 __put_user(ect, uct);
760 console_unlock();
697 return ((ect <= ct) ? 0 : -ENOMEM); 761 return ((ect <= ct) ? 0 : -ENOMEM);
698} 762}
699 763
700void con_protect_unimap(struct vc_data *vc, int rdonly)
701{
702 struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
703
704 if (p)
705 p->readonly = rdonly;
706}
707
708/* 764/*
709 * Always use USER_MAP. These functions are used by the keyboard, 765 * Always use USER_MAP. These functions are used by the keyboard,
710 * which shouldn't be affected by G0/G1 switching, etc. 766 * which shouldn't be affected by G0/G1 switching, etc.
711 * If the user map still contains default values, i.e. the 767 * If the user map still contains default values, i.e. the
712 * direct-to-font mapping, then assume user is using Latin1. 768 * direct-to-font mapping, then assume user is using Latin1.
769 *
770 * FIXME: at some point we need to decide if we want to lock the table
771 * update element itself via the keyboard_event_lock for consistency with the
772 * keyboard driver as well as the consoles
713 */ 773 */
714/* may be called during an interrupt */ 774/* may be called during an interrupt */
715u32 conv_8bit_to_uni(unsigned char c) 775u32 conv_8bit_to_uni(unsigned char c)
@@ -777,4 +837,3 @@ console_map_init(void)
777 con_set_default_unimap(vc_cons[i].d); 837 con_set_default_unimap(vc_cons[i].d);
778} 838}
779 839
780EXPORT_SYMBOL(con_copy_unimap);
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index ede2ef18d2fb..64618547be11 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -910,7 +910,9 @@ int vt_ioctl(struct tty_struct *tty,
910 ret = con_font_op(vc_cons[fg_console].d, &op); 910 ret = con_font_op(vc_cons[fg_console].d, &op);
911 if (ret) 911 if (ret)
912 break; 912 break;
913 console_lock();
913 con_set_default_unimap(vc_cons[fg_console].d); 914 con_set_default_unimap(vc_cons[fg_console].d);
915 console_unlock();
914 break; 916 break;
915 } 917 }
916#endif 918#endif
@@ -934,33 +936,23 @@ int vt_ioctl(struct tty_struct *tty,
934 case PIO_SCRNMAP: 936 case PIO_SCRNMAP:
935 if (!perm) 937 if (!perm)
936 ret = -EPERM; 938 ret = -EPERM;
937 else { 939 else
938 tty_lock();
939 ret = con_set_trans_old(up); 940 ret = con_set_trans_old(up);
940 tty_unlock();
941 }
942 break; 941 break;
943 942
944 case GIO_SCRNMAP: 943 case GIO_SCRNMAP:
945 tty_lock();
946 ret = con_get_trans_old(up); 944 ret = con_get_trans_old(up);
947 tty_unlock();
948 break; 945 break;
949 946
950 case PIO_UNISCRNMAP: 947 case PIO_UNISCRNMAP:
951 if (!perm) 948 if (!perm)
952 ret = -EPERM; 949 ret = -EPERM;
953 else { 950 else
954 tty_lock();
955 ret = con_set_trans_new(up); 951 ret = con_set_trans_new(up);
956 tty_unlock();
957 }
958 break; 952 break;
959 953
960 case GIO_UNISCRNMAP: 954 case GIO_UNISCRNMAP:
961 tty_lock();
962 ret = con_get_trans_new(up); 955 ret = con_get_trans_new(up);
963 tty_unlock();
964 break; 956 break;
965 957
966 case PIO_UNIMAPCLR: 958 case PIO_UNIMAPCLR:
@@ -970,19 +962,14 @@ int vt_ioctl(struct tty_struct *tty,
970 ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); 962 ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
971 if (ret) 963 if (ret)
972 ret = -EFAULT; 964 ret = -EFAULT;
973 else { 965 else
974 tty_lock();
975 con_clear_unimap(vc, &ui); 966 con_clear_unimap(vc, &ui);
976 tty_unlock();
977 }
978 break; 967 break;
979 } 968 }
980 969
981 case PIO_UNIMAP: 970 case PIO_UNIMAP:
982 case GIO_UNIMAP: 971 case GIO_UNIMAP:
983 tty_lock();
984 ret = do_unimap_ioctl(cmd, up, perm, vc); 972 ret = do_unimap_ioctl(cmd, up, perm, vc);
985 tty_unlock();
986 break; 973 break;
987 974
988 case VT_LOCKSWITCH: 975 case VT_LOCKSWITCH:
@@ -1196,9 +1183,7 @@ long vt_compat_ioctl(struct tty_struct *tty,
1196 1183
1197 case PIO_UNIMAP: 1184 case PIO_UNIMAP:
1198 case GIO_UNIMAP: 1185 case GIO_UNIMAP:
1199 tty_lock();
1200 ret = compat_unimap_ioctl(cmd, up, perm, vc); 1186 ret = compat_unimap_ioctl(cmd, up, perm, vc);
1201 tty_unlock();
1202 break; 1187 break;
1203 1188
1204 /* 1189 /*
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index e33d77f15bda..50ae7d0c279e 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -70,7 +70,6 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list);
70int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list); 70int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list);
71int con_set_default_unimap(struct vc_data *vc); 71int con_set_default_unimap(struct vc_data *vc);
72void con_free_unimap(struct vc_data *vc); 72void con_free_unimap(struct vc_data *vc);
73void con_protect_unimap(struct vc_data *vc, int rdonly);
74int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc); 73int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
75 74
76#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \ 75#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \