vt_ioctl.c revision 533475d3d48eb839be2b57f6b020150abae91063
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> 267ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl#include <linux/signal.h> 27bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus#include <linux/timex.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_kern.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_diacr.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/selection.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char vt_dont_switch; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct tty_driver *console_driver; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count) 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Console (vt and kd) routines, as defined by USL SVR4 manual, and by 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * experimentation and study of X386 SYSV handling. 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console, 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the current console is done by the main ioctl code. 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/syscalls.h> 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these are the valid i/o ports we're allowed to change. they map all the 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * video ports 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPFIRST 0x3b4 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPLAST 0x3df 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPNUM (GPLAST - GPFIRST + 1) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define i (tmp.kb_index) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define s (tmp.kb_table) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define v (tmp.kb_value) 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbentry tmp; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort *key_map, val, ov; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 82e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti if (!capable(CAP_SYS_TTY_CONFIG)) 83e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti perm = 0; 84e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = key_maps[s]; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key_map) { 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = U(key_map[i]); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = K_HOLE; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = (i ? K_HOLE : K_NOSUCHMAP); 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(val, &user_kbe->kb_value); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i && v == K_NOSUCHMAP) { 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* disallocate map */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = key_maps[s]; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s && key_map) { 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_maps[s] = NULL; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key_map[0] == U(K_ALLOCATED)) { 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(key_map); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keymap_count--; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (KTYP(v) < NR_TYPES) { 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (KVAL(v) > max_vals[KTYP(v)]) 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kbd->kbdmode != VC_UNICODE) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ++Geert: non-PC keyboards may generate keycode zero */ 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__mc68000__) && !defined(__powerpc__) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* assignment to entry 0 only tests validity of args */ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(key_map = key_maps[s])) { 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int j; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !capable(CAP_SYS_RESOURCE)) 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = (ushort *) kmalloc(sizeof(plain_map), 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_KERNEL); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!key_map) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_maps[s] = key_map; 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[0] = U(K_ALLOCATED); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = 1; j < NR_KEYS; j++) 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[j] = U(K_HOLE); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keymap_count++; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ov = U(key_map[i]); 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (v == ov) 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* nothing to do */ 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Attention Key. 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[i] = U(v); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT)) 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef i 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef s 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef v 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm) 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbkeycode tmp; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int kc = 0; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode))) 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = getkeycode(tmp.scancode); 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kc >= 0) 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = put_user(kc, &user_kbkc->keycode); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = setkeycode(tmp.scancode, tmp.keycode); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return kc; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbsentry *kbs; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *p; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *q; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char __user *up; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sz; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int delta; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *first_free, *fj, *fnw; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j, k; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1970b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton if (!capable(CAP_SYS_TTY_CONFIG)) 198e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti perm = 0; 1990b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!kbs) { 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we mostly copy too much here (512bytes), but who cares ;) */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) { 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = kbs->kb_func; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = sizeof(kbs->kb_string) - 1; /* sz should have been 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a struct member */ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up = user_kdgkb->kb_string; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = func_table[i]; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for ( ; *p && sz; p++, sz--) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(*p, up++)) { 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user('\0', up)) { 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(kbs); 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((p && *p) ? -EOVERFLOW : 0); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) { 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EPERM; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = func_table[i]; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds first_free = funcbufptr + (funcbufsize - funcbufleft); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j < MAX_NR_FUNC) 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fj = func_table[j]; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fj = first_free; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (delta <= funcbufleft) { /* it fits in current buf */ 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j < MAX_NR_FUNC) { 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fj + delta, fj, first_free - fj); 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = j; k < MAX_NR_FUNC; k++) 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] += delta; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!q) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[i] = fj; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufleft -= delta; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* allocate a larger buffer */ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = 256; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (sz < funcbufsize - funcbufleft + delta) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz <<= 1; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fnw = (char *) kmalloc(sz, GFP_KERNEL); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!fnw) { 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!q) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[i] = fj; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fj > funcbufptr) 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fnw, funcbufptr, fj - funcbufptr); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = 0; k < j; k++) 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] = fnw + (func_table[k] - funcbufptr); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (first_free > fj) { 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = j; k < MAX_NR_FUNC; k++) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] = fnw + (func_table[k] - funcbufptr) + delta; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (funcbufptr != func_buf) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(funcbufptr); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufptr = fnw; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufleft = funcbufleft - delta + sz - funcbufsize; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufsize = sz; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(func_table[i], kbs->kb_string); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreterr: 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(kbs); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct consolefontdesc cfdarg; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_SET; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, op); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: { 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_GET; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc_cons[fg_console].d, op); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charheight = op->height; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charcount = op->charcount; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc) 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct unimapdesc tmp; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_ud, sizeof tmp)) 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp.entries) 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, tmp.entries, 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.entry_ct*sizeof(struct unipair))) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_unimap(vc, tmp.entry_ct, tmp.entries); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && fg_console != vc->vc_num) 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We handle the console-specific ioctl's here. We allow the 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * capability to modify any console, not just the fg_console. 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vt_ioctl(struct tty_struct *tty, struct file * file, 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd, unsigned long arg) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vc_data *vc = (struct vc_data *)tty->driver_data; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct console_font_op op; /* used in multiple places here */ 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_struct * kbd; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int console; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char ucval; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *up = (void __user *)arg; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, perm; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds console = vc->vc_num; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!vc_cons_allocated(console)) /* impossible? */ 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To have permissions to do most of the vt ioctls, we either have 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 0; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 1; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd = kbd_table + console; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KIOCSOUND: 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg) 395bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus arg = CLOCK_TICK_RATE / arg; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(arg, 0); 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMKTONE: 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ticks, count; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Generate the tone for the appropriate number of ticks. 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the time is zero, turn off sound ourselves. 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ticks = HZ * ((arg >> 16) & 0xffff) / 1000; 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = ticks ? (arg & 0xffff) : 0; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count) 412bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus count = CLOCK_TICK_RATE / count; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(count, ticks); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBTYPE: 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this is naive. 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = KB_101; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setchar; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These cannot be implemented on any machine that implements 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioperm() in user level (such as Alpha PCs) or not at all. 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX: you should never use these, just call ioperm directly.. 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDADDIO: 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDELIO: 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KDADDIO and KDDELIO may be able to add ports beyond what 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we reject here, but to be safe... 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg < GPFIRST || arg > GPLAST) 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDENABIO: 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDISABIO: 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sys_ioperm(GPFIRST, GPNUM, 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cmd == KDENABIO)) ? -ENXIO : 0; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDKBDREP: 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_repeat kbrep; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = kbd_rate(&kbrep); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETMODE: 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * currently, setting the mode from KD_TEXT to KD_GRAPHICS 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't do a whole lot. i'm not sure if it should do any 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * restoration of modes or what... 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX It should at least call into the driver, fbdev's definitely 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need to restore their engine state. --BenH 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (arg) { 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_GRAPHICS: 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT0: 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT1: 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg = KD_TEXT; 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT: 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == (unsigned char) arg) 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = (unsigned char) arg; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (console != fg_console) 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * explicitly blank/unblank the screen if switching modes 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == KD_TEXT) 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETMODE: 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = vc->vc_mode; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMAPDISP: 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDUNMAPDISP: 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these work like a combination of mmap and KDENABIO. 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this could be easily finished. 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMODE: 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(arg) { 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_RAW: 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_RAW; 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_MEDIUMRAW: 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_MEDIUMRAW; 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_XLATE: 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_XLATE; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_UNICODE: 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_UNICODE; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_ldisc_flush(tty); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMODE: 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds K_XLATE); 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this could be folded into KDSKBMODE, but for compatibility 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMETA: 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(arg) { 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_METABIT: 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clr_vc_kbd_mode(kbd, VC_META); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_ESCPREFIX: 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_vc_kbd_mode(kbd, VC_META); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMETA: 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setint: 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(ucval, (int __user *)arg); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!capable(CAP_SYS_TTY_CONFIG)) 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm=0; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_kbkeycode_ioctl(cmd, up, perm); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_kdsk_ioctl(cmd, up, perm, kbd); 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_kdgkb_ioctl(cmd, up, perm); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBDIACR: 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbdiacrs __user *a = up; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(accent_table_size, &a->kb_cnt)) 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr))) 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBDIACR: 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbdiacrs __user *a = up; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ct; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(ct,&a->kb_cnt)) 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ct >= MAX_DIACR) 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds accent_table_size = ct; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr))) 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below read/set the flags usually shown in the leds */ 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't use them - they will go away without warning */ 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBLED: 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setchar; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBLED: 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg & ~0x77) 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->ledflagstate = (arg & 7); 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->default_ledflagstate = ((arg >> 4) & 7); 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_leds(); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below only set the lights, not the functions */ 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for those, see KDGKBLED and KDSKBLED above */ 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETLED: 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = getledstate(); 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setchar: 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(ucval, (char __user *)arg); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETLED: 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setledstate(kbd, arg); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A process can indicate its willingness to accept signals 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * generated by pressing an appropriate key combination. 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thus, one can have a daemon that e.g. spawns a new console 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upon a keypress and then changes to it. 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See also the kbrequest field of inittab(5). 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSIGACCEPT: 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds extern int spawnpid, spawnsig; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm || !capable(CAP_KILL)) 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6517ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spawnpid = current->pid; 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spawnsig = arg; 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_SETMODE: 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode = tmp; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the frsig is ignored, so we set it to 0 */ 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_pid = current->pid; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no switch is required -- saw@shade.msu.ru */ 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETMODE: 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode)); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc ? -EFAULT : 0; 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns global vt state. Note that VT 0 is always open, since 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's an alias for the current VT, and people can't use it here. 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cannot return state for more than 16 VTs, since v_state is short. 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETSTATE: 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_stat __user *vtstat = up; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short state, mask; 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(fg_console + 1, &vtstat->v_active)) 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state = 1; /* /dev/tty0 is always open */ 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1) 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (VT_IS_IN_USE(i)) 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds state |= mask; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(state, &vtstat->v_state); 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the first available (non-opened) console. 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_OPENQRY: 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; ++i) 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_IS_IN_USE(i)) 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = i < MAX_NR_CONSOLES ? (i+1) : -1; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with num >= 1 (switches to vt 0, our console, are not allowed, just 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to preserve sanity). 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_ACTIVATE: 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg--; 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = vc_allocate(arg); 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_console(arg); 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * wait until the specified VT has been activated 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_WAITACTIVE: 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return vt_waitactive(arg-1); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If a vt is under process control, the kernel will not switch to it 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * immediately, but postpone the operation until the process calls this 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl, allowing the switch to complete. 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * According to the X sources this is the behavior: 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0: pending switch-from not OK 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1: pending switch-from OK 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2: completed switch-to OK 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RELDISP: 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_mode.mode != VT_PROCESS) 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switching-from response 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_newvt >= 0) { 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch disallowed, so forget we were trying 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to do it. 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The current vt has been released, so 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complete the switch. 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int newvt; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newvt = vc->vt_newvt; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = vc_allocate(newvt); 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) { 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When we actually do the console switch, 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * make sure we are atomic with respect to 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other console switches.. 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(vc_cons[newvt].d); 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switched-to response 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it's just an ACK, ignore it 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg != VT_ACKACQ) 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Disallocate memory associated to VT (but leave VT1) 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_DISALLOCATE: 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg > MAX_NR_CONSOLES) 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) { 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* disallocate all unused consoles, but leave 0 */ 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=1; i<MAX_NR_CONSOLES; i++) 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_BUSY(i)) 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_disallocate(i); 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* disallocate a single console, if possible */ 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg--; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (VT_BUSY(arg)) 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg) { /* leave 0 */ 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_disallocate(arg); 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZE: 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_sizes __user *vtsizes = up; 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc; 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(ll, &vtsizes->v_rows) || 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_user(cc, &vtsizes->v_cols)) 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; i++) { 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_resize(vc_cons[i].d, cc, ll); 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZEX: 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_consize __user *vtconsize = up; 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc,vlin,clin,vcol,ccol; 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, vtconsize, 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct vt_consize))) 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ll, &vtconsize->v_rows); 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(cc, &vtconsize->v_cols); 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vlin, &vtconsize->v_vlin); 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(clin, &vtconsize->v_clin); 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vcol, &vtconsize->v_vcol); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ccol, &vtconsize->v_ccol); 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vlin = vlin ? vlin : vc->vc_scan_lines; 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) { 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ll) { 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ll != vlin/clin) 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; /* Parameters don't add up */ 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ll = vlin/clin; 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vcol && ccol) { 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cc) { 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cc != vcol/ccol) 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cc = vcol/ccol; 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin > 32) 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; i++) { 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!vc_cons[i].d) 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vlin) 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_scan_lines = vlin; 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_font.height = clin; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_resize(vc_cons[i].d, cc, ll); 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONT: { 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET; 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 0; 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, &op); 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONT: { 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_GET; 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD; 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 32; 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, &op); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_CMAP: 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_cmap(up); 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_CMAP: 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_cmap(up); 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_fontx_ioctl(cmd, up, perm, &op); 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTRESET: 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BROKEN_GRAPHICS_PROGRAMS 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* With BROKEN_GRAPHICS_PROGRAMS defined, the default 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds font is not saved. */ 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOSYS; 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET_DEFAULT; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = NULL; 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc_cons[fg_console].d, &op); 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds con_set_default_unimap(vc_cons[fg_console].d); 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDFONTOP: { 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&op, up, sizeof(op))) 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && op.op != KD_FONT_OP_GET) 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc, &op); 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) return i; 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &op, sizeof(op))) 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_SCRNMAP: 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_trans_old(up); 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_SCRNMAP: 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_trans_old(up); 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNISCRNMAP: 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_trans_new(up); 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNISCRNMAP: 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_trans_new(up); 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAPCLR: 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { struct unimapinit ui; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = copy_from_user(&ui, up, sizeof(struct unimapinit)); 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) return -EFAULT; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds con_clear_unimap(vc, &ui); 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return do_unimap_ioctl(cmd, up, perm, vc); 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_LOCKSWITCH: 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 1; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_UNLOCKSWITCH: 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 0; 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1014533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault case VT_GETHIFONTMASK: 1015533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg); 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOIOCTLCMD; 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sometimes we want to wait until a particular VT has been activated. We 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * do it in a very simple manner. Everybody waits on a single queue and 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get woken up at once. Those that are satisfied go on with their business, 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * while those not ready go back to sleep. Seems overkill to add a wait 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to each vt just for this - usually this does nothing! 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue); 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Sleeps until a vt is activated, or the task is interrupted. Returns 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 if activation, -EINTR if interrupted. 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vt_waitactive(int vt) 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DECLARE_WAITQUEUE(wait, current); 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_wait_queue(&vt_activate_queue, &wait); 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_current_state(TASK_INTERRUPTIBLE); 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = 0; 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vt == fg_console) 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = -EINTR; 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (signal_pending(current)) 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schedule(); 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_wait_queue(&vt_activate_queue, &wait); 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current->state = TASK_RUNNING; 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define vt_wake_waitactive() wake_up(&vt_activate_queue) 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid reset_vc(struct vc_data *vc) 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = KD_TEXT; 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd_table[vc->vc_num].kbdmode = VC_XLATE; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.mode = VT_AUTO; 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.waitv = 0; 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.relsig = 0; 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.acqsig = 0; 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_pid = -1; 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_palette(vc); 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the back end of a vt switch 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc) 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char old_vc_mode; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_console = fg_console; 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we're switching, we could be going from KD_GRAPHICS to 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KD_TEXT mode or vice versa, which means we need to blank or 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unblank the screen later. 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_vc_mode = vc_cons[fg_console].d->vc_mode; 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch_screen(vc); 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This can't appear below a successful kill_proc(). If it did, 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then the *blank_screen operation could occur while X, having 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * received acqsig, is waking up on another processor. This 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * condition can lead to overlapping accesses to the VGA range 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the framebuffer (causing system lockups). 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To account for this we duplicate this code below only if the 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controlling process is gone and we've called reset_vc. 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this new console is under process control, send it a signal 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * telling it that it has acquired. Also check if it has died and 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clean up (similar to logic employed in change_console()) 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_mode.mode == VT_PROCESS) { 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send the signal as privileged - kill_proc() will 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is awry 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kill_proc(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The controlling process has died, so we revert back to 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * normal operation. In this case, we'll also change back 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to KD_TEXT mode. I'm not sure if this is strictly correct 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but it saves the agony when the X server dies and the screen 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remains blanked due to KD_GRAPHICS! It would be nice to do 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this outside of VT_PROCESS but there is no single process 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to account for and tracking tty count may be undesirable. 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_vc(vc); 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wake anyone waiting for their VT to activate 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_wake_waitactive(); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the front-end of a vt switch 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid change_console(struct vc_data *new_vc) 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vc_data *vc; 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch) 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this vt is in process mode, then we need to handshake with 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that process before switching. Essentially, we store where that 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt wants to switch to and wait for it to tell us when it's done 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (via VT_RELDISP ioctl). 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We also check to see if the controlling process still exists. 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it doesn't, we reset this vt to auto mode and continue. 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a cheap way to track process control. The worst thing 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that can happen is: we send a signal to a process, it dies, and 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the switch gets "lost" waiting for a response; hopefully, the 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user will try again, we'll detect the process is gone (unless 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the user waits just the right amount of time :-) and revert the 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt to auto control. 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc = vc_cons[fg_console].d; 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_mode.mode == VT_PROCESS) { 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send the signal as privileged - kill_proc() will 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is awry 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kill_proc(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * It worked. Mark the vt to switch to and 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return. The process needs to send us a 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * VT_RELDISP ioctl to complete the switch. 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = new_vc->vc_num; 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The controlling process has died, so we revert back to 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * normal operation. In this case, we'll also change back 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to KD_TEXT mode. I'm not sure if this is strictly correct 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but it saves the agony when the X server dies and the screen 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remains blanked due to KD_GRAPHICS! It would be nice to do 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this outside of VT_PROCESS but there is no single process 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to account for and tracking tty count may be undesirable. 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_vc(vc); 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fall through to normal (VT_AUTO) handling of the switch... 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ignore all switches in KD_GRAPHICS+VT_AUTO mode 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_GRAPHICS) 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(new_vc); 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1211