This source file includes following definitions.
- kd_size_changed
- kd_nosound
- kd_mksound
- vt_ioctl
1
2
3
4
5
6
7
8
9
10
11 #include <linux/types.h>
12 #include <linux/errno.h>
13 #include <linux/sched.h>
14 #include <linux/tty.h>
15 #include <linux/timer.h>
16 #include <linux/kernel.h>
17 #include <linux/kd.h>
18 #include <linux/vt.h>
19 #include <linux/string.h>
20 #include <linux/malloc.h>
21 #include <linux/major.h>
22 #include <linux/fs.h>
23
24 #include <asm/io.h>
25 #include <asm/segment.h>
26
27 #include "kbd_kern.h"
28 #include "vt_kern.h"
29 #include "diacr.h"
30 #include "selection.h"
31
32 extern char vt_dont_switch;
33 extern struct tty_driver console_driver;
34
35 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
36 #define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
52
53 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
54
55 extern int getkeycode(unsigned int scancode);
56 extern int setkeycode(unsigned int scancode, unsigned int keycode);
57 extern void compute_shiftstate(void);
58 extern void change_console(unsigned int new_console);
59 extern void complete_change_console(unsigned int new_console);
60 extern int vt_waitactive(void);
61 extern void do_blank_screen(int nopowersave);
62
63 extern unsigned int keymap_count;
64
65
66
67
68
69 extern int con_set_trans_old(unsigned char * table);
70 extern int con_get_trans_old(unsigned char * table);
71 extern int con_set_trans_new(unsigned short * table);
72 extern int con_get_trans_new(unsigned short * table);
73 extern void con_clear_unimap(struct unimapinit *ui);
74 extern int con_set_unimap(ushort ct, struct unipair *list);
75 extern int con_get_unimap(ushort ct, ushort *uct, struct unipair *list);
76 extern void con_set_default_unimap(void);
77 extern int con_set_font(char * fontmap, int ch512);
78 extern int con_get_font(char * fontmap);
79 extern int con_set_cmap(unsigned char *cmap);
80 extern int con_get_cmap(unsigned char *cmap);
81 extern void reset_palette(int currcons);
82 extern int con_adjust_height(unsigned long fontheight);
83
84 extern int video_mode_512ch;
85 extern unsigned long video_font_height;
86 extern unsigned long default_font_height;
87 extern unsigned long video_scan_lines;
88
89
90
91
92
93 #define GPFIRST 0x3b4
94 #define GPLAST 0x3df
95 #define GPNUM (GPLAST - GPFIRST + 1)
96
97
98
99
100
101
102
103
104
105 static int
106 kd_size_changed(int row, int col)
107 {
108 struct task_struct *p;
109 int i;
110
111 if ( !row && !col ) return 0;
112
113 for ( i = 0 ; i < MAX_NR_CONSOLES ; i++ )
114 {
115 if ( console_driver.table[i] )
116 {
117 if ( row ) console_driver.table[i]->winsize.ws_row = row;
118 if ( col ) console_driver.table[i]->winsize.ws_col = col;
119 }
120 }
121
122 for_each_task(p)
123 {
124 if ( p->tty && MAJOR(p->tty->device) == TTY_MAJOR &&
125 MINOR(p->tty->device) <= MAX_NR_CONSOLES && MINOR(p->tty->device) )
126 {
127 send_sig(SIGWINCH, p, 1);
128 }
129 }
130
131 return 0;
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 static void
150 kd_nosound(unsigned long ignored)
151 {
152
153 outb(inb_p(0x61)&0xFC, 0x61);
154 return;
155 }
156
157 void
158 kd_mksound(unsigned int count, unsigned int ticks)
159 {
160 static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
161
162 cli();
163 del_timer(&sound_timer);
164 if (count) {
165
166 outb_p(inb_p(0x61)|3, 0x61);
167
168 outb_p(0xB6, 0x43);
169
170 outb_p(count & 0xff, 0x42);
171 outb((count >> 8) & 0xff, 0x42);
172
173 if (ticks) {
174 sound_timer.expires = jiffies+ticks;
175 add_timer(&sound_timer);
176 }
177 } else
178 kd_nosound(0);
179 sti();
180 return;
181 }
182
183
184
185
186
187 int vt_ioctl(struct tty_struct *tty, struct file * file,
188 unsigned int cmd, unsigned long arg)
189 {
190 int i, perm;
191 unsigned int console;
192 unsigned char ucval;
193 struct kbd_struct * kbd;
194 struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
195
196 console = vt->vc_num;
197
198 if (!vc_cons_allocated(console))
199 return -ENOIOCTLCMD;
200
201
202
203
204
205 perm = 0;
206 if (current->tty == tty || suser())
207 perm = 1;
208
209 kbd = kbd_table + console;
210 switch (cmd) {
211 case KIOCSOUND:
212 if (!perm)
213 return -EPERM;
214 kd_mksound((unsigned int)arg, 0);
215 return 0;
216
217 case KDMKTONE:
218 if (!perm)
219 return -EPERM;
220 {
221 unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
222
223
224
225
226
227 kd_mksound(arg & 0xffff, ticks);
228 if (ticks == 0)
229 kd_nosound(0);
230 return 0;
231 }
232
233 case KDGKBTYPE:
234
235
236
237 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
238 if (!i)
239 put_user(KB_101, (char *) arg);
240 return i;
241
242 case KDADDIO:
243 case KDDELIO:
244
245
246
247
248 if (arg < GPFIRST || arg > GPLAST)
249 return -EINVAL;
250 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
251
252 case KDENABIO:
253 case KDDISABIO:
254 return sys_ioperm(GPFIRST, GPNUM,
255 (cmd == KDENABIO)) ? -ENXIO : 0;
256
257 case KDSETMODE:
258
259
260
261
262
263 if (!perm)
264 return -EPERM;
265 switch (arg) {
266 case KD_GRAPHICS:
267 break;
268 case KD_TEXT0:
269 case KD_TEXT1:
270 arg = KD_TEXT;
271 case KD_TEXT:
272 break;
273 default:
274 return -EINVAL;
275 }
276 if (vt_cons[console]->vc_mode == (unsigned char) arg)
277 return 0;
278 vt_cons[console]->vc_mode = (unsigned char) arg;
279 if (console != fg_console)
280 return 0;
281
282
283
284 if (arg == KD_TEXT)
285 do_unblank_screen();
286 else
287 do_blank_screen(1);
288 return 0;
289
290 case KDGETMODE:
291 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
292 if (!i)
293 put_user(vt_cons[console]->vc_mode, (int *) arg);
294 return i;
295
296 case KDMAPDISP:
297 case KDUNMAPDISP:
298
299
300
301
302 return -EINVAL;
303
304 case KDSKBMODE:
305 if (!perm)
306 return -EPERM;
307 switch(arg) {
308 case K_RAW:
309 kbd->kbdmode = VC_RAW;
310 break;
311 case K_MEDIUMRAW:
312 kbd->kbdmode = VC_MEDIUMRAW;
313 break;
314 case K_XLATE:
315 kbd->kbdmode = VC_XLATE;
316 compute_shiftstate();
317 break;
318 case K_UNICODE:
319 kbd->kbdmode = VC_UNICODE;
320 compute_shiftstate();
321 break;
322 default:
323 return -EINVAL;
324 }
325 if (tty->ldisc.flush_buffer)
326 tty->ldisc.flush_buffer(tty);
327 return 0;
328
329 case KDGKBMODE:
330 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
331 if (!i) {
332 ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
333 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
334 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
335 K_XLATE);
336 put_user(ucval, (int *) arg);
337 }
338 return i;
339
340
341
342 case KDSKBMETA:
343 switch(arg) {
344 case K_METABIT:
345 clr_vc_kbd_mode(kbd, VC_META);
346 break;
347 case K_ESCPREFIX:
348 set_vc_kbd_mode(kbd, VC_META);
349 break;
350 default:
351 return -EINVAL;
352 }
353 return 0;
354
355 case KDGKBMETA:
356 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
357 if (!i) {
358 ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
359 K_METABIT);
360 put_user(ucval, (int *) arg);
361 }
362 return i;
363
364 case KDGETKEYCODE:
365 {
366 struct kbkeycode * const a = (struct kbkeycode *)arg;
367 unsigned int sc;
368 int kc;
369
370 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
371 if (i)
372 return i;
373 sc = get_user(&a->scancode);
374 kc = getkeycode(sc);
375 if (kc < 0)
376 return kc;
377 put_user(kc, &a->keycode);
378 return 0;
379 }
380
381 case KDSETKEYCODE:
382 {
383 struct kbkeycode * const a = (struct kbkeycode *)arg;
384 unsigned int sc, kc;
385
386 if (!perm)
387 return -EPERM;
388 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
389 if (i)
390 return i;
391 sc = get_user(&a->scancode);
392 kc = get_user(&a->keycode);
393 return setkeycode(sc, kc);
394 }
395
396 case KDGKBENT:
397 {
398 struct kbentry * const a = (struct kbentry *)arg;
399 ushort *key_map, val;
400 u_char s;
401
402 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
403 if (i)
404 return i;
405 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
406 return -EINVAL;
407 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
408 return -EINVAL;
409 key_map = key_maps[s];
410 if (key_map) {
411 val = U(key_map[i]);
412 if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
413 val = K_HOLE;
414 } else
415 val = (i ? K_HOLE : K_NOSUCHMAP);
416 put_user(val, &a->kb_value);
417 return 0;
418 }
419
420 case KDSKBENT:
421 {
422 const struct kbentry * a = (struct kbentry *)arg;
423 ushort *key_map;
424 u_char s;
425 u_short v, ov;
426
427 if (!perm)
428 return -EPERM;
429 i = verify_area(VERIFY_READ, (const void *)a, sizeof(struct kbentry));
430 if (i)
431 return i;
432 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
433 return -EINVAL;
434 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
435 return -EINVAL;
436 v = get_user(&a->kb_value);
437 if (!i && v == K_NOSUCHMAP) {
438
439 key_map = key_maps[s];
440 if (s && key_map) {
441 key_maps[s] = 0;
442 if (key_map[0] == U(K_ALLOCATED)) {
443 kfree_s(key_map, sizeof(plain_map));
444 keymap_count--;
445 }
446 }
447 return 0;
448 }
449
450 if (KTYP(v) < NR_TYPES) {
451 if (KVAL(v) > max_vals[KTYP(v)])
452 return -EINVAL;
453 } else
454 if (kbd->kbdmode != VC_UNICODE)
455 return -EINVAL;
456
457
458 if (!i)
459 return 0;
460
461 if (!(key_map = key_maps[s])) {
462 int j;
463
464 if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
465 return -EPERM;
466
467 key_map = (ushort *) kmalloc(sizeof(plain_map),
468 GFP_KERNEL);
469 if (!key_map)
470 return -ENOMEM;
471 key_maps[s] = key_map;
472 key_map[0] = U(K_ALLOCATED);
473 for (j = 1; j < NR_KEYS; j++)
474 key_map[j] = U(K_HOLE);
475 keymap_count++;
476 }
477 ov = U(key_map[i]);
478 if (v == ov)
479 return 0;
480
481
482
483
484 if (((ov == K_SAK) || (v == K_SAK)) && !suser())
485 return -EPERM;
486 key_map[i] = U(v);
487 if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
488 compute_shiftstate();
489 return 0;
490 }
491
492 case KDGKBSENT:
493 {
494 struct kbsentry *a = (struct kbsentry *)arg;
495 char *p;
496 u_char *q;
497 int sz;
498
499 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
500 if (i)
501 return i;
502 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
503 return -EINVAL;
504 sz = sizeof(a->kb_string) - 1;
505
506 q = a->kb_string;
507 p = func_table[i];
508 if(p)
509 for ( ; *p && sz; p++, sz--)
510 put_user(*p, q++);
511 put_user('\0', q);
512 return ((p && *p) ? -EOVERFLOW : 0);
513 }
514
515 case KDSKBSENT:
516 {
517 struct kbsentry * const a = (struct kbsentry *)arg;
518 int delta;
519 char *first_free, *fj, *fnw;
520 int j, k, sz;
521 u_char *p;
522 char *q;
523
524 if (!perm)
525 return -EPERM;
526 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
527 if (i)
528 return i;
529 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC)
530 return -EINVAL;
531 q = func_table[i];
532
533 first_free = funcbufptr + (funcbufsize - funcbufleft);
534 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
535 if (j < MAX_NR_FUNC)
536 fj = func_table[j];
537 else
538 fj = first_free;
539
540 delta = (q ? -strlen(q) : 1);
541 sz = sizeof(a->kb_string);
542
543 for (p = a->kb_string; get_user(p) && sz; p++,sz--)
544 delta++;
545 if (!sz)
546 return -EOVERFLOW;
547 if (delta <= funcbufleft) {
548 if (j < MAX_NR_FUNC) {
549 memmove(fj + delta, fj, first_free - fj);
550 for (k = j; k < MAX_NR_FUNC; k++)
551 if (func_table[k])
552 func_table[k] += delta;
553 }
554 if (!q)
555 func_table[i] = fj;
556 funcbufleft -= delta;
557 } else {
558 sz = 256;
559 while (sz < funcbufsize - funcbufleft + delta)
560 sz <<= 1;
561 fnw = (char *) kmalloc(sz, GFP_KERNEL);
562 if(!fnw)
563 return -ENOMEM;
564
565 if (!q)
566 func_table[i] = fj;
567 if (fj > funcbufptr)
568 memmove(fnw, funcbufptr, fj - funcbufptr);
569 for (k = 0; k < j; k++)
570 if (func_table[k])
571 func_table[k] = fnw + (func_table[k] - funcbufptr);
572
573 if (first_free > fj) {
574 memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
575 for (k = j; k < MAX_NR_FUNC; k++)
576 if (func_table[k])
577 func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
578 }
579 if (funcbufptr != func_buf)
580 kfree_s(funcbufptr, funcbufsize);
581 funcbufptr = fnw;
582 funcbufleft = funcbufleft - delta + sz - funcbufsize;
583 funcbufsize = sz;
584 }
585 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
586 if (!(*q = get_user(p)))
587 break;
588 return 0;
589 }
590
591 case KDGKBDIACR:
592 {
593 struct kbdiacrs *a = (struct kbdiacrs *)arg;
594
595 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
596 if (i)
597 return i;
598 put_user(accent_table_size, &a->kb_cnt);
599 memcpy_tofs(a->kbdiacr, accent_table,
600 accent_table_size*sizeof(struct kbdiacr));
601 return 0;
602 }
603
604 case KDSKBDIACR:
605 {
606 struct kbdiacrs *a = (struct kbdiacrs *)arg;
607 unsigned int ct;
608
609 if (!perm)
610 return -EPERM;
611 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
612 if (i)
613 return i;
614 ct = get_user(&a->kb_cnt);
615 if (ct >= MAX_DIACR)
616 return -EINVAL;
617 accent_table_size = ct;
618 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
619 return 0;
620 }
621
622
623
624 case KDGKBLED:
625 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
626 if (i)
627 return i;
628 put_user(kbd->ledflagstate |
629 (kbd->default_ledflagstate << 4), (char *) arg);
630 return 0;
631
632 case KDSKBLED:
633 if (!perm)
634 return -EPERM;
635 if (arg & ~0x77)
636 return -EINVAL;
637 kbd->ledflagstate = (arg & 7);
638 kbd->default_ledflagstate = ((arg >> 4) & 7);
639 set_leds();
640 return 0;
641
642
643
644 case KDGETLED:
645 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
646 if (i)
647 return i;
648 put_user(getledstate(), (char *) arg);
649 return 0;
650
651 case KDSETLED:
652 if (!perm)
653 return -EPERM;
654 setledstate(kbd, arg);
655 return 0;
656
657
658
659
660
661
662
663
664
665
666
667 case KDSIGACCEPT:
668 {
669 extern int spawnpid, spawnsig;
670 if (!perm)
671 return -EPERM;
672 if (arg < 1 || arg > NSIG || arg == SIGKILL)
673 return -EINVAL;
674 spawnpid = current->pid;
675 spawnsig = arg;
676 return 0;
677 }
678
679 case VT_SETMODE:
680 {
681 struct vt_mode *vtmode = (struct vt_mode *)arg;
682 char mode;
683
684 if (!perm)
685 return -EPERM;
686 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
687 if (i)
688 return i;
689 mode = get_user(&vtmode->mode);
690 if (mode != VT_AUTO && mode != VT_PROCESS)
691 return -EINVAL;
692 vt_cons[console]->vt_mode.mode = mode;
693 vt_cons[console]->vt_mode.waitv = get_user(&vtmode->waitv);
694 vt_cons[console]->vt_mode.relsig = get_user(&vtmode->relsig);
695 vt_cons[console]->vt_mode.acqsig = get_user(&vtmode->acqsig);
696
697 vt_cons[console]->vt_mode.frsig = 0;
698 vt_cons[console]->vt_pid = current->pid;
699 vt_cons[console]->vt_newvt = 0;
700 return 0;
701 }
702
703 case VT_GETMODE:
704 {
705 struct vt_mode *vtmode = (struct vt_mode *)arg;
706
707 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
708 if (i)
709 return i;
710 put_user(vt_cons[console]->vt_mode.mode, &vtmode->mode);
711 put_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
712 put_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
713 put_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
714 put_user(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
715 return 0;
716 }
717
718
719
720
721
722
723 case VT_GETSTATE:
724 {
725 struct vt_stat *vtstat = (struct vt_stat *)arg;
726 unsigned short state, mask;
727
728 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
729 if (i)
730 return i;
731 put_user(fg_console + 1, &vtstat->v_active);
732 state = 1;
733 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
734 if (VT_IS_IN_USE(i))
735 state |= mask;
736 put_user(state, &vtstat->v_state);
737 return 0;
738 }
739
740
741
742
743 case VT_OPENQRY:
744 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
745 if (i)
746 return i;
747 for (i = 0; i < MAX_NR_CONSOLES; ++i)
748 if (! VT_IS_IN_USE(i))
749 break;
750 put_user(i < MAX_NR_CONSOLES ? (i+1) : -1, (int *) arg);
751 return 0;
752
753
754
755
756
757
758 case VT_ACTIVATE:
759 if (!perm)
760 return -EPERM;
761 if (arg == 0 || arg > MAX_NR_CONSOLES)
762 return -ENXIO;
763 arg--;
764 i = vc_allocate(arg);
765 if (i)
766 return i;
767 change_console(arg);
768 return 0;
769
770
771
772
773 case VT_WAITACTIVE:
774 if (!perm)
775 return -EPERM;
776 if (arg == 0 || arg > MAX_NR_CONSOLES)
777 return -ENXIO;
778 arg--;
779 while (fg_console != arg)
780 {
781 if (vt_waitactive() < 0)
782 return -EINTR;
783 }
784 return 0;
785
786
787
788
789
790
791
792
793
794
795
796 case VT_RELDISP:
797 if (!perm)
798 return -EPERM;
799 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
800 return -EINVAL;
801
802
803
804
805 if (vt_cons[console]->vt_newvt >= 0)
806 {
807 if (arg == 0)
808
809
810
811
812 vt_cons[console]->vt_newvt = -1;
813
814 else
815 {
816
817
818
819
820 int newvt = vt_cons[console]->vt_newvt;
821 vt_cons[console]->vt_newvt = -1;
822 i = vc_allocate(newvt);
823 if (i)
824 return i;
825 complete_change_console(newvt);
826 }
827 }
828
829
830
831
832 else
833 {
834
835
836
837 if (arg != VT_ACKACQ)
838 return -EINVAL;
839 }
840
841 return 0;
842
843
844
845
846 case VT_DISALLOCATE:
847 if (arg > MAX_NR_CONSOLES)
848 return -ENXIO;
849 if (arg == 0) {
850
851 for (i=1; i<MAX_NR_CONSOLES; i++)
852 if (! VT_BUSY(i))
853 vc_disallocate(i);
854 } else {
855
856 arg--;
857 if (VT_BUSY(arg))
858 return -EBUSY;
859 if (arg)
860 vc_disallocate(arg);
861 }
862 return 0;
863
864 case VT_RESIZE:
865 {
866 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
867 ushort ll,cc;
868 if (!perm)
869 return -EPERM;
870 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
871 if (i)
872 return i;
873 ll = get_user(&vtsizes->v_rows);
874 cc = get_user(&vtsizes->v_cols);
875 i = vc_resize(ll, cc);
876 return i ? i : kd_size_changed(ll, cc);
877 }
878
879 case VT_RESIZEX:
880 {
881 struct vt_consize *vtconsize = (struct vt_consize *) arg;
882 ushort ll,cc,vlin,clin,vcol,ccol;
883 if (!perm)
884 return -EPERM;
885 i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
886 if (i)
887 return i;
888 ll = get_user(&vtconsize->v_rows);
889 cc = get_user(&vtconsize->v_cols);
890 vlin = get_user(&vtconsize->v_vlin);
891 clin = get_user(&vtconsize->v_clin);
892 vcol = get_user(&vtconsize->v_vcol);
893 ccol = get_user(&vtconsize->v_ccol);
894 vlin = vlin ? vlin : video_scan_lines;
895 if ( clin )
896 {
897 if ( ll )
898 {
899 if ( ll != vlin/clin )
900 return EINVAL;
901 }
902 else
903 ll = vlin/clin;
904 }
905 if ( vcol && ccol )
906 {
907 if ( cc )
908 {
909 if ( cc != vcol/ccol )
910 return EINVAL;
911 }
912 else
913 cc = vcol/ccol;
914 }
915
916 if ( clin > 32 )
917 return EINVAL;
918
919 if ( vlin )
920 video_scan_lines = vlin;
921 if ( clin )
922 video_font_height = clin;
923
924 i = vc_resize(ll, cc);
925 if (i)
926 return i;
927
928 kd_size_changed(ll, cc);
929 return 0;
930 }
931
932 case PIO_FONT:
933 if (!perm)
934 return -EPERM;
935 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
936 return -EINVAL;
937 return con_set_font((char *)arg, 0);
938
939
940 case GIO_FONT:
941 if (vt_cons[fg_console]->vc_mode != KD_TEXT ||
942 video_mode_512ch)
943 return -EINVAL;
944 return con_get_font((char *)arg);
945
946
947 case PIO_CMAP:
948 if (!perm)
949 return -EPERM;
950 return con_set_cmap((char *)arg);
951
952
953 case GIO_CMAP:
954 return con_get_cmap((char *)arg);
955
956
957 case PIO_FONTX:
958 {
959 struct consolefontdesc cfdarg;
960
961 if (!perm)
962 return -EPERM;
963 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
964 return -EINVAL;
965 i = verify_area(VERIFY_READ, (void *)arg,
966 sizeof(struct consolefontdesc));
967 if (i) return i;
968 memcpy_fromfs(&cfdarg, (void *)arg,
969 sizeof(struct consolefontdesc));
970
971 if ( cfdarg.charcount == 256 ||
972 cfdarg.charcount == 512 ) {
973 i = con_set_font(cfdarg.chardata,
974 cfdarg.charcount == 512);
975 if (i)
976 return i;
977 i = con_adjust_height(cfdarg.charheight);
978 return (i <= 0) ? i : kd_size_changed(i, 0);
979 } else
980 return -EINVAL;
981 }
982
983 case PIO_FONTRESET:
984 {
985 if (!perm)
986 return -EPERM;
987 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
988 return -EINVAL;
989
990 #ifdef BROKEN_GRAPHICS_PROGRAMS
991
992
993 return -ENOSYS;
994 #else
995
996 i = con_set_font(NULL, 0);
997 if (i) return i;
998
999 i = con_adjust_height(default_font_height);
1000 if ( i > 0 ) kd_size_changed(i, 0);
1001 con_set_default_unimap();
1002
1003 return 0;
1004 #endif
1005 }
1006
1007 case GIO_FONTX:
1008 {
1009 struct consolefontdesc cfdarg;
1010 int nchar;
1011
1012 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1013 return -EINVAL;
1014 i = verify_area(VERIFY_WRITE, (void *)arg,
1015 sizeof(struct consolefontdesc));
1016 if (i) return i;
1017 memcpy_fromfs(&cfdarg, (void *) arg,
1018 sizeof(struct consolefontdesc));
1019 i = cfdarg.charcount;
1020 cfdarg.charcount = nchar = video_mode_512ch ? 512 : 256;
1021 cfdarg.charheight = video_font_height;
1022 memcpy_tofs((void *) arg, &cfdarg,
1023 sizeof(struct consolefontdesc));
1024 if ( cfdarg.chardata )
1025 {
1026 if ( i < nchar )
1027 return -ENOMEM;
1028 return con_get_font(cfdarg.chardata);
1029 } else
1030 return 0;
1031 }
1032
1033 case PIO_SCRNMAP:
1034 if (!perm)
1035 return -EPERM;
1036 return con_set_trans_old((unsigned char *)arg);
1037
1038 case GIO_SCRNMAP:
1039 return con_get_trans_old((unsigned char *)arg);
1040
1041 case PIO_UNISCRNMAP:
1042 if (!perm)
1043 return -EPERM;
1044 return con_set_trans_new((unsigned short *)arg);
1045
1046 case GIO_UNISCRNMAP:
1047 return con_get_trans_new((unsigned short *)arg);
1048
1049 case PIO_UNIMAPCLR:
1050 { struct unimapinit ui;
1051 if (!perm)
1052 return -EPERM;
1053 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
1054 if (i)
1055 return i;
1056 memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
1057 con_clear_unimap(&ui);
1058 return 0;
1059 }
1060
1061 case PIO_UNIMAP:
1062 { struct unimapdesc *ud;
1063 u_short ct;
1064 struct unipair *list;
1065
1066 if (!perm)
1067 return -EPERM;
1068 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
1069 if (i == 0) {
1070 ud = (struct unimapdesc *) arg;
1071 ct = get_user(&ud->entry_ct);
1072 list = get_user(&ud->entries);
1073 i = verify_area(VERIFY_READ, (void *) list,
1074 ct*sizeof(struct unipair));
1075 }
1076 if (i)
1077 return i;
1078 return con_set_unimap(ct, list);
1079 }
1080
1081 case GIO_UNIMAP:
1082 { struct unimapdesc *ud;
1083 u_short ct;
1084 struct unipair *list;
1085
1086 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
1087 if (i == 0) {
1088 ud = (struct unimapdesc *) arg;
1089 ct = get_user(&ud->entry_ct);
1090 list = get_user(&ud->entries);
1091 if (ct)
1092 i = verify_area(VERIFY_WRITE, (void *) list,
1093 ct*sizeof(struct unipair));
1094 }
1095 if (i)
1096 return i;
1097 return con_get_unimap(ct, &(ud->entry_ct), list);
1098 }
1099 case VT_LOCKSWITCH:
1100 if (!suser())
1101 return -EPERM;
1102 vt_dont_switch = 1;
1103 return 0;
1104 case VT_UNLOCKSWITCH:
1105 if (!suser())
1106 return -EPERM;
1107 vt_dont_switch = 0;
1108 return 0;
1109 default:
1110 return -ENOIOCTLCMD;
1111 }
1112 }