1 /* vi: set sw=4 ts=4: */
3 * loadfont.c - Eugene Crosser & Andries Brouwer
7 * Loads the console font, and possibly the corresponding screen map(s).
8 * (Adapted for busybox by Matej Vela.)
14 #define KDFONTOP 0x4B72
15 struct console_font_op {
16 unsigned op; /* KD_FONT_OP_* */
17 unsigned flags; /* KD_FONT_FLAG_* */
18 unsigned width, height;
20 unsigned char *data; /* font data with height fixed to 32 */
23 #define KD_FONT_OP_SET 0 /* Set font */
24 #define KD_FONT_OP_GET 1 /* Get font */
25 #define KD_FONT_OP_SET_DEFAULT 2 /* Set font to default,
26 data points to name / NULL */
27 #define KD_FONT_OP_COPY 3 /* Copy from another console */
29 #define KD_FONT_FLAG_OLD 0x80000000 /* Invoked via old interface */
30 #define KD_FONT_FLAG_DONT_RECALC 1 /* Don't call adjust_height() */
31 /* (Used internally for PIO_FONT support) */
40 PSF_MODEHASTAB = 0x02,
42 PSF_SEPARATOR = 0xffff
46 unsigned char magic1, magic2; /* Magic number */
47 unsigned char mode; /* PSF font mode */
48 unsigned char charsize; /* Character size */
51 #define PSF_MAGIC_OK(x) ((x)->magic1 == PSF_MAGIC1 && (x)->magic2 == PSF_MAGIC2)
53 static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
58 if (unit < 1 || unit > 32)
59 bb_error_msg_and_die("bad character size %d", unit);
61 buf = xzalloc(16 * 1024);
62 for (i = 0; i < fontsize; i++)
63 memcpy(buf + (32 * i), inbuf + (unit * i), unit);
66 struct console_font_op cfo;
68 cfo.op = KD_FONT_OP_SET;
72 cfo.charcount = fontsize;
73 cfo.data = (void*)buf;
75 if (!ioctl_or_perror(fd, KDFONTOP, &cfo, "KDFONTOP ioctl failed (will try PIO_FONTX)"))
76 goto ret; /* success */
78 xioctl(fd, KDFONTOP, &cfo);
83 /* These ones do not honour -C tty (they set font on current tty regardless)
84 * On x86, this distinction is visible on framebuffer consoles
85 * (regular character consoles may have only one shared font anyway)
87 #if defined(PIO_FONTX) && !defined(__sparc__)
89 struct consolefontdesc cfd;
91 cfd.charcount = fontsize;
92 cfd.charheight = unit;
95 if (!ioctl_or_perror(fd, PIO_FONTX, &cfd, "PIO_FONTX ioctl failed (will try PIO_FONT)"))
96 goto ret; /* success */
99 xioctl(fd, PIO_FONT, buf);
105 static void do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
107 struct unimapinit advice;
108 struct unimapdesc ud;
114 maxct = tailsz; /* more than enough */
115 up = xmalloc(maxct * sizeof(struct unipair));
117 for (glyph = 0; glyph < fontsize; glyph++) {
118 while (tailsz >= 2) {
119 unicode = (((uint16_t) inbuf[1]) << 8) + inbuf[0];
122 if (unicode == PSF_SEPARATOR)
124 up[ct].unicode = unicode;
125 up[ct].fontpos = glyph;
130 /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP
131 this printf did not work on many kernels */
133 advice.advised_hashsize = 0;
134 advice.advised_hashstep = 0;
135 advice.advised_hashlevel = 0;
136 xioctl(fd, PIO_UNIMAPCLR, &advice);
139 xioctl(fd, PIO_UNIMAP, &ud);
142 static void do_load(int fd, struct psf_header *psfhdr, size_t len)
147 unsigned head0, head = head;
149 /* test for psf first */
150 if (len >= sizeof(struct psf_header) && PSF_MAGIC_OK(psfhdr)) {
151 if (psfhdr->mode > PSF_MAXMODE)
152 bb_error_msg_and_die("unsupported psf file mode");
153 fontsize = ((psfhdr->mode & PSF_MODE512) ? 512 : 256);
154 #if !defined(PIO_FONTX) || defined(__sparc__)
156 bb_error_msg_and_die("only fontsize 256 supported");
158 hastable = (psfhdr->mode & PSF_MODEHASTAB);
159 unit = psfhdr->charsize;
160 head0 = sizeof(struct psf_header);
162 head = head0 + fontsize * unit;
163 if (head > len || (!hastable && head != len))
164 bb_error_msg_and_die("input file: bad length");
166 /* file with three code pages? */
173 bb_error_msg_and_die("input file: bad length");
181 do_loadfont(fd, (unsigned char *)psfhdr + head0, unit, fontsize);
183 do_loadtable(fd, (unsigned char *)psfhdr + head, len - head, fontsize);
187 int loadfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
188 int loadfont_main(int argc UNUSED_PARAM, char **argv)
191 struct psf_header *psfhdr;
193 // no arguments allowed!
194 opt_complementary = "=0";
198 * We used to look at the length of the input file
199 * with stat(); now that we accept compressed files,
200 * just read the entire file.
202 len = 32*1024; // can't be larger
203 psfhdr = xmalloc_read(STDIN_FILENO, &len);
204 // xmalloc_open_zipped_read_close(filename, &len);
206 bb_perror_msg_and_die("error reading input font");
207 do_load(get_console_fd_or_die(), psfhdr, len);
218 setfont [-O font+umap.orig] [-o font.orig] [-om cmap.orig]
219 [-ou umap.orig] [-N] [font.new ...] [-m cmap] [-u umap] [-C console]
222 -h NN Override font height
224 Save previous font in file
226 Save previous font and Unicode map in file
228 Store console map in file
230 Save previous Unicode map in file
232 Load console map or Unicode console map from file
234 Load Unicode table describing the font from file
239 0x80 U+0410 # CYRILLIC CAPITAL LETTER A
240 0x81 U+0411 # CYRILLIC CAPITAL LETTER BE
241 0x82 U+0412 # CYRILLIC CAPITAL LETTER VE
243 Set the font for the indicated console
248 #if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
249 static int ctoi(char *s)
251 if (s[0] == '\'' && s[1] != '\0' && s[2] == '\'' && s[3] == '\0')
254 if (s[0] == 'U' && s[1] == '+') {
260 return xstrtoul(s, 0);
264 int setfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
265 int setfont_main(int argc UNUSED_PARAM, char **argv)
270 struct psf_header *psfhdr;
272 const char *tty_name = CURRENT_TTY;
274 opt_complementary = "=1";
275 opts = getopt32(argv, "m:C:", &mapfilename, &tty_name);
278 fd = xopen(tty_name, O_NONBLOCK);
280 if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not ""
281 if (*argv[0] != '/') {
282 // goto default fonts location. don't die if doesn't exist
283 chdir(CONFIG_DEFAULT_SETFONT_DIR "/consolefonts");
287 len = 32*1024; // can't be larger
288 psfhdr = xmalloc_open_zipped_read_close(*argv, &len);
290 bb_simple_perror_msg_and_die(*argv);
291 do_load(fd, psfhdr, len);
293 // load the screen map, if any
294 if (opts & 1) { // -m
295 unsigned mode = PIO_SCRNMAP;
298 if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not ""
299 if (mapfilename[0] != '/') {
300 // goto default keymaps location
301 chdir(CONFIG_DEFAULT_SETFONT_DIR "/consoletrans");
305 map = xmalloc_open_zipped_read_close(mapfilename, &len);
307 bb_simple_perror_msg_and_die(mapfilename);
308 // file size is 256 or 512 bytes? -> assume binary map
309 if (len == E_TABSZ || len == 2*E_TABSZ) {
310 if (len == 2*E_TABSZ)
311 mode = PIO_UNISCRNMAP;
313 #if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
314 // assume textual Unicode console maps:
315 // 0x00 U+0000 # NULL (NUL)
316 // 0x01 U+0001 # START OF HEADING (SOH)
317 // 0x02 U+0002 # START OF TEXT (STX)
318 // 0x03 U+0003 # END OF TEXT (ETX)
324 if (ENABLE_FEATURE_CLEAN_UP)
326 map = xmalloc(E_TABSZ * sizeof(unsigned short));
328 #define unicodes ((unsigned short *)map)
330 for (i = 0; i < E_TABSZ; i++)
331 unicodes[i] = 0xf000 + i;
333 parser = config_open(mapfilename);
334 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) {
335 // parse code/value pair
336 int a = ctoi(token[0]);
337 int b = ctoi(token[1]);
338 if (a < 0 || a >= E_TABSZ
339 || b < 0 || b > 65535
341 bb_error_msg_and_die("map format");
345 // unicode character is met?
347 mode = PIO_UNISCRNMAP;
349 if (ENABLE_FEATURE_CLEAN_UP)
350 config_close(parser);
352 if (mode != PIO_UNISCRNMAP) {
353 #define asciis ((unsigned char *)map)
354 for (i = 0; i < E_TABSZ; i++)
355 asciis[i] = unicodes[i];
360 #endif // ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
363 xioctl(fd, mode, map);
365 if (ENABLE_FEATURE_CLEAN_UP)