^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 1992 obz under the linux copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Some code moved for less code duplication - Andi Kleen - Mar 1997
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/tty.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/kd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/vt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/console.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/consolemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/timex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/nospec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <linux/kbd_kern.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <linux/vt_kern.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <linux/kbd_diacr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <linux/selection.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) bool vt_dont_switch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static inline bool vt_in_use(unsigned int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) const struct vc_data *vc = vc_cons[i].d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * console_lock must be held to prevent the vc from being deallocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * while we're checking whether it's in-use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) WARN_CONSOLE_UNLOCKED();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return vc && kref_read(&vc->port.kref) > 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static inline bool vt_busy(int i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (vt_in_use(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (i == fg_console)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (vc_is_sel(vc_cons[i].d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * experimentation and study of X386 SYSV handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * to the current console is done by the main ioctl code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <asm/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static void complete_change_console(struct vc_data *vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * User space VT_EVENT handlers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct vt_event_wait {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct vt_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static LIST_HEAD(vt_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static DEFINE_SPINLOCK(vt_event_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static DECLARE_WAIT_QUEUE_HEAD(vt_event_waitqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * vt_event_post
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * @event: the event that occurred
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @old: old console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @new: new console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * Post an VT event to interested VT handlers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) void vt_event_post(unsigned int event, unsigned int old, unsigned int new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct list_head *pos, *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int wake = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) spin_lock_irqsave(&vt_event_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) head = &vt_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) list_for_each(pos, head) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct vt_event_wait *ve = list_entry(pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct vt_event_wait, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!(ve->event.event & event))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ve->event.event = event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* kernel view is consoles 0..n-1, user space view is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) console 1..n with 0 meaning current, so we must bias */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ve->event.oldev = old + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ve->event.newev = new + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) wake = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ve->done = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) spin_unlock_irqrestore(&vt_event_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (wake)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) wake_up_interruptible(&vt_event_waitqueue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static void __vt_event_queue(struct vt_event_wait *vw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* Prepare the event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) INIT_LIST_HEAD(&vw->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) vw->done = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* Queue our event */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) spin_lock_irqsave(&vt_event_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) list_add(&vw->list, &vt_events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) spin_unlock_irqrestore(&vt_event_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static void __vt_event_wait(struct vt_event_wait *vw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) /* Wait for it to pass */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) wait_event_interruptible(vt_event_waitqueue, vw->done);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) static void __vt_event_dequeue(struct vt_event_wait *vw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* Dequeue it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) spin_lock_irqsave(&vt_event_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) list_del(&vw->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) spin_unlock_irqrestore(&vt_event_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * vt_event_wait - wait for an event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @vw: our event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Waits for an event to occur which completes our vt_event_wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * structure. On return the structure has wv->done set to 1 for success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * or 0 if some event such as a signal ended the wait.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static void vt_event_wait(struct vt_event_wait *vw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) __vt_event_queue(vw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) __vt_event_wait(vw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) __vt_event_dequeue(vw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * vt_event_wait_ioctl - event ioctl handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @event: argument to ioctl (the event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Implement the VT_WAITEVENT ioctl using the VT event interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static int vt_event_wait_ioctl(struct vt_event __user *event)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct vt_event_wait vw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (copy_from_user(&vw.event, event, sizeof(struct vt_event)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* Highest supported event for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (vw.event.event & ~VT_MAX_EVENT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) vt_event_wait(&vw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* If it occurred report it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (vw.done) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (copy_to_user(event, &vw.event, sizeof(struct vt_event)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * vt_waitactive - active console wait
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * @n: new console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * Helper for event waits. Used to implement the legacy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * event waiting ioctls in terms of events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int vt_waitactive(int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct vt_event_wait vw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) vw.event.event = VT_EVENT_SWITCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) __vt_event_queue(&vw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (n == fg_console + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) __vt_event_dequeue(&vw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) __vt_event_wait(&vw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) __vt_event_dequeue(&vw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (vw.done == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) } while (vw.event.newev != n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * these are the valid i/o ports we're allowed to change. they map all the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * video ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #define GPFIRST 0x3b4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define GPLAST 0x3df
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define GPNUM (GPLAST - GPFIRST + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * currently, setting the mode from KD_TEXT to KD_GRAPHICS doesn't do a whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * lot. i'm not sure if it should do any restoration of modes or what...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * XXX It should at least call into the driver, fbdev's definitely need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * restore their engine state. --BenH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Called with the console lock held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) switch (mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case KD_GRAPHICS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case KD_TEXT0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case KD_TEXT1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) mode = KD_TEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case KD_TEXT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (vc->vc_mode == mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) vc->vc_mode = mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (vc->vc_num != fg_console)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) /* explicitly blank/unblank the screen if switching modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (mode == KD_TEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) do_unblank_screen(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) do_blank_screen(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) unsigned long arg, bool perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct vc_data *vc = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) void __user *up = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) unsigned int console = vc->vc_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) case KIOCSOUND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * The use of PIT_TICK_RATE is historic, it used to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * the platform-dependent CLOCK_TICK_RATE between 2.6.12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * and 2.6.36, which was a minor but unfortunate ABI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * change. kd_mksound is locked by the input layer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) arg = PIT_TICK_RATE / arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) kd_mksound(arg, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) case KDMKTONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) unsigned int ticks, count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * Generate the tone for the appropriate number of ticks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * If the time is zero, turn off sound ourselves.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ticks = msecs_to_jiffies((arg >> 16) & 0xffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) count = ticks ? (arg & 0xffff) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) count = PIT_TICK_RATE / count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) kd_mksound(count, ticks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) case KDGKBTYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * this is naïve.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return put_user(KB_101, (char __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * These cannot be implemented on any machine that implements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * ioperm() in user level (such as Alpha PCs) or not at all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) * XXX: you should never use these, just call ioperm directly..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) case KDADDIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) case KDDELIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * KDADDIO and KDDELIO may be able to add ports beyond what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * we reject here, but to be safe...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * These are locked internally via sys_ioperm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (arg < GPFIRST || arg > GPLAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case KDENABIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case KDDISABIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return ksys_ioperm(GPFIRST, GPNUM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) (cmd == KDENABIO)) ? -ENXIO : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) case KDKBDREP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) struct kbd_repeat kbrep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (!capable(CAP_SYS_TTY_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ret = kbd_rate(&kbrep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) case KDSETMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) ret = vt_kdsetmode(vc, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) case KDGETMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return put_user(vc->vc_mode, (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) case KDMAPDISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) case KDUNMAPDISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * these work like a combination of mmap and KDENABIO.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * this could be easily finished.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case KDSKBMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) ret = vt_do_kdskbmode(console, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) tty_ldisc_flush(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) case KDGKBMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return put_user(vt_do_kdgkbmode(console), (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) /* this could be folded into KDSKBMODE, but for compatibility
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) case KDSKBMETA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) return vt_do_kdskbmeta(console, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) case KDGKBMETA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) /* FIXME: should review whether this is worth locking */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) return put_user(vt_do_kdgkbmeta(console), (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) case KDGETKEYCODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) case KDSETKEYCODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if(!capable(CAP_SYS_TTY_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) perm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return vt_do_kbkeycode_ioctl(cmd, up, perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) case KDGKBENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) case KDSKBENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return vt_do_kdsk_ioctl(cmd, up, perm, console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) case KDGKBSENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case KDSKBSENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) return vt_do_kdgkb_ioctl(cmd, up, perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* Diacritical processing. Handled in keyboard.c as it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) to operate on the keyboard locks and structures */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case KDGKBDIACR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) case KDGKBDIACRUC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) case KDSKBDIACR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) case KDSKBDIACRUC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return vt_do_diacrit(cmd, up, perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) /* the ioctls below read/set the flags usually shown in the leds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /* don't use them - they will go away without warning */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) case KDGKBLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) case KDSKBLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) case KDGETLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) case KDSETLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return vt_do_kdskled(console, cmd, arg, perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) * A process can indicate its willingness to accept signals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * generated by pressing an appropriate key combination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * Thus, one can have a daemon that e.g. spawns a new console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * upon a keypress and then changes to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * See also the kbrequest field of inittab(5).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) case KDSIGACCEPT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (!perm || !capable(CAP_KILL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) spin_lock_irq(&vt_spawn_con.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) put_pid(vt_spawn_con.pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) vt_spawn_con.pid = get_pid(task_pid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) vt_spawn_con.sig = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) spin_unlock_irq(&vt_spawn_con.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) case KDFONTOP: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) struct console_font_op op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (copy_from_user(&op, up, sizeof(op)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (!perm && op.op != KD_FONT_OP_GET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) ret = con_font_op(vc, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (copy_to_user(up, &op, sizeof(op)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) static inline int do_fontx_ioctl(struct vc_data *vc, int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct consolefontdesc __user *user_cfd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct console_font_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) struct consolefontdesc cfdarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) case PIO_FONTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) op->op = KD_FONT_OP_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) op->flags = KD_FONT_FLAG_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) op->width = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) op->height = cfdarg.charheight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) op->charcount = cfdarg.charcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) op->data = cfdarg.chardata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return con_font_op(vc, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) case GIO_FONTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) op->op = KD_FONT_OP_GET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) op->flags = KD_FONT_FLAG_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) op->width = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) op->height = cfdarg.charheight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) op->charcount = cfdarg.charcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) op->data = cfdarg.chardata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) i = con_font_op(vc, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) cfdarg.charheight = op->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) cfdarg.charcount = op->charcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) static int vt_io_fontreset(struct vc_data *vc, struct console_font_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (__is_defined(BROKEN_GRAPHICS_PROGRAMS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * With BROKEN_GRAPHICS_PROGRAMS defined, the default font is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * not saved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) op->op = KD_FONT_OP_SET_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) op->data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ret = con_font_op(vc, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) con_set_default_unimap(vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) bool perm, struct vc_data *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct unimapdesc tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (copy_from_user(&tmp, user_ud, sizeof tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) case PIO_UNIMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) case GIO_UNIMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!perm && fg_console != vc->vc_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) tmp.entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) bool perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) struct console_font_op op; /* used in multiple places here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) case PIO_FONT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) op.op = KD_FONT_OP_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) op.width = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) op.height = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) op.charcount = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) op.data = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return con_font_op(vc, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) case GIO_FONT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) op.op = KD_FONT_OP_GET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) op.flags = KD_FONT_FLAG_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) op.width = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) op.height = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) op.charcount = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) op.data = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return con_font_op(vc, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case PIO_CMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) return con_set_cmap(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case GIO_CMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) return con_get_cmap(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) case PIO_FONTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) case GIO_FONTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) return do_fontx_ioctl(vc, cmd, up, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) case PIO_FONTRESET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return vt_io_fontreset(vc, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) case PIO_SCRNMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return con_set_trans_old(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) case GIO_SCRNMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return con_get_trans_old(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) case PIO_UNISCRNMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) return con_set_trans_new(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) case GIO_UNISCRNMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return con_get_trans_new(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) case PIO_UNIMAPCLR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) con_clear_unimap(vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case PIO_UNIMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) case GIO_UNIMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) return do_unimap_ioctl(cmd, up, perm, vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) static int vt_reldisp(struct vc_data *vc, unsigned int swtch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) int newvt, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (vc->vt_mode.mode != VT_PROCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /* Switched-to response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) if (vc->vt_newvt < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) /* If it's just an ACK, ignore it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return swtch == VT_ACKACQ ? 0 : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) /* Switching-from response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (swtch == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* Switch disallowed, so forget we were trying to do it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) vc->vt_newvt = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) /* The current vt has been released, so complete the switch. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) newvt = vc->vt_newvt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) vc->vt_newvt = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ret = vc_allocate(newvt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * When we actually do the console switch, make sure we are atomic with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * respect to other console switches..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) complete_change_console(vc_cons[newvt].d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static int vt_setactivate(struct vt_setactivate __user *sa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) struct vt_setactivate vsa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) struct vc_data *nvc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (copy_from_user(&vsa, sa, sizeof(vsa)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) vsa.console--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) ret = vc_allocate(vsa.console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * This is safe providing we don't drop the console sem between
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * vc_allocate and finishing referencing nvc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) nvc = vc_cons[vsa.console].d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) nvc->vt_mode = vsa.mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) nvc->vt_mode.frsig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) put_pid(nvc->vt_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) nvc->vt_pid = get_pid(task_pid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /* Commence switch and lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) /* Review set_console locks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) set_console(vsa.console);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* deallocate a single console, if possible (leave 0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) static int vt_disallocate(unsigned int vc_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct vc_data *vc = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (vt_busy(vc_num))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) ret = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) else if (vc_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) vc = vc_deallocate(vc_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (vc && vc_num >= MIN_NR_CONSOLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) tty_port_put(&vc->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* deallocate all unused consoles, but leave 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) static void vt_disallocate_all(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct vc_data *vc[MAX_NR_CONSOLES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) for (i = 1; i < MAX_NR_CONSOLES; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (!vt_busy(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) vc[i] = vc_deallocate(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) vc[i] = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) for (i = 1; i < MAX_NR_CONSOLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (vc[i] && i >= MIN_NR_CONSOLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) tty_port_put(&vc[i]->port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) struct vt_consize v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (copy_from_user(&v, cs, sizeof(struct vt_consize)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) /* FIXME: Should check the copies properly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (!v.v_vlin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) v.v_vlin = vc->vc_scan_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (v.v_clin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) int rows = v.v_vlin / v.v_clin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (v.v_rows != rows) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) if (v.v_rows) /* Parameters don't add up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) v.v_rows = rows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (v.v_vcol && v.v_ccol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) int cols = v.v_vcol / v.v_ccol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (v.v_cols != cols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) if (v.v_cols)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) v.v_cols = cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (v.v_clin > 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) for (i = 0; i < MAX_NR_CONSOLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct vc_data *vcp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (!vc_cons[i].d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) vcp = vc_cons[i].d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) if (vcp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) int save_scan_lines = vcp->vc_scan_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) int save_cell_height = vcp->vc_cell_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (v.v_vlin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) vcp->vc_scan_lines = v.v_vlin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (v.v_clin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) vcp->vc_cell_height = v.v_clin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) vcp->vc_resize_user = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) ret = vc_resize(vcp, v.v_cols, v.v_rows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) vcp->vc_scan_lines = save_scan_lines;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) vcp->vc_cell_height = save_cell_height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * We handle the console-specific ioctl's here. We allow the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * capability to modify any console, not just the fg_console.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) int vt_ioctl(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) struct vc_data *vc = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) void __user *up = (void __user *)arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) int i, perm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * To have permissions to do most of the vt ioctls, we either have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) perm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) perm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) ret = vt_k_ioctl(tty, cmd, arg, perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if (ret != -ENOIOCTLCMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) ret = vt_io_ioctl(vc, cmd, up, perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (ret != -ENOIOCTLCMD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) case TIOCLINUX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return tioclinux(tty, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) case VT_SETMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) struct vt_mode tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (copy_from_user(&tmp, up, sizeof(struct vt_mode)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) vc->vt_mode = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) /* the frsig is ignored, so we set it to 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) vc->vt_mode.frsig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) put_pid(vc->vt_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) vc->vt_pid = get_pid(task_pid(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /* no switch is required -- saw@shade.msu.ru */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) vc->vt_newvt = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) case VT_GETMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct vt_mode tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * Returns global vt state. Note that VT 0 is always open, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) * it's an alias for the current VT, and people can't use it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * We cannot return state for more than 16 VTs, since v_state is short.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) case VT_GETSTATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) struct vt_stat __user *vtstat = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) unsigned short state, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) if (put_user(fg_console + 1, &vtstat->v_active))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) state = 1; /* /dev/tty0 is always open */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) console_lock(); /* required by vt_in_use() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ++i, mask <<= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (vt_in_use(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) state |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) return put_user(state, &vtstat->v_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * Returns the first available (non-opened) console.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) case VT_OPENQRY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) console_lock(); /* required by vt_in_use() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) for (i = 0; i < MAX_NR_CONSOLES; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (!vt_in_use(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) i = i < MAX_NR_CONSOLES ? (i+1) : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return put_user(i, (int __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) * with num >= 1 (switches to vt 0, our console, are not allowed, just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) * to preserve sanity).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case VT_ACTIVATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) if (arg == 0 || arg > MAX_NR_CONSOLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) arg--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) arg = array_index_nospec(arg, MAX_NR_CONSOLES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) ret = vc_allocate(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) set_console(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case VT_SETACTIVATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) return vt_setactivate(up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * wait until the specified VT has been activated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) case VT_WAITACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) if (arg == 0 || arg > MAX_NR_CONSOLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return vt_waitactive(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) * If a vt is under process control, the kernel will not switch to it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) * immediately, but postpone the operation until the process calls this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) * ioctl, allowing the switch to complete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * According to the X sources this is the behavior:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * 0: pending switch-from not OK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) * 1: pending switch-from OK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * 2: completed switch-to OK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case VT_RELDISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) ret = vt_reldisp(vc, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * Disallocate memory associated to VT (but leave VT1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) case VT_DISALLOCATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (arg > MAX_NR_CONSOLES)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (arg == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) vt_disallocate_all();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return vt_disallocate(--arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) case VT_RESIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) struct vt_sizes __user *vtsizes = up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) struct vc_data *vc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) ushort ll,cc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (get_user(ll, &vtsizes->v_rows) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) get_user(cc, &vtsizes->v_cols))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) for (i = 0; i < MAX_NR_CONSOLES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) vc = vc_cons[i].d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (vc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) vc->vc_resize_user = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) /* FIXME: review v tty lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) vc_resize(vc_cons[i].d, cc, ll);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) case VT_RESIZEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return vt_resizex(vc, up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) case VT_LOCKSWITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) if (!capable(CAP_SYS_TTY_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) vt_dont_switch = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) case VT_UNLOCKSWITCH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (!capable(CAP_SYS_TTY_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) vt_dont_switch = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) case VT_GETHIFONTMASK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return put_user(vc->vc_hi_font_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) (unsigned short __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) case VT_WAITEVENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return vt_event_wait_ioctl((struct vt_event __user *)arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) return -ENOIOCTLCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) void reset_vc(struct vc_data *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) vc->vc_mode = KD_TEXT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) vt_reset_unicode(vc->vc_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) vc->vt_mode.mode = VT_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) vc->vt_mode.waitv = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) vc->vt_mode.relsig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) vc->vt_mode.acqsig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) vc->vt_mode.frsig = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) put_pid(vc->vt_pid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) vc->vt_pid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) vc->vt_newvt = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) if (!in_interrupt()) /* Via keyboard.c:SAK() - akpm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) reset_palette(vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) void vc_SAK(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) struct vc *vc_con =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) container_of(work, struct vc, SAK_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) struct vc_data *vc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) struct tty_struct *tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) vc = vc_con->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (vc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) /* FIXME: review tty ref counting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) tty = vc->port.tty;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) * SAK should also work in all raw modes and reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) * them properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if (tty)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) __do_SAK(tty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) reset_vc(vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) #ifdef CONFIG_COMPAT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) struct compat_consolefontdesc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) unsigned short charcount; /* characters in font (256 or 512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) unsigned short charheight; /* scan lines per character (1-32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) compat_caddr_t chardata; /* font data in expanded form */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) compat_fontx_ioctl(struct vc_data *vc, int cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) struct compat_consolefontdesc __user *user_cfd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) int perm, struct console_font_op *op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) struct compat_consolefontdesc cfdarg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) case PIO_FONTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) op->op = KD_FONT_OP_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) op->flags = KD_FONT_FLAG_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) op->width = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) op->height = cfdarg.charheight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) op->charcount = cfdarg.charcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) op->data = compat_ptr(cfdarg.chardata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return con_font_op(vc, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) case GIO_FONTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) op->op = KD_FONT_OP_GET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) op->flags = KD_FONT_FLAG_OLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) op->width = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) op->height = cfdarg.charheight;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) op->charcount = cfdarg.charcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) op->data = compat_ptr(cfdarg.chardata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) i = con_font_op(vc, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) cfdarg.charheight = op->height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) cfdarg.charcount = op->charcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) struct compat_console_font_op {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) compat_uint_t op; /* operation code KD_FONT_OP_* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) compat_uint_t flags; /* KD_FONT_FLAG_* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) compat_uint_t width, height; /* font size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) compat_uint_t charcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) compat_caddr_t data; /* font data with height fixed to 32 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) int perm, struct console_font_op *op, struct vc_data *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (copy_from_user(op, fontop, sizeof(struct compat_console_font_op)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (!perm && op->op != KD_FONT_OP_GET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) i = con_font_op(vc, op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) ((struct compat_console_font_op *)op)->data = (unsigned long)op->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (copy_to_user(fontop, op, sizeof(struct compat_console_font_op)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct compat_unimapdesc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) unsigned short entry_ct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) compat_caddr_t entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) static inline int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) compat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) int perm, struct vc_data *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct compat_unimapdesc tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) struct unipair __user *tmp_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) if (copy_from_user(&tmp, user_ud, sizeof tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) tmp_entries = compat_ptr(tmp.entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) case PIO_UNIMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (!perm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) return con_set_unimap(vc, tmp.entry_ct, tmp_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) case GIO_UNIMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (!perm && fg_console != vc->vc_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) return -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) long vt_compat_ioctl(struct tty_struct *tty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) unsigned int cmd, unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct vc_data *vc = tty->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) struct console_font_op op; /* used in multiple places here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) void __user *up = compat_ptr(arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) int perm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) * To have permissions to do most of the vt ioctls, we either have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) perm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) perm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * these need special handlers for incompatible data structures
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) case PIO_FONTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) case GIO_FONTX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) return compat_fontx_ioctl(vc, cmd, up, perm, &op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) case KDFONTOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return compat_kdfontop_ioctl(up, perm, &op, vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) case PIO_UNIMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) case GIO_UNIMAP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) return compat_unimap_ioctl(cmd, up, perm, vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) * all these treat 'arg' as an integer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) case KIOCSOUND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) case KDMKTONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) #ifdef CONFIG_X86
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) case KDADDIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) case KDDELIO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) case KDSETMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) case KDMAPDISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) case KDUNMAPDISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) case KDSKBMODE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) case KDSKBMETA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) case KDSKBLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) case KDSETLED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) case KDSIGACCEPT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) case VT_ACTIVATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) case VT_WAITACTIVE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) case VT_RELDISP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) case VT_DISALLOCATE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) case VT_RESIZE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) case VT_RESIZEX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) return vt_ioctl(tty, cmd, arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) * the rest has a compatible data structure behind arg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * but we have to convert it to a proper 64 bit pointer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) return vt_ioctl(tty, cmd, (unsigned long)up);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) #endif /* CONFIG_COMPAT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * Performs the back end of a vt switch. Called under the console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) * semaphore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) static void complete_change_console(struct vc_data *vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) unsigned char old_vc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) int old = fg_console;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) last_console = fg_console;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) * If we're switching, we could be going from KD_GRAPHICS to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) * KD_TEXT mode or vice versa, which means we need to blank or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) * unblank the screen later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) old_vc_mode = vc_cons[fg_console].d->vc_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) switch_screen(vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) * This can't appear below a successful kill_pid(). If it did,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) * then the *blank_screen operation could occur while X, having
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * received acqsig, is waking up on another processor. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) * condition can lead to overlapping accesses to the VGA range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * and the framebuffer (causing system lockups).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) * To account for this we duplicate this code below only if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) * controlling process is gone and we've called reset_vc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (old_vc_mode != vc->vc_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (vc->vc_mode == KD_TEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) do_unblank_screen(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) do_blank_screen(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) * If this new console is under process control, send it a signal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) * telling it that it has acquired. Also check if it has died and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) * clean up (similar to logic employed in change_console())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (vc->vt_mode.mode == VT_PROCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) * Send the signal as privileged - kill_pid() will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) * tell us if the process has gone or something else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) * is awry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) * The controlling process has died, so we revert back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) * normal operation. In this case, we'll also change back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * to KD_TEXT mode. I'm not sure if this is strictly correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) * but it saves the agony when the X server dies and the screen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * remains blanked due to KD_GRAPHICS! It would be nice to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * this outside of VT_PROCESS but there is no single process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) * to account for and tracking tty count may be undesirable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) reset_vc(vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (old_vc_mode != vc->vc_mode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) if (vc->vc_mode == KD_TEXT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) do_unblank_screen(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) do_blank_screen(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) * Wake anyone waiting for their VT to activate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) vt_event_post(VT_EVENT_SWITCH, old, vc->vc_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) * Performs the front-end of a vt switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) void change_console(struct vc_data *new_vc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) struct vc_data *vc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) * If this vt is in process mode, then we need to handshake with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) * that process before switching. Essentially, we store where that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) * vt wants to switch to and wait for it to tell us when it's done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) * (via VT_RELDISP ioctl).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) * We also check to see if the controlling process still exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) * If it doesn't, we reset this vt to auto mode and continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) * This is a cheap way to track process control. The worst thing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) * that can happen is: we send a signal to a process, it dies, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * the switch gets "lost" waiting for a response; hopefully, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * user will try again, we'll detect the process is gone (unless
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * the user waits just the right amount of time :-) and revert the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) * vt to auto control.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) vc = vc_cons[fg_console].d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) if (vc->vt_mode.mode == VT_PROCESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * Send the signal as privileged - kill_pid() will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) * tell us if the process has gone or something else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) * is awry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * We need to set vt_newvt *before* sending the signal or we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) * have a race.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) vc->vt_newvt = new_vc->vc_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * It worked. Mark the vt to switch to and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * return. The process needs to send us a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) * VT_RELDISP ioctl to complete the switch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * The controlling process has died, so we revert back to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) * normal operation. In this case, we'll also change back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * to KD_TEXT mode. I'm not sure if this is strictly correct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) * but it saves the agony when the X server dies and the screen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * remains blanked due to KD_GRAPHICS! It would be nice to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) * this outside of VT_PROCESS but there is no single process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) * to account for and tracking tty count may be undesirable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) reset_vc(vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) * Fall through to normal (VT_AUTO) handling of the switch...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) if (vc->vc_mode == KD_GRAPHICS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) complete_change_console(new_vc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) /* Perform a kernel triggered VT switch for suspend/resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) static int disable_vt_switch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) int vt_move_to_console(unsigned int vt, int alloc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) int prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) /* Graphics mode - up to X */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (disable_vt_switch) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) prev = fg_console;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) if (alloc && vc_allocate(vt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) /* we can't have a free VC for now. Too bad,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) * we don't want to mess the screen for now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (set_console(vt)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) * We're unable to switch to the SUSPEND_CONSOLE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) * Let the calling function know so it can decide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) * what to do.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) if (vt_waitactive(vt + 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) pr_debug("Suspend: Can't switch VCs.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) return prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) * Normally during a suspend, we allocate a new console and switch to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) * When we resume, we switch back to the original console. This switch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) * can be slow, so on systems where the framebuffer can handle restoration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) * of video registers anyways, there's little point in doing the console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) * switch. This function allows you to disable it by passing it '0'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) void pm_set_vt_switch(int do_switch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) console_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) disable_vt_switch = !do_switch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) console_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) EXPORT_SYMBOL(pm_set_vt_switch);