vt_ioctl.c revision 4001d7b7fc271052ebff43f327c26dc64806bbdf
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1992 obz under the linux copyright 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Dynamic keymap and string allocation - aeb@cwi.nl - May 1994 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some code moved for less code duplication - Andi Kleen - Mar 1997 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 17e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#include <linux/compat.h> 188d233558cd99a888571bb5a88a74970879e0aba4Alan Cox#include <linux/module.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kd.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/major.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h> 2604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault#include <linux/consolemap.h> 277ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl#include <linux/signal.h> 28bcc8ca09920755520ba8a1e2d9f72fe8ff892643Emmanuel Colbus#include <linux/timex.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_kern.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kbd_diacr.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/selection.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38b257bc051f06607beb3004d9a1c297085e728becAndrew Johnsonchar vt_dont_switch; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern struct tty_driver *console_driver; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons) 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Console (vt and kd) routines, as defined by USL SVR4 manual, and by 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * experimentation and study of X386 SYSV handling. 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console, 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the current console is done by the main ioctl code. 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/syscalls.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 648b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * User space VT_EVENT handlers 658b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 668b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 678b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstruct vt_event_wait { 688b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct list_head list; 698b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event event; 708b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox int done; 718b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox}; 728b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 738b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic LIST_HEAD(vt_events); 748b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic DEFINE_SPINLOCK(vt_event_lock); 758b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic DECLARE_WAIT_QUEUE_HEAD(vt_event_waitqueue); 768b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 778b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/** 788b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * vt_event_post 798b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @event: the event that occurred 808b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @old: old console 818b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @new: new console 828b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * 838b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * Post an VT event to interested VT handlers 848b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 858b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 868b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxvoid vt_event_post(unsigned int event, unsigned int old, unsigned int new) 878b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{ 888b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct list_head *pos, *head; 898b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox unsigned long flags; 908b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox int wake = 0; 918b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 928b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_lock_irqsave(&vt_event_lock, flags); 938b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox head = &vt_events; 948b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 958b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox list_for_each(pos, head) { 968b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event_wait *ve = list_entry(pos, 978b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event_wait, list); 988b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (!(ve->event.event & event)) 998b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox continue; 1008b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox ve->event.event = event; 1018b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* kernel view is consoles 0..n-1, user space view is 1028b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox console 1..n with 0 meaning current, so we must bias */ 103308efab5e231d1510cd35931d87629bf5171caaeAlan Cox ve->event.oldev = old + 1; 104308efab5e231d1510cd35931d87629bf5171caaeAlan Cox ve->event.newev = new + 1; 1058b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox wake = 1; 1068b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox ve->done = 1; 1078b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox } 1088b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_unlock_irqrestore(&vt_event_lock, flags); 1098b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (wake) 1108b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox wake_up_interruptible(&vt_event_waitqueue); 1118b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox} 1128b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1138b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/** 1148b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * vt_event_wait - wait for an event 1158b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @vw: our event 1168b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * 1178b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * Waits for an event to occur which completes our vt_event_wait 1188b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * structure. On return the structure has wv->done set to 1 for success 1198b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * or 0 if some event such as a signal ended the wait. 1208b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 1218b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1228b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic void vt_event_wait(struct vt_event_wait *vw) 1238b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{ 1248b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox unsigned long flags; 1258b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Prepare the event */ 1268b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox INIT_LIST_HEAD(&vw->list); 1278b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vw->done = 0; 1288b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Queue our event */ 1298b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_lock_irqsave(&vt_event_lock, flags); 1308b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox list_add(&vw->list, &vt_events); 1318b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_unlock_irqrestore(&vt_event_lock, flags); 1328b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Wait for it to pass */ 133be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann wait_event_interruptible_tty(vt_event_waitqueue, vw->done); 1348b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Dequeue it */ 1358b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_lock_irqsave(&vt_event_lock, flags); 1368b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox list_del(&vw->list); 1378b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox spin_unlock_irqrestore(&vt_event_lock, flags); 1388b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox} 1398b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1408b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/** 1418b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * vt_event_wait_ioctl - event ioctl handler 1428b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @arg: argument to ioctl 1438b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * 1448b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * Implement the VT_WAITEVENT ioctl using the VT event interface 1458b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 1468b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1478b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxstatic int vt_event_wait_ioctl(struct vt_event __user *event) 1488b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{ 1498b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event_wait vw; 1508b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1518b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (copy_from_user(&vw.event, event, sizeof(struct vt_event))) 1528b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EFAULT; 1538b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* Highest supported event for now */ 1548b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (vw.event.event & ~VT_MAX_EVENT) 1558b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EINVAL; 1568b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1578b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vt_event_wait(&vw); 1588b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox /* If it occurred report it */ 1598b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (vw.done) { 1608b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (copy_to_user(event, &vw.event, sizeof(struct vt_event))) 1618b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EFAULT; 1628b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return 0; 1638b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox } 1648b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EINTR; 1658b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox} 1668b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1678b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/** 1688b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * vt_waitactive - active console wait 1698b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @event: event code 1708b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * @n: new console 1718b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * 1728b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * Helper for event waits. Used to implement the legacy 1738b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox * event waiting ioctls in terms of events 1748b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox */ 1758b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1768b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Coxint vt_waitactive(int n) 1778b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox{ 1788b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox struct vt_event_wait vw; 1798b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox do { 1808b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (n == fg_console + 1) 1818b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox break; 1828b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vw.event.event = VT_EVENT_SWITCH; 1838b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vt_event_wait(&vw); 1848b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox if (vw.done == 0) 1858b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return -EINTR; 186308efab5e231d1510cd35931d87629bf5171caaeAlan Cox } while (vw.event.newev != n); 1878b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox return 0; 1888b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox} 1898b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 1908b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox/* 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these are the valid i/o ports we're allowed to change. they map all the 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * video ports 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPFIRST 0x3b4 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPLAST 0x3df 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GPNUM (GPLAST - GPFIRST + 1) 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op) 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct consolefontdesc cfdarg; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc))) 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_SET; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_font_op(vc_cons[fg_console].d, op); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: { 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->op = KD_FONT_OP_GET; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->flags = KD_FONT_FLAG_OLD; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->width = 8; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->height = cfdarg.charheight; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->charcount = cfdarg.charcount; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op->data = cfdarg.chardata; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = con_font_op(vc_cons[fg_console].d, op); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charheight = op->height; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfdarg.charcount = op->charcount; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc))) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdo_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct unimapdesc tmp; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_from_user(&tmp, user_ud, sizeof tmp)) 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tmp.entries) 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, tmp.entries, 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp.entry_ct*sizeof(struct unipair))) 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_set_unimap(vc, tmp.entry_ct, tmp.entries); 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && fg_console != vc->vc_num) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2648b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 2658b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We handle the console-specific ioctl's here. We allow the 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * capability to modify any console, not just the fg_console. 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2706caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxint vt_ioctl(struct tty_struct *tty, 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int cmd, unsigned long arg) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 273c9f19e96a2f33cd56c2bd19f87a0c4982d011c2bAlan Cox struct vc_data *vc = tty->driver_data; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct console_font_op op; /* used in multiple places here */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int console; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char ucval; 2771e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower unsigned int uival; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __user *up = (void __user *)arg; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, perm; 2809cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox int ret = 0; 2819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds console = vc->vc_num; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 2859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (!vc_cons_allocated(console)) { /* impossible? */ 2869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOIOCTLCMD; 2879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 2889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 2899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To have permissions to do most of the vt ioctls, we either have 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 0; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds perm = 1; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (cmd) { 300e6885107736a4dd23e7d3bc103fe6d043c63c4deAlan Cox case TIOCLINUX: 3014001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 302a115902f67ef51fbbe83e214fb761aaa9734c1ceJiri Slaby ret = tioclinux(tty, arg); 3034001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 304a115902f67ef51fbbe83e214fb761aaa9734c1ceJiri Slaby break; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KIOCSOUND: 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3074001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 3082c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann /* 3092c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann * The use of PIT_TICK_RATE is historic, it used to be 3102c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann * the platform-dependent CLOCK_TICK_RATE between 2.6.12 3112c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann * and 2.6.36, which was a minor but unfortunate ABI 3124001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox * change. kd_mksound is locked by the input layer. 3132c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann */ 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg) 3152c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann arg = PIT_TICK_RATE / arg; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(arg, 0); 3179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMKTONE: 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 3214001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int ticks, count; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Generate the tone for the appropriate number of ticks. 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the time is zero, turn off sound ourselves. 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ticks = HZ * ((arg >> 16) & 0xffff) / 1000; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = ticks ? (arg & 0xffff) : 0; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count) 3322c4e9671edfef534e9726366707d64e63d44e7e6Arnd Bergmann count = PIT_TICK_RATE / count; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kd_mksound(count, ticks); 3349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBTYPE: 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3394001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox * this is naïve. 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ucval = KB_101; 342079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox ret = put_user(ucval, (char __user *)arg); 343079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox break; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These cannot be implemented on any machine that implements 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioperm() in user level (such as Alpha PCs) or not at all. 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX: you should never use these, just call ioperm directly.. 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_X86 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDADDIO: 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDELIO: 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KDADDIO and KDDELIO may be able to add ports beyond what 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we reject here, but to be safe... 3574001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox * 3584001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox * These are locked internally via sys_ioperm 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3609cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg < GPFIRST || arg > GPLAST) { 3619cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 3629cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 3639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 3649cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; 3659cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDENABIO: 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDDISABIO: 3699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = sys_ioperm(GPFIRST, GPNUM, 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cmd == KDENABIO)) ? -ENXIO : 0; 3719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDKBDREP: 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct kbd_repeat kbrep; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 3814001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) { 3849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 3859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 3869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 3879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = kbd_rate(&kbrep); 3889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 3899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) 3919cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 3929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETMODE: 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * currently, setting the mode from KD_TEXT to KD_GRAPHICS 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * doesn't do a whole lot. i'm not sure if it should do any 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * restoration of modes or what... 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX It should at least call into the driver, fbdev's definitely 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * need to restore their engine state. --BenH 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4054001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (arg) { 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_GRAPHICS: 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT0: 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT1: 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg = KD_TEXT; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KD_TEXT: 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 4169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4184001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox /* FIXME: this needs the console lock extending */ 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == (unsigned char) arg) 4209cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = (unsigned char) arg; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (console != fg_console) 4239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * explicitly blank/unblank the screen if switching modes 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 427ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == KD_TEXT) 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 432ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 4339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETMODE: 4361e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower uival = vc->vc_mode; 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDMAPDISP: 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDUNMAPDISP: 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * these work like a combination of mmap and KDENABIO. 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this could be easily finished. 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 4469cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMODE: 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 4504001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 451079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox ret = vt_do_kdskbmode(console, arg); 452079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox if (ret == 0) 453079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox tty_ldisc_flush(tty); 4549cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMODE: 457079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox uival = vt_do_kdgkbmode(console); 458079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox ret = put_user(uival, (int __user *)arg); 459079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox break; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* this could be folded into KDSKBMODE, but for compatibility 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */ 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBMETA: 464079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox ret = vt_do_kdskbmeta(console, arg); 4659cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBMETA: 468079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox /* FIXME: should review whether this is worth locking */ 469079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox uival = vt_do_kdgkbmeta(console); 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setint: 4711e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower ret = put_user(uival, (int __user *)arg); 4729cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETKEYCODE: 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETKEYCODE: 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!capable(CAP_SYS_TTY_CONFIG)) 4779cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox perm = 0; 478079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox ret = vt_do_kbkeycode_ioctl(cmd, up, perm); 4799cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBENT: 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBENT: 483079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox ret = vt_do_kdsk_ioctl(cmd, up, perm, console); 4849cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBSENT: 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBSENT: 488079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox ret = vt_do_kdgkb_ioctl(cmd, up, perm); 4899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491247ff8e610cb63c015de19191db9666754c2ed79Alan Cox /* Diacritical processing. Handled in keyboard.c as it has 492247ff8e610cb63c015de19191db9666754c2ed79Alan Cox to operate on the keyboard locks and structures */ 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBDIACR: 49404c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault case KDGKBDIACRUC: 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBDIACR: 49604c71976500352d02f60616d2b960267d8c5fe24Samuel Thibault case KDSKBDIACRUC: 497247ff8e610cb63c015de19191db9666754c2ed79Alan Cox ret = vt_do_diacrit(cmd, up, perm); 4989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the ioctls below read/set the flags usually shown in the leds */ 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't use them - they will go away without warning */ 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGKBLED: 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSKBLED: 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDGETLED: 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSETLED: 506079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox ret = vt_do_kdskled(console, cmd, arg, perm); 5079cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * A process can indicate its willingness to accept signals 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * generated by pressing an appropriate key combination. 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Thus, one can have a daemon that e.g. spawns a new console 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * upon a keypress and then changes to it. 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See also the kbrequest field of inittab(5). 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDSIGACCEPT: 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm || !capable(CAP_KILL)) 5194001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 5207ed20e1ad521b5f5df61bf6559ae60738e393741Jesper Juhl if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) 5219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 5229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 5239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox spin_lock_irq(&vt_spawn_con.lock); 5249cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox put_pid(vt_spawn_con.pid); 5259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vt_spawn_con.pid = get_pid(task_pid(current)); 5269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vt_spawn_con.sig = arg; 5279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox spin_unlock_irq(&vt_spawn_con.lock); 5289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 5299cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_SETMODE: 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 5374001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 5389cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) { 5399cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 5409cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 5419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 54287a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) { 5439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 5449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox goto out; 5459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 546ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode = tmp; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* the frsig is ignored, so we set it to 0 */ 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 5508b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman put_pid(vc->vt_pid); 5518b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc->vt_pid = get_pid(task_pid(current)); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* no switch is required -- saw@shade.msu.ru */ 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 554ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 5559cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETMODE: 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_mode tmp; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 563ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode)); 565ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); 5689cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (rc) 5699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 5709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns global vt state. Note that VT 0 is always open, since 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it's an alias for the current VT, and people can't use it here. 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We cannot return state for more than 16 VTs, since v_state is short. 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_GETSTATE: 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_stat __user *vtstat = up; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned short state, mask; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5834001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox /* Review: FIXME: Console lock ? */ 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (put_user(fg_console + 1, &vtstat->v_active)) 5859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 5869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 5879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox state = 1; /* /dev/tty0 is always open */ 5889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; 5899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ++i, mask <<= 1) 5909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (VT_IS_IN_USE(i)) 5919cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox state |= mask; 5929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(state, &vtstat->v_state); 5939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 5949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Returns the first available (non-opened) console. 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_OPENQRY: 6014001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox /* FIXME: locking ? - but then this is a stupid API */ 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; ++i) 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_IS_IN_USE(i)) 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6051e0ad2881d50becaeea70ec696a80afeadf944d2Graham Gower uival = i < MAX_NR_CONSOLES ? (i+1) : -1; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto setint; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num, 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with num >= 1 (switches to vt 0, our console, are not allowed, just 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to preserve sanity). 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_ACTIVATE: 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6154001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 6179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 6189cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 6199cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox arg--; 620ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 6219cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = vc_allocate(arg); 622ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 6239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 6249cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox set_console(arg); 6269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 6279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 629d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox case VT_SETACTIVATE: 630d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox { 631d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox struct vt_setactivate vsa; 632d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox 633d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (!perm) 6344001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 635d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox 636d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg, 637a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby sizeof(struct vt_setactivate))) { 638a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby ret = -EFAULT; 639a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby goto out; 640a09efb07b5025fb75f42e903d31767a3cafede89Jiri Slaby } 641d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES) 642d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox ret = -ENXIO; 643d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox else { 644d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox vsa.console--; 645ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 646d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox ret = vc_allocate(vsa.console); 647d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (ret == 0) { 648d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox struct vc_data *nvc; 649d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox /* This is safe providing we don't drop the 650d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox console sem between vc_allocate and 651d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox finishing referencing nvc */ 652d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox nvc = vc_cons[vsa.console].d; 653d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox nvc->vt_mode = vsa.mode; 654d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox nvc->vt_mode.frsig = 0; 655d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox put_pid(nvc->vt_pid); 656d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox nvc->vt_pid = get_pid(task_pid(current)); 657d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox } 658ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 659d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox if (ret) 660d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox break; 661d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox /* Commence switch and lock */ 6624001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox /* Review set_console locks */ 663d637837583163a1a70331ce48097f697cac85e32Jiri Olsa set_console(vsa.console); 664d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox } 665d637837583163a1a70331ce48097f697cac85e32Jiri Olsa break; 666d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox } 667d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * wait until the specified VT has been activated 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_WAITACTIVE: 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6734001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0 || arg > MAX_NR_CONSOLES) 6759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 6764001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox else { 6774001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 6788b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox ret = vt_waitactive(arg); 6794001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 6804001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox } 6819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If a vt is under process control, the kernel will not switch to it 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * immediately, but postpone the operation until the process calls this 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ioctl, allowing the switch to complete. 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * According to the X sources this is the behavior: 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0: pending switch-from not OK 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1: pending switch-from OK 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2: completed switch-to OK 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RELDISP: 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 6954001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6974001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox console_lock(); 6989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (vc->vt_mode.mode != VT_PROCESS) { 6994001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox console_unlock(); 7009cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 7019cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7029cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switching-from response 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vt_newvt >= 0) { 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch disallowed, so forget we were trying 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to do it. 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The current vt has been released, so 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * complete the switch. 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int newvt; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds newvt = vc->vt_newvt; 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 7229cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = vc_allocate(newvt); 7239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) { 724ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 7259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * When we actually do the console switch, 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * make sure we are atomic with respect to 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * other console switches.. 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(vc_cons[newvt].d); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } else { 7359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* 7369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox * Switched-to response 7379cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox */ 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it's just an ACK, ignore it 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg != VT_ACKACQ) 7429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 744ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 7459cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Disallocate memory associated to VT (but leave VT1) 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_DISALLOCATE: 7519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (arg > MAX_NR_CONSOLES) { 7529cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENXIO; 7539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7549cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (arg == 0) { 756ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate all unused consoles, but leave 0 */ 757ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=1; i<MAX_NR_CONSOLES; i++) 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (! VT_BUSY(i)) 760ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox vc_deallocate(i); 761ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 763ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox /* deallocate a single console, if possible */ 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arg--; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (VT_BUSY(arg)) 7669cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EBUSY; 7679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else if (arg) { /* leave 0 */ 768ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 769ca9bda00b4aafc42cd3d1b9d32934463e2993b4cAlan Cox vc_deallocate(arg); 770ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7739cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZE: 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_sizes __user *vtsizes = up; 778e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas struct vc_data *vc; 779e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc; 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 7824001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (get_user(ll, &vtsizes->v_rows) || 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds get_user(cc, &vtsizes->v_cols)) 7859cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 7869cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else { 787ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 7889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox for (i = 0; i < MAX_NR_CONSOLES; i++) { 7899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vc = vc_cons[i].d; 790e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas 7919cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (vc) { 7929cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox vc->vc_resize_user = 1; 7934001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox /* FIXME: review v tty lock */ 7948c9a9dd0fa3a269d380eaae2dc1bee39e865fae1Alan Cox vc_resize(vc_cons[i].d, cc, ll); 7959cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 796e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas } 797ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 798e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas } 7999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_RESIZEX: 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vt_consize __user *vtconsize = up; 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ushort ll,cc,vlin,clin,vcol,ccol; 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8074001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, vtconsize, 8099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox sizeof(struct vt_consize))) { 8109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 8119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8129cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* FIXME: Should check the copies properly */ 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ll, &vtconsize->v_rows); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(cc, &vtconsize->v_cols); 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vlin, &vtconsize->v_vlin); 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(clin, &vtconsize->v_clin); 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(vcol, &vtconsize->v_vcol); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(ccol, &vtconsize->v_ccol); 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vlin = vlin ? vlin : vc->vc_scan_lines; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) { 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ll) { 8239cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ll != vlin/clin) { 8249cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox /* Parameters don't add up */ 8259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 8269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ll = vlin/clin; 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vcol && ccol) { 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cc) { 8339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (cc != vcol/ccol) { 8349cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 8359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cc = vcol/ccol; 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (clin > 32) { 8429cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EINVAL; 8439cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MAX_NR_CONSOLES; i++) { 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!vc_cons[i].d) 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 849ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vlin) 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_scan_lines = vlin; 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (clin) 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_cons[i].d->vc_font.height = clin; 854e400b6ec4ede4dc0aa8e5640425df5b29796fe0eAntonino A. Daplas vc_cons[i].d->vc_resize_user = 1; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc_resize(vc_cons[i].d, cc, ll); 856ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8589cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONT: { 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8634001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET; 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 0; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 8709cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 8719cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONT: { 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_GET; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.flags = KD_FONT_FLAG_OLD; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.width = 8; 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.height = 32; 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.charcount = 256; 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = up; 8819cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 8829cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_CMAP: 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 8879cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 8889cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox else 8899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_cmap(up); 8909cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_CMAP: 8939cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_cmap(up); 8949cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTX: 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_FONTX: 8989cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_fontx_ioctl(cmd, up, perm, &op); 8999cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_FONTRESET: 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9044001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BROKEN_GRAPHICS_PROGRAMS 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* With BROKEN_GRAPHICS_PROGRAMS defined, the default 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds font is not saved. */ 9099cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOSYS; 9109cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.op = KD_FONT_OP_SET_DEFAULT; 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds op.data = NULL; 9159cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc_cons[fg_console].d, &op); 9169cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 9179cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds con_set_default_unimap(vc_cons[fg_console].d); 9199cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case KDFONTOP: { 9259cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (copy_from_user(&op, up, sizeof(op))) { 9269cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 9279cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9289cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox } 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm && op.op != KD_FONT_OP_GET) 9304001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 9319cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_font_op(vc, &op); 9329cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox if (ret) 9339cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(up, &op, sizeof(op))) 9359cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EFAULT; 9369cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_SCRNMAP: 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9419cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 9424001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox else { 9434001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 9449cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_trans_old(up); 9454001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 9464001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox } 9479cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_SCRNMAP: 9504001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 9519cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_trans_old(up); 9524001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 9539cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNISCRNMAP: 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9579cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -EPERM; 9584001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox else { 9594001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 9609cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_set_trans_new(up); 9614001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 9624001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox } 9639cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNISCRNMAP: 9664001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 9679cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = con_get_trans_new(up); 9684001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 9699cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAPCLR: 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { struct unimapinit ui; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!perm) 9744001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 9759cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); 9763fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter if (ret) 9773fde85df5421eb01f563fef6f111ba73ab0d120eDan Carpenter ret = -EFAULT; 9784001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox else { 9794001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 9809cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox con_clear_unimap(vc, &ui); 9814001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 9824001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox } 9839cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PIO_UNIMAP: 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case GIO_UNIMAP: 9884001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 9899cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = do_unimap_ioctl(cmd, up, perm, vc); 9904001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 9919cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_LOCKSWITCH: 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 9954001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 1; 9979cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case VT_UNLOCKSWITCH: 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!capable(CAP_SYS_TTY_CONFIG)) 10004001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox return -EPERM; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vt_dont_switch = 0; 10029cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 1003533475d3d48eb839be2b57f6b020150abae91063Samuel Thibault case VT_GETHIFONTMASK: 10049cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = put_user(vc->vc_hi_font_mask, 10059cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox (unsigned short __user *)arg); 10069cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox break; 10078b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox case VT_WAITEVENT: 10088b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox ret = vt_event_wait_ioctl((struct vt_event __user *)arg); 10098b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox break; 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 10119cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox ret = -ENOIOCTLCMD; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10139cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Coxout: 10149cc3c22bf017f33612748aeb466fdc3695fb1e1dAlan Cox return ret; 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid reset_vc(struct vc_data *vc) 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vc_mode = KD_TEXT; 1020079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox vt_reset_unicode(vc->vc_num); 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.mode = VT_AUTO; 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.waitv = 0; 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.relsig = 0; 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.acqsig = 0; 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_mode.frsig = 0; 10268b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman put_pid(vc->vt_pid); 10278b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc->vt_pid = NULL; 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc->vt_newvt = -1; 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */ 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_palette(vc); 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10338b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biedermanvoid vc_SAK(struct work_struct *work) 10348b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman{ 10358b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct vc *vc_con = 10368b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman container_of(work, struct vc, SAK_work); 10378b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct vc_data *vc; 10388b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman struct tty_struct *tty; 10398b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman 1040ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 10418b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman vc = vc_con->d; 10428b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman if (vc) { 1043079c9534a96da9a85a2a2f9715851050fbfbf749Alan Cox /* FIXME: review tty ref counting */ 10448ce73264b75be4d5ed480440ac32dfc1f25ff678Alan Cox tty = vc->port.tty; 10458b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman /* 10468b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman * SAK should also work in all raw modes and reset 10478b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman * them properly. 10488b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman */ 10498b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman if (tty) 10508b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman __do_SAK(tty); 10518b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman reset_vc(vc); 10528b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman } 1053ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 10548b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman} 10558b6312f4dcc1efe7975731b6c47dd134282bd9acEric W. Biederman 1056e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#ifdef CONFIG_COMPAT 1057e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1058e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_consolefontdesc { 1059e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned short charcount; /* characters in font (256 or 512) */ 1060e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned short charheight; /* scan lines per character (1-32) */ 1061e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_caddr_t chardata; /* font data in expanded form */ 1062e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}; 1063e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1064e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int 1065e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_fontx_ioctl(int cmd, struct compat_consolefontdesc __user *user_cfd, 1066e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int perm, struct console_font_op *op) 1067e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{ 1068e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct compat_consolefontdesc cfdarg; 1069e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int i; 1070e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1071e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc))) 1072e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1073e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1074e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann switch (cmd) { 1075e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case PIO_FONTX: 1076e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!perm) 1077e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EPERM; 1078e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->op = KD_FONT_OP_SET; 1079e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->flags = KD_FONT_FLAG_OLD; 1080e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->width = 8; 1081e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->height = cfdarg.charheight; 1082e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->charcount = cfdarg.charcount; 1083e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->data = compat_ptr(cfdarg.chardata); 1084e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return con_font_op(vc_cons[fg_console].d, op); 1085e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case GIO_FONTX: 1086e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->op = KD_FONT_OP_GET; 1087e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->flags = KD_FONT_FLAG_OLD; 1088e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->width = 8; 1089e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->height = cfdarg.charheight; 1090e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->charcount = cfdarg.charcount; 1091e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->data = compat_ptr(cfdarg.chardata); 1092e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann i = con_font_op(vc_cons[fg_console].d, op); 1093e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (i) 1094e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return i; 1095e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann cfdarg.charheight = op->height; 1096e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann cfdarg.charcount = op->charcount; 1097e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc))) 1098e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1099e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return 0; 1100e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann } 1101e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EINVAL; 1102e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann} 1103e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1104e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_console_font_op { 1105e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_uint_t op; /* operation code KD_FONT_OP_* */ 1106e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_uint_t flags; /* KD_FONT_FLAG_* */ 1107e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_uint_t width, height; /* font size */ 1108e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_uint_t charcount; 1109e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_caddr_t data; /* font data with height fixed to 32 */ 1110e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}; 1111e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1112e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int 1113e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_kdfontop_ioctl(struct compat_console_font_op __user *fontop, 1114e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int perm, struct console_font_op *op, struct vc_data *vc) 1115e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{ 1116e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int i; 1117e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1118e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_from_user(op, fontop, sizeof(struct compat_console_font_op))) 1119e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1120e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!perm && op->op != KD_FONT_OP_GET) 1121e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EPERM; 1122e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann op->data = compat_ptr(((struct compat_console_font_op *)op)->data); 1123e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann i = con_font_op(vc, op); 1124e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (i) 1125e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return i; 1126e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann ((struct compat_console_font_op *)op)->data = (unsigned long)op->data; 1127e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_to_user(fontop, op, sizeof(struct compat_console_font_op))) 1128e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1129e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return 0; 1130e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann} 1131e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1132e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstruct compat_unimapdesc { 1133e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned short entry_ct; 1134e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann compat_caddr_t entries; 1135e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann}; 1136e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1137e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannstatic inline int 1138e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmanncompat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud, 1139e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int perm, struct vc_data *vc) 1140e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{ 1141e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct compat_unimapdesc tmp; 1142e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct unipair __user *tmp_entries; 1143e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1144e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (copy_from_user(&tmp, user_ud, sizeof tmp)) 1145e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1146e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann tmp_entries = compat_ptr(tmp.entries); 1147e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (tmp_entries) 1148e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!access_ok(VERIFY_WRITE, tmp_entries, 1149e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann tmp.entry_ct*sizeof(struct unipair))) 1150e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EFAULT; 1151e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann switch (cmd) { 1152e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case PIO_UNIMAP: 1153e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!perm) 1154e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EPERM; 1155e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return con_set_unimap(vc, tmp.entry_ct, tmp_entries); 1156e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case GIO_UNIMAP: 1157e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!perm && fg_console != vc->vc_num) 1158e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return -EPERM; 1159e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp_entries); 1160e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann } 1161e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return 0; 1162e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann} 1163e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 11646caa76b7786891b42b66a0e61e2c2fff2c884620Alan Coxlong vt_compat_ioctl(struct tty_struct *tty, 1165e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned int cmd, unsigned long arg) 1166e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann{ 1167e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct vc_data *vc = tty->driver_data; 1168e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann struct console_font_op op; /* used in multiple places here */ 1169e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann unsigned int console; 1170e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann void __user *up = (void __user *)arg; 1171e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int perm; 1172e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann int ret = 0; 1173e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1174e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann console = vc->vc_num; 1175e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1176e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (!vc_cons_allocated(console)) { /* impossible? */ 1177e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann ret = -ENOIOCTLCMD; 1178e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann goto out; 1179e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann } 1180e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1181e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann /* 1182e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * To have permissions to do most of the vt ioctls, we either have 1183e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. 1184e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann */ 1185e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann perm = 0; 1186e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG)) 1187e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann perm = 1; 1188e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1189e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann switch (cmd) { 1190e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann /* 1191e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * these need special handlers for incompatible data structures 1192e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann */ 1193e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case PIO_FONTX: 1194e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case GIO_FONTX: 1195e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann ret = compat_fontx_ioctl(cmd, up, perm, &op); 1196e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann break; 1197e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1198e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDFONTOP: 1199e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann ret = compat_kdfontop_ioctl(up, perm, &op, vc); 1200e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann break; 1201e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1202e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case PIO_UNIMAP: 1203e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case GIO_UNIMAP: 12044001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_lock(); 12054b1fe7797270e866adc17fc603bddf8768bc187fAndreas Schwab ret = compat_unimap_ioctl(cmd, up, perm, vc); 12064001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox tty_unlock(); 1207e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann break; 1208e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1209e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann /* 1210e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * all these treat 'arg' as an integer 1211e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann */ 1212e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KIOCSOUND: 1213e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDMKTONE: 1214e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#ifdef CONFIG_X86 1215e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDADDIO: 1216e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDDELIO: 1217e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#endif 1218e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSETMODE: 1219e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDMAPDISP: 1220e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDUNMAPDISP: 1221e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSKBMODE: 1222e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSKBMETA: 1223e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSKBLED: 1224e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSETLED: 1225e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case KDSIGACCEPT: 1226e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_ACTIVATE: 1227e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_WAITACTIVE: 1228e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_RELDISP: 1229e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_DISALLOCATE: 1230e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_RESIZE: 1231e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann case VT_RESIZEX: 1232e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann goto fallback; 1233e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1234e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann /* 1235e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * the rest has a compatible data structure behind arg, 1236e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann * but we have to convert it to a proper 64 bit pointer. 1237e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann */ 1238e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann default: 1239e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann arg = (unsigned long)compat_ptr(arg); 1240e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann goto fallback; 1241e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann } 1242e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannout: 1243e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann return ret; 1244e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1245e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmannfallback: 12466caa76b7786891b42b66a0e61e2c2fff2c884620Alan Cox return vt_ioctl(tty, cmd, arg); 1247e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann} 1248e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1249e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1250e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann#endif /* CONFIG_COMPAT */ 1251e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 1252e92166517e3ca9bfb416f91e69cf0373b55b6edeArnd Bergmann 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1254d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox * Performs the back end of a vt switch. Called under the console 1255d3b5cffcf84a8bdc7073dce4745d67c72629af85Alan Cox * semaphore. 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void complete_change_console(struct vc_data *vc) 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char old_vc_mode; 12608b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox int old = fg_console; 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_console = fg_console; 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we're switching, we could be going from KD_GRAPHICS to 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * KD_TEXT mode or vice versa, which means we need to blank or 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unblank the screen later. 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_vc_mode = vc_cons[fg_console].d->vc_mode; 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch_screen(vc); 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12733dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * This can't appear below a successful kill_pid(). If it did, 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * then the *blank_screen operation could occur while X, having 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * received acqsig, is waking up on another processor. This 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * condition can lead to overlapping accesses to the VGA range 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and the framebuffer (causing system lockups). 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To account for this we duplicate this code below only if the 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * controlling process is gone and we've called reset_vc. 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this new console is under process control, send it a signal 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * telling it that it has acquired. Also check if it has died and 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clean up (similar to logic employed in change_console()) 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 129487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman if (vc->vt_mode.mode == VT_PROCESS) { 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12963dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * Send the signal as privileged - kill_pid() will 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is awry 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1300bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) { 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The controlling process has died, so we revert back to 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * normal operation. In this case, we'll also change back 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to KD_TEXT mode. I'm not sure if this is strictly correct 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but it saves the agony when the X server dies and the screen 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * remains blanked due to KD_GRAPHICS! It would be nice to do 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this outside of VT_PROCESS but there is no single process 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to account for and tracking tty count may be undesirable. 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_vc(vc); 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (old_vc_mode != vc->vc_mode) { 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_TEXT) 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_unblank_screen(1); 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_blank_screen(1); 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wake anyone waiting for their VT to activate 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13248b92e87d39bfd046e7581e1fe0f40eac40f88608Alan Cox vt_event_post(VT_EVENT_SWITCH, old, vc->vc_num); 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Performs the front-end of a vt switch 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid change_console(struct vc_data *new_vc) 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct vc_data *vc; 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch) 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If this vt is in process mode, then we need to handshake with 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that process before switching. Essentially, we store where that 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt wants to switch to and wait for it to tell us when it's done 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (via VT_RELDISP ioctl). 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We also check to see if the controlling process still exists. 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If it doesn't, we reset this vt to auto mode and continue. 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is a cheap way to track process control. The worst thing 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that can happen is: we send a signal to a process, it dies, and 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the switch gets "lost" waiting for a response; hopefully, the 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * user will try again, we'll detect the process is gone (unless 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the user waits just the right amount of time :-) and revert the 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * vt to auto control. 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds vc = vc_cons[fg_console].d; 135487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman if (vc->vt_mode.mode == VT_PROCESS) { 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13563dfcaf16135150d0f025047a7525664a41bb2adfEric W. Biederman * Send the signal as privileged - kill_pid() will 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * tell us if the process has gone or something else 1358a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * is awry. 1359a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * 1360a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * We need to set vt_newvt *before* sending the signal or we 1361a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe * have a race. 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1363a64314e62d89562b6fc77593648bec3acc35bf61Jan Lübbe vc->vt_newvt = new_vc->vc_num; 1364bde0d2c98bcfc9acc83ac79c33a6ac1335b95a92Eric W. Biederman if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) { 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 136687a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * It worked. Mark the vt to switch to and 136787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * return. The process needs to send us a 136887a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * VT_RELDISP ioctl to complete the switch. 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 137087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman return; 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 137487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * The controlling process has died, so we revert back to 137587a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * normal operation. In this case, we'll also change back 137687a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * to KD_TEXT mode. I'm not sure if this is strictly correct 137787a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * but it saves the agony when the X server dies and the screen 137887a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * remains blanked due to KD_GRAPHICS! It would be nice to do 137987a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * this outside of VT_PROCESS but there is no single process 138087a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * to account for and tracking tty count may be undesirable. 138187a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman */ 138287a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman reset_vc(vc); 138387a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman 138487a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman /* 138587a6aca504d65f242589583e04df5e74b5eae1feGreg Kroah-Hartman * Fall through to normal (VT_AUTO) handling of the switch... 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ignore all switches in KD_GRAPHICS+VT_AUTO mode 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (vc->vc_mode == KD_GRAPHICS) 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds complete_change_console(new_vc); 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13978d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 13988d233558cd99a888571bb5a88a74970879e0aba4Alan Cox/* Perform a kernel triggered VT switch for suspend/resume */ 13998d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 14008d233558cd99a888571bb5a88a74970879e0aba4Alan Coxstatic int disable_vt_switch; 14018d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 14028d233558cd99a888571bb5a88a74970879e0aba4Alan Coxint vt_move_to_console(unsigned int vt, int alloc) 14038d233558cd99a888571bb5a88a74970879e0aba4Alan Cox{ 14048d233558cd99a888571bb5a88a74970879e0aba4Alan Cox int prev; 14058d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 1406ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 14078d233558cd99a888571bb5a88a74970879e0aba4Alan Cox /* Graphics mode - up to X */ 14088d233558cd99a888571bb5a88a74970879e0aba4Alan Cox if (disable_vt_switch) { 1409ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 14108d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return 0; 14118d233558cd99a888571bb5a88a74970879e0aba4Alan Cox } 14128d233558cd99a888571bb5a88a74970879e0aba4Alan Cox prev = fg_console; 14138d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 14148d233558cd99a888571bb5a88a74970879e0aba4Alan Cox if (alloc && vc_allocate(vt)) { 14158d233558cd99a888571bb5a88a74970879e0aba4Alan Cox /* we can't have a free VC for now. Too bad, 14168d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * we don't want to mess the screen for now. */ 1417ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 14188d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return -ENOSPC; 14198d233558cd99a888571bb5a88a74970879e0aba4Alan Cox } 14208d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 14218d233558cd99a888571bb5a88a74970879e0aba4Alan Cox if (set_console(vt)) { 14228d233558cd99a888571bb5a88a74970879e0aba4Alan Cox /* 14238d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * We're unable to switch to the SUSPEND_CONSOLE. 14248d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * Let the calling function know so it can decide 14258d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * what to do. 14268d233558cd99a888571bb5a88a74970879e0aba4Alan Cox */ 1427ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 14288d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return -EIO; 14298d233558cd99a888571bb5a88a74970879e0aba4Alan Cox } 1430ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 14314001d7b7fc271052ebff43f327c26dc64806bbdfAlan Cox /* Review: I don't see why we need tty_lock here FIXME */ 1432be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann tty_lock(); 1433797938b5e33991dadf4dd9228b932cc69c3e905aJiri Slaby if (vt_waitactive(vt + 1)) { 14348d233558cd99a888571bb5a88a74970879e0aba4Alan Cox pr_debug("Suspend: Can't switch VCs."); 1435be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann tty_unlock(); 14368d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return -EINTR; 14378d233558cd99a888571bb5a88a74970879e0aba4Alan Cox } 1438be1bc2889a4db4961ef69f47fb471ecae9f23adeArnd Bergmann tty_unlock(); 14398d233558cd99a888571bb5a88a74970879e0aba4Alan Cox return prev; 14408d233558cd99a888571bb5a88a74970879e0aba4Alan Cox} 14418d233558cd99a888571bb5a88a74970879e0aba4Alan Cox 14428d233558cd99a888571bb5a88a74970879e0aba4Alan Cox/* 14438d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * Normally during a suspend, we allocate a new console and switch to it. 14448d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * When we resume, we switch back to the original console. This switch 14458d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * can be slow, so on systems where the framebuffer can handle restoration 14468d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * of video registers anyways, there's little point in doing the console 14478d233558cd99a888571bb5a88a74970879e0aba4Alan Cox * switch. This function allows you to disable it by passing it '0'. 14488d233558cd99a888571bb5a88a74970879e0aba4Alan Cox */ 14498d233558cd99a888571bb5a88a74970879e0aba4Alan Coxvoid pm_set_vt_switch(int do_switch) 14508d233558cd99a888571bb5a88a74970879e0aba4Alan Cox{ 1451ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 14528d233558cd99a888571bb5a88a74970879e0aba4Alan Cox disable_vt_switch = !do_switch; 1453ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 14548d233558cd99a888571bb5a88a74970879e0aba4Alan Cox} 14558d233558cd99a888571bb5a88a74970879e0aba4Alan CoxEXPORT_SYMBOL(pm_set_vt_switch); 1456