Modify Linux Kernel Font

Published on Author Artem Butusov7 Comments

Reasons

There are not so much reasons to change integrated in kernel fonts.

But I will publish my reasons for that:
– I would like to see kernel boot console
– MacBookPro has no way to change screen resolution through efifb kernel module, so on my MacBookPro Retina 13″ I have 2560×1600 native screen resolution. Default 8×16 font looks very small and almost unreadable in kernel boot console
– I would like to see kernel boot console font style matching with system boot console

Intro

If I can’t change console resolution then I could change font size!
The idea is simple, if default kernel font 8×16 looks fine on 1280×800 then 16×32 will look fine on 2560×1600.
We need to find good monospace bitmap font with unicode and ascii support. I suggest to use Terminus.
I will show here how to set Terminus font as kernel console font based on Gentoo Linux distribution.

The procedure below will double font in size for any system with framebuffer, so it’s suitable for MacBookPro Retina 15″ and others.

Install terminus font

emerge terminus-font

Install PSF tools

echo media-gfx/psftools >> /etc/portage/package.accept_keywords/psftools
emerge media-gfx/psftools -1

Convert PSF font to kernel font

To simplify kernel configuration we will just overwrite integrated font_8x16.c font in kernel with terminus 16×32 bold ascii.

mkdir ~/new-font
cd ~/new-font
cp /usr/share/consolefonts/ter-i32b.psf.gz .
gunzip ter-i32b.psf.gz

Here:
32 is font height
i is cp437 codepage (we no need unicode in kernel boot console)
b is bold (we need not only to double font but also make it bold to get better visual experience)
– psf tools can’t work with compressed fonts, so we have to gunzip it before

The we need to dump font:

psf2inc ter-i32b.psf > ter-i32b.inc

The we need to extract just font bitmap data from dump:

cat ter-i32b.inc | sed '0,/Char height/d' | sed '2049,$d' > ter-i32b.hex

2049 = 1 + (FontCharsNumber * FontWidth * FontHeight / DotsPerByte) / BytesPerLine = 1 + (256 * 16 * 32 / 8) / 8

But sometimes it could be easier to just open inc file and remove useless header and everything after last 256 glyph which has comment /* 255 */

We will use hex code as default text for font file:

cat ter-i32b.hex > font_8x16.c

Then we need edit font file so he will look like below:

#include <linux/font.h>
#include <linux/module.h>
#define FONTDATAMAX 16384
static const unsigned char fontdata_8x16[FONTDATAMAX] = {
        {GLYPH HEX SHOULD BE HERE}
};
const struct font_desc font_vga_8x16 = {
        .idx    = VGA8x16_IDX,
        .name   = "VGA8x16",
        .width  = 16,
        .height = 32,
        .data   = fontdata_8x16,
        .pref   = 0,
};
EXPORT_SYMBOL(font_vga_8x16);

We need to fill fontdata_8x16 with data from ter-i32b.hex.
We need to change FONTDATAMAX to make sure that FONTDATAMAX = FontCharsNumber * FontWidth * FontHeight / DotsPerByte
Also we need to change font_vga_8x16.width and font_vga_8x16.height.
All remaining text is grabbed from original font_8x16.c

Install kernel font

mv /usr/src/linux/lib/fonts/font_8x16.c /usr/src/linux/lib/fonts/font_8x16.c.org
cp font_8x16.c /usr/src/linux/lib/fonts/
cd ~
rm ~/new-font -rf
rm /usr/src/linux/lib/fonts/*.o
genkernel kernel --no-clean

Here:
– we backup old font sources
– we install new font sources
– we remove old compiled objects for font sources to be sure that genkernel will recompile fonts
– we recompile kernel without cleaning for speedup (it will just take a couple minutes to generate new kernel and ramdisk)

Set console font

OpenRC

After kernel will boot we could switch console to Terminus Unicode font.

/etc/conf.d/consolefont:

consolefont="ter-v32b"

Set console font:

/etc/init.d/consolefont restart

Set console font on boot:

rc-update add consolefont default

systemd

setfont ter-v32b
nano /etc/vconsole.conf
FONT=ter-v32b

Done

Reboot and you will be able to see new font in kernel boot console and the same font in system boot console.
And font will be readable on MacBookPro Retina 13″.

7 Responses to Modify Linux Kernel Font

    • Unfortunately, I don’t have it available now but if you are getting exactly the same font as before changes then previously compiled obj file is most-likely used. Remove compiled obj file and rebuild the kernel.

      • Thank you! compiled in successfully on 2nd try.

        Since I had some free time, I added Terminus as a new font entry in kernel’s Kconfig. This way you can leave the 8×16 untouched and you can select the Terminus by passing a boot parameter, e.g fbcon=font:FONTNAME

        Obviously your method is easier as you mentioned! Thanks again!

  1. How can I find or calculate DotsPerByte and BytesPerLine values? I want to use a different font so I can’t just take yours.

Leave a Reply to Artem Butusov Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.