#include <linux/workqueue.h>
#include <linux/bootmem.h>
#include <linux/pm.h>
+#include <linux/font.h>
#include <asm/io.h>
#include <asm/system.h>
* kernel memory allocation is available.
*/
char con_buf[PAGE_SIZE];
-#define CON_BUF_SIZE PAGE_SIZE
DECLARE_MUTEX(con_buf_sem);
/* acquires console_sem */
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);
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);
#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.
*/