vt_ioctl.c revision 8ce73264b75be4d5ed480440ac32dfc1f25ff678
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> 19e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#include <linux/compat.h> 208d233558cd99a888571bb5a88a74970879e0aba4Alan Cox#include <linux/module.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kd.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h> 2804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault#include <linux/consolemap.h> 297ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl#include <linux/signal.h> 30405f55712dfe464b3240d7816cc4fe4174831be2Alexey Dobriyan#include <linux/smp_lock.h> 31bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus#include <linux/timex.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_kern.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_diacr.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/selection.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41b257bc051f06607beb3004d9a1c297085e728becAndrew Johnsonchar vt_dont_switch; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct tty_driver *console_driver; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count) 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons) 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Console (vt and kd) routines, as defined by USL SVR4 manual, and by 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * experimentation and study of X386 SYSV handling. 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console, 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the current console is done by the main ioctl code. 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/syscalls.h> 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 678b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * User space VT_EVENT handlers 688b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 698b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 708b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstruct vt_event_wait { 718b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct list_head list; 728b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event event; 738b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox int done; 748b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox}; 758b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 768b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic LIST_HEAD(vt_events); 778b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic DEFINE_SPINLOCK(vt_event_lock); 788b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic DECLARE_WAIT_QUEUE_HEAD(vt_event_waitqueue); 798b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 808b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/** 818b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * vt_event_post 828b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @event: the event that occurred 838b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @old: old console 848b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @new: new console 858b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * 868b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * Post an VT event to interested VT handlers 878b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 888b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 898b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxvoid vt_event_post(unsigned int event, unsigned int old, unsigned int new) 908b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{ 918b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct list_head *pos, *head; 928b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox unsigned long flags; 938b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox int wake = 0; 948b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 958b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_lock_irqsave(&vt_event_lock, flags); 968b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox head = &vt_events; 978b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 988b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox list_for_each(pos, head) { 998b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event_wait *ve = list_entry(pos, 1008b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event_wait, list); 1018b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (!(ve->event.event & event)) 1028b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox continue; 1038b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox ve->event.event = event; 1048b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* kernel view is consoles 0..n-1, user space view is 1058b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox console 1..n with 0 meaning current, so we must bias */ 106308efab5e231d1510cd35931d87629bf5171caaeAlan Cox ve->event.oldev = old + 1; 107308efab5e231d1510cd35931d87629bf5171caaeAlan Cox ve->event.newev = new + 1; 1088b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox wake = 1; 1098b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox ve->done = 1; 1108b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox } 1118b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_unlock_irqrestore(&vt_event_lock, flags); 1128b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (wake) 1138b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox wake_up_interruptible(&vt_event_waitqueue); 1148b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox} 1158b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1168b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/** 1178b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * vt_event_wait - wait for an event 1188b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @vw: our event 1198b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * 1208b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * Waits for an event to occur which completes our vt_event_wait 1218b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * structure. On return the structure has wv->done set to 1 for success 1228b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * or 0 if some event such as a signal ended the wait. 1238b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 1248b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1258b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic void vt_event_wait(struct vt_event_wait *vw) 1268b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{ 1278b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox unsigned long flags; 1288b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Prepare the event */ 1298b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox INIT_LIST_HEAD(&vw->list); 1308b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vw->done = 0; 1318b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Queue our event */ 1328b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_lock_irqsave(&vt_event_lock, flags); 1338b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox list_add(&vw->list, &vt_events); 1348b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_unlock_irqrestore(&vt_event_lock, flags); 1358b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Wait for it to pass */ 1368b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox wait_event_interruptible(vt_event_waitqueue, vw->done); 1378b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Dequeue it */ 1388b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_lock_irqsave(&vt_event_lock, flags); 1398b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox list_del(&vw->list); 1408b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_unlock_irqrestore(&vt_event_lock, flags); 1418b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox} 1428b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1438b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/** 1448b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * vt_event_wait_ioctl - event ioctl handler 1458b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @arg: argument to ioctl 1468b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * 1478b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * Implement the VT_WAITEVENT ioctl using the VT event interface 1488b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 1498b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1508b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic int vt_event_wait_ioctl(struct vt_event __user *event) 1518b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{ 1528b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event_wait vw; 1538b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1548b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (copy_from_user(&vw.event, event, sizeof(struct vt_event))) 1558b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EFAULT; 1568b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Highest supported event for now */ 1578b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (vw.event.event & ~VT_MAX_EVENT) 1588b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EINVAL; 1598b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1608b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vt_event_wait(&vw); 1618b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* If it occurred report it */ 1628b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (vw.done) { 1638b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (copy_to_user(event, &vw.event, sizeof(struct vt_event))) 1648b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EFAULT; 1658b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return 0; 1668b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox } 1678b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EINTR; 1688b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox} 1698b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1708b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/** 1718b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * vt_waitactive - active console wait 1728b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @event: event code 1738b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @n: new console 1748b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * 1758b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * Helper for event waits. Used to implement the legacy 1768b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * event waiting ioctls in terms of events 1778b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 1788b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1798b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxint vt_waitactive(int n) 1808b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{ 1818b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event_wait vw; 1828b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox do { 1838b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (n == fg_console + 1) 1848b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox break; 1858b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vw.event.event = VT_EVENT_SWITCH; 1868b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vt_event_wait(&vw); 1878b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (vw.done == 0) 1888b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EINTR; 189308efab5e231d1510cd35931d87629bf5171caaeAlan Cox } while (vw.event.newev != n); 1908b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return 0; 1918b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox} 1928b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1938b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/* 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these are the valid i/o ports we're allowed to change. they map all the 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * video ports 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPFIRST 0x3b4 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPLAST 0x3df 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPNUM (GPLAST - GPFIRST + 1) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define i (tmp.kb_index) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define s (tmp.kb_table) 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define v (tmp.kb_value) 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdsk_ioctl(int cmd, struct kbentry __user *user_kbe, int perm, struct kbd_struct *kbd) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbentry tmp; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort *key_map, val, ov; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry))) 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 213e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti if (!capable(CAP_SYS_TTY_CONFIG)) 214e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti perm = 0; 215e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = key_maps[s]; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key_map) { 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = U(key_map[i]); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = K_HOLE; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds val = (i ? K_HOLE : K_NOSUCHMAP); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return put_user(val, &user_kbe->kb_value); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i && v == K_NOSUCHMAP) { 230ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate map */ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map = key_maps[s]; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s && key_map) { 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_maps[s] = NULL; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (key_map[0] == U(K_ALLOCATED)) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(key_map); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keymap_count--; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (KTYP(v) < NR_TYPES) { 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (KVAL(v) > max_vals[KTYP(v)]) 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kbd->kbdmode != VC_UNICODE) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ++Geert: non-PC keyboards may generate keycode zero */ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if !defined(__mc68000__) && !defined(__powerpc__) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* assignment to entry 0 only tests validity of args */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!i) 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(key_map = key_maps[s])) { 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int j; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !capable(CAP_SYS_RESOURCE)) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2635cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day key_map = kmalloc(sizeof(plain_map), 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_KERNEL); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!key_map) 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_maps[s] = key_map; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[0] = U(K_ALLOCATED); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = 1; j < NR_KEYS; j++) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[j] = U(K_HOLE); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds keymap_count++; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ov = U(key_map[i]); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (v == ov) 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* nothing to do */ 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Attention Key. 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN)) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds key_map[i] = U(v); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT)) 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef i 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef s 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef v 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kbkeycode_ioctl(int cmd, struct kbkeycode __user *user_kbkc, int perm) 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbkeycode tmp; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int kc = 0; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode))) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = getkeycode(tmp.scancode); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (kc >= 0) 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = put_user(kc, &user_kbkc->keycode); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kc = setkeycode(tmp.scancode, tmp.keycode); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return kc; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbsentry *kbs; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *p; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char *q; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u_char __user *up; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int sz; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int delta; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *first_free, *fj, *fnw; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, j, k; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3280b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton if (!capable(CAP_SYS_TTY_CONFIG)) 329e3f17f0f6e98f58edb13cb38810d93e6d4808e68Marcelo Tosatti perm = 0; 3300b360adbdb54d5b98b78d57ba0916bc4b8871968Andrew Morton 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbs = kmalloc(sizeof(*kbs), GFP_KERNEL); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!kbs) { 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* we mostly copy too much here (512bytes), but who cares ;) */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(kbs, user_kdgkb, sizeof(struct kbsentry))) { 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0'; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = kbs->kb_func; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = sizeof(kbs->kb_string) - 1; /* sz should have been 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a struct member */ 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up = user_kdgkb->kb_string; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = func_table[i]; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(p) 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for ( ; *p && sz; p++, sz--) 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(*p, up++)) { 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user('\0', up)) { 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EFAULT; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(kbs); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ((p && *p) ? -EOVERFLOW : 0); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) { 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EPERM; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds q = func_table[i]; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds first_free = funcbufptr + (funcbufsize - funcbufleft); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j < MAX_NR_FUNC) 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fj = func_table[j]; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fj = first_free; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds delta = (q ? -strlen(q) : 1) + strlen(kbs->kb_string); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (delta <= funcbufleft) { /* it fits in current buf */ 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (j < MAX_NR_FUNC) { 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fj + delta, fj, first_free - fj); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = j; k < MAX_NR_FUNC; k++) 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] += delta; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!q) 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[i] = fj; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufleft -= delta; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* allocate a larger buffer */ 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz = 256; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (sz < funcbufsize - funcbufleft + delta) 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sz <<= 1; 3935cbded585d129d0226cb48ac4202b253c781be26Robert P. J. Day fnw = kmalloc(sz, GFP_KERNEL); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!fnw) { 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -ENOMEM; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reterr; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!q) 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[i] = fj; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fj > funcbufptr) 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fnw, funcbufptr, fj - funcbufptr); 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = 0; k < j; k++) 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] = fnw + (func_table[k] - funcbufptr); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (first_free > fj) { 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj); 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (k = j; k < MAX_NR_FUNC; k++) 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (func_table[k]) 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds func_table[k] = fnw + (func_table[k] - funcbufptr) + delta; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (funcbufptr != func_buf) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(funcbufptr); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufptr = fnw; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufleft = funcbufleft - delta + sz - funcbufsize; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds funcbufsize = sz; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(func_table[i], kbs->kb_string); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = 0; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreterr: 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(kbs); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct consolefontdesc cfdarg; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_SET; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, op); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: { 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_GET; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc_cons[fg_console].d, op); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charheight = op->height; 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charcount = op->charcount; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct unimapdesc tmp; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_ud, sizeof tmp)) 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp.entries) 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, tmp.entries, 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.entry_ct*sizeof(struct unipair))) 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_unimap(vc, tmp.entry_ct, tmp.entries); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && fg_console != vc->vc_num) 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4928b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 4938b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We handle the console-specific ioctl's here. We allow the 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * capability to modify any console, not just the fg_console. 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint vt_ioctl(struct tty_struct *tty, struct file * file, 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd, unsigned long arg) 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 501c9f19e96a2f33cd56c2bd19f87a0c4982d011c2bAlan Cox struct vc_data *vc = tty->driver_data; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct console_font_op op; /* used in multiple places here */ 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_struct * kbd; 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int console; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char ucval; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *up = (void __user *)arg; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, perm; 5089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox int ret = 0; 5099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds console = vc->vc_num; 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox lock_kernel(); 5139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 5149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (!vc_cons_allocated(console)) { /* impossible? */ 5159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOIOCTLCMD; 5169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 5179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 5189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To have permissions to do most of the vt ioctls, we either have 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 0; 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 1; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd = kbd_table + console; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 530e6885107736a4dd23e7d3bc103fe6d043c63c4deAlan Cox case TIOCLINUX: 531a115902f67ef51fbbe83e214fb761aaa9734c1ceJiri Slaby ret = tioclinux(tty, arg); 532a115902f67ef51fbbe83e214fb761aaa9734c1ceJiri Slaby break; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KIOCSOUND: 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 5359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 536fab892232e275e4e9351a50d018c0a9513155814Alan Cox /* FIXME: This is an old broken API but we need to keep it 537fab892232e275e4e9351a50d018c0a9513155814Alan Cox supported and somehow separate the historic advertised 538fab892232e275e4e9351a50d018c0a9513155814Alan Cox tick rate from any real one */ 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg) 540bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus arg = CLOCK_TICK_RATE / arg; 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(arg, 0); 5429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMKTONE: 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 5469cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ticks, count; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Generate the tone for the appropriate number of ticks. 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the time is zero, turn off sound ourselves. 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ticks = HZ * ((arg >> 16) & 0xffff) / 1000; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = ticks ? (arg & 0xffff) : 0; 556fab892232e275e4e9351a50d018c0a9513155814Alan Cox /* FIXME: This is an old broken API but we need to keep it 557fab892232e275e4e9351a50d018c0a9513155814Alan Cox supported and somehow separate the historic advertised 558fab892232e275e4e9351a50d018c0a9513155814Alan Cox tick rate from any real one */ 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count) 560bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus count = CLOCK_TICK_RATE / count; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(count, ticks); 5629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBTYPE: 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this is naive. 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = KB_101; 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setchar; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These cannot be implemented on any machine that implements 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioperm() in user level (such as Alpha PCs) or not at all. 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX: you should never use these, just call ioperm directly.. 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDADDIO: 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDELIO: 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KDADDIO and KDDELIO may be able to add ports beyond what 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we reject here, but to be safe... 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg < GPFIRST || arg > GPLAST) { 5869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 5879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 5899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; 5909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDENABIO: 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDISABIO: 5949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = sys_ioperm(GPFIRST, GPNUM, 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cmd == KDENABIO)) ? -ENXIO : 0; 5969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDKBDREP: 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_repeat kbrep; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 6069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) { 6099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 6129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = kbd_rate(&kbrep); 6139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 6149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) 6169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 6179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETMODE: 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * currently, setting the mode from KD_TEXT to KD_GRAPHICS 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't do a whole lot. i'm not sure if it should do any 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * restoration of modes or what... 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX It should at least call into the driver, fbdev's definitely 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need to restore their engine state. --BenH 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (arg) { 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_GRAPHICS: 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT0: 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT1: 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg = KD_TEXT; 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT: 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 6419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == (unsigned char) arg) 6449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = (unsigned char) arg; 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (console != fg_console) 6479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * explicitly blank/unblank the screen if switching modes 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == KD_TEXT) 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 6579cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETMODE: 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = vc->vc_mode; 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMAPDISP: 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDUNMAPDISP: 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these work like a combination of mmap and KDENABIO. 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this could be easily finished. 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 6709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMODE: 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(arg) { 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_RAW: 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_RAW; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_MEDIUMRAW: 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_MEDIUMRAW; 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_XLATE: 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_XLATE; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_UNICODE: 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->kbdmode = VC_UNICODE; 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compute_shiftstate(); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 6919cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 6929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tty_ldisc_flush(tty); 6959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMODE: 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW : 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (kbd->kbdmode == VC_UNICODE) ? K_UNICODE : 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds K_XLATE); 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this could be folded into KDSKBMODE, but for compatibility 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMETA: 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(arg) { 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_METABIT: 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clr_vc_kbd_mode(kbd, VC_META); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case K_ESCPREFIX: 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_vc_kbd_mode(kbd, VC_META); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 7159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMETA: 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setint: 7229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(ucval, (int __user *)arg); 7239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!capable(CAP_SYS_TTY_CONFIG)) 7289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox perm = 0; 7299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_kbkeycode_ioctl(cmd, up, perm); 7309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 7349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_kdsk_ioctl(cmd, up, perm, kbd); 7359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 7399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_kdgkb_ioctl(cmd, up, perm); 7409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBDIACR: 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbdiacrs __user *a = up; 74504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacr diacr; 74604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault int i; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7489cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (put_user(accent_table_size, &a->kb_cnt)) { 7499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 75204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault for (i = 0; i < accent_table_size; i++) { 75304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr); 75404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.base = conv_uni_to_8bit(accent_table[i].base); 75504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault diacr.result = conv_uni_to_8bit(accent_table[i].result); 7569cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) { 7579cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7589cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7599cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 76004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 7619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 76204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 76304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault case KDGKBDIACRUC: 76404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault { 76504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacrsuc __user *a = up; 76604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 76704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (put_user(accent_table_size, &a->kb_cnt)) 7689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else if (copy_to_user(a->kbdiacruc, accent_table, 7709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox accent_table_size*sizeof(struct kbdiacruc))) 7719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBDIACR: 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbdiacrs __user *a = up; 77804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacr diacr; 77904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault unsigned int ct; 78004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault int i; 78104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 78204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (!perm) 7839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 7849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (get_user(ct,&a->kb_cnt)) { 7859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 7889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ct >= MAX_DIACR) { 7899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 7909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7919cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 79204c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table_size = ct; 79304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault for (i = 0; i < ct; i++) { 7949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) { 7959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7969cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 79804c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr); 79904c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].base = conv_8bit_to_uni(diacr.base); 80004c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault accent_table[i].result = conv_8bit_to_uni(diacr.result); 80104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 8029cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 80304c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault } 80404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault 80504c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault case KDSKBDIACRUC: 80604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault { 80704c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault struct kbdiacrsuc __user *a = up; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ct; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 8129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (get_user(ct,&a->kb_cnt)) { 8139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 8149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ct >= MAX_DIACR) { 8179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 8189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8199cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds accent_table_size = ct; 82104c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc))) 8229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 8239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below read/set the flags usually shown in the leds */ 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't use them - they will go away without warning */ 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBLED: 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setchar; 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBLED: 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 8359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg & ~0x77) { 8369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 8379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->ledflagstate = (arg & 7); 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kbd->default_ledflagstate = ((arg >> 4) & 7); 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_leds(); 8429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below only set the lights, not the functions */ 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for those, see KDGKBLED and KDSKBLED above */ 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETLED: 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = getledstate(); 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setchar: 8499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(ucval, (char __user *)arg); 8509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETLED: 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8549cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setledstate(kbd, arg); 8569cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A process can indicate its willingness to accept signals 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * generated by pressing an appropriate key combination. 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thus, one can have a daemon that e.g. spawns a new console 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upon a keypress and then changes to it. 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See also the kbrequest field of inittab(5). 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSIGACCEPT: 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm || !capable(CAP_KILL)) 8689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 8697ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) 8709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 8719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 8729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox spin_lock_irq(&vt_spawn_con.lock); 8739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox put_pid(vt_spawn_con.pid); 8749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vt_spawn_con.pid = get_pid(task_pid(current)); 8759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vt_spawn_con.sig = arg; 8769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox spin_unlock_irq(&vt_spawn_con.lock); 8779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_SETMODE: 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 8879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) { 8889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 8899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 8909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 89187a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) { 8929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 8939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 8949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode = tmp; 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the frsig is ignored, so we set it to 0 */ 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 8998b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman put_pid(vc->vt_pid); 9008b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc->vt_pid = get_pid(task_pid(current)); 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no switch is required -- saw@shade.msu.ru */ 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 9049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETMODE: 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode)); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); 9179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (rc) 9189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 9199cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns global vt state. Note that VT 0 is always open, since 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's an alias for the current VT, and people can't use it here. 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cannot return state for more than 16 VTs, since v_state is short. 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETSTATE: 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_stat __user *vtstat = up; 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short state, mask; 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(fg_console + 1, &vtstat->v_active)) 9339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 9349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 9359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox state = 1; /* /dev/tty0 is always open */ 9369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; 9379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ++i, mask <<= 1) 9389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (VT_IS_IN_USE(i)) 9399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox state |= mask; 9409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(state, &vtstat->v_state); 9419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 9429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the first available (non-opened) console. 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_OPENQRY: 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; ++i) 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_IS_IN_USE(i)) 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = i < MAX_NR_CONSOLES ? (i+1) : -1; 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with num >= 1 (switches to vt 0, our console, are not allowed, just 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to preserve sanity). 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_ACTIVATE: 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 9649cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 9659cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 9669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox arg--; 9679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox acquire_console_sem(); 9689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = vc_allocate(arg); 9699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox release_console_sem(); 9709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 9719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox set_console(arg); 9739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 9749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 976d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox case VT_SETACTIVATE: 977d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox { 978d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox struct vt_setactivate vsa; 979d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox 980d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (!perm) 981d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox goto eperm; 982d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox 983d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg, 984a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby sizeof(struct vt_setactivate))) { 985a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby ret = -EFAULT; 986a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby goto out; 987a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby } 988d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) 989d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox ret = -ENXIO; 990d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox else { 991d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox vsa.console--; 992d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox acquire_console_sem(); 993d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox ret = vc_allocate(vsa.console); 994d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (ret == 0) { 995d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox struct vc_data *nvc; 996d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox /* This is safe providing we don't drop the 997d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox console sem between vc_allocate and 998d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox finishing referencing nvc */ 999d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox nvc = vc_cons[vsa.console].d; 1000d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox nvc->vt_mode = vsa.mode; 1001d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox nvc->vt_mode.frsig = 0; 1002d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox put_pid(nvc->vt_pid); 1003d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox nvc->vt_pid = get_pid(task_pid(current)); 1004d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox } 1005d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox release_console_sem(); 1006d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (ret) 1007d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox break; 1008d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox /* Commence switch and lock */ 1009d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox set_console(arg); 1010d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox } 1011d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox } 1012d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * wait until the specified VT has been activated 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_WAITACTIVE: 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 10189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 10209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 10219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 10228b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox ret = vt_waitactive(arg); 10239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If a vt is under process control, the kernel will not switch to it 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * immediately, but postpone the operation until the process calls this 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl, allowing the switch to complete. 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * According to the X sources this is the behavior: 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0: pending switch-from not OK 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1: pending switch-from OK 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2: completed switch-to OK 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RELDISP: 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 10379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (vc->vt_mode.mode != VT_PROCESS) { 10409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 10419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switching-from response 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10468792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz acquire_console_sem(); 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_newvt >= 0) { 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch disallowed, so forget we were trying 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to do it. 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The current vt has been released, so 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complete the switch. 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int newvt; 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newvt = vc->vt_newvt; 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 10639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = vc_allocate(newvt); 10649cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) { 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 10669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When we actually do the console switch, 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * make sure we are atomic with respect to 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other console switches.. 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(vc_cons[newvt].d); 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } else { 10769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* 10779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox * Switched-to response 10789cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox */ 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it's just an ACK, ignore it 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg != VT_ACKACQ) 10839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10858792f961ba8057d9f27987def3600253a3ba060fSamuel Ortiz release_console_sem(); 10869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Disallocate memory associated to VT (but leave VT1) 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_DISALLOCATE: 10929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg > MAX_NR_CONSOLES) { 10939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 10949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) { 1097ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate all unused consoles, but leave 0 */ 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=1; i<MAX_NR_CONSOLES; i++) 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_BUSY(i)) 1101ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox vc_deallocate(i); 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1104ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate a single console, if possible */ 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg--; 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (VT_BUSY(arg)) 11079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EBUSY; 11089cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else if (arg) { /* leave 0 */ 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 1110ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox vc_deallocate(arg); 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZE: 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_sizes __user *vtsizes = up; 1119e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas struct vc_data *vc; 1120e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 11239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(ll, &vtsizes->v_rows) || 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_user(cc, &vtsizes->v_cols)) 11269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 11279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 11288c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox acquire_console_sem(); 11299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox for (i = 0; i < MAX_NR_CONSOLES; i++) { 11309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vc = vc_cons[i].d; 1131e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 11329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (vc) { 11339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vc->vc_resize_user = 1; 11348c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox vc_resize(vc_cons[i].d, cc, ll); 11359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 1136e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas } 11378c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox release_console_sem(); 1138e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas } 11399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZEX: 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_consize __user *vtconsize = up; 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc,vlin,clin,vcol,ccol; 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 11479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, vtconsize, 11499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox sizeof(struct vt_consize))) { 11509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 11519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11529cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 11539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* FIXME: Should check the copies properly */ 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ll, &vtconsize->v_rows); 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(cc, &vtconsize->v_cols); 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vlin, &vtconsize->v_vlin); 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(clin, &vtconsize->v_clin); 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vcol, &vtconsize->v_vcol); 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ccol, &vtconsize->v_ccol); 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vlin = vlin ? vlin : vc->vc_scan_lines; 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) { 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ll) { 11639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ll != vlin/clin) { 11649cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* Parameters don't add up */ 11659cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 11669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ll = vlin/clin; 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vcol && ccol) { 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cc) { 11739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (cc != vcol/ccol) { 11749cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 11759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cc = vcol/ccol; 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (clin > 32) { 11829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 11839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; i++) { 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!vc_cons[i].d) 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acquire_console_sem(); 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vlin) 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_scan_lines = vlin; 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_font.height = clin; 1194e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas vc_cons[i].d->vc_resize_user = 1; 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_resize(vc_cons[i].d, cc, ll); 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_console_sem(); 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONT: { 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 12039cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET; 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 0; 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 12109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 12119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONT: { 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_GET; 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD; 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 32; 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 12219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 12229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_CMAP: 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 12279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 12289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 12299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_cmap(up); 12309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_CMAP: 12339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_cmap(up); 12349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: 12389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_fontx_ioctl(cmd, up, perm, &op); 12399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTRESET: 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 12449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BROKEN_GRAPHICS_PROGRAMS 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* With BROKEN_GRAPHICS_PROGRAMS defined, the default 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds font is not saved. */ 12499cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOSYS; 12509cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET_DEFAULT; 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = NULL; 12559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 12569cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 12579cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds con_set_default_unimap(vc_cons[fg_console].d); 12599cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDFONTOP: { 12659cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&op, up, sizeof(op))) { 12669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 12679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && op.op != KD_FONT_OP_GET) 12709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 12719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc, &op); 12729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 12739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &op, sizeof(op))) 12759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 12769cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_SCRNMAP: 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 12819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 12829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 12839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_trans_old(up); 12849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_SCRNMAP: 12879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_trans_old(up); 12889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNISCRNMAP: 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 12929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 12939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 12949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_trans_new(up); 12959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNISCRNMAP: 12989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_trans_new(up); 12999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAPCLR: 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { struct unimapinit ui; 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 13049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 13059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); 13063fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter if (ret) 13073fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter ret = -EFAULT; 13083fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter else 13099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox con_clear_unimap(vc, &ui); 13109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 13159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_unimap_ioctl(cmd, up, perm, vc); 13169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_LOCKSWITCH: 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 13209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 1; 13229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_UNLOCKSWITCH: 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 13259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto eperm; 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 0; 13279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 1328533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault case VT_GETHIFONTMASK: 13299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(vc->vc_hi_font_mask, 13309cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox (unsigned short __user *)arg); 13319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 13328b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox case VT_WAITEVENT: 13338b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox ret = vt_event_wait_ioctl((struct vt_event __user *)arg); 13348b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox break; 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 13369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOIOCTLCMD; 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Coxout: 13399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox unlock_kernel(); 13409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox return ret; 13419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Coxeperm: 13429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 13439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid reset_vc(struct vc_data *vc) 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = KD_TEXT; 13492e8ecb9db0bcc19e1cc8bb51e9252fe6a86a9863Bill Nottingham kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE; 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.mode = VT_AUTO; 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.waitv = 0; 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.relsig = 0; 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.acqsig = 0; 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 13558b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman put_pid(vc->vt_pid); 13568b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc->vt_pid = NULL; 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_palette(vc); 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13628b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biedermanvoid vc_SAK(struct work_struct *work) 13638b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman{ 13648b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct vc *vc_con = 13658b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman container_of(work, struct vc, SAK_work); 13668b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct vc_data *vc; 13678b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct tty_struct *tty; 13688b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman 13698b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman acquire_console_sem(); 13708b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc = vc_con->d; 13718b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman if (vc) { 13728ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox tty = vc->port.tty; 13738b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman /* 13748b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman * SAK should also work in all raw modes and reset 13758b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman * them properly. 13768b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman */ 13778b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman if (tty) 13788b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman __do_SAK(tty); 13798b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman reset_vc(vc); 13808b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman } 13818b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman release_console_sem(); 13828b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman} 13838b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman 1384e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#ifdef CONFIG_COMPAT 1385e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1386e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_consolefontdesc { 1387e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned short charcount; /* characters in font (256 or 512) */ 1388e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned short charheight; /* scan lines per character (1-32) */ 1389e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_caddr_t chardata; /* font data in expanded form */ 1390e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}; 1391e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1392e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int 1393e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd, 1394e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int perm, struct console_font_op *op) 1395e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{ 1396e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct compat_consolefontdesc cfdarg; 1397e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int i; 1398e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1399e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc))) 1400e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1401e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1402e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann switch (cmd) { 1403e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case PIO_FONTX: 1404e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!perm) 1405e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EPERM; 1406e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->op = KD_FONT_OP_SET; 1407e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->flags = KD_FONT_FLAG_OLD; 1408e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->width = 8; 1409e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->height = cfdarg.charheight; 1410e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->charcount = cfdarg.charcount; 1411e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->data = compat_ptr(cfdarg.chardata); 1412e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return con_font_op(vc_cons[fg_console].d, op); 1413e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case GIO_FONTX: 1414e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->op = KD_FONT_OP_GET; 1415e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->flags = KD_FONT_FLAG_OLD; 1416e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->width = 8; 1417e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->height = cfdarg.charheight; 1418e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->charcount = cfdarg.charcount; 1419e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->data = compat_ptr(cfdarg.chardata); 1420e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann i = con_font_op(vc_cons[fg_console].d, op); 1421e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (i) 1422e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return i; 1423e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann cfdarg.charheight = op->height; 1424e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann cfdarg.charcount = op->charcount; 1425e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc))) 1426e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1427e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return 0; 1428e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann } 1429e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EINVAL; 1430e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann} 1431e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1432e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_console_font_op { 1433e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_uint_t op; /* operation code KD_FONT_OP_* */ 1434e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_uint_t flags; /* KD_FONT_FLAG_* */ 1435e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_uint_t width, height; /* font size */ 1436e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_uint_t charcount; 1437e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_caddr_t data; /* font data with height fixed to 32 */ 1438e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}; 1439e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1440e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int 1441e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_kdfontop_ioctl(struct compat_console_font_op __user *fontop, 1442e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int perm, struct console_font_op *op, struct vc_data *vc) 1443e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{ 1444e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int i; 1445e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1446e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_from_user(op, fontop, sizeof(struct compat_console_font_op))) 1447e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1448e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!perm && op->op != KD_FONT_OP_GET) 1449e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EPERM; 1450e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->data = compat_ptr(((struct compat_console_font_op *)op)->data); 1451e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->flags |= KD_FONT_FLAG_OLD; 1452e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann i = con_font_op(vc, op); 1453e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (i) 1454e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return i; 1455e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann ((struct compat_console_font_op *)op)->data = (unsigned long)op->data; 1456e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_to_user(fontop, op, sizeof(struct compat_console_font_op))) 1457e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1458e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return 0; 1459e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann} 1460e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1461e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_unimapdesc { 1462e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned short entry_ct; 1463e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_caddr_t entries; 1464e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}; 1465e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1466e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int 1467e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud, 1468e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int perm, struct vc_data *vc) 1469e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{ 1470e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct compat_unimapdesc tmp; 1471e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct unipair __user *tmp_entries; 1472e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1473e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_from_user(&tmp, user_ud, sizeof tmp)) 1474e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1475e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann tmp_entries = compat_ptr(tmp.entries); 1476e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (tmp_entries) 1477e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!access_ok(VERIFY_WRITE, tmp_entries, 1478e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann tmp.entry_ct*sizeof(struct unipair))) 1479e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1480e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann switch (cmd) { 1481e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case PIO_UNIMAP: 1482e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!perm) 1483e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EPERM; 1484e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return con_set_unimap(vc, tmp.entry_ct, tmp_entries); 1485e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case GIO_UNIMAP: 1486e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!perm && fg_console != vc->vc_num) 1487e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EPERM; 1488e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp_entries); 1489e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann } 1490e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return 0; 1491e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann} 1492e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1493e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannlong vt_compat_ioctl(struct tty_struct *tty, struct file * file, 1494e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned int cmd, unsigned long arg) 1495e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{ 1496e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct vc_data *vc = tty->driver_data; 1497e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct console_font_op op; /* used in multiple places here */ 1498e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct kbd_struct *kbd; 1499e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned int console; 1500e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann void __user *up = (void __user *)arg; 1501e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int perm; 1502e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int ret = 0; 1503e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1504e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann console = vc->vc_num; 1505e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1506e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann lock_kernel(); 1507e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1508e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!vc_cons_allocated(console)) { /* impossible? */ 1509e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann ret = -ENOIOCTLCMD; 1510e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann goto out; 1511e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann } 1512e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1513e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann /* 1514e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * To have permissions to do most of the vt ioctls, we either have 1515e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 1516e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann */ 1517e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann perm = 0; 1518e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 1519e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann perm = 1; 1520e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1521e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann kbd = kbd_table + console; 1522e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann switch (cmd) { 1523e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann /* 1524e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * these need special handlers for incompatible data structures 1525e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann */ 1526e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case PIO_FONTX: 1527e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case GIO_FONTX: 1528e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann ret = compat_fontx_ioctl(cmd, up, perm, &op); 1529e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann break; 1530e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1531e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDFONTOP: 1532e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann ret = compat_kdfontop_ioctl(up, perm, &op, vc); 1533e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann break; 1534e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1535e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case PIO_UNIMAP: 1536e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case GIO_UNIMAP: 15374b1fe7797270e866adc17fc603bddf8768bc187fAndreas Schwab ret = compat_unimap_ioctl(cmd, up, perm, vc); 1538e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann break; 1539e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1540e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann /* 1541e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * all these treat 'arg' as an integer 1542e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann */ 1543e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KIOCSOUND: 1544e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDMKTONE: 1545e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#ifdef CONFIG_X86 1546e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDADDIO: 1547e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDDELIO: 1548e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#endif 1549e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSETMODE: 1550e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDMAPDISP: 1551e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDUNMAPDISP: 1552e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSKBMODE: 1553e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSKBMETA: 1554e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSKBLED: 1555e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSETLED: 1556e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSIGACCEPT: 1557e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_ACTIVATE: 1558e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_WAITACTIVE: 1559e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_RELDISP: 1560e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_DISALLOCATE: 1561e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_RESIZE: 1562e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_RESIZEX: 1563e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann goto fallback; 1564e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1565e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann /* 1566e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * the rest has a compatible data structure behind arg, 1567e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * but we have to convert it to a proper 64 bit pointer. 1568e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann */ 1569e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann default: 1570e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann arg = (unsigned long)compat_ptr(arg); 1571e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann goto fallback; 1572e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann } 1573e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannout: 1574e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unlock_kernel(); 1575e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return ret; 1576e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1577e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannfallback: 1578e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unlock_kernel(); 1579e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return vt_ioctl(tty, file, cmd, arg); 1580e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann} 1581e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1582e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1583e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#endif /* CONFIG_COMPAT */ 1584e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1585e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1587d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox * Performs the back end of a vt switch. Called under the console 1588d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox * semaphore. 15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc) 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char old_vc_mode; 15938b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox int old = fg_console; 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_console = fg_console; 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we're switching, we could be going from KD_GRAPHICS to 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KD_TEXT mode or vice versa, which means we need to blank or 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unblank the screen later. 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_vc_mode = vc_cons[fg_console].d->vc_mode; 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch_screen(vc); 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16063dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * This can't appear below a successful kill_pid(). If it did, 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then the *blank_screen operation could occur while X, having 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * received acqsig, is waking up on another processor. This 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * condition can lead to overlapping accesses to the VGA range 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the framebuffer (causing system lockups). 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To account for this we duplicate this code below only if the 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controlling process is gone and we've called reset_vc. 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this new console is under process control, send it a signal 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * telling it that it has acquired. Also check if it has died and 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clean up (similar to logic employed in change_console()) 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 162787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman if (vc->vt_mode.mode == VT_PROCESS) { 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16293dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * Send the signal as privileged - kill_pid() will 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is awry 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1633bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The controlling process has died, so we revert back to 16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * normal operation. In this case, we'll also change back 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to KD_TEXT mode. I'm not sure if this is strictly correct 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but it saves the agony when the X server dies and the screen 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remains blanked due to KD_GRAPHICS! It would be nice to do 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this outside of VT_PROCESS but there is no single process 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to account for and tracking tty count may be undesirable. 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_vc(vc); 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wake anyone waiting for their VT to activate 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16578b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vt_event_post(VT_EVENT_SWITCH, old, vc->vc_num); 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the front-end of a vt switch 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid change_console(struct vc_data *new_vc) 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vc_data *vc; 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch) 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this vt is in process mode, then we need to handshake with 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that process before switching. Essentially, we store where that 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt wants to switch to and wait for it to tell us when it's done 16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (via VT_RELDISP ioctl). 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We also check to see if the controlling process still exists. 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it doesn't, we reset this vt to auto mode and continue. 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a cheap way to track process control. The worst thing 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that can happen is: we send a signal to a process, it dies, and 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the switch gets "lost" waiting for a response; hopefully, the 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user will try again, we'll detect the process is gone (unless 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the user waits just the right amount of time :-) and revert the 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt to auto control. 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc = vc_cons[fg_console].d; 168787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman if (vc->vt_mode.mode == VT_PROCESS) { 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16893dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * Send the signal as privileged - kill_pid() will 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 1691a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * is awry. 1692a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * 1693a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * We need to set vt_newvt *before* sending the signal or we 1694a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * have a race. 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1696a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe vc->vt_newvt = new_vc->vc_num; 1697bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 169987a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * It worked. Mark the vt to switch to and 170087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * return. The process needs to send us a 170187a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * VT_RELDISP ioctl to complete the switch. 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 170387a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman return; 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 170787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * The controlling process has died, so we revert back to 170887a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * normal operation. In this case, we'll also change back 170987a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * to KD_TEXT mode. I'm not sure if this is strictly correct 171087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * but it saves the agony when the X server dies and the screen 171187a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * remains blanked due to KD_GRAPHICS! It would be nice to do 171287a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * this outside of VT_PROCESS but there is no single process 171387a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * to account for and tracking tty count may be undesirable. 171487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman */ 171587a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman reset_vc(vc); 171687a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman 171787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman /* 171887a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * Fall through to normal (VT_AUTO) handling of the switch... 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ignore all switches in KD_GRAPHICS+VT_AUTO mode 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_GRAPHICS) 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(new_vc); 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17308d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 17318d233558cd99a888571bb5a88a74970879e0aba4Alan Cox/* Perform a kernel triggered VT switch for suspend/resume */ 17328d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 17338d233558cd99a888571bb5a88a74970879e0aba4Alan Coxstatic int disable_vt_switch; 17348d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 17358d233558cd99a888571bb5a88a74970879e0aba4Alan Coxint vt_move_to_console(unsigned int vt, int alloc) 17368d233558cd99a888571bb5a88a74970879e0aba4Alan Cox{ 17378d233558cd99a888571bb5a88a74970879e0aba4Alan Cox int prev; 17388d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 17398d233558cd99a888571bb5a88a74970879e0aba4Alan Cox acquire_console_sem(); 17408d233558cd99a888571bb5a88a74970879e0aba4Alan Cox /* Graphics mode - up to X */ 17418d233558cd99a888571bb5a88a74970879e0aba4Alan Cox if (disable_vt_switch) { 17428d233558cd99a888571bb5a88a74970879e0aba4Alan Cox release_console_sem(); 17438d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return 0; 17448d233558cd99a888571bb5a88a74970879e0aba4Alan Cox } 17458d233558cd99a888571bb5a88a74970879e0aba4Alan Cox prev = fg_console; 17468d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 17478d233558cd99a888571bb5a88a74970879e0aba4Alan Cox if (alloc && vc_allocate(vt)) { 17488d233558cd99a888571bb5a88a74970879e0aba4Alan Cox /* we can't have a free VC for now. Too bad, 17498d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * we don't want to mess the screen for now. */ 17508d233558cd99a888571bb5a88a74970879e0aba4Alan Cox release_console_sem(); 17518d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return -ENOSPC; 17528d233558cd99a888571bb5a88a74970879e0aba4Alan Cox } 17538d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 17548d233558cd99a888571bb5a88a74970879e0aba4Alan Cox if (set_console(vt)) { 17558d233558cd99a888571bb5a88a74970879e0aba4Alan Cox /* 17568d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * We're unable to switch to the SUSPEND_CONSOLE. 17578d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * Let the calling function know so it can decide 17588d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * what to do. 17598d233558cd99a888571bb5a88a74970879e0aba4Alan Cox */ 17608d233558cd99a888571bb5a88a74970879e0aba4Alan Cox release_console_sem(); 17618d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return -EIO; 17628d233558cd99a888571bb5a88a74970879e0aba4Alan Cox } 17638d233558cd99a888571bb5a88a74970879e0aba4Alan Cox release_console_sem(); 1764797938b5e33991dadf4dd9228b932cc69c3e905aJiri Slaby if (vt_waitactive(vt + 1)) { 17658d233558cd99a888571bb5a88a74970879e0aba4Alan Cox pr_debug("Suspend: Can't switch VCs."); 17668d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return -EINTR; 17678d233558cd99a888571bb5a88a74970879e0aba4Alan Cox } 17688d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return prev; 17698d233558cd99a888571bb5a88a74970879e0aba4Alan Cox} 17708d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 17718d233558cd99a888571bb5a88a74970879e0aba4Alan Cox/* 17728d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * Normally during a suspend, we allocate a new console and switch to it. 17738d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * When we resume, we switch back to the original console. This switch 17748d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * can be slow, so on systems where the framebuffer can handle restoration 17758d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * of video registers anyways, there's little point in doing the console 17768d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * switch. This function allows you to disable it by passing it '0'. 17778d233558cd99a888571bb5a88a74970879e0aba4Alan Cox */ 17788d233558cd99a888571bb5a88a74970879e0aba4Alan Coxvoid pm_set_vt_switch(int do_switch) 17798d233558cd99a888571bb5a88a74970879e0aba4Alan Cox{ 17808d233558cd99a888571bb5a88a74970879e0aba4Alan Cox acquire_console_sem(); 17818d233558cd99a888571bb5a88a74970879e0aba4Alan Cox disable_vt_switch = !do_switch; 17828d233558cd99a888571bb5a88a74970879e0aba4Alan Cox release_console_sem(); 17838d233558cd99a888571bb5a88a74970879e0aba4Alan Cox} 17848d233558cd99a888571bb5a88a74970879e0aba4Alan CoxEXPORT_SYMBOL(pm_set_vt_switch); 1785