The default built-in font, Boldface, which is loaded at boot-time on a framebuffer (whether genfb or DRM) console is too small as it is 8x16. The other font built into the kernel is Boldface 16x32, and this, if you load it, will give you a console approximating a 80x25 screen--ie. this font is too large. Try it:

$ sudo wsconsctl -f $(tty) -dw font="Boldface 16x32"

The other fonts in /usr/share/wscons/fonts/ are all also small (8x16, 8x10, 8x8), as their extensions indicate.

The solution that is usually advocated to get a reasonable-size font is to a) edit the kernel config, b) add one of the fonts in /usr/src/sys/dev/wsfont/ using directives like options FONT_SPLEEN16x32, and c) then recompile the kernel. But, this is a pain. Simpler to write a program to suck in the fonts and load them into the kernel as needed. This is what the code below does.

Compile, and then run it as follows:

$ ./wsfont list
Compiled in fonts:
Fontname               Int. Name        1ch Nch Enc   Wid Hei Str bO BO   Size
DejaVu_Sans_Mono_12x22 DejaVu Sans Mono   0 256 iso    12  22  12 LR LR  67584
Droid_Sans_Mono_12x22  Droid Sans Mono    0 256 iso    12  22  12 LR LR  67584
Droid_Sans_Mono_19x36  Droid Sans Mono    0 256 iso    19  36  19 LR LR 175104
Droid_Sans_Mono_9x18   Droid Sans Mono    0 256 iso     9  18   9 LR LR  41472
Go_Mono_12x23          Go Mono            0 256 iso    12  23  12 LR LR  70656
bold16x32              Boldface 16x32     1 254 ibm    16  32   2 LR LR  16256
bold8x16               Boldface           1 254 ibm     8  16   1 LR LR   4064
gallant12x22           Gallant            0 256 iso    12  22   2 LR LR  11264
Glass_TTY_VT220_10x19  Glass TTY VT220    0 256 iso    10  19  10 LR LR  48640
Glass_TTY_VT220_10x25  Glass TTY VT220    0 256 iso    10  25  10 LR LR  64000
lucida16x29            Lucida            32  95 iso    16  29   2 LR LR   5510
omron12x20             omron12x20        32  95 iso    12  20   2 LR LR   3800
qvss8x15               QVSS              32 224 iso     8  15   1 RL LR   3360
sony12x24              sony12x24         32 224 iso    12  24   2 LR LR  10752
sony8x16               sony8x16          32 224 iso     8  16   1 LR LR   3584
spleen12x24            Spleen 12x24      32 224 iso    12  24   2 LR LR  10752
spleen16x32            Spleen 16x32      32 224 iso    16  32   2 LR LR  14336
spleen32x64            Spleen 32x64      32 224 iso    32  64   4 LR LR  57344
spleen5x8              Spleen 5x8        32  96 iso     5   8   1 LR LR    768
spleen8x16             Spleen 8x16       32 224 iso     8  16   1 LR LR   3584
vt220iso8x16           vt220iso8x16      32 224 iso     8  16   1 LR LR   3584
vt220iso8x8            vt220iso8x8       32 224 iso     8   8   1 LR LR   1792
vt220l8x10             vt220l             0 256 ibm     8  10   1 LR LR   2560
vt220l8x16             vt220l             0 256 ibm     8  16   1 LR LR   4096
vt220l8x8              vt220l             0 256 ibm     8   8   1 LR LR   2048
$ sudo ./wsfont set DejaVu_Sans_Mono_12x22
# Font should change on current console.

After you've checked out the fonts available on NetBSD (9.1 shown above), you can write all the fonts into /usr/share/wscons/fonts/ and then load your choice at boot-time via /etc/wsconf.conf:

$ sudo ./wsfont dump /usr/share/wscons/fonts/
$ ls -ltr /usr/share/wscons/fonts/*.fnt
-rw-r--r--  1 root  wheel   67684 Nov 15 10:28 DejaVu_Sans_Mono_12x22.fnt
-rw-r--r--  1 root  wheel   67684 Nov 15 10:28 Droid_Sans_Mono_12x22.fnt
-rw-r--r--  1 root  wheel  175204 Nov 15 10:28 Droid_Sans_Mono_19x36.fnt
-rw-r--r--  1 root  wheel   41572 Nov 15 10:28 Droid_Sans_Mono_9x18.fnt
-rw-r--r--  1 root  wheel   70756 Nov 15 10:28 Go_Mono_12x23.fnt
-rw-r--r--  1 root  wheel   16356 Nov 15 10:28 bold16x32.fnt
-rw-r--r--  1 root  wheel    4164 Nov 15 10:28 bold8x16.fnt
-rw-r--r--  1 root  wheel   11364 Nov 15 10:28 gallant12x22.fnt
-rw-r--r--  1 root  wheel   48740 Nov 15 10:28 Glass_TTY_VT220_10x19.fnt
-rw-r--r--  1 root  wheel   64100 Nov 15 10:28 Glass_TTY_VT220_10x25.fnt
-rw-r--r--  1 root  wheel    5610 Nov 15 10:28 lucida16x29.fnt
-rw-r--r--  1 root  wheel    3900 Nov 15 10:28 omron12x20.fnt
-rw-r--r--  1 root  wheel    3460 Nov 15 10:28 qvss8x15.fnt
-rw-r--r--  1 root  wheel   10852 Nov 15 10:28 sony12x24.fnt
-rw-r--r--  1 root  wheel    3684 Nov 15 10:28 sony8x16.fnt
-rw-r--r--  1 root  wheel   10852 Nov 15 10:28 spleen12x24.fnt
-rw-r--r--  1 root  wheel   14436 Nov 15 10:28 spleen16x32.fnt
-rw-r--r--  1 root  wheel   57444 Nov 15 10:28 spleen32x64.fnt
-rw-r--r--  1 root  wheel     868 Nov 15 10:28 spleen5x8.fnt
-rw-r--r--  1 root  wheel    3684 Nov 15 10:28 spleen8x16.fnt
-rw-r--r--  1 root  wheel    3684 Nov 15 10:28 vt220iso8x16.fnt
-rw-r--r--  1 root  wheel    1892 Nov 15 10:28 vt220iso8x8.fnt
-rw-r--r--  1 root  wheel    2660 Nov 15 10:28 vt220l8x10.fnt
-rw-r--r--  1 root  wheel    4196 Nov 15 10:28 vt220l8x16.fnt
-rw-r--r--  1 root  wheel    2148 Nov 15 10:28 vt220l8x8.fnt
$ 

Edit your /etc/wsconf.conf and add lines like these (read the wscons.conf(5), wsfontload(8) and wsconsctl(8) man-pages for details):

font    dejavu  12      22      iso     /usr/share/wscons/fonts/DejaVu_Sans_Mono_12x22.fnt

setvar  ttyE0   font            dejavu
setvar  ttyE1   font            dejavu
setvar  ttyE2   font            dejavu
setvar  ttyE3   font            dejavu

You'll easily find the locations where you should add those lines. Check out the QVSS font, where somebody's clearly been having fun.

Makefile (imp: all blanks at the beginning are actually tabs):
CC ?= gcc
CFLAGS ?= -Wall -Wextra -g -pipe
LDFLAGS ?=

INC = -I/usr/src/sys

EXE = wsfont
SRC = wsfont.c
HDR = wsfont.h

${EXE}: ${SRC} ${HDR}
	${CC} ${CFLAGS} ${INC} -o ${EXE} ${SRC} ${LDFLAGS}

${HDR}:
	awk -f mkhdr.awk /usr/src/sys/dev/wsfont/*.h > ${HDR}

clean:
	rm -f ${EXE} ${HDR}
mkhdr.awk:
#!/usr/bin/awk -f

BEGIN {
	N = 0
}

{
	FNAME = FILENAME
	gsub(/^.+\//, "", FNAME)
	sub(/\.h$/, "", FNAME)
	if (FNAME ~ /vt220koi8x10/)
		nextfile	# we get a macro--skip this

	PAT = "(static[[:blank:]]+)?struct[[:blank:]]+wsdisplay_font[[:blank:]]+[^[:blank:]]+[[:blank:]]*=[[:blank:]]*{"
	if ($0 ~ PAT) {
		printf("#include <dev/wsfont/%s.h>\n", FNAME)
		PFX = "(static[[:blank:]]+)?struct[[:blank:]]+wsdisplay_font[[:blank:]]+"
		SUF = "[[:blank:]]*=[[:blank:]]*{"
		FONT = $0
		sub(PFX, "", FONT)
		sub(SUF, "", FONT)
		if (length FONT > 0)
			FONTS[N++] = FONT
		nextfile
	}
}
END {
	printf("\nstatic struct wsfont {\n")
	printf("\tchar* fname;\n")
	printf("\tstruct wsdisplay_font* wsdfont;\n")
	printf("} wsfonts[] = {\n")
	for (i = 0; i < N; i++)
		printf("\t{ \"%s\", \t&%s },\n", FONTS[i], FONTS[i])
	printf("\t{ NULL, NULL }\n};\n");
}
wsfont.c:
#include <dev/wscons/wsconsio.h>
#include <sys/ioctl.h>
#include <endian.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "wsfont.h"

static int do_help(void);
static int do_list(void);
static int do_set(int argc, char* argv[]);
static int do_dump(int argc, char* argv[]);
static int wr_font(struct wsdisplay_font* wsf, char* path);
static void pr_font(struct wsdisplay_font* wsf);
static int set_font(char* fname, struct wsdisplay_font* wsf, char* cdev);
static char* bord2s(int b_order);
static char* enc2s(int encoding);

static char* prog;

int
main(int argc, char* argv[])
{
	char* cmd;
	int rc = EXIT_FAILURE;

	prog = argv[0];
	if (argc == 1) {
		rc = do_help();
		exit(rc);
	}

	cmd = argv[1];
	if (strcmp(cmd, "help") == 0)
		rc = do_help();
	else if (strcmp(cmd, "list") == 0)
		rc = do_list();
	else if (strcmp(cmd, "dump") == 0)
		rc = do_dump(argc, argv);
	else if (strcmp(cmd, "set") == 0)
		rc = do_set(argc, argv);
	else
		warnx("%s: unknown command.\nTry: help\n", cmd);
	return rc;
}

static int
do_help(void)
{
	printf(
	"Available commands:\n"
	"  list:            List compiled-in fonts\n"
	"\n"
	"  dump DIR:        Dump fonts into \"DIR\" (which must exist)\n"
	"                   eg.: wsfont dump /usr/share/wscons/fonts\n"
	"\n"
	"  set FONT [DEV]:  Load & set \"FONT\" on console \"DEV\" (or current)\n"
	"                   eg.: wsfont set Go_Mono_12x23 /dev/ttyE0\n"
	"                   eg.: wsfont set Go_Mono_12x23\n"
	"\n"
	"  help:            This list\n");
	return EXIT_SUCCESS;
}

static int
do_list(void)
{
	int i, rc = EXIT_FAILURE;

	for (i = 0; wsfonts[i].fname != NULL; i++) {
		if (i == 0) {	/* print heading */
			printf("Compiled in fonts:\n");
			printf("%-22s %-16s ", "Fontname", "Int. Name");
			printf("%3s %3s %-5s ", "1ch", "Nch", "Enc");
			printf("%3s %3s %3s ", "Wid", "Hei", "Str");
			printf("%-2s %-2s %6s\n", "bO", "BO", "Size");
		}
		printf("%-22s", wsfonts[i].fname);
		pr_font(wsfonts[i].wsdfont);
	}
	if (i == 0)
		warnx("error: no fonts compiled in!");
	else
		rc = EXIT_SUCCESS;
	return rc;
}

static void
pr_font(struct wsdisplay_font* wsf)
{
	printf(" %-16s %3d %3d", wsf->name, wsf->firstchar, wsf->numchars);
	printf(" ");
	printf("%-5s", enc2s(wsf->encoding));
	printf(" %3d %3d %3d", wsf->fontwidth, wsf->fontheight, wsf->stride);
	printf(" %-2s", bord2s(wsf->bitorder));
	printf(" %-2s", bord2s(wsf->byteorder));
	printf(" %6u\n", wsf->fontheight * wsf->stride * wsf->numchars);
}

static char*
enc2s(int encoding)
{
	switch (encoding) {
	case WSDISPLAY_FONTENC_ISO: return "iso";
	case WSDISPLAY_FONTENC_IBM: return "ibm";
	case WSDISPLAY_FONTENC_PCVT: return "pcvt";
	case WSDISPLAY_FONTENC_ISO7: return "iso7";
	case WSDISPLAY_FONTENC_ISO2: return "iso2";
	case WSDISPLAY_FONTENC_KOI8_R: return "koi8r";
	default: return "?";
	}
}

static char*
bord2s(int b_order)
{
	switch (b_order) {
	case WSDISPLAY_FONTORDER_KNOWN: return "K";
	case WSDISPLAY_FONTORDER_L2R: return "LR";
	case WSDISPLAY_FONTORDER_R2L: return "RL";
	default: return "?";
	}
}

static int
do_dump(int argc, char* argv[])
{
	int i, rc = EXIT_FAILURE;
	char* dir, *p;

	if (argc != 3) {
		warnx("Usage: %s dump DIR", prog);
		return rc;
	}
	dir = argv[2];
	if (*dir == '\0') {
		warnx("error: empty directory name");
		return rc;
	}

	p = dir + strlen(dir);
	while (--p >= dir && *p == '/')
		*p = '\0';
	rc = EXIT_SUCCESS;
	for (i = 0; wsfonts[i].fname != NULL; i++) {
		char path[PATH_MAX];
		snprintf(path, sizeof path, "%s/%s.fnt", dir, wsfonts[i].fname);
		rc = wr_font(wsfonts[i].wsdfont, path);
		if (rc != EXIT_SUCCESS)
			break;
	}

	return rc;
}

static int
wr_font(struct wsdisplay_font* wsf, char* path)
{
	char buf[4 + 64];
	int fd, n, rc = EXIT_FAILURE;

	if ((fd = open(path, O_WRONLY | O_CREAT, 0644)) == -1) {
		warn("%s: open failed", path);
		return rc;
	}
	memset(buf, 0, sizeof buf);
	memcpy(buf, "WSFT", 4);
	strcpy(buf + 4, wsf->name);
	n = sizeof buf;
	if (write(fd, buf, n) != n) {
		warn("%s: write failed", path);
		unlink(path);
		goto out;
	}
	n = htole32(wsf->firstchar); write(fd, &n, 4);
	n = htole32(wsf->numchars); write(fd, &n, 4);
	n = htole32(wsf->encoding); write(fd, &n, 4);
	n = htole32(wsf->fontwidth); write(fd, &n, 4);
	n = htole32(wsf->fontheight); write(fd, &n, 4);
	n = htole32(wsf->stride); write(fd, &n, 4);
	n = htole32(wsf->bitorder); write(fd, &n, 4);
	n = htole32(wsf->byteorder); write(fd, &n, 4);
	n =  wsf->numchars * wsf->fontheight * wsf->stride;
	if (write(fd, wsf->data, n) != n) {
		warn("%s: write failed", path);
		unlink(path);
	} else
		rc = EXIT_SUCCESS;
out:
	close(fd);
	return rc;
}

static int
do_set(int argc, char* argv[])
{
	char* cdev, *fname;
	int i, rc = EXIT_FAILURE;

	if (argc < 3) {
		warnx("Usage: %s set fontname console_device", prog);
		return rc;
	}

	fname = argv[2];
	if (argc == 4)
		cdev = argv[3];
	else {		/* set font on current tty */
		cdev = ttyname(STDIN_FILENO);
		if (cdev == NULL) {
			warn("ttyname failed");
			return rc;
		}
	}
	for (i = 0; wsfonts[i].fname != NULL; i++) {
		if (strcmp(wsfonts[i].fname, fname) == 0) {
			rc = set_font(fname, wsfonts[i].wsdfont, cdev);
			break;
		}
	}

	return rc;
}

static int
set_font(char* fname, struct wsdisplay_font* wsf, char* cdev)
{
	int fd, rc = EXIT_FAILURE;
	char* cmd = NULL;

	if ((fd = open("/dev/wsfont", O_RDWR)) < 0) {
		warn("/dev/wsfont: open failed");
		return rc;
	}
	wsf->name = fname;	/* VT220 has multiple fonts with same name */
	if (ioctl(fd, WSDISPLAYIO_LDFONT, wsf) < 0) {
		if (errno == EEXIST)
			warnx("%s: font already loaded", wsf->name);
		else {
			warn("ioctl WSDISPLAYIO_LDFONT failed");
			return rc;
		}
	}
	close(fd);
	if (asprintf(&cmd, "/sbin/wsconsctl -f \"%s\" -dw font=\"%s\"",
	    cdev, wsf->name) == -1) {
		warn("asprintf failed");
		return rc;
	}
	if (system(cmd) != 0)
		warn("warning: %s: cmd failed", cmd);
	else
		rc = EXIT_SUCCESS;
	free(cmd);

	return rc;
}

Enjoy.

    rvp interesting... I wouldn't actually mind to make them smaller as I find the default a bit too large 😅

    • rvp replied to this.

      pin The default font seems to depend on the framebuffer being used. With i915drmkms the default is Boldface which is 8x16. With genfb, the font switches to Boldface 16x32--which is too large for my taste.

      • pin replied to this.

        rvp Hmm... the thing is that I believe I'm seeing both of them at boot time.
        The font is huge up to this point in the booting process, when everything is resized.

        [     6.916128] intelfb0 at i915drmkms0
        [     6.916128] intelfb0: framebuffer at 0xffffd000a64d8000, size 1366x768, depth 32, stride 5504
        [     7.946671] wsdisplay0 at intelfb0 kbdmux 1: console (default, vt100 emulation), using wskbd0

        But, I wouldn't mind if, even the later font was a bit smaller. Anyway, I'm soon on X and its not something I'll be diving into, I'm only inside this environment whenever I screw-up something and have to login as root to fix it 😉

        • rvp replied to this.
        • Jay likes this.

          pin the thing is that I believe I'm seeing both of them at boot time.
          The font is huge up to this point in the booting process, when everything is resized.

          There is a difference between the font size appearing to change because of resolution/mode switches, and larger fonts being used at the same resolution😁. You seem tot be describing the former; my focus was on the latter.

            rvp You're right, my bad... Anyway, when the resolution changes they are fine, even if I wouldn't mind them slightly smaller.

            6 months later

            rvp thats a good useful program. any ideas on how to convert ttf to this raw font format?

              doug213 any ideas on how to convert ttf to this raw font format?

              Talk to Fred Cambus first. He creates some of those fonts, I think. Otherwise, I could hack something up for you.

              2 months later
              6 days later

              rvp You seem tot be describing the former; my focus was on the latter.

              Is it possible to change the former? Would be awesome to have the same font during the entire boot-up process, before and after the resolution/mode switch.

              • rvp replied to this.

                oui Is it possible to change the former?

                As you may have intuited from the TTF -> WSFont conversion step, the kernel does not scale TTF fonts on its own (unlike Xorg). You can, however, use the same TTF font and scale it to different WSFonts, then load whichever you want. That work for you?

                • oui replied to this.
                • Jay likes this.

                  rvp Loading different WSfonts only works for me after the resolution/mode switch. As previously discussed in this thread, the default font during the boot-up process for me is Boldface 16x32 until i195drmkms loads and the font switches to Boldface 8x16.

                  For instance, I would like to use the SPLEEN6x12 WSfont during the entire boot-up process if possible. I compiled a custom kernel only using this font: options FONT_SPLEEN6x12 . However, the huge Boldface 16x32 font is still displayed at the start of the boot-up until i195drmkms loads and then it switches to the SPLEEN6x12 font.

                  • rvp replied to this.

                    oui I would like to use the SPLEEN6x12 WSfont during the entire boot-up process if possible.

                    That should work. Make sure that a) only FONT_SPLEEN6x12 is compiled in:

                    $ fgrep FONT_ /usr/src/sys/arch/amd64/conf/MYKERNEL
                    # options       FONT_BOLD8x16
                    # options       FONT_BOLD16x32
                    options         FONT_SPLEEN6x12
                    $

                    and,
                    b) both display drivers, genfb/vesafb and your DRMKMS one, use the same display resolution.
                    Since DRMKMS picks the highest possible one (and you can't change this conveniently), you'll have to make sure that genfb matches:

                    $ fgrep gop /boot.cfg
                    menu=Boot normally:gop 0;rndseed /var/db/entropy-file;boot
                    $

                    (On my laptop genfb picks the 1024x768 mode as default, rather than the 1366x768 chosen by intelfb. gop 0 makes it switch to 1366x768.)
                    Now you should have the same resolution in both drivers, and the also the same font.

                      rvp Thanks for the explanation rvp!

                      It seems that I'm having problem in getting the framebuffer drivers to use the exact same display resolution, adding gop 0 to boot.cfg doesn't unfortunately do anything for me..

                      • oui replied to this.

                        oui After some digging I found this page on changing the framebuffer resolution. It seems that gop 0 is UEFI specific but I'm using BIOS. According to the page, I could use the vesa command instead of gop but neither of these commands are available on my system and adding them to my boot.cfg has no effect.

                        • rvp replied to this.

                          oui Can you drop into the bootloader prompt, then type ? or help and see if either gop (amd64/aarch64) or vesa (x86) are displayed? Try gop list to get a list of available modes, then use the same one chosen by intelfb.

                          And, if you put that working gop command in /boot.cfg, put it in a menu entry item as I've shown. A standalone gop N command only works on 9.x. It no longer works in -HEAD that way.

                            rvp It works! vesa list only worked in the bootloader prompt. Thanks mvp!

                            • rvp replied to this.
                            • Jay likes this.

                              I built a custom kernel with FONT_SPLEEN no sooner had fcambus committed it to src a couple of years ago, but rolled back to default as I didn't like its rounded look. Well, to each one their own 😉.

                              One thing I often do when I compiling a custom kernel is setting console foreground color to bright green as opposed to white