Factor out the allocation code for font_data_t from font import in font_data_import(). Retrieve a writable glyph buffer from the new helper __font_data_wrbuf().
Having the allocation code in separate functions makes it available for font rotation and maybe other font utilities. The _wrbuf() helper returns a writable glyph buffer. Font data is only readable in general. Signed-off-by: Thomas Zimmermann <[email protected]> --- lib/fonts/font.h | 12 +++++++++ lib/fonts/fonts.c | 63 ++++++++++++++++++++++++++++++----------------- 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/lib/fonts/font.h b/lib/fonts/font.h index 4f1adf0b6b54..eae8c563f148 100644 --- a/lib/fonts/font.h +++ b/lib/fonts/font.h @@ -4,6 +4,7 @@ #define _LIB_FONTS_FONT_H #include <linux/font.h> +#include <linux/types.h> /* * Font data @@ -16,6 +17,17 @@ struct font_data { unsigned char data[]; } __packed; +/* + * font_data_t and helpers + */ + +static inline unsigned char *__font_data_wrbuf(font_data_t *fd) +{ + return (unsigned char *)fd; +} + +font_data_t *__font_data_alloc(unsigned int size, gfp_t flags); + /* * Built-in fonts */ diff --git a/lib/fonts/fonts.c b/lib/fonts/fonts.c index 4fc66722d00d..e66a5b6fc3bb 100644 --- a/lib/fonts/fonts.c +++ b/lib/fonts/fonts.c @@ -47,6 +47,39 @@ static bool font_data_is_internal(font_data_t *fd) return !REFCOUNT(fd); /* internal fonts have no reference counting */ } +font_data_t *__font_data_alloc(unsigned int size, gfp_t flags) +{ + unsigned int alloc_size; + struct font_data *font_data; + font_data_t *fd; + + /* Check for overflow in allocation size calculation */ + if (check_add_overflow(sizeof(*font_data), size, &alloc_size)) + return ERR_PTR(-EINVAL); + + font_data = kzalloc(alloc_size, flags); + if (!font_data) + return ERR_PTR(-ENOMEM); + + fd = font_data->data; + REFCOUNT(fd) = 1; /* start with reference acquired */ + FNTSIZE(fd) = size; + + return fd; +} + +static font_data_t *font_data_alloc(unsigned int pitch, unsigned int h, unsigned int charcount) +{ + unsigned int size; + + /* 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); + + return __font_data_alloc(size, GFP_USER); +} + static void font_data_free(font_data_t *fd) { kfree(to_font_data_struct(fd)); @@ -75,36 +108,20 @@ font_data_t *font_data_import(const struct console_font *font, unsigned int vpit 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 char *font_data; 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)); + fd = font_data_alloc(pitch, h, charcount); + if (IS_ERR(fd)) + return fd; + font_data = __font_data_wrbuf(fd); for (i = 0; i < charcount; ++i) - memcpy(font_data->data + i * h * pitch, data + i * vpitch * pitch, h * pitch); + memcpy(font_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; + FNTSUM(fd) = calc_csum(0, font_data, FNTSIZE(fd)); return fd; } -- 2.56.0
