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

Reply via email to