vt: if loader did pass the font via metadata, use it

The built in 8x16 font may be way too small with large framebuffer
resolutions, to improve readability, use loader provied font.
This commit is contained in:
Toomas Soome 2020-11-30 11:45:47 +00:00
parent ed2b70e8af
commit 93b18e3730
4 changed files with 150 additions and 5 deletions

View File

@ -39,9 +39,11 @@ __FBSDID("$FreeBSD$");
#include <sys/consio.h>
#include <sys/eventhandler.h>
#include <sys/fbio.h>
#include <sys/font.h>
#include <sys/kbio.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
@ -163,8 +165,15 @@ extern unsigned char vt_logo_image[];
const unsigned int vt_logo_sprite_height;
#endif
/* Font. */
/*
* Console font. vt_font_loader will be filled with font data passed
* by loader. If there is no font passed by boot loader, we use built in
* default.
*/
extern struct vt_font vt_font_default;
static struct vt_font vt_font_loader;
static struct vt_font *vt_font_assigned = &vt_font_default;
#ifndef SC_NO_CUTPASTE
extern struct vt_mouse_cursor vt_default_mouse_pointer;
#endif
@ -1445,6 +1454,130 @@ vtterm_splash(struct vt_device *vd)
}
#endif
static struct vt_font *
parse_font_info_static(struct font_info *fi)
{
struct vt_font *vfp;
uintptr_t ptr;
uint32_t checksum;
if (fi == NULL)
return (NULL);
ptr = (uintptr_t)fi;
/*
* Compute and verify checksum. The total sum of all the fields
* must be 0.
*/
checksum = fi->fi_width;
checksum += fi->fi_height;
checksum += fi->fi_bitmap_size;
for (unsigned i = 0; i < VFNT_MAPS; i++)
checksum += fi->fi_map_count[i];
if (checksum + fi->fi_checksum != 0)
return (NULL);
ptr += sizeof(struct font_info);
ptr = roundup2(ptr, 8);
vfp = &vt_font_loader;
vfp->vf_height = fi->fi_height;
vfp->vf_width = fi->fi_width;
for (unsigned i = 0; i < VFNT_MAPS; i++) {
if (fi->fi_map_count[i] == 0)
continue;
vfp->vf_map_count[i] = fi->fi_map_count[i];
vfp->vf_map[i] = (vfnt_map_t *)ptr;
ptr += (fi->fi_map_count[i] * sizeof(vfnt_map_t));
ptr = roundup2(ptr, 8);
}
vfp->vf_bytes = (uint8_t *)ptr;
return (vfp);
}
static struct vt_font *
parse_font_info(struct font_info *fi)
{
struct vt_font *vfp;
uintptr_t ptr;
uint32_t checksum;
size_t size;
if (fi == NULL)
return (NULL);
ptr = (uintptr_t)fi;
/*
* Compute and verify checksum. The total sum of all the fields
* must be 0.
*/
checksum = fi->fi_width;
checksum += fi->fi_height;
checksum += fi->fi_bitmap_size;
for (unsigned i = 0; i < VFNT_MAPS; i++)
checksum += fi->fi_map_count[i];
if (checksum + fi->fi_checksum != 0)
return (NULL);
ptr += sizeof(struct font_info);
ptr = roundup2(ptr, 8);
vfp = &vt_font_loader;
vfp->vf_height = fi->fi_height;
vfp->vf_width = fi->fi_width;
for (unsigned i = 0; i < VFNT_MAPS; i++) {
if (fi->fi_map_count[i] == 0)
continue;
vfp->vf_map_count[i] = fi->fi_map_count[i];
size = fi->fi_map_count[i] * sizeof(vfnt_map_t);
vfp->vf_map[i] = malloc(size, M_VT, M_WAITOK | M_ZERO);
bcopy((vfnt_map_t *)ptr, vfp->vf_map[i], size);
ptr += size;
ptr = roundup2(ptr, 8);
}
vfp->vf_bytes = malloc(fi->fi_bitmap_size, M_VT, M_WAITOK | M_ZERO);
bcopy((uint8_t *)ptr, vfp->vf_bytes, fi->fi_bitmap_size);
return (vfp);
}
static void
vt_init_font(void *arg)
{
caddr_t kmdp;
struct font_info *fi;
struct vt_font *font;
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
fi = MD_FETCH(kmdp, MODINFOMD_FONT, struct font_info *);
font = parse_font_info(fi);
if (font != NULL)
vt_font_assigned = font;
}
SYSINIT(vt_init_font, SI_SUB_KMEM, SI_ORDER_ANY, vt_init_font, &vt_consdev);
static void
vt_init_font_static(void)
{
caddr_t kmdp;
struct font_info *fi;
struct vt_font *font;
kmdp = preload_search_by_type("elf kernel");
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
fi = MD_FETCH(kmdp, MODINFOMD_FONT, struct font_info *);
font = parse_font_info_static(fi);
if (font != NULL)
vt_font_assigned = font;
}
static void
vtterm_cnprobe(struct terminal *tm, struct consdev *cp)
{
@ -1491,9 +1624,11 @@ vtterm_cnprobe(struct terminal *tm, struct consdev *cp)
vd->vd_windows[VT_CONSWINDOW] = vw;
sprintf(cp->cn_name, "ttyv%r", VT_UNIT(vw));
vt_init_font_static();
/* Attach default font if not in TEXTMODE. */
if ((vd->vd_flags & VDF_TEXTMODE) == 0) {
vw->vw_font = vtfont_ref(&vt_font_default);
vw->vw_font = vtfont_ref(vt_font_assigned);
vt_compute_drawable_area(vw);
}
@ -2431,7 +2566,7 @@ vtterm_ioctl(struct terminal *tm, u_long cmd, caddr_t data,
}
case PIO_VFONT_DEFAULT: {
/* Reset to default font. */
error = vt_change_font(vw, &vt_font_default);
error = vt_change_font(vw, vt_font_assigned);
return (error);
}
case GIO_SCRNMAP: {
@ -2691,7 +2826,7 @@ vt_allocate_window(struct vt_device *vd, unsigned int window)
vw->vw_kbdmode = K_XLATE;
if ((vd->vd_flags & VDF_TEXTMODE) == 0) {
vw->vw_font = vtfont_ref(&vt_font_default);
vw->vw_font = vtfont_ref(vt_font_assigned);
vt_compute_drawable_area(vw);
}
@ -2788,7 +2923,7 @@ vt_resize(struct vt_device *vd)
VT_LOCK(vd);
/* Assign default font to window, if not textmode. */
if (!(vd->vd_flags & VDF_TEXTMODE) && vw->vw_font == NULL)
vw->vw_font = vtfont_ref(&vt_font_default);
vw->vw_font = vtfont_ref(vt_font_assigned);
VT_UNLOCK(vd);
/* Resize terminal windows */

View File

@ -295,6 +295,7 @@ preload_bootstrap_relocate(vm_offset_t offset)
/* Deal with the ones that we know we have to fix */
switch (hdr[0]) {
case MODINFO_ADDR:
case MODINFO_METADATA|MODINFOMD_FONT:
case MODINFO_METADATA|MODINFOMD_SSYM:
case MODINFO_METADATA|MODINFOMD_ESYM:
ptr = (vm_offset_t *)(curp + (sizeof(uint32_t) * 2));

View File

@ -57,6 +57,14 @@ enum vfnt_map_type {
VFNT_MAPS /* Number of maps. */
};
struct font_info {
int32_t fi_checksum;
uint32_t fi_width;
uint32_t fi_height;
uint32_t fi_bitmap_size;
uint32_t fi_map_count[VFNT_MAPS];
};
struct vfnt_map {
uint32_t vfm_src;
uint16_t vfm_dst;

View File

@ -226,6 +226,7 @@ void *linker_hwpmc_list_objects(void);
#define MODINFOMD_CTORS_SIZE 0x000b /* size of .ctors */
#define MODINFOMD_FW_HANDLE 0x000c /* Firmware dependent handle */
#define MODINFOMD_KEYBUF 0x000d /* Crypto key intake buffer */
#define MODINFOMD_FONT 0x000e /* Console font */
#define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */
#define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY) /* depends on */