This moves 32x32 font size limitation checking down to drivers, so that
fbcon can allow large fonts.
We still keep a limitation to 64x128 pixels so as to have a simple bounded
allocation for con_font_get and in the userland kbd tool. That glyph size
will however be enough to have 128x36 characters on a "16/9 8K display".
Signed-off-by: Samuel Thibault <[email protected]>
---
V1 -> V2: Switch con_font_get to kvmalloc/kvfree instead of kmalloc/kfree
Index: linux-6.0/drivers/tty/vt/vt.c
===================================================================
--- linux-6.0.orig/drivers/tty/vt/vt.c
+++ linux-6.0/drivers/tty/vt/vt.c
@@ -4575,17 +4575,20 @@ void reset_palette(struct vc_data *vc)
/*
* Font switching
*
- * Currently we only support fonts up to 32 pixels wide, at a maximum height
- * of 32 pixels. Userspace fontdata is stored with 32 bytes (shorts/ints,
- * depending on width) reserved for each character which is kinda wasty, but
- * this is done in order to maintain compatibility with the EGA/VGA fonts. It
- * is up to the actual low-level console-driver convert data into its favorite
- * format (maybe we should add a `fontoffset' field to the `display'
- * structure so we won't have to convert the fontdata all the time.
+ * Currently we only support fonts up to 128 pixels wide, at a maximum height
+ * of 128 pixels. Userspace fontdata may have to be stored with 32 bytes
+ * (shorts/ints, depending on width) reserved for each character which is
+ * kinda wasty, but this is done in order to maintain compatibility with the
+ * EGA/VGA fonts. It is up to the actual low-level console-driver convert data
+ * into its favorite format (maybe we should add a `fontoffset' field to the
+ * `display' structure so we won't have to convert the fontdata all the time.
* /Jes
*/
-#define max_font_size 65536
+#define max_font_width 64
+#define max_font_height 128
+#define max_font_glyphs 512
+#define max_font_size (max_font_glyphs*max_font_width*max_font_height)
static int con_font_get(struct vc_data *vc, struct console_font_op *op)
{
@@ -4595,7 +4598,7 @@ static int con_font_get(struct vc_data *
unsigned int vpitch = op->op == KD_FONT_OP_GET_TALL ? op->height : 32;
if (op->data) {
- font.data = kmalloc(max_font_size, GFP_KERNEL);
+ font.data = kvmalloc(max_font_size, GFP_KERNEL);
if (!font.data)
return -ENOMEM;
} else
@@ -4630,7 +4633,7 @@ static int con_font_get(struct vc_data *
rc = -EFAULT;
out:
- kfree(font.data);
+ kvfree(font.data);
return rc;
}
@@ -4645,9 +4648,10 @@ static int con_font_set(struct vc_data *
return -EINVAL;
if (!op->data)
return -EINVAL;
- if (op->charcount > 512)
+ if (op->charcount > max_font_glyphs)
return -EINVAL;
- if (op->width <= 0 || op->width > 32 || !op->height || op->height > 32)
+ if (op->width <= 0 || op->width > max_font_width || !op->height ||
+ op->height > max_font_height)
return -EINVAL;
if (vpitch < op->height)
return -EINVAL;
Index: linux-6.0/drivers/usb/misc/sisusbvga/sisusb_con.c
===================================================================
--- linux-6.0.orig/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ linux-6.0/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -1203,7 +1203,7 @@ sisusbcon_font_set(struct vc_data *c, st
struct sisusb_usb_data *sisusb;
unsigned charcount = font->charcount;
- if (font->width != 8 || vpitch != 32 ||
+ if (font->width != 8 || font->height > 32 || vpitch != 32 ||
(charcount != 256 && charcount != 512))
return -EINVAL;
Index: linux-6.0/drivers/video/console/vgacon.c
===================================================================
--- linux-6.0.orig/drivers/video/console/vgacon.c
+++ linux-6.0/drivers/video/console/vgacon.c
@@ -1037,7 +1037,7 @@ static int vgacon_font_set(struct vc_dat
if (vga_video_type < VIDEO_TYPE_EGAM)
return -EINVAL;
- if (font->width != VGA_FONTWIDTH || vpitch != 32 ||
+ if (font->width != VGA_FONTWIDTH || font->height > 32 || vpitch != 32 ||
(charcount != 256 && charcount != 512))
return -EINVAL;
Index: linux-6.0/drivers/video/fbdev/core/fbcon.c
===================================================================
--- linux-6.0.orig/drivers/video/fbdev/core/fbcon.c
+++ linux-6.0/drivers/video/fbdev/core/fbcon.c
@@ -2279,6 +2279,8 @@ static int fbcon_get_font(struct vc_data
font->width = vc->vc_font.width;
font->height = vc->vc_font.height;
+ if (font->height > vpitch)
+ return -ENOSPC;
font->charcount = vc->vc_hi_font_mask ? 512 : 256;
if (!font->data)
return 0;
On Sun, Dec 18, 2022 at 01:32:12AM +0100, Samuel Thibault wrote:
> This moves 32x32 font size limitation checking down to drivers, so that
> fbcon can allow large fonts.
>
> We still keep a limitation to 64x128 pixels so as to have a simple bounded
> allocation for con_font_get and in the userland kbd tool. That glyph size
> will however be enough to have 128x36 characters on a "16/9 8K display".
>
> Signed-off-by: Samuel Thibault <[email protected]>
>
> ---
> V1 -> V2: Switch con_font_get to kvmalloc/kvfree instead of kmalloc/kfree
>
> Index: linux-6.0/drivers/tty/vt/vt.c
> ===================================================================
> --- linux-6.0.orig/drivers/tty/vt/vt.c
> +++ linux-6.0/drivers/tty/vt/vt.c
> @@ -4575,17 +4575,20 @@ void reset_palette(struct vc_data *vc)
> /*
> * Font switching
> *
> - * Currently we only support fonts up to 32 pixels wide, at a maximum height
> - * of 32 pixels. Userspace fontdata is stored with 32 bytes (shorts/ints,
> - * depending on width) reserved for each character which is kinda wasty, but
> - * this is done in order to maintain compatibility with the EGA/VGA fonts. It
> - * is up to the actual low-level console-driver convert data into its favorite
> - * format (maybe we should add a `fontoffset' field to the `display'
> - * structure so we won't have to convert the fontdata all the time.
> + * Currently we only support fonts up to 128 pixels wide, at a maximum height
> + * of 128 pixels. Userspace fontdata may have to be stored with 32 bytes
> + * (shorts/ints, depending on width) reserved for each character which is
> + * kinda wasty, but this is done in order to maintain compatibility with the
> + * EGA/VGA fonts. It is up to the actual low-level console-driver convert data
> + * into its favorite format (maybe we should add a `fontoffset' field to the
> + * `display' structure so we won't have to convert the fontdata all the time.
> * /Jes
> */
>
> -#define max_font_size 65536
> +#define max_font_width 64
> +#define max_font_height 128
> +#define max_font_glyphs 512
> +#define max_font_size (max_font_glyphs*max_font_width*max_font_height)
As a suggestion that you can safely ignore. Maybe make max_font_glyphs a
sysctl parameter to be able to use larger fonts ?
I get requests from time to time in kbd that it is not possible to load a
larger font.
> static int con_font_get(struct vc_data *vc, struct console_font_op *op)
> {
> @@ -4595,7 +4598,7 @@ static int con_font_get(struct vc_data *
> unsigned int vpitch = op->op == KD_FONT_OP_GET_TALL ? op->height : 32;
>
> if (op->data) {
> - font.data = kmalloc(max_font_size, GFP_KERNEL);
> + font.data = kvmalloc(max_font_size, GFP_KERNEL);
> if (!font.data)
> return -ENOMEM;
> } else
> @@ -4630,7 +4633,7 @@ static int con_font_get(struct vc_data *
> rc = -EFAULT;
>
> out:
> - kfree(font.data);
> + kvfree(font.data);
> return rc;
> }
>
> @@ -4645,9 +4648,10 @@ static int con_font_set(struct vc_data *
> return -EINVAL;
> if (!op->data)
> return -EINVAL;
> - if (op->charcount > 512)
> + if (op->charcount > max_font_glyphs)
> return -EINVAL;
> - if (op->width <= 0 || op->width > 32 || !op->height || op->height > 32)
> + if (op->width <= 0 || op->width > max_font_width || !op->height ||
> + op->height > max_font_height)
> return -EINVAL;
> if (vpitch < op->height)
> return -EINVAL;
> Index: linux-6.0/drivers/usb/misc/sisusbvga/sisusb_con.c
> ===================================================================
> --- linux-6.0.orig/drivers/usb/misc/sisusbvga/sisusb_con.c
> +++ linux-6.0/drivers/usb/misc/sisusbvga/sisusb_con.c
> @@ -1203,7 +1203,7 @@ sisusbcon_font_set(struct vc_data *c, st
> struct sisusb_usb_data *sisusb;
> unsigned charcount = font->charcount;
>
> - if (font->width != 8 || vpitch != 32 ||
> + if (font->width != 8 || font->height > 32 || vpitch != 32 ||
> (charcount != 256 && charcount != 512))
> return -EINVAL;
>
> Index: linux-6.0/drivers/video/console/vgacon.c
> ===================================================================
> --- linux-6.0.orig/drivers/video/console/vgacon.c
> +++ linux-6.0/drivers/video/console/vgacon.c
> @@ -1037,7 +1037,7 @@ static int vgacon_font_set(struct vc_dat
> if (vga_video_type < VIDEO_TYPE_EGAM)
> return -EINVAL;
>
> - if (font->width != VGA_FONTWIDTH || vpitch != 32 ||
> + if (font->width != VGA_FONTWIDTH || font->height > 32 || vpitch != 32 ||
> (charcount != 256 && charcount != 512))
> return -EINVAL;
>
> Index: linux-6.0/drivers/video/fbdev/core/fbcon.c
> ===================================================================
> --- linux-6.0.orig/drivers/video/fbdev/core/fbcon.c
> +++ linux-6.0/drivers/video/fbdev/core/fbcon.c
> @@ -2279,6 +2279,8 @@ static int fbcon_get_font(struct vc_data
>
> font->width = vc->vc_font.width;
> font->height = vc->vc_font.height;
> + if (font->height > vpitch)
> + return -ENOSPC;
> font->charcount = vc->vc_hi_font_mask ? 512 : 256;
> if (!font->data)
> return 0;
>
> _______________________________________________
> kbd mailing list
> [email protected]
> https://lists.altlinux.org/mailman/listinfo/kbd
>
--
Rgrds, legion