X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Fconsole%2Ffbcon.c;h=691ae83e087da0fd279acfbad3678b0d0c4e304f;hb=052710fcf296f48df03c0e248eface251a7ab22c;hp=2fcb51a57381fffe6e271c6efa8942256b7819ba;hpb=a91482bdcc2e0f6035702e46f1b99043a0893346;p=linux-2.6.git diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2fcb51a57..691ae83e0 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -165,6 +165,7 @@ 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, @@ -2000,36 +2001,36 @@ static void fbcon_free_font(struct display *p) p->userfont = 0; } -static int fbcon_get_font(struct vc_data *vc, struct console_font *font) +static inline int fbcon_get_font(struct vc_data *vc, struct console_font_op *op) { u8 *fontdata = vc->vc_font.data; - u8 *data = font->data; + u8 *data = op->data; int i, j; - font->width = vc->vc_font.width; - font->height = vc->vc_font.height; - font->charcount = vc->vc_hi_font_mask ? 512 : 256; - if (!font->data) + op->width = vc->vc_font.width; + op->height = vc->vc_font.height; + op->charcount = vc->vc_hi_font_mask ? 512 : 256; + if (!op->data) return 0; - if (font->width <= 8) { + if (op->width <= 8) { j = vc->vc_font.height; - for (i = 0; i < font->charcount; i++) { + for (i = 0; i < op->charcount; i++) { memcpy(data, fontdata, j); memset(data + j, 0, 32 - j); data += 32; fontdata += j; } - } else if (font->width <= 16) { + } else if (op->width <= 16) { j = vc->vc_font.height * 2; - for (i = 0; i < font->charcount; i++) { + for (i = 0; i < op->charcount; i++) { memcpy(data, fontdata, j); memset(data + j, 0, 64 - j); data += 64; fontdata += j; } - } else if (font->width <= 24) { - for (i = 0; i < font->charcount; i++) { + } else if (op->width <= 24) { + for (i = 0; i < op->charcount; i++) { for (j = 0; j < vc->vc_font.height; j++) { *data++ = fontdata[0]; *data++ = fontdata[1]; @@ -2041,7 +2042,7 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font) } } else { j = vc->vc_font.height * 4; - for (i = 0; i < font->charcount; i++) { + for (i = 0; i < op->charcount; i++) { memcpy(data, fontdata, j); memset(data + j, 0, 128 - j); data += 128; @@ -2051,15 +2052,23 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font) return 0; } -static int fbcon_do_set_font(struct vc_data *vc, int w, int h, +static int fbcon_do_set_font(struct vc_data *vc, struct console_font_op *op, u8 * data, int userfont) { struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; int resize; + int w = op->width; + int h = op->height; int cnt; char *old_data = NULL; + if (!w > 32) { + if (userfont && op->op != KD_FONT_OP_COPY) + kfree(data - FONT_EXTRA_WORDS * sizeof(int)); + return -ENXIO; + } + if (CON_IS_VISIBLE(vc) && softback_lines) fbcon_set_origin(vc); @@ -2159,32 +2168,33 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, return 0; } -static int fbcon_copy_font(struct vc_data *vc, int con) +static inline int fbcon_copy_font(struct vc_data *vc, struct console_font_op *op) { - struct display *od = &fb_display[con]; - struct console_font *f = &vc->vc_font; - - if (od->fontdata == f->data) + struct display *od; + int h = op->height; + + if (h < 0 || !vc_cons_allocated(h)) + return -ENOTTY; + if (h == vc->vc_num) + return 0; /* nothing to do */ + od = &fb_display[h]; + if (od->fontdata == vc->vc_font.data) return 0; /* already the same font... */ - return fbcon_do_set_font(vc, f->width, f->height, od->fontdata, od->userfont); + op->width = vc->vc_font.width; + op->height = vc->vc_font.height; + return fbcon_do_set_font(vc, op, od->fontdata, od->userfont); } -/* - * User asked to set font; we are guaranteed that - * a) width and height are in range 1..32 - * b) charcount does not exceed 512 - */ - -static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags) +static inline int fbcon_set_font(struct vc_data *vc, struct console_font_op *op) { - unsigned charcount = font->charcount; - int w = font->width; - int h = font->height; + int w = op->width; + int h = op->height; int size = h; int i, k; - u8 *new_data, *data = font->data, *p; + u8 *new_data, *data = op->data, *p; - if (charcount != 256 && charcount != 512) + if ((w <= 0) || (w > 32) + || (op->charcount != 256 && op->charcount != 512)) return -EINVAL; if (w > 8) { @@ -2193,33 +2203,32 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne else size *= 4; } - size *= charcount; - - new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER); + size *= op->charcount; - if (!new_data) + if (! + (new_data = + kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER))) return -ENOMEM; - new_data += FONT_EXTRA_WORDS * sizeof(int); FNTSIZE(new_data) = size; - FNTCHARCNT(new_data) = charcount; + FNTCHARCNT(new_data) = op->charcount; REFCOUNT(new_data) = 0; /* usage counter */ p = new_data; if (w <= 8) { - for (i = 0; i < charcount; i++) { + for (i = 0; i < op->charcount; i++) { memcpy(p, data, h); data += 32; p += h; } } else if (w <= 16) { h *= 2; - for (i = 0; i < charcount; i++) { + for (i = 0; i < op->charcount; i++) { memcpy(p, data, h); data += 64; p += h; } } else if (w <= 24) { - for (i = 0; i < charcount; i++) { + for (i = 0; i < op->charcount; i++) { int j; for (j = 0; j < h; j++) { memcpy(p, data, 3); @@ -2231,7 +2240,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne } } else { h *= 4; - for (i = 0; i < charcount; i++) { + for (i = 0; i < op->charcount; i++) { memcpy(p, data, h); data += 128; p += h; @@ -2261,22 +2270,43 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne break; } } - return fbcon_do_set_font(vc, font->width, font->height, new_data, 1); + return fbcon_do_set_font(vc, op, new_data, 1); } -static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name) +static inline 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]; struct font_desc *f; - if (!name) + if (!op->data) f = get_default_font(info->var.xres, info->var.yres); - else if (!(f = find_font(name))) - return -ENOENT; + else if (strncpy_from_user(name, op->data, MAX_FONT_NAME - 1) < 0) + return -EFAULT; + else { + name[MAX_FONT_NAME - 1] = 0; + if (!(f = find_font(name))) + return -ENOENT; + } + op->width = f->width; + op->height = f->height; + return fbcon_do_set_font(vc, op, f->data, 0); +} - font->width = f->width; - font->height = f->height; - return fbcon_do_set_font(vc, f->width, f->height, 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]; @@ -2310,7 +2340,7 @@ static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) else palette_cmap.len = 16; palette_cmap.start = 0; - return fb_set_cmap(&palette_cmap, info); + return fb_set_cmap(&palette_cmap, 1, info); } static u16 *fbcon_screen_pos(struct vc_data *vc, int offset) @@ -2579,10 +2609,7 @@ const struct consw fb_con = { .con_bmove = fbcon_bmove, .con_switch = fbcon_switch, .con_blank = fbcon_blank, - .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_font_op = fbcon_font_op, .con_set_palette = fbcon_set_palette, .con_scrolldelta = fbcon_scrolldelta, .con_set_origin = fbcon_set_origin,