Commit a95b87ea authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] con_font_op split

Preparations for cleanups: con_font_op() is turned into a switch calling
con_font_{get,set,default,copy} depending on the operation required;
method ->con_font_op() also split, with NULL resulting in -ENOSYS on
operation in question.

Code that used to be in con_font_op() got slightly cleaned up after move
into new helpers (we are beginning to untangle the mess; there will be
more cleanups in the next patches).

Methods are currently using exact same arguments as old ->con_font_op().
That will change in subsequent patches, method by method (right now there's
a hell of a scary field reuse between them, making impossible to do any
static checks and practically begging for bugs).
Signed-off-by: default avatarAl Viro <viro@parcelfarce.linux.org.uk>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 3c9841b9
......@@ -3023,98 +3023,167 @@ 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_op old_op;
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;
return -EINVAL;
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;
}
if (op->data) {
temp = kmalloc(size, GFP_KERNEL);
temp = kmalloc(max_font_size, GFP_KERNEL);
if (!temp)
return -ENOMEM;
if (set && copy_from_user(temp, op->data, size)) {
rc = -EFAULT;
goto quit;
}
op->data = temp;
}
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, op);
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 = (op->width+7)/8 * 32 * op->charcount;
if (op->data && op->charcount > old_op.charcount)
rc = -ENOSPC;
if (!(op->flags & KD_FONT_FLAG_OLD)) {
if (op->width > old_op.width ||
op->height > old_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 (op->width != 8)
rc = -EIO;
else if ((old_op.height && op->height > old_op.height) ||
op->height > 32)
rc = -ENOSPC;
}
if (rc)
goto out;
if (op->data && copy_to_user(op->data, temp, c))
rc = -EFAULT;
out:
kfree(temp);
return rc;
}
int con_font_set(int currcons, struct console_font_op *op)
{
struct console_font_op old_op;
int rc = -EINVAL;
int size;
u8 *temp;
if (vt_cons[currcons]->vc_mode != KD_TEXT)
return -EINVAL;
memcpy(&old_op, op, sizeof(old_op));
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;
}
quit: if (temp)
kfree(temp);
if (op->width > 32 || op->height > 32)
return -EINVAL;
size = (op->width+7)/8 * 32 * op->charcount;
if (size > max_font_size)
return -ENOSPC;
temp = kmalloc(size, GFP_KERNEL);
if (!temp)
return -ENOMEM;
if (copy_from_user(temp, op->data, size)) {
rc = -EFAULT;
goto out;
}
op->data = temp;
acquire_console_sem();
if (sw->con_font_set)
rc = sw->con_font_set(vc_cons[currcons].d, op);
else
rc = -ENOSYS;
release_console_sem();
op->data = old_op.data;
out:
kfree(temp);
return rc;
}
int con_font_default(int currcons, struct console_font_op *op)
{
int rc;
if (vt_cons[currcons]->vc_mode != KD_TEXT)
return -EINVAL;
acquire_console_sem();
if (sw->con_font_default)
rc = sw->con_font_default(vc_cons[currcons].d, op);
else
rc = -ENOSYS;
release_console_sem();
return rc;
}
int con_font_copy(int currcons, struct console_font_op *op)
{
int rc;
if (vt_cons[currcons]->vc_mode != KD_TEXT)
return -EINVAL;
acquire_console_sem();
if (sw->con_font_copy)
rc = sw->con_font_copy(vc_cons[currcons].d, op);
else
rc = -ENOSYS;
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.
*/
......
......@@ -71,7 +71,10 @@ const struct consw dummy_con = {
.con_bmove = DUMMY,
.con_switch = DUMMY,
.con_blank = DUMMY,
.con_font_op = DUMMY,
.con_font_set = DUMMY,
.con_font_get = DUMMY,
.con_font_default = DUMMY,
.con_font_copy = DUMMY,
.con_set_palette = DUMMY,
.con_scrolldelta = DUMMY,
};
......@@ -165,7 +165,6 @@ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
int height, int width);
static int fbcon_switch(struct vc_data *vc);
static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch);
static int fbcon_font_op(struct vc_data *vc, struct console_font_op *op);
static int fbcon_set_palette(struct vc_data *vc, unsigned char *table);
static int fbcon_scrolldelta(struct vc_data *vc, int lines);
void accel_clear_margins(struct vc_data *vc, struct fb_info *info,
......@@ -2001,7 +2000,7 @@ static void fbcon_free_font(struct display *p)
p->userfont = 0;
}
static inline int fbcon_get_font(struct vc_data *vc, struct console_font_op *op)
static int fbcon_get_font(struct vc_data *vc, struct console_font_op *op)
{
u8 *fontdata = vc->vc_font.data;
u8 *data = op->data;
......@@ -2168,7 +2167,7 @@ static int fbcon_do_set_font(struct vc_data *vc, struct console_font_op *op,
return 0;
}
static inline int fbcon_copy_font(struct vc_data *vc, struct console_font_op *op)
static int fbcon_copy_font(struct vc_data *vc, struct console_font_op *op)
{
struct display *od;
int h = op->height;
......@@ -2185,7 +2184,7 @@ static inline int fbcon_copy_font(struct vc_data *vc, struct console_font_op *op
return fbcon_do_set_font(vc, op, od->fontdata, od->userfont);
}
static inline int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
static int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
{
int w = op->width;
int h = op->height;
......@@ -2273,7 +2272,7 @@ static inline int fbcon_set_font(struct vc_data *vc, struct console_font_op *op)
return fbcon_do_set_font(vc, op, new_data, 1);
}
static inline int fbcon_set_def_font(struct vc_data *vc, struct console_font_op *op)
static int fbcon_set_def_font(struct vc_data *vc, struct console_font_op *op)
{
struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
char name[MAX_FONT_NAME];
......@@ -2293,22 +2292,6 @@ static inline int fbcon_set_def_font(struct vc_data *vc, struct console_font_op
return fbcon_do_set_font(vc, op, f->data, 0);
}
static int fbcon_font_op(struct vc_data *vc, struct console_font_op *op)
{
switch (op->op) {
case KD_FONT_OP_SET:
return fbcon_set_font(vc, op);
case KD_FONT_OP_GET:
return fbcon_get_font(vc, op);
case KD_FONT_OP_SET_DEFAULT:
return fbcon_set_def_font(vc, op);
case KD_FONT_OP_COPY:
return fbcon_copy_font(vc, op);
default:
return -ENOSYS;
}
}
static u16 palette_red[16];
static u16 palette_green[16];
static u16 palette_blue[16];
......@@ -2609,7 +2592,10 @@ const struct consw fb_con = {
.con_bmove = fbcon_bmove,
.con_switch = fbcon_switch,
.con_blank = fbcon_blank,
.con_font_op = fbcon_font_op,
.con_font_set = fbcon_set_font,
.con_font_get = fbcon_get_font,
.con_font_default = fbcon_set_def_font,
.con_font_copy = fbcon_copy_font,
.con_set_palette = fbcon_set_palette,
.con_scrolldelta = fbcon_scrolldelta,
.con_set_origin = fbcon_set_origin,
......
......@@ -517,11 +517,6 @@ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch)
}
}
static int mdacon_font_op(struct vc_data *c, struct console_font_op *op)
{
return -ENOSYS;
}
static int mdacon_scrolldelta(struct vc_data *c, int lines)
{
return 0;
......@@ -594,7 +589,6 @@ const struct consw mda_con = {
.con_bmove = mdacon_bmove,
.con_switch = mdacon_switch,
.con_blank = mdacon_blank,
.con_font_op = mdacon_font_op,
.con_set_palette = mdacon_set_palette,
.con_scrolldelta = mdacon_scrolldelta,
.con_build_attr = mdacon_build_attr,
......
......@@ -543,18 +543,14 @@ static int newport_set_def_font(int unit, struct console_font_op *op)
return 0;
}
static int newport_font_op(struct vc_data *vc, struct console_font_op *op)
static int newport_font_default(struct vc_data *vc, struct console_font_op *op)
{
int unit = vc->vc_num;
switch (op->op) {
case KD_FONT_OP_SET:
return newport_set_font(unit, op);
case KD_FONT_OP_SET_DEFAULT:
return newport_set_def_font(unit, op);
default:
return -ENOSYS;
}
return newport_set_def_font(vc->vc_num, op);
}
static int newport_font_set(struct vc_data *vc, struct console_font_op *op)
{
return newport_set_font(vc->vc_num, op);
}
static int newport_set_palette(struct vc_data *vc, unsigned char *table)
......@@ -717,7 +713,8 @@ const struct consw newport_con = {
.con_bmove = newport_bmove,
.con_switch = newport_switch,
.con_blank = newport_blank,
.con_font_op = newport_font_op,
.con_font_set = newport_font_set,
.con_font_default = newport_font_default,
.con_set_palette = newport_set_palette,
.con_scrolldelta = newport_scrolldelta,
.con_set_origin = DUMMY,
......
......@@ -456,12 +456,6 @@ promcon_cursor(struct vc_data *conp, int mode)
}
}
static int
promcon_font_op(struct vc_data *conp, struct console_font_op *op)
{
return -ENOSYS;
}
static int
promcon_blank(struct vc_data *conp, int blank, int mode_switch)
{
......@@ -586,7 +580,6 @@ const struct consw prom_con = {
.con_bmove = promcon_bmove,
.con_switch = promcon_switch,
.con_blank = promcon_blank,
.con_font_op = promcon_font_op,
.con_set_palette = DUMMY,
.con_scrolldelta = DUMMY,
#if !(PROMCON_COLOR)
......
......@@ -85,11 +85,6 @@ static int sticon_set_palette(struct vc_data *c, unsigned char *table)
return -EINVAL;
}
static int sticon_font_op(struct vc_data *c, struct console_font_op *op)
{
return -ENOSYS;
}
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
{
int unit = conp->vc_num;
......@@ -366,7 +361,6 @@ static struct consw sti_con = {
.con_bmove = sticon_bmove,
.con_switch = sticon_switch,
.con_blank = sticon_blank,
.con_font_op = sticon_font_op,
.con_set_palette = sticon_set_palette,
.con_scrolldelta = sticon_scrolldelta,
.con_set_origin = sticon_set_origin,
......
......@@ -77,7 +77,6 @@ static void vgacon_deinit(struct vc_data *c);
static void vgacon_cursor(struct vc_data *c, int mode);
static int vgacon_switch(struct vc_data *c);
static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
static int vgacon_font_op(struct vc_data *c, struct console_font_op *op);
static int vgacon_set_palette(struct vc_data *vc, unsigned char *table);
static int vgacon_scrolldelta(struct vc_data *c, int lines);
static int vgacon_set_origin(struct vc_data *c);
......@@ -908,39 +907,43 @@ static int vgacon_adjust_height(struct vc_data *vc, unsigned fontheight)
return 0;
}
static int vgacon_font_op(struct vc_data *c, struct console_font_op *op)
static int vgacon_font_set(struct vc_data *c, struct console_font_op *op)
{
int rc;
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
if (op->op == KD_FONT_OP_SET) {
if (op->width != 8
|| (op->charcount != 256 && op->charcount != 512))
return -EINVAL;
rc = vgacon_do_font_op(&state, op->data, 1, op->charcount == 512);
if (!rc && !(op->flags & KD_FONT_FLAG_DONT_RECALC))
rc = vgacon_adjust_height(c, op->height);
} else if (op->op == KD_FONT_OP_GET) {
op->width = 8;
op->height = c->vc_font.height;
op->charcount = vga_512_chars ? 512 : 256;
if (!op->data)
return 0;
rc = vgacon_do_font_op(&state, op->data, 0, 0);
} else
rc = -ENOSYS;
if (op->width != 8 || (op->charcount != 256 && op->charcount != 512))
return -EINVAL;
rc = vgacon_do_font_op(&state, op->data, 1, op->charcount == 512);
if (rc)
return rc;
if (!(op->flags & KD_FONT_FLAG_DONT_RECALC))
rc = vgacon_adjust_height(c, op->height);
return rc;
}
#else
static int vgacon_font_op(struct vc_data *c, struct console_font_op *op)
static int vgacon_font_get(struct vc_data *c, struct console_font_op *op)
{
return -ENOSYS;
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
op->width = 8;
op->height = c->vc_font.height;
op->charcount = vga_512_chars ? 512 : 256;
if (!op->data)
return 0;
return vgacon_do_font_op(&state, op->data, 0, 0);
}
#else
#define vgacon_font_set NULL
#define vgacon_font_get NULL
#endif
static int vgacon_scrolldelta(struct vc_data *c, int lines)
......@@ -1079,7 +1082,8 @@ const struct consw vga_con = {
.con_bmove = DUMMY,
.con_switch = vgacon_switch,
.con_blank = vgacon_blank,
.con_font_op = vgacon_font_op,
.con_font_set = vgacon_font_set,
.con_font_get = vgacon_font_get,
.con_set_palette = vgacon_set_palette,
.con_scrolldelta = vgacon_scrolldelta,
.con_set_origin = vgacon_set_origin,
......
......@@ -40,7 +40,10 @@ struct consw {
void (*con_bmove)(struct vc_data *, int, int, int, int, int, int);
int (*con_switch)(struct vc_data *);
int (*con_blank)(struct vc_data *, int, int);
int (*con_font_op)(struct vc_data *, struct console_font_op *);
int (*con_font_set)(struct vc_data *, struct console_font_op *);
int (*con_font_get)(struct vc_data *, struct console_font_op *);
int (*con_font_default)(struct vc_data *, struct console_font_op *);
int (*con_font_copy)(struct vc_data *, struct console_font_op *);
int (*con_resize)(struct vc_data *, unsigned int, unsigned int);
int (*con_set_palette)(struct vc_data *, unsigned char *);
int (*con_scrolldelta)(struct vc_data *, int);
......
......@@ -50,6 +50,10 @@ void do_unblank_screen(int leaving_gfx);
void unblank_screen(void);
void poke_blanked_console(void);
int con_font_op(int currcons, struct console_font_op *op);
int con_font_set(int currcons, struct console_font_op *op);
int con_font_get(int currcons, struct console_font_op *op);
int con_font_default(int currcons, struct console_font_op *op);
int con_font_copy(int currcons, struct console_font_op *op);
int con_set_cmap(unsigned char __user *cmap);
int con_get_cmap(unsigned char __user *cmap);
void scrollback(int);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment