vt_ioctl.c revision 8c9a9dd0fa3a269d380eaae2dc1bee39e865fae1
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/char/vt_ioctl.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1992 obz under the linux copyright 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic keymap and string allocation - aeb@cwi.nl - May 1994 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some code moved for less code duplication - Andi Kleen - Mar 1997 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kd.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h> 2604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault#include <linux/consolemap.h> 277ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl#include <linux/signal.h> 28bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus#include <linux/timex.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_kern.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_diacr.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/selection.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38b257bc051f06607beb3004d9a1c297085e728becAndrew Johnsonchar vt_dont_switch; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct tty_driver *console_driver; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons) 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Console (vt and kd) routines, as defined by USL SVR4 manual, and by 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * experimentation and study of X386 SYSV handling. 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the current console is done by the main ioctl code. 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/syscalls.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these are the valid i/o ports we're allowed to change. they map all the 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * video ports 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPFIRST 0x3b4 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPLAST 0x3df 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPNUM (GPLAST - GPFIRST + 1) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define i (tmp.kb_index) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define s (tmp.kb_table) 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define v (tmp.kb_value) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbentry tmp; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort *key_map, val, ov; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 83e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti if (!capable(CAP_SYS_TTY_CONFIG)) 84e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti perm = 0; 85e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = key_maps[s]; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key_map) { 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = U(key_map[i]); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES) 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = K_HOLE; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = (i ? K_HOLE : K_NOSUCHMAP); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(val, &user_kbe->kb_value); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i && v == K_NOSUCHMAP) { 100ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate map */ 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = key_maps[s]; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s && key_map) { 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_maps[s] = NULL; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key_map[0] == U(K_ALLOCATED)) { 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(key_map); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keymap_count--; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (KTYP(v) < NR_TYPES) { 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (KVAL(v) > max_vals[KTYP(v)]) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kbd->kbdmode != VC_UNICODE) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ++Geert: non-PC keyboards may generate keycode zero */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__mc68000__) && !defined(__powerpc__) 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* assignment to entry 0 only tests validity of args */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(key_map = key_maps[s])) { 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int j; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !capable(CAP_SYS_RESOURCE)) 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1335cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day key_map = kmalloc(sizeof(plain_map), 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_KERNEL); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!key_map) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_maps[s] = key_map; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[0] = U(K_ALLOCATED); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = 1; j < NR_KEYS; j++) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[j] = U(K_HOLE); 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keymap_count++; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ov = U(key_map[i]); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (v == ov) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* nothing to do */ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Attention Key. 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[i] = U(v); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT)) 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef i 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef s 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef v 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm) 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbkeycode tmp; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int kc = 0; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode))) 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = getkeycode(tmp.scancode); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kc >= 0) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = put_user(kc, &user_kbkc->keycode); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = setkeycode(tmp.scancode, tmp.keycode); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return kc; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbsentry *kbs; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *p; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *q; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char __user *up; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sz; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int delta; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *first_free, *fj, *fnw; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j, k; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1980b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton if (!capable(CAP_SYS_TTY_CONFIG)) 199e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti perm = 0; 2000b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!kbs) { 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we mostly copy too much here (512bytes), but who cares ;) */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = kbs->kb_func; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = sizeof(kbs->kb_string) - 1; /* sz should have been 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a struct member */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up = user_kdgkb->kb_string; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = func_table[i]; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for ( ; *p && sz; p++, sz--) 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(*p, up++)) { 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user('\0', up)) { 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(kbs); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((p && *p) ? -EOVERFLOW : 0); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EPERM; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = func_table[i]; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds first_free = funcbufptr + (funcbufsize - funcbufleft); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j < MAX_NR_FUNC) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fj = func_table[j]; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fj = first_free; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (delta <= funcbufleft) { /* it fits in current buf */ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j < MAX_NR_FUNC) { 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fj + delta, fj, first_free - fj); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = j; k < MAX_NR_FUNC; k++) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] += delta; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!q) 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[i] = fj; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufleft -= delta; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* allocate a larger buffer */ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = 256; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (sz < funcbufsize - funcbufleft + delta) 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz <<= 1; 2635cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day fnw = kmalloc(sz, GFP_KERNEL); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!fnw) { 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!q) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[i] = fj; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fj > funcbufptr) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fnw, funcbufptr, fj - funcbufptr); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = 0; k < j; k++) 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] = fnw + (func_table[k] - funcbufptr); 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (first_free > fj) { 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = j; k < MAX_NR_FUNC; k++) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] = fnw + (func_table[k] - funcbufptr) + delta; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (funcbufptr != func_buf) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(funcbufptr); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufptr = fnw; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufleft = funcbufleft - delta + sz - funcbufsize; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufsize = sz; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(func_table[i], kbs->kb_string); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreterr: 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(kbs); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct consolefontdesc cfdarg; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_SET; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, op); 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: { 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_GET; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc_cons[fg_console].d, op); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charheight = op->height; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charcount = op->charcount; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc) 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct unimapdesc tmp; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_ud, sizeof tmp)) 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp.entries) 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, tmp.entries, 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.entry_ct*sizeof(struct unipair))) 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_unimap(vc, tmp.entry_ct, tmp.entries); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && fg_console != vc->vc_num) 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries); 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We handle the console-specific ioctl's here. We allow the 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * capability to modify any console, not just the fg_console. 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vt_ioctl(struct tty_struct *tty, struct file * file, 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd, unsigned long arg) 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vc_data *vc = (struct vc_data *)tty->driver_data; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct console_font_op op; /* used in multiple places here */ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_struct * kbd; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int console; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char ucval; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *up = (void __user *)arg; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, perm; 3769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox int ret = 0; 3779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds console = vc->vc_num; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3809cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox lock_kernel(); 3819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 3829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (!vc_cons_allocated(console)) { /* impossible? */ 3839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOIOCTLCMD; 3849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 3859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 3869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To have permissions to do most of the vt ioctls, we either have 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 0; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 1; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd = kbd_table + console; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KIOCSOUND: 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4009cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg) 402bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus arg = CLOCK_TICK_RATE / arg; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(arg, 0); 4049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMKTONE: 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ticks, count; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Generate the tone for the appropriate number of ticks. 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the time is zero, turn off sound ourselves. 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ticks = HZ * ((arg >> 16) & 0xffff) / 1000; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = ticks ? (arg & 0xffff) : 0; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count) 419bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus count = CLOCK_TICK_RATE / count; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(count, ticks); 4219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBTYPE: 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this is naive. 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = KB_101; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setchar; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These cannot be implemented on any machine that implements 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioperm() in user level (such as Alpha PCs) or not at all. 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX: you should never use these, just call ioperm directly.. 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDADDIO: 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDELIO: 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KDADDIO and KDDELIO may be able to add ports beyond what 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we reject here, but to be safe... 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg < GPFIRST || arg > GPLAST) { 4459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 4469cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 4489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; 4499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDENABIO: 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDISABIO: 4539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = sys_ioperm(GPFIRST, GPNUM, 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cmd == KDENABIO)) ? -ENXIO : 0; 4559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDKBDREP: 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_repeat kbrep; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 4659cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) { 4689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 4699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 4719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = kbd_rate(&kbrep); 4729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 4739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) 4759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 4769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETMODE: 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * currently, setting the mode from KD_TEXT to KD_GRAPHICS 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't do a whole lot. i'm not sure if it should do any 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * restoration of modes or what... 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX It should at least call into the driver, fbdev's definitely 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need to restore their engine state. --BenH 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (arg) { 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_GRAPHICS: 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT0: 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT1: 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg = KD_TEXT; 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT: 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 5009cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == (unsigned char) arg) 5039cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = (unsigned char) arg; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (console != fg_console) 5069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * explicitly blank/unblank the screen if switching modes 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == KD_TEXT) 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 5169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETMODE: 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = vc->vc_mode; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMAPDISP: 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDUNMAPDISP: 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these work like a combination of mmap and KDENABIO. 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this could be easily finished. 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 5299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMODE: 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 5339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(arg) { 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_RAW: 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_RAW; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_MEDIUMRAW: 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_MEDIUMRAW; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_XLATE: 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_XLATE; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_UNICODE: 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_UNICODE; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 5519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_ldisc_flush(tty); 5549cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMODE: 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds K_XLATE); 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this could be folded into KDSKBMODE, but for compatibility 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMETA: 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(arg) { 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_METABIT: 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clr_vc_kbd_mode(kbd, VC_META); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_ESCPREFIX: 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_vc_kbd_mode(kbd, VC_META); 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMETA: 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setint: 5819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(ucval, (int __user *)arg); 5829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!capable(CAP_SYS_TTY_CONFIG)) 5879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox perm = 0; 5889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_kbkeycode_ioctl(cmd, up, perm); 5899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 5939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_kdsk_ioctl(cmd, up, perm, kbd); 5949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 5989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_kdgkb_ioctl(cmd, up, perm); 5999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBDIACR: 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbdiacrs __user *a = up; 60404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacr diacr; 60504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault int i; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (put_user(accent_table_size, &a->kb_cnt)) { 6089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 61104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault for (i = 0; i < accent_table_size; i++) { 61204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr); 61304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.base = conv_uni_to_8bit(accent_table[i].base); 61404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.result = conv_uni_to_8bit(accent_table[i].result); 6159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) { 6169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 61904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 6209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 62104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 62204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault case KDGKBDIACRUC: 62304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault { 62404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacrsuc __user *a = up; 62504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 62604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (put_user(accent_table_size, &a->kb_cnt)) 6279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else if (copy_to_user(a->kbdiacruc, accent_table, 6299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox accent_table_size*sizeof(struct kbdiacruc))) 6309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBDIACR: 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbdiacrs __user *a = up; 63704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacr diacr; 63804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault unsigned int ct; 63904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault int i; 64004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 64104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (!perm) 6429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 6439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (get_user(ct,&a->kb_cnt)) { 6449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6469cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 6479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ct >= MAX_DIACR) { 6489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 6499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 65104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table_size = ct; 65204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault for (i = 0; i < ct; i++) { 6539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) { 6549cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6569cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 65704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr); 65804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].base = conv_8bit_to_uni(diacr.base); 65904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].result = conv_8bit_to_uni(diacr.result); 66004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 6619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 66204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 66304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 66404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault case KDSKBDIACRUC: 66504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault { 66604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacrsuc __user *a = up; 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ct; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 6719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (get_user(ct,&a->kb_cnt)) { 6729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 6759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ct >= MAX_DIACR) { 6769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 6779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds accent_table_size = ct; 68004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc))) 6819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below read/set the flags usually shown in the leds */ 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't use them - they will go away without warning */ 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBLED: 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setchar; 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBLED: 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 6949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg & ~0x77) { 6959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 6969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->ledflagstate = (arg & 7); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->default_ledflagstate = ((arg >> 4) & 7); 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_leds(); 7019cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below only set the lights, not the functions */ 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for those, see KDGKBLED and KDSKBLED above */ 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETLED: 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = getledstate(); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setchar: 7089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(ucval, (char __user *)arg); 7099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETLED: 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setledstate(kbd, arg); 7159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A process can indicate its willingness to accept signals 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * generated by pressing an appropriate key combination. 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thus, one can have a daemon that e.g. spawns a new console 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upon a keypress and then changes to it. 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See also the kbrequest field of inittab(5). 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSIGACCEPT: 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm || !capable(CAP_KILL)) 7279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 7287ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) 7299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 7309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 7319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox spin_lock_irq(&vt_spawn_con.lock); 7329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox put_pid(vt_spawn_con.pid); 7339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vt_spawn_con.pid = get_pid(task_pid(current)); 7349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vt_spawn_con.sig = arg; 7359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox spin_unlock_irq(&vt_spawn_con.lock); 7369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 7379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_SETMODE: 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 7469cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) { 7479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 7499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 7509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) { 7519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 7529cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 7539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode = tmp; 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the frsig is ignored, so we set it to 0 */ 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 7588b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman put_pid(vc->vt_pid); 7598b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc->vt_pid = get_pid(task_pid(current)); 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no switch is required -- saw@shade.msu.ru */ 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 7639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETMODE: 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode)); 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); 7769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (rc) 7779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns global vt state. Note that VT 0 is always open, since 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's an alias for the current VT, and people can't use it here. 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cannot return state for more than 16 VTs, since v_state is short. 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETSTATE: 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_stat __user *vtstat = up; 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short state, mask; 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(fg_console + 1, &vtstat->v_active)) 7929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 7949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox state = 1; /* /dev/tty0 is always open */ 7959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; 7969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ++i, mask <<= 1) 7979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (VT_IS_IN_USE(i)) 7989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox state |= mask; 7999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(state, &vtstat->v_state); 8009cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8019cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the first available (non-opened) console. 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_OPENQRY: 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; ++i) 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_IS_IN_USE(i)) 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = i < MAX_NR_CONSOLES ? (i+1) : -1; 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with num >= 1 (switches to vt 0, our console, are not allowed, just 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to preserve sanity). 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_ACTIVATE: 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 8239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 8249cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 8259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox arg--; 8269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox acquire_console_sem(); 8279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = vc_allocate(arg); 8289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox release_console_sem(); 8299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 8309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox set_console(arg); 8329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * wait until the specified VT has been activated 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_WAITACTIVE: 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 8429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 8439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 8449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = vt_waitactive(arg - 1); 8459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If a vt is under process control, the kernel will not switch to it 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * immediately, but postpone the operation until the process calls this 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl, allowing the switch to complete. 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * According to the X sources this is the behavior: 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0: pending switch-from not OK 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1: pending switch-from OK 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2: completed switch-to OK 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RELDISP: 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8599cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (vc->vt_mode.mode != VT_PROCESS) { 8629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 8639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8649cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switching-from response 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8688792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz acquire_console_sem(); 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_newvt >= 0) { 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch disallowed, so forget we were trying 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to do it. 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The current vt has been released, so 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complete the switch. 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int newvt; 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newvt = vc->vt_newvt; 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 8859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = vc_allocate(newvt); 8869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) { 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 8889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When we actually do the console switch, 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * make sure we are atomic with respect to 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other console switches.. 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(vc_cons[newvt].d); 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } else { 8989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* 8999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox * Switched-to response 9009cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox */ 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it's just an ACK, ignore it 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg != VT_ACKACQ) 9059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9078792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz release_console_sem(); 9089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Disallocate memory associated to VT (but leave VT1) 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_DISALLOCATE: 9149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg > MAX_NR_CONSOLES) { 9159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 9169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) { 919ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate all unused consoles, but leave 0 */ 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=1; i<MAX_NR_CONSOLES; i++) 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_BUSY(i)) 923ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox vc_deallocate(i); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 926ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate a single console, if possible */ 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg--; 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (VT_BUSY(arg)) 9299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EBUSY; 9309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else if (arg) { /* leave 0 */ 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 932ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox vc_deallocate(arg); 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZE: 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_sizes __user *vtsizes = up; 941e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas struct vc_data *vc; 942e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc; 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(ll, &vtsizes->v_rows) || 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_user(cc, &vtsizes->v_cols)) 9489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 9499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 9508c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox acquire_console_sem(); 9519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox for (i = 0; i < MAX_NR_CONSOLES; i++) { 9529cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vc = vc_cons[i].d; 953e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 9549cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (vc) { 9559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vc->vc_resize_user = 1; 9568c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox vc_resize(vc_cons[i].d, cc, ll); 9579cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 958e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas } 9598c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox release_console_sem(); 960e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas } 9619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZEX: 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_consize __user *vtconsize = up; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc,vlin,clin,vcol,ccol; 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, vtconsize, 9719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox sizeof(struct vt_consize))) { 9729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 9739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 9759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* FIXME: Should check the copies properly */ 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ll, &vtconsize->v_rows); 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(cc, &vtconsize->v_cols); 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vlin, &vtconsize->v_vlin); 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(clin, &vtconsize->v_clin); 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vcol, &vtconsize->v_vcol); 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ccol, &vtconsize->v_ccol); 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vlin = vlin ? vlin : vc->vc_scan_lines; 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) { 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ll) { 9859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ll != vlin/clin) { 9869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* Parameters don't add up */ 9879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 9889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ll = vlin/clin; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vcol && ccol) { 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cc) { 9959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (cc != vcol/ccol) { 9969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 9979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cc = vcol/ccol; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10039cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (clin > 32) { 10049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 10059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; i++) { 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!vc_cons[i].d) 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vlin) 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_scan_lines = vlin; 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_font.height = clin; 1016e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas vc_cons[i].d->vc_resize_user = 1; 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_resize(vc_cons[i].d, cc, ll); 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONT: { 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 10259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET; 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 0; 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 10329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 10339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONT: { 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_GET; 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD; 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 32; 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 10439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 10449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_CMAP: 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 10499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 10509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 10519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_cmap(up); 10529cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_CMAP: 10559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_cmap(up); 10569cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: 10609cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_fontx_ioctl(cmd, up, perm, &op); 10619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTRESET: 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 10669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BROKEN_GRAPHICS_PROGRAMS 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* With BROKEN_GRAPHICS_PROGRAMS defined, the default 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds font is not saved. */ 10719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOSYS; 10729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET_DEFAULT; 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = NULL; 10779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 10789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 10799cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds con_set_default_unimap(vc_cons[fg_console].d); 10819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDFONTOP: { 10879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&op, up, sizeof(op))) { 10889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 10899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && op.op != KD_FONT_OP_GET) 10929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 10939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc, &op); 10949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 10959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &op, sizeof(op))) 10979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 10989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_SCRNMAP: 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 11039cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 11049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 11059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_trans_old(up); 11069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_SCRNMAP: 11099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_trans_old(up); 11109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNISCRNMAP: 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 11149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 11159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 11169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_trans_new(up); 11179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNISCRNMAP: 11209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_trans_new(up); 11219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAPCLR: 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { struct unimapinit ui; 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 11269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 11279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); 11289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (!ret) 11299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox con_clear_unimap(vc, &ui); 11309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 11359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_unimap_ioctl(cmd, up, perm, vc); 11369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_LOCKSWITCH: 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 11409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 1; 11429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_UNLOCKSWITCH: 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 11459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 0; 11479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 1148533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault case VT_GETHIFONTMASK: 11499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(vc->vc_hi_font_mask, 11509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox (unsigned short __user *)arg); 11519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 11539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOIOCTLCMD; 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Coxout: 11569cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox unlock_kernel(); 11579cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox return ret; 11589cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Coxeperm: 11599cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 11609cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sometimes we want to wait until a particular VT has been activated. We 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do it in a very simple manner. Everybody waits on a single queue and 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get woken up at once. Those that are satisfied go on with their business, 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * while those not ready go back to sleep. Seems overkill to add a wait 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to each vt just for this - usually this does nothing! 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue); 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sleeps until a vt is activated, or the task is interrupted. Returns 117470cb97935b8859f27296772885104b599f560576Linus Torvalds * 0 if activation, -EINTR if interrupted by a signal handler. 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vt_waitactive(int vt) 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_WAITQUEUE(wait, current); 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_wait_queue(&vt_activate_queue, &wait); 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 1184f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski 1185f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski /* 1186f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * Synchronize with redraw_screen(). By acquiring the console 1187f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * semaphore we make sure that the console switch is completed 1188f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * before we return. If we didn't wait for the semaphore, we 1189f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * could return at a point where fg_console has already been 1190f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski * updated, but the console switch hasn't been completed. 1191f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski */ 1192f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski acquire_console_sem(); 1193f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski set_current_state(TASK_INTERRUPTIBLE); 1194f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski if (vt == fg_console) { 1195f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski release_console_sem(); 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1197f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski } 1198f991519c197534811046e5e47389b6fafcdf1e48Michal Januszewski release_console_sem(); 119970cb97935b8859f27296772885104b599f560576Linus Torvalds retval = -ERESTARTNOHAND; 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule(); 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_wait_queue(&vt_activate_queue, &wait); 1205cc0a8fbb7ce00f65dc337dd91389b7151f44ed30Milind Arun Choudhary __set_current_state(TASK_RUNNING); 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define vt_wake_waitactive() wake_up(&vt_activate_queue) 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid reset_vc(struct vc_data *vc) 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = KD_TEXT; 12142e8ecb9db0bcc19e1cc8bb51e9252fe6a86a9863Bill Nottingham kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE; 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.mode = VT_AUTO; 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.waitv = 0; 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.relsig = 0; 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.acqsig = 0; 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 12208b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman put_pid(vc->vt_pid); 12218b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc->vt_pid = NULL; 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_palette(vc); 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12278b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biedermanvoid vc_SAK(struct work_struct *work) 12288b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman{ 12298b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct vc *vc_con = 12308b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman container_of(work, struct vc, SAK_work); 12318b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct vc_data *vc; 12328b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct tty_struct *tty; 12338b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman 12348b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman acquire_console_sem(); 12358b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc = vc_con->d; 12368b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman if (vc) { 12378b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman tty = vc->vc_tty; 12388b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman /* 12398b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman * SAK should also work in all raw modes and reset 12408b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman * them properly. 12418b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman */ 12428b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman if (tty) 12438b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman __do_SAK(tty); 12448b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman reset_vc(vc); 12458b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman } 12468b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman release_console_sem(); 12478b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman} 12488b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the back end of a vt switch 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc) 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char old_vc_mode; 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_console = fg_console; 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we're switching, we could be going from KD_GRAPHICS to 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KD_TEXT mode or vice versa, which means we need to blank or 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unblank the screen later. 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_vc_mode = vc_cons[fg_console].d->vc_mode; 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch_screen(vc); 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12673dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * This can't appear below a successful kill_pid(). If it did, 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then the *blank_screen operation could occur while X, having 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * received acqsig, is waking up on another processor. This 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * condition can lead to overlapping accesses to the VGA range 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the framebuffer (causing system lockups). 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To account for this we duplicate this code below only if the 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controlling process is gone and we've called reset_vc. 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this new console is under process control, send it a signal 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * telling it that it has acquired. Also check if it has died and 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clean up (similar to logic employed in change_console()) 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_mode.mode == VT_PROCESS) { 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12903dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * Send the signal as privileged - kill_pid() will 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is awry 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1294bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The controlling process has died, so we revert back to 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * normal operation. In this case, we'll also change back 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to KD_TEXT mode. I'm not sure if this is strictly correct 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but it saves the agony when the X server dies and the screen 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remains blanked due to KD_GRAPHICS! It would be nice to do 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this outside of VT_PROCESS but there is no single process 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to account for and tracking tty count may be undesirable. 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_vc(vc); 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wake anyone waiting for their VT to activate 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_wake_waitactive(); 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the front-end of a vt switch 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid change_console(struct vc_data *new_vc) 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vc_data *vc; 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch) 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this vt is in process mode, then we need to handshake with 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that process before switching. Essentially, we store where that 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt wants to switch to and wait for it to tell us when it's done 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (via VT_RELDISP ioctl). 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We also check to see if the controlling process still exists. 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it doesn't, we reset this vt to auto mode and continue. 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a cheap way to track process control. The worst thing 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that can happen is: we send a signal to a process, it dies, and 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the switch gets "lost" waiting for a response; hopefully, the 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user will try again, we'll detect the process is gone (unless 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the user waits just the right amount of time :-) and revert the 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt to auto control. 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc = vc_cons[fg_console].d; 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_mode.mode == VT_PROCESS) { 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13503dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * Send the signal as privileged - kill_pid() will 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 1352a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * is awry. 1353a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * 1354a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * We need to set vt_newvt *before* sending the signal or we 1355a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * have a race. 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1357a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe vc->vt_newvt = new_vc->vc_num; 1358bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It worked. Mark the vt to switch to and 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return. The process needs to send us a 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VT_RELDISP ioctl to complete the switch. 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The controlling process has died, so we revert back to 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * normal operation. In this case, we'll also change back 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to KD_TEXT mode. I'm not sure if this is strictly correct 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but it saves the agony when the X server dies and the screen 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remains blanked due to KD_GRAPHICS! It would be nice to do 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this outside of VT_PROCESS but there is no single process 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to account for and tracking tty count may be undesirable. 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_vc(vc); 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fall through to normal (VT_AUTO) handling of the switch... 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ignore all switches in KD_GRAPHICS+VT_AUTO mode 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_GRAPHICS) 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(new_vc); 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1391