Commit 2a0f3635 authored by Antonino Daplas's avatar Antonino Daplas Committed by Linus Torvalds

[PATCH] fbdev: Fix for using >16 pixel wide font in fb console

From: Jani Jaakkola <jjaakkol@cs.Helsinki.FI>:

The first one was that fbcon_set_font() used one byte padding for fonts having
width 16 <= width < 24, which was wrong since the pieces of code actually
using the font did not use any padding.  This is fixed in the included patch
and also fbcon_set_font() is made a little cleaner.  After the patch the
following font is not garbled in fb console:
http://www.cs.helsinki.fi/u/jjaakkol/psf/bitstream_vera_sans_mono_roman.16x30.psf

The other bug is that fonts having height == 32 crash the kernel.  I have no
fix for this (at least not yet), but it can be reproduced with font:
http://www.cs.helsinki.fi/u/jjaakkol/psf/bitstream_vera_sans_mono_roman.17x32.psf.
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 599c4eeb
...@@ -105,6 +105,7 @@ config DUMMY_CONSOLE ...@@ -105,6 +105,7 @@ config DUMMY_CONSOLE
config FRAMEBUFFER_CONSOLE config FRAMEBUFFER_CONSOLE
tristate "Framebuffer Console support" tristate "Framebuffer Console support"
depends on FB depends on FB
select CRC32
config FONTS config FONTS
bool "Select compiled-in fonts" bool "Select compiled-in fonts"
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/crc32.h> /* For counting font checksums */
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -2257,6 +2257,12 @@ static int fbcon_copy_font(struct vc_data *vc, int con) ...@@ -2257,6 +2257,12 @@ static int fbcon_copy_font(struct vc_data *vc, int con)
* User asked to set font; we are guaranteed that * User asked to set font; we are guaranteed that
* a) width and height are in range 1..32 * a) width and height are in range 1..32
* b) charcount does not exceed 512 * b) charcount does not exceed 512
* but lets not assume that, since someone might someday want to use larger
* fonts. And charcount of 512 is small for unicode support.
*
* However, user space gives the font in 32 rows , regardless of
* actual font height. So a new API is needed if support for larger fonts
* is ever implemented.
*/ */
static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags) static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags)
...@@ -2264,20 +2270,17 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne ...@@ -2264,20 +2270,17 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
unsigned charcount = font->charcount; unsigned charcount = font->charcount;
int w = font->width; int w = font->width;
int h = font->height; int h = font->height;
int size = h; int size;
int i, k; int i, csum;
u8 *new_data, *data = font->data, *p; u8 *new_data, *data = font->data;
int pitch = (font->width+7) >> 3;
/* Is there a reason why fbconsole couldn't handle any charcount >256?
* If not this check should be changed to charcount < 256 */
if (charcount != 256 && charcount != 512) if (charcount != 256 && charcount != 512)
return -EINVAL; return -EINVAL;
if (w > 8) { size = h * pitch * charcount;
if (w <= 16)
size *= 2;
else
size *= 4;
}
size *= charcount;
new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER); new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
...@@ -2288,55 +2291,22 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne ...@@ -2288,55 +2291,22 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
FNTSIZE(new_data) = size; FNTSIZE(new_data) = size;
FNTCHARCNT(new_data) = charcount; FNTCHARCNT(new_data) = charcount;
REFCOUNT(new_data) = 0; /* usage counter */ REFCOUNT(new_data) = 0; /* usage counter */
p = new_data; for (i=0; i< charcount; i++) {
if (w <= 8) { memcpy(new_data + i*h*pitch, data + i*32*pitch, h*pitch);
for (i = 0; i < charcount; i++) {
memcpy(p, data, h);
data += 32;
p += h;
}
} else if (w <= 16) {
h *= 2;
for (i = 0; i < charcount; i++) {
memcpy(p, data, h);
data += 64;
p += h;
}
} else if (w <= 24) {
for (i = 0; i < charcount; i++) {
int j;
for (j = 0; j < h; j++) {
memcpy(p, data, 3);
p[3] = 0;
data += 3;
p += sizeof(u32);
}
data += 3 * (32 - h);
}
} else {
h *= 4;
for (i = 0; i < charcount; i++) {
memcpy(p, data, h);
data += 128;
p += h;
}
}
/* we can do it in u32 chunks because of charcount is 256 or 512, so
font length must be multiple of 256, at least. And 256 is multiple
of 4 */
k = 0;
while (p > new_data) {
p = (u8 *)((u32 *)p - 1);
k += *(u32 *) p;
} }
FNTSUM(new_data) = k;
/* Since linux has a nice crc32 function use it for counting font
* checksums. */
csum = crc32(0, new_data, size);
FNTSUM(new_data) = csum;
/* Check if the same font is on some other console already */ /* Check if the same font is on some other console already */
for (i = 0; i < MAX_NR_CONSOLES; i++) { for (i = 0; i < MAX_NR_CONSOLES; i++) {
struct vc_data *tmp = vc_cons[i].d; struct vc_data *tmp = vc_cons[i].d;
if (fb_display[i].userfont && if (fb_display[i].userfont &&
fb_display[i].fontdata && fb_display[i].fontdata &&
FNTSUM(fb_display[i].fontdata) == k && FNTSUM(fb_display[i].fontdata) == csum &&
FNTSIZE(fb_display[i].fontdata) == size && FNTSIZE(fb_display[i].fontdata) == size &&
tmp->vc_font.width == w && tmp->vc_font.width == w &&
!memcmp(fb_display[i].fontdata, new_data, size)) { !memcmp(fb_display[i].fontdata, new_data, size)) {
......
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