/* * Copyright (c) Rene Ladan , 2-claused BSD license * * biosfont character device * * Based on 5.X version of echo device, FreeBSD Architecture Handbook */ #include "biosfont.h" #include /* printf, bootverbose */ #include #include /* defines used in kernel.h */ #include /* types used in module initialization */ #include /* cdevsw struct */ #include /* S_Ixxxx */ #include /* required for vm/pmap.h */ #include /* required for machine/pmap.h */ #include /* required for vmparam.h */ #include /* KERNBASE */ /* Function prototypes */ static d_ioctl_t biosfont_ioctl; /* Character device entry points */ static struct cdevsw biosfont_cdevsw = { .d_version = D_VERSION, .d_flags = D_MEM, /* prevent kernel panic */ .d_name = "biosfont", .d_ioctl = biosfont_ioctl, }; /* Character device */ static struct cdev *biosfont_dev; /* * Addresses are stored as segment:offset, in little endian, thus * 0x000ffa6e aka f000:fa6e is stored as 0x6e 0xfa 0x00 0xf0 * Absolute address is segment * 16 + offset. * * XXX This define is i386-specific, but there is a rumour that the font * bitmaps only exist on i386 */ #define SEGOFS(i) (((i & 0xffff0000) >> 12) + ((i & 0x0000ffff))) static u_long fontbase; /* * This function is called by the kld[un]load(2) system calls to * determine what actions to take when a module is loaded or unloaded. */ static int biosfont_loader(struct module *m __unused, int what, void *arg __unused) { int err = 0; u_long *p; /* "read-only" variable to prevent garbling memory */ switch (what) { case MOD_LOAD: /* kldload */ p = (u_long *) (KERNBASE + 0x0000007CL); /* correct byte order for i386 */ fontbase = SEGOFS(*p); biosfont_dev = make_dev(&biosfont_cdevsw, 0, /* auto-minor-device */ UID_ROOT, GID_WHEEL, S_IRUSR | S_IRGRP | S_IROTH, biosfont_cdevsw.d_name); if (bootverbose) printf(": upper=%08lx\n", fontbase); break; case MOD_UNLOAD: destroy_dev(biosfont_dev); break; default: err = EINVAL; break; } return(err); } int biosfont_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, int fflag __unused, struct thread *td __unused) { u_char i; u_long start; u_char *p; t_biosfont *request = (t_biosfont *) data; switch (cmd) { case BIOSFONT_ASCII: /* determine start of bitmap table */ start = (u_long) (KERNBASE + request->nr * 8); if (request->nr < 0x80) start += 0x000FFA6EL; else start += (u_long) (fontbase - 1024); /* copy bitmap to userland */ for (i = 0; i < 8; i++) { p = (u_char *) (start + i); request->bitmap[i] = *p; } return(0); default: /* should not happen */ printf(": cmd, nr = %08lx, %02x\n", cmd, request->nr); return(EINVAL); } } DEV_MODULE(biosfont, biosfont_loader, NULL);