From: Aivils S. <ai...@us...> - 2004-08-24 05:32:38
|
Update of /cvsroot/linuxconsole/ruby/ruby-2.6/drivers/char In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27075/ruby-2.6/drivers/char Modified Files: Kconfig Makefile keyboard.c tty_io.c vc_screen.c vt.c vt_ioctl.c Log Message: sync to 2.6.8 Index: Kconfig =================================================================== RCS file: /cvsroot/linuxconsole/ruby/ruby-2.6/drivers/char/Kconfig,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- Kconfig 17 Jun 2004 10:44:52 -0000 1.9 +++ Kconfig 24 Aug 2004 05:31:53 -0000 1.10 @@ -210,7 +210,7 @@ config ISI tristate "Multi-Tech multiport card support (EXPERIMENTAL)" - depends on SERIAL_NONSTANDARD && EXPERIMENTAL && BROKEN_ON_SMP && m + depends on SERIAL_NONSTANDARD && PCI && EXPERIMENTAL && BROKEN_ON_SMP && m help This is a driver for the Multi-Tech cards which provide several serial ports. The driver is experimental and can currently only be @@ -219,7 +219,7 @@ config SYNCLINK tristate "Microgate SyncLink card support" - depends on SERIAL_NONSTANDARD + depends on SERIAL_NONSTANDARD && PCI help Provides support for the SyncLink ISA and PCI multiprotocol serial adapters. These adapters support asynchronous and HDLC bit @@ -356,7 +356,7 @@ module will be called istallion. config SERIAL_TX3912 - bool "TMPTX3912/PR31700 serial port support" + bool "TX3912/PR31700 serial port support" depends on SERIAL_NONSTANDARD && MIPS && BROKEN_ON_SMP help The TX3912 is a Toshiba RISC processor based o the MIPS 3900 core; @@ -364,7 +364,7 @@ Say Y here to enable kernel support for the on-board serial port. config SERIAL_TX3912_CONSOLE - bool "Console on TMPTX3912/PR31700 serial port" + bool "Console on TX3912/PR31700 serial port" depends on SERIAL_TX3912 help The TX3912 is a Toshiba RISC processor based o the MIPS 3900 core; @@ -378,22 +378,6 @@ If you have an Alchemy AU1000 processor (MIPS based) and you want to use serial ports, say Y. Otherwise, say N. -config SGI_L1_SERIAL - bool "SGI Altix L1 serial support" - depends on SERIAL_NONSTANDARD && IA64 - help - If you have an SGI Altix and you want to use the serial port - connected to the system controller (you want this!), say Y. - Otherwise, say N. - -config SGI_L1_SERIAL_CONSOLE - bool "SGI Altix L1 serial console support" - depends on SGI_L1_SERIAL - help - If you have an SGI Altix and you would like to use the system - controller serial port as your console (you want this!), - say Y. Otherwise, say N. - config AU1000_SERIAL_CONSOLE bool "Enable Au1000 serial console" depends on AU1000_UART @@ -593,16 +577,22 @@ console. This driver allows each pSeries partition to have a console which is accessed via the HMC. -config PC9800_OLDLP - tristate "NEC PC-9800 old-style printer port support" - depends on X86_PC9800 && !PARPORT - ---help--- - If you intend to attach a printer to the parallel port of NEC PC-9801 - /PC-9821 with OLD compatibility mode, Say Y. +config HVCS + tristate "IBM Hypervisor Virtual Console Server support" + depends on PPC_PSERIES + help + Partitionable IBM Power5 ppc64 machines allow hosting of + firmware virtual consoles from one Linux partition by + another Linux partition. This driver allows console data + from Linux partitions to be accessed through TTY device + interfaces in the device tree of a Linux partition running + this driver. -config PC9800_OLDLP_CONSOLE - bool "Support for console on line printer" - depends on PC9800_OLDLP + To compile this driver as a module, choose M here: the + module will be called hvcs.ko. Additionally, this module + will depend on arch specific APIs exported from hvcserver.ko + which will also be compiled when this driver is built as a + module. config QIC02_TAPE tristate "QIC-02 tape support" @@ -747,7 +737,7 @@ config RTC tristate "Enhanced Real Time Clock Support" - depends on !PPC32 && !PARISC && !IA64 && !X86_PC9800 && !M68K + depends on !PPC32 && !PARISC && !IA64 && !M68K ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you @@ -771,6 +761,28 @@ To compile this driver as a module, choose M here: the module will be called rtc. +config SGI_DS1286 + tristate "SGI DS1286 RTC support" + depends on SGI_IP22 + help + If you say Y here and create a character special file /dev/rtc with + major number 10 and minor number 135 using mknod ("man mknod"), you + will get access to the real time clock built into your computer. + Every SGI has such a clock built in. It reports status information + via the file /proc/rtc and its behaviour is set by various ioctls on + /dev/rtc. + +config SGI_IP27_RTC + bool "SGI M48T35 RTC support" + depends on SGI_IP27 + help + If you say Y here and create a character special file /dev/rtc with + major number 10 and minor number 135 using mknod ("man mknod"), you + will get access to the real time clock built into your computer. + Every SGI has such a clock built in. It reports status information + via the file /proc/rtc and its behaviour is set by various ioctls on + /dev/rtc. + config GEN_RTC tristate "Generic /dev/rtc emulation" depends on RTC!=y && !IA64 @@ -800,24 +812,12 @@ bool "EFI Real Time Clock Services" depends on IA64 -config RTC98 - tristate "NEC PC-9800 Real Time Clock Support" - depends on X86_PC9800 - default y - ---help--- - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock (or hardware clock) built - -config H8 - bool "Tadpole ANA H8 Support (OBSOLETE)" - depends on OBSOLETE && ALPHA_BOOK1 +config COBALT_LCD + bool "Support for Cobalt LCD" + depends on MIPS_COBALT help - The Hitachi H8/337 is a microcontroller used to deal with the power - and thermal environment. If you say Y here, you will be able to - communicate with it via a character special device. - - If unsure, say N. + This option enables support for the LCD display and buttons found + on Cobalt systems through a misc device. config DTLK tristate "Double Talk PC internal speech card support" @@ -843,6 +843,7 @@ config APPLICOM tristate "Applicom intelligent fieldbus card support" + depends on PCI ---help--- This driver provides the kernel-side support for the intelligent fieldbus cards made by Applicom International. More information @@ -873,7 +874,7 @@ config FTAPE tristate "Ftape (QIC-80/Travan) support" - depends on BROKEN_ON_SMP + depends on BROKEN_ON_SMP && (ALPHA || X86) ---help--- If you have a tape drive that is connected to your floppy controller, say Y here. @@ -964,6 +965,37 @@ kernels. Applications should simply open the device (eg /dev/hda1) with the O_DIRECT flag. +config HPET + bool "HPET - High Precision Event Timer" if (X86 || IA64) + default n + depends on ACPI + help + If you say Y here, you will have a miscdevice named "/dev/hpet/". Each + open selects one of the timers supported by the HPET. The timers are + non-periodioc and/or periodic. + +config HPET_RTC_IRQ + bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC + default n + depends on HPET + help + If you say Y here, you will disable RTC_IRQ in drivers/char/rtc.c. It + is assumed the platform called hpet_alloc with the RTC IRQ values for + the HPET timers. + +config HPET_MMAP + bool "Allow mmap of HPET" + default y + depends on HPET + help + If you say Y here, user applications will be able to mmap + the HPET registers. + + In some hardware implementations, the page containing HPET + registers may also contain other things that shouldn't be + exposed to the user. If this applies to your hardware, + say N here. + config MAX_RAW_DEVS int "Maximum number of RAW devices to support (1-8192)" depends on RAW_DRIVER Index: Makefile =================================================================== RCS file: /cvsroot/linuxconsole/ruby/ruby-2.6/drivers/char/Makefile,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- Makefile 17 Jun 2004 10:44:52 -0000 1.10 +++ Makefile 24 Aug 2004 05:31:53 -0000 1.11 @@ -41,21 +41,23 @@ obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o obj-$(CONFIG_RAW_DRIVER) += raw.o -obj-$(CONFIG_SGI_L1_SERIAL) += sn_serial.o obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o +obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o -obj-$(CONFIG_PC9800_OLDLP) += lp_old98.o obj-$(CONFIG_DTLK) += dtlk.o obj-$(CONFIG_R3964) += n_r3964.o obj-$(CONFIG_APPLICOM) += applicom.o obj-$(CONFIG_SONYPI) += sonypi.o obj-$(CONFIG_RTC) += rtc.o +obj-$(CONFIG_HPET) += hpet.o obj-$(CONFIG_GEN_RTC) += genrtc.o obj-$(CONFIG_EFI_RTC) += efirtc.o +obj-$(CONFIG_SGI_DS1286) += ds1286.o +obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o ifeq ($(CONFIG_GENERIC_NVRAM),y) obj-$(CONFIG_NVRAM) += generic_nvram.o else @@ -67,7 +69,7 @@ obj-$(CONFIG_HW_RANDOM) += hw_random.o obj-$(CONFIG_QIC02_TAPE) += tpqic02.o obj-$(CONFIG_FTAPE) += ftape/ -obj-$(CONFIG_H8) += h8.o +obj-$(CONFIG_COBALT_LCD) += lcd.o obj-$(CONFIG_PPDEV) += ppdev.o obj-$(CONFIG_NWBUTTON) += nwbutton.o obj-$(CONFIG_NWFLASH) += nwflash.o Index: keyboard.c =================================================================== RCS file: /cvsroot/linuxconsole/ruby/ruby-2.6/drivers/char/keyboard.c,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- keyboard.c 20 Feb 2004 06:52:18 -0000 1.13 +++ keyboard.c 24 Aug 2004 05:31:53 -0000 1.14 @@ -888,7 +888,7 @@ } } -#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SH_MPC1211) +#if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) || defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) static unsigned short x86_keycodes[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, Index: tty_io.c =================================================================== RCS file: /cvsroot/linuxconsole/ruby/ruby-2.6/drivers/char/tty_io.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- tty_io.c 17 Jun 2004 10:44:52 -0000 1.11 +++ tty_io.c 24 Aug 2004 05:31:53 -0000 1.12 @@ -91,6 +91,7 @@ #include <linux/module.h> #include <linux/smp_lock.h> #include <linux/device.h> +#include <linux/idr.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -128,6 +129,8 @@ #ifdef CONFIG_UNIX98_PTYS extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ extern int pty_limit; /* Config limit on Unix98 ptys */ +static DEFINE_IDR(allocated_ptys); +static DECLARE_MUTEX(allocated_ptys_lock); #endif extern void disable_early_printk(void); @@ -342,18 +345,12 @@ static ssize_t hung_up_tty_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { - /* Can't seek (pread) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; return 0; } static ssize_t hung_up_tty_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { - /* Can't seek (pwrite) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; return -EIO; } @@ -645,10 +642,6 @@ struct tty_struct * tty; struct inode *inode; - /* Can't seek (pread) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; - tty = (struct tty_struct *)file->private_data; inode = file->f_dentry->d_inode; if (tty_paranoia_check(tty, inode, "tty_read")) @@ -723,10 +716,6 @@ struct tty_struct * tty; struct inode *inode = file->f_dentry->d_inode; - /* Can't seek (pwrite) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; - tty = (struct tty_struct *)file->private_data; if (tty_paranoia_check(tty, inode, "tty_write")) return -EIO; @@ -752,9 +741,6 @@ if (p) { ssize_t res; - /* Can't seek (pwrite) on ttys. */ - if (ppos != &file->f_pos) - return -ESPIPE; res = vfs_write(p, buf, count, &p->f_pos); fput(p); return res; @@ -1065,6 +1051,7 @@ { struct tty_struct *tty, *o_tty; int pty_master, tty_closing, o_tty_closing, do_sleep; + int devpts_master, devpts; int idx; char buf[64]; @@ -1079,6 +1066,8 @@ idx = tty->index; pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER); + devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; + devpts_master = pty_master && devpts; o_tty = tty->link; #ifdef TTY_PARANOIA_CHECK @@ -1295,11 +1284,21 @@ o_tty->ldisc = ldiscs[N_TTY]; } - /* + /* * The release_mem function takes care of the details of clearing * the slots and preserving the termios structure. */ release_mem(tty, idx); + +#ifdef CONFIG_UNIX98_PTYS + /* Make this pty number available for reallocation */ + if (devpts) { + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, idx); + up(&allocated_ptys_lock); + } +#endif + } /* @@ -1322,8 +1321,13 @@ int index; dev_t device = inode->i_rdev; unsigned short saved_flags = filp->f_flags; + + nonseekable_open(inode, filp); retry_open: noctty = filp->f_flags & O_NOCTTY; + index = -1; + retval = 0; + if (device == MKDEV(TTYAUX_MAJOR,0)) { if (!current->signal->tty) return -ENXIO; @@ -1353,13 +1357,8 @@ } #endif if (device == MKDEV(TTYAUX_MAJOR,1)) { - struct console *c = console_drivers; - for (c = console_drivers; c; c = c->next) { - if (!c->device) - continue; - driver = c->device(c, &index); - if (!driver) - continue; + driver = console_device(&index); + if (driver) { /* Don't let /dev/console block */ filp->f_flags |= O_NONBLOCK; noctty = 1; @@ -1370,24 +1369,40 @@ #ifdef CONFIG_UNIX98_PTYS if (device == MKDEV(TTYAUX_MAJOR,2)) { + int idr_ret; + /* find a device that is not in use. */ - static int next_ptmx_dev = 0; - retval = -1; + down(&allocated_ptys_lock); + if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { + up(&allocated_ptys_lock); + return -ENOMEM; + } + idr_ret = idr_get_new(&allocated_ptys, NULL, &index); + if (idr_ret < 0) { + up(&allocated_ptys_lock); + if (idr_ret == -EAGAIN) + return -ENOMEM; + return -EIO; + } + if (index >= pty_limit) { + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return -EIO; + } + up(&allocated_ptys_lock); + driver = ptm_driver; - while (driver->refcount < pty_limit) { - index = next_ptmx_dev; - next_ptmx_dev = (next_ptmx_dev+1) % driver->num; - if (!init_dev(driver, index, &tty)) - goto ptmx_found; /* ok! */ + retval = init_dev(driver, index, &tty); + if (retval) { + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return retval; } - return -EIO; /* no free ptys */ - ptmx_found: + set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ - if (devpts_pty_new(tty->link)) { - /* BADNESS - need to destroy both ptm and pts! */ - return -ENOMEM; - } - noctty = 1; + if (devpts_pty_new(tty->link)) + retval = -ENOMEM; } else #endif { @@ -1409,10 +1424,12 @@ #ifdef TTY_DEBUG_HANGUP printk(KERN_DEBUG "opening %s...", tty->name); #endif - if (tty->driver->open) - retval = tty->driver->open(tty, filp); - else - retval = -ENODEV; + if (!retval) { + if (tty->driver->open) + retval = tty->driver->open(tty, filp); + else + retval = -ENODEV; + } filp->f_flags = saved_flags; if (!retval && test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) @@ -1424,6 +1441,14 @@ tty->name); #endif +#ifdef CONFIG_UNIX98_PTYS + if (index != -1) { + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + } +#endif + release_dev(filp); if (retval != -ERESTARTSYS) return retval; Index: vc_screen.c =================================================================== RCS file: /cvsroot/linuxconsole/ruby/ruby-2.6/drivers/char/vc_screen.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- vc_screen.c 17 Jun 2004 10:44:52 -0000 1.6 +++ vc_screen.c 24 Aug 2004 05:31:53 -0000 1.7 @@ -103,11 +103,11 @@ { int size; - lock_kernel(); + down(&con_buf_sem); size = vcs_size(file->f_dentry->d_inode); switch (orig) { default: - unlock_kernel(); + up(&con_buf_sem); return -EINVAL; case 2: offset += size; @@ -118,29 +118,21 @@ break; } if (offset < 0 || offset > size) { - unlock_kernel(); + up(&con_buf_sem); return -EINVAL; } file->f_pos = offset; - unlock_kernel(); + up(&con_buf_sem); return file->f_pos; } -/* We share this temporary buffer with the console write code - * so that we can easily avoid touching user space while holding the - * console spinlock. - */ -//extern char con_buf[PAGE_SIZE]; -#define CON_BUF_SIZE PAGE_SIZE -extern struct semaphore con_buf_sem; - static ssize_t vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; unsigned int currcons = iminor(inode); struct vc_data *vc; - long pos = *ppos; + long pos; long viewed, attr, read; int col, maxcol; unsigned short *org = NULL; @@ -148,6 +140,8 @@ down(&con_buf_sem); + pos = *ppos; + /* Select the proper current console and verify * sanity of the situation under the console lock. */ @@ -311,7 +305,7 @@ struct inode *inode = file->f_dentry->d_inode; unsigned int currcons = iminor(inode); struct vc_data *vc; - long pos = *ppos; + long pos; long viewed, attr, size, written; char *con_buf0; int col, maxcol; @@ -320,6 +314,8 @@ down(&con_buf_sem); + pos = *ppos; + /* Select the proper current console and verify * sanity of the situation under the console lock. */ Index: vt.c =================================================================== RCS file: /cvsroot/linuxconsole/ruby/ruby-2.6/drivers/char/vt.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- vt.c 17 Jun 2004 10:44:52 -0000 1.20 +++ vt.c 24 Aug 2004 05:31:53 -0000 1.21 @@ -99,6 +99,7 @@ #include <linux/workqueue.h> #include <linux/bootmem.h> #include <linux/pm.h> +#include <linux/font.h> #include <asm/io.h> #include <asm/system.h> @@ -1205,7 +1206,6 @@ * kernel memory allocation is available. */ //char con_buf[PAGE_SIZE]; -#define CON_BUF_SIZE PAGE_SIZE DECLARE_MUTEX(con_buf_sem); static int do_con_write(struct tty_struct *tty, int from_user, @@ -1958,6 +1958,10 @@ if (vc) { old_was_color = vc->vc_can_do_color; cons_num = vt->first_vc + i; + origin = (unsigned long) screenbuf; + visible_origin = origin; + scr_end = origin + screenbuf_size; + pos = origin + video_size_row*y + 2*x; visual_init(vc, 0); update_attr(vc); Index: vt_ioctl.c =================================================================== RCS file: /cvsroot/linuxconsole/ruby/ruby-2.6/drivers/char/vt_ioctl.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- vt_ioctl.c 17 Jun 2004 10:44:52 -0000 1.8 +++ vt_ioctl.c 24 Aug 2004 05:31:53 -0000 1.9 @@ -30,6 +30,7 @@ #include <linux/vt_kern.h> #include <linux/kbd_diacr.h> #include <linux/selection.h> +#include <linux/font.h> #define VT_IS_IN_USE(vc)(vc->vc_tty && vc->vc_tty->count) #define VT_BUSY(vc) (VT_IS_IN_USE(vc) || IS_VISIBLE || vc->vc_num == sel_cons) @@ -128,7 +129,7 @@ /* disallocate map */ key_map = key_maps[s]; if (s && key_map) { - key_maps[s] = 0; + key_maps[s] = NULL; if (key_map[0] == U(K_ALLOCATED)) { kfree(key_map); keymap_count--; @@ -328,94 +329,180 @@ #define max_font_size 65536 -int con_font_op(struct vc_data *vc, struct console_font_op *op) +int con_font_get(struct vc_data *vc, struct console_font_op *op) { - struct console_font_op old_op; - int size = max_font_size, set; + struct console_font font; int rc = -EINVAL; - u8 *temp = NULL; + int c; if (vc->vc_mode != KD_TEXT) - goto quit; - memcpy(&old_op, op, sizeof(old_op)); - if (op->op == KD_FONT_OP_SET) { - if (!op->data) - return -EINVAL; - if (op->charcount > 512) - goto quit; - if (!op->height) {/* Need to guess font height [compat] */ - int h, i; - u8 __user *charmap = op->data; - u8 tmp; + return -EINVAL; - /* If from KDFONTOP ioctl, don't allow things which can - be done in userland, - so that we can get rid of this soon */ - if (!(op->flags & KD_FONT_FLAG_OLD)) - goto quit; - rc = -EFAULT; - for (h = 32; h > 0; h--) - for (i = 0; i < op->charcount; i++) { - if (get_user(tmp, &charmap[32*i+h-1])) - goto quit; - if (tmp) - goto nonzero; - } - rc = -EINVAL; - goto quit; - nonzero: - rc = -EINVAL; - op->height = h; - } - if (op->width > 32 || op->height > 32) - goto quit; - size = (op->width+7)/8 * 32 * op->charcount; - if (size > max_font_size) - return -ENOSPC; - set = 1; - } else if (op->op == KD_FONT_OP_GET) - set = 0; - else - return vc->display_fg->vt_sw->con_font_op(vc, op); if (op->data) { - temp = kmalloc(size, GFP_KERNEL); - if (!temp) + font.data = kmalloc(max_font_size, GFP_KERNEL); + if (!font.data) return -ENOMEM; - if (set && copy_from_user(temp, op->data, size)) { - rc = -EFAULT; - goto quit; - } - op->data = temp; - } + } else + font.data = NULL; acquire_console_sem(); - rc = vc->display_fg->vt_sw->con_font_op(vc, op); + if (vc->display_fg->vt_sw->con_font_get) + rc = vc->display_fg->vt_sw->con_font_get(vc, &font); + else + rc = -ENOSYS; release_console_sem(); - op->data = old_op.data; - if (!rc && !set) { - int c = (op->width+7)/8 * 32 * op->charcount; + if (rc) + goto out; - if (op->data && op->charcount > old_op.charcount) + c = (font.width+7)/8 * 32 * font.charcount; + + if (op->data && font.charcount > op->charcount) + rc = -ENOSPC; + if (!(op->flags & KD_FONT_FLAG_OLD)) { + if (font.width > op->width || font.height > op->height) + rc = -ENOSPC; + } else { + if (font.width != 8) + rc = -EIO; + else if ((op->height && font.height > op->height) || + font.height > 32) rc = -ENOSPC; - if (!(op->flags & KD_FONT_FLAG_OLD)) { - if (op->width > old_op.width || - op->height > old_op.height) - rc = -ENOSPC; - } else { - if (op->width != 8) - rc = -EIO; - else if ((old_op.height && op->height > old_op.height) || op->height > 32) - rc = -ENOSPC; - } - if (!rc && op->data && copy_to_user(op->data, temp, c)) - rc = -EFAULT; } -quit: if (temp) - kfree(temp); + if (rc) + goto out; + + if (op->data && copy_to_user(op->data, font.data, c)) + rc = -EFAULT; + +out: + kfree(font.data); return rc; } +int con_font_set(struct vc_data *vc, struct console_font_op *op) +{ + struct console_font font; + int rc = -EINVAL; + int size; + + if (vc->vc_mode != KD_TEXT) + return -EINVAL; + if (!op->data) + return -EINVAL; + if (op->charcount > 512) + return -EINVAL; + if (!op->height) { /* Need to guess font height [compat] */ + int h, i; + u8 __user *charmap = op->data; + u8 tmp; + + /* If from KDFONTOP ioctl, don't allow things which can be done in userland, + so that we can get rid of this soon */ + if (!(op->flags & KD_FONT_FLAG_OLD)) + return -EINVAL; + for (h = 32; h > 0; h--) + for (i = 0; i < op->charcount; i++) { + if (get_user(tmp, &charmap[32*i+h-1])) + return -EFAULT; + if (tmp) + goto nonzero; + } + return -EINVAL; + nonzero: + op->height = h; + } + if (op->width <= 0 || op->width > 32 || op->height > 32) + return -EINVAL; + size = (op->width+7)/8 * 32 * op->charcount; + if (size > max_font_size) + return -ENOSPC; + font.charcount = op->charcount; + font.height = op->height; + font.width = op->width; + font.data = kmalloc(size, GFP_KERNEL); + if (!font.data) + return -ENOMEM; + if (copy_from_user(font.data, op->data, size)) { + kfree(font.data); + return -EFAULT; + } + acquire_console_sem(); + if (vc->display_fg->vt_sw->con_font_set) + rc = vc->display_fg->vt_sw->con_font_set(vc, &font, op->flags); + else + rc = -ENOSYS; + release_console_sem(); + kfree(font.data); + return rc; +} + +int con_font_default(struct vc_data *vc, struct console_font_op *op) +{ + struct console_font font = {.width = op->width, .height = op->height}; + char name[MAX_FONT_NAME]; + char *s = name; + int rc; + + if (vc->vc_mode != KD_TEXT) + return -EINVAL; + + if (!op->data) + s = NULL; + else if (strncpy_from_user(name, op->data, MAX_FONT_NAME - 1) < 0) + return -EFAULT; + else + name[MAX_FONT_NAME - 1] = 0; + + acquire_console_sem(); + if (vc->display_fg->vt_sw->con_font_default) + rc = vc->display_fg->vt_sw->con_font_default(vc, &font, s); + else + rc = -ENOSYS; + release_console_sem(); + if (!rc) { + op->width = font.width; + op->height = font.height; + } + return rc; +} + +int con_font_copy(struct vc_data *vc, struct console_font_op *op) +{ + int con = op->height; + int rc; + + if (vc->vc_mode != KD_TEXT) + return -EINVAL; + + acquire_console_sem(); + if (!vc->display_fg->vt_sw->con_font_copy) + rc = -ENOSYS; + else if (!find_vc(con)) + rc = -ENOTTY; + else if (con == vc->vc_num) /* nothing to do */ + rc = 0; + else + rc = vc->display_fg->vt_sw->con_font_copy(vc, con); + release_console_sem(); + return rc; +} + +int con_font_op(struct vc_data *vc, struct console_font_op *op) +{ + switch (op->op) { + case KD_FONT_OP_SET: + return con_font_set(vc, op); + case KD_FONT_OP_GET: + return con_font_get(vc, op); + case KD_FONT_OP_SET_DEFAULT: + return con_font_default(vc, op); + case KD_FONT_OP_COPY: + return con_font_copy(vc, op); + } + return -ENOSYS; +} + static inline int do_fontx_ioctl(struct vc_data *vc, struct console_font_op *op, struct consolefontdesc __user *user_cfd, int cmd, int perm) { @@ -1259,7 +1346,7 @@ op.width = 8; op.height = 0; op.charcount = 256; - op.data = (char *) arg; + op.data = up; return con_font_op(vc, &op); case GIO_FONT: @@ -1268,7 +1355,7 @@ op.width = 8; op.height = 32; op.charcount = 256; - op.data = (char *) arg; + op.data = up; return con_font_op(vc, &op); case PIO_CMAP: |