VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / char / vt.c
index 521b6fb..a204572 100644 (file)
 #include <linux/workqueue.h>
 #include <linux/bootmem.h>
 #include <linux/pm.h>
+#include <linux/font.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -1865,7 +1866,6 @@ static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
  * kernel memory allocation is available.
  */
 char con_buf[PAGE_SIZE];
-#define CON_BUF_SIZE   PAGE_SIZE
 DECLARE_MUTEX(con_buf_sem);
 
 /* acquires console_sem */
@@ -2499,7 +2499,7 @@ static void con_close(struct tty_struct *tty, struct file *filp)
                vt = tty->driver_data;
                if (vt)
                        vc_cons[vt->vc_num].d->vc_tty = NULL;
-               tty->driver_data = 0;
+               tty->driver_data = NULL;
                release_console_sem();
                vcs_remove_devfs(tty);
                up(&tty_sem);
@@ -2712,6 +2712,10 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
                        save_screen(i);
                old_was_color = vc_cons[i].d->vc_can_do_color;
                vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
+               origin = (unsigned long) screenbuf;
+               visible_origin = origin;
+               scr_end = origin + screenbuf_size;
+               pos = origin + video_size_row*y + 2*x;
                visual_init(i, 0);
                update_attr(i);
 
@@ -3020,98 +3024,182 @@ void reset_palette(int currcons)
 
 #define max_font_size 65536
 
-int con_font_op(int currcons, struct console_font_op *op)
+int con_font_get(int currcons, struct console_font_op *op)
 {
+       struct console_font font;
        int rc = -EINVAL;
-       int size = max_font_size, set;
-       u8 *temp = NULL;
-       struct console_font_op old_op;
+       int c;
 
        if (vt_cons[currcons]->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;
-                       
-                       /* 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 {
-               acquire_console_sem();
-               rc = sw->con_font_op(vc_cons[currcons].d, op);
-               release_console_sem();
-               return rc;
-       }
+               return -EINVAL;
+
        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 = sw->con_font_op(vc_cons[currcons].d, op);
+       if (sw->con_font_get)
+               rc = sw->con_font_get(vc_cons[currcons].d, &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 (op->data && op->charcount > old_op.charcount)
+       if (rc)
+               goto out;
+
+       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;
-               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;
+       } else {
+               if (font.width != 8)
+                       rc = -EIO;
+               else if ((op->height && font.height > op->height) ||
+                        font.height > 32)
+                       rc = -ENOSPC;
+       }
+       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(int currcons, struct console_font_op *op)
+{
+       struct console_font font;
+       int rc = -EINVAL;
+       int size;
+
+       if (vt_cons[currcons]->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;
        }
-quit:  if (temp)
-               kfree(temp);
+       acquire_console_sem();
+       if (sw->con_font_set)
+               rc = sw->con_font_set(vc_cons[currcons].d, &font, op->flags);
+       else
+               rc = -ENOSYS;
+       release_console_sem();
+       kfree(font.data);
        return rc;
 }
 
+int con_font_default(int currcons, 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 (vt_cons[currcons]->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 (sw->con_font_default)
+               rc = sw->con_font_default(vc_cons[currcons].d, &font, s);
+       else
+               rc = -ENOSYS;
+       release_console_sem();
+       if (!rc) {
+               op->width = font.width;
+               op->height = font.height;
+       }
+       return rc;
+}
+
+int con_font_copy(int currcons, struct console_font_op *op)
+{
+       int con = op->height;
+       struct vc_data *vc;
+       int rc;
+
+       if (vt_cons[currcons]->vc_mode != KD_TEXT)
+               return -EINVAL;
+
+       acquire_console_sem();
+       vc = vc_cons[currcons].d;
+       if (!sw->con_font_copy)
+               rc = -ENOSYS;
+       else if (con < 0 || !vc_cons_allocated(con))
+               rc = -ENOTTY;
+       else if (con == vc->vc_num)     /* nothing to do */
+               rc = 0;
+       else
+               rc = sw->con_font_copy(vc, con);
+       release_console_sem();
+       return rc;
+}
+
+int con_font_op(int currcons, struct console_font_op *op)
+{
+       switch (op->op) {
+       case KD_FONT_OP_SET:
+               return con_font_set(currcons, op);
+       case KD_FONT_OP_GET:
+               return con_font_get(currcons, op);
+       case KD_FONT_OP_SET_DEFAULT:
+               return con_font_default(currcons, op);
+       case KD_FONT_OP_COPY:
+               return con_font_copy(currcons, op);
+       }
+       return -ENOSYS;
+}
+
 /*
  *     Interface exported to selection and vcs.
  */