From: Thomas Zimmermann <tzimmermann@suse.de>
To: gregkh@linuxfoundation.org, deller@gmx.de, sam@ravnborg.org
Cc: linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org,
linux-kernel@vger.kernel.org,
Thomas Zimmermann <tzimmermann@suse.de>
Subject: [PATCH v3 11/13] lib/fonts: Create font_data_t from struct console_font with font_data_import()
Date: Mon, 9 Mar 2026 15:14:53 +0100 [thread overview]
Message-ID: <20260309141723.137364-12-tzimmermann@suse.de> (raw)
In-Reply-To: <20260309141723.137364-1-tzimmermann@suse.de>
Add font_data_import() and update consoles to use it.
The implementation of font_data_import() is based on code from fbcon,
which supports overflow checks and crc32 checksums. Fbcon uses the crc32
checksum.
Newport_con now implements the same overflow checks as fbcon. As before,
this console does not support checksums, which are optional. Newport_con
can now also handle input font data with a vertical pitch other than 32
bytes. (The vertical pitch is the offset between two glyphs in the font
data.)
As an internal change, remove the const qualifier from the data field
if struct font_data. This allows font_data_import() to write the data
without type casting. For all users of the font data via font_data_t,
the stored data is still read only.
v3:
- fix typos
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
drivers/video/console/newport_con.c | 22 ++--------
drivers/video/fbdev/core/fbcon.c | 38 ++----------------
include/linux/font.h | 6 ++-
lib/fonts/fonts.c | 62 +++++++++++++++++++++++++++++
4 files changed, 75 insertions(+), 53 deletions(-)
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index 1bc3cb1ea116..ecbbe2e4e2a6 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -501,31 +501,17 @@ static int newport_set_font(int unit, const struct console_font *op,
{
int w = op->width;
int h = op->height;
- int size = h * op->charcount;
int i;
font_data_t *new_data;
- unsigned char *data = op->data, *p;
/* ladis: when I grow up, there will be a day... and more sizes will
* be supported ;-) */
- if ((w != 8) || (h != 16) || (vpitch != 32)
- || (op->charcount != 256 && op->charcount != 512))
+ if (w != 8 || h != 16 || (op->charcount != 256 && op->charcount != 512))
return -EINVAL;
- 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;
- REFCOUNT(new_data) = 1; /* usage counter */
- FNTSUM(new_data) = 0;
-
- p = (unsigned char *)font_data_buf(new_data);
- for (i = 0; i < op->charcount; i++) {
- memcpy(p, data, h);
- data += 32;
- p += h;
- }
+ new_data = font_data_import(op, vpitch, NULL);
+ if (IS_ERR(new_data))
+ return PTR_ERR(new_data);
/* check if font is already used by other console */
for (i = 0; i < MAX_NR_CONSOLES; i++) {
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 00255ac92e42..53677c09a0ec 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2039,8 +2039,6 @@ static void updatescrollmode(struct fbcon_display *p,
updatescrollmode_accel(p, info, vc);
}
-#define PITCH(w) (((w) + 7) >> 3)
-
static int fbcon_resize(struct vc_data *vc, unsigned int width,
unsigned int height, bool from_user)
{
@@ -2424,7 +2422,6 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
p->fontdata = data;
vc->vc_font.data = font_data_buf(p->fontdata);
-
old_width = vc->vc_font.width;
old_height = vc->vc_font.height;
old_charcount = vc->vc_font.charcount;
@@ -2482,11 +2479,8 @@ static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
unsigned charcount = font->charcount;
int w = font->width;
int h = font->height;
- int size, alloc_size;
- int i, csum, ret;
+ int i, ret;
font_data_t *new_data;
- const u8 *data = font->data;
- int pitch = PITCH(font->width);
/* Is there a reason why fbconsole couldn't handle any charcount >256?
* If not this check should be changed to charcount < 256 */
@@ -2510,34 +2504,10 @@ static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
if (fbcon_invalid_charcount(info, charcount))
return -EINVAL;
- /* Check for integer overflow in font size calculation */
- if (check_mul_overflow(h, pitch, &size) ||
- check_mul_overflow(size, charcount, &size))
- return -EINVAL;
-
- /* Check for overflow in allocation size calculation */
- if (check_add_overflow(FONT_EXTRA_WORDS * sizeof(int), size, &alloc_size))
- return -EINVAL;
-
- new_data = kmalloc(alloc_size, GFP_USER);
-
- if (!new_data)
- return -ENOMEM;
-
- memset((u8 *)new_data, 0, FONT_EXTRA_WORDS * sizeof(int));
-
- new_data += FONT_EXTRA_WORDS * sizeof(int);
- FNTSIZE(new_data) = size;
- REFCOUNT(new_data) = 1; /* usage counter */
- for (i=0; i< charcount; i++) {
- memcpy((u8 *)new_data + i * h * pitch, data + i * vpitch * pitch, h * pitch);
- }
-
- /* Since linux has a nice crc32 function use it for counting font
- * checksums. */
- csum = crc32(0, new_data, size);
+ new_data = font_data_import(font, vpitch, crc32);
+ if (IS_ERR(new_data))
+ return PTR_ERR(new_data);
- FNTSUM(new_data) = csum;
/* Check if the same font is on some other console already */
for (i = first_fb_vc; i <= last_fb_vc; i++) {
if (fb_display[i].fontdata &&
diff --git a/include/linux/font.h b/include/linux/font.h
index 58bf3c64cabb..3eb4818402c5 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -13,6 +13,8 @@
#include <linux/types.h>
+struct console_font;
+
/*
* font_data_t and helpers
*/
@@ -54,6 +56,8 @@ static inline const unsigned char *font_data_buf(font_data_t *fd)
return (const unsigned char *)fd;
}
+font_data_t *font_data_import(const struct console_font *font, unsigned int vpitch,
+ u32 (*calc_csum)(u32, const void *, size_t));
void font_data_get(font_data_t *fd);
bool font_data_put(font_data_t *fd);
unsigned int font_data_size(font_data_t *fd);
@@ -124,7 +128,7 @@ extern const struct font_desc *get_default_font(int xres, int yres,
struct font_data {
unsigned int extra[FONT_EXTRA_WORDS];
- const unsigned char data[];
+ unsigned char data[];
} __packed;
#endif /* _VIDEO_FONT_H */
diff --git a/lib/fonts/fonts.c b/lib/fonts/fonts.c
index 3fb76d185647..16e75c3d2a0f 100644
--- a/lib/fonts/fonts.c
+++ b/lib/fonts/fonts.c
@@ -14,7 +14,9 @@
#include <linux/container_of.h>
#include <linux/font.h>
+#include <linux/kd.h>
#include <linux/module.h>
+#include <linux/overflow.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
@@ -23,6 +25,8 @@
#include <asm/setup.h>
#endif
+#define console_font_pitch(font) DIV_ROUND_UP((font)->width, 8)
+
/*
* Helpers for font_data_t
*/
@@ -42,6 +46,64 @@ static void font_data_free(font_data_t *fd)
kfree(to_font_data_struct(fd));
}
+/**
+ * font_data_import - Allocates and initializes font data from user space
+ * @font: A font from user space
+ * @vpitch: The size of a single glyph in @font in bytes
+ * @calc_csum: An optional helper to calculate a chechsum
+ *
+ * Font data from user space must be translated to the kernel's format. The
+ * font's glyph geometry and data is provided in @font. The parameter @vpitch
+ * gives the number of bytes per glyph, including trailing bytes.
+ *
+ * The parameter @calc_csum is optional. Fbcon passes crc32() to calculate the
+ * font data's checksum.
+ *
+ * Returns:
+ * Newly initialized font data on success, or a pointer-encoded errno value otherwise.
+ */
+font_data_t *font_data_import(const struct console_font *font, unsigned int vpitch,
+ u32 (*calc_csum)(u32, const void *, size_t))
+{
+ unsigned int pitch = console_font_pitch(font);
+ unsigned int h = font->height;
+ unsigned int charcount = font->charcount;
+ const unsigned char *data = font->data;
+ u32 csum = 0;
+ struct font_data *font_data;
+ int size, alloc_size;
+ unsigned int i;
+ font_data_t *fd;
+
+ /* Check for integer overflow in font-size calculation */
+ if (check_mul_overflow(h, pitch, &size) ||
+ check_mul_overflow(size, charcount, &size))
+ return ERR_PTR(-EINVAL);
+
+ /* Check for overflow in allocation size calculation */
+ if (check_add_overflow(sizeof(*font_data), size, &alloc_size))
+ return ERR_PTR(-EINVAL);
+
+ font_data = kmalloc(alloc_size, GFP_USER);
+ if (!font_data)
+ return ERR_PTR(-ENOMEM);
+ memset(font_data->extra, 0, sizeof(font_data->extra));
+
+ for (i = 0; i < charcount; ++i)
+ memcpy(font_data->data + i * h * pitch, data + i * vpitch * pitch, h * pitch);
+
+ if (calc_csum)
+ csum = calc_csum(0, font_data->data, size);
+
+ fd = font_data->data;
+ REFCOUNT(fd) = 1; /* start with reference acquired */
+ FNTSIZE(fd) = size;
+ FNTSUM(fd) = csum;
+
+ return fd;
+}
+EXPORT_SYMBOL_GPL(font_data_import);
+
/**
* font_data_get - Acquires a reference on font data
* @fd: Font data
--
2.53.0
next prev parent reply other threads:[~2026-03-09 14:18 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-09 14:14 [PATCH v3 00/13] vc,fbcon,fonts: Proper handling of font data Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 01/13] fbdev: Declare src parameter of fb_pad_ helpers as constant Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 02/13] vt: Remove trailing whitespaces Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 03/13] vt: Store font in struct vc_font Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 04/13] vt: Calculate font-buffer size with vc_font_size() Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 05/13] lib/fonts: Remove trailing whitespaces Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 06/13] lib/fonts: Remove FNTCHARCNT() Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 07/13] lib/fonts: Store font data as font_data_t; update consoles Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 08/13] lib/fonts: Read font size with font_data_size() Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 09/13] lib/fonts: Manage font-data lifetime with font_data_get/_put() Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 10/13] lib/fonts: Compare font data for equality with font_data_is_equal() Thomas Zimmermann
2026-03-09 14:14 ` Thomas Zimmermann [this message]
2026-03-09 14:14 ` [PATCH v3 12/13] lib/fonts: Store font data for user space with font_data_export() Thomas Zimmermann
2026-03-09 14:14 ` [PATCH v3 13/13] lib/fonts: Remove internal symbols and macros from public header file Thomas Zimmermann
2026-03-09 14:48 ` [PATCH v3 00/13] vc,fbcon,fonts: Proper handling of font data Helge Deller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260309141723.137364-12-tzimmermann@suse.de \
--to=tzimmermann@suse.de \
--cc=deller@gmx.de \
--cc=dri-devel@lists.freedesktop.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-fbdev@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=sam@ravnborg.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox