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.)
18 PSF_MODEHASTAB = 0x02,
20 PSF_SEPARATOR = 0xffff
24 unsigned char magic1, magic2; /* Magic number */
25 unsigned char mode; /* PSF font mode */
26 unsigned char charsize; /* Character size */
29 #define PSF_MAGIC_OK(x) ((x)->magic1 == PSF_MAGIC1 && (x)->magic2 == PSF_MAGIC2)
31 static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize)
36 if (unit < 1 || unit > 32)
37 bb_error_msg_and_die("bad character size %d", unit);
39 buf = xzalloc(16 * 1024);
40 for (i = 0; i < fontsize; i++)
41 memcpy(buf + (32 * i), inbuf + (unit * i), unit);
43 #if defined(PIO_FONTX) && !defined(__sparc__)
45 struct consolefontdesc cfd;
47 cfd.charcount = fontsize;
48 cfd.charheight = unit;
51 if (!ioctl_or_perror(fd, PIO_FONTX, &cfd, "PIO_FONTX ioctl failed (will try PIO_FONT)"))
52 goto ret; /* success */
55 xioctl(fd, PIO_FONT, buf);
60 static void do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize)
62 struct unimapinit advice;
69 maxct = tailsz; /* more than enough */
70 up = xmalloc(maxct * sizeof(struct unipair));
72 for (glyph = 0; glyph < fontsize; glyph++) {
74 unicode = (((uint16_t) inbuf[1]) << 8) + inbuf[0];
77 if (unicode == PSF_SEPARATOR)
79 up[ct].unicode = unicode;
80 up[ct].fontpos = glyph;
85 /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP
86 this printf did not work on many kernels */
88 advice.advised_hashsize = 0;
89 advice.advised_hashstep = 0;
90 advice.advised_hashlevel = 0;
91 xioctl(fd, PIO_UNIMAPCLR, &advice);
94 xioctl(fd, PIO_UNIMAP, &ud);
97 static void do_load(int fd, struct psf_header *psfhdr, size_t len)
102 unsigned head0, head = head;
104 /* test for psf first */
105 if (len >= sizeof(struct psf_header) && PSF_MAGIC_OK(psfhdr)) {
106 if (psfhdr->mode > PSF_MAXMODE)
107 bb_error_msg_and_die("unsupported psf file mode");
108 fontsize = ((psfhdr->mode & PSF_MODE512) ? 512 : 256);
109 #if !defined(PIO_FONTX) || defined(__sparc__)
111 bb_error_msg_and_die("only fontsize 256 supported");
113 hastable = (psfhdr->mode & PSF_MODEHASTAB);
114 unit = psfhdr->charsize;
115 head0 = sizeof(struct psf_header);
117 head = head0 + fontsize * unit;
118 if (head > len || (!hastable && head != len))
119 bb_error_msg_and_die("input file: bad length");
121 /* file with three code pages? */
128 bb_error_msg_and_die("input file: bad length");
136 do_loadfont(fd, (unsigned char *)psfhdr + head0, unit, fontsize);
138 do_loadtable(fd, (unsigned char *)psfhdr + head, len - head, fontsize);
142 int loadfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
143 int loadfont_main(int argc UNUSED_PARAM, char **argv)
146 struct psf_header *psfhdr;
148 // no arguments allowed!
149 opt_complementary = "=0";
153 * We used to look at the length of the input file
154 * with stat(); now that we accept compressed files,
155 * just read the entire file.
157 len = 32*1024; // can't be larger
158 psfhdr = (struct psf_header *) xmalloc_read(STDIN_FILENO, &len);
159 // xmalloc_open_zipped_read_close(filename, &len);
161 bb_perror_msg_and_die("error reading input font");
162 do_load(get_console_fd_or_die(), psfhdr, len);
173 setfont [-O font+umap.orig] [-o font.orig] [-om cmap.orig]
174 [-ou umap.orig] [-N] [font.new ...] [-m cmap] [-u umap] [-C console]
177 -h NN Override font height
179 Save previous font in file
181 Save previous font and Unicode map in file
183 Store console map in file
185 Save previous Unicode map in file
187 Load console map or Unicode console map from file
189 Load Unicode table describing the font from file
194 0x80 U+0410 # CYRILLIC CAPITAL LETTER A
195 0x81 U+0411 # CYRILLIC CAPITAL LETTER BE
196 0x82 U+0412 # CYRILLIC CAPITAL LETTER VE
198 Set the font for the indicated console
203 #if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
204 static int ctoi(char *s)
206 if (s[0] == '\'' && s[1] != '\0' && s[2] == '\'' && s[3] == '\0')
209 if (s[0] == 'U' && s[1] == '+') {
215 return xstrtoul(s, 0);
219 int setfont_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
220 int setfont_main(int argc UNUSED_PARAM, char **argv)
225 struct psf_header *psfhdr;
227 const char *tty_name = CURRENT_TTY;
229 opt_complementary = "=1";
230 opts = getopt32(argv, "m:C:", &mapfilename, &tty_name);
233 fd = xopen(tty_name, O_NONBLOCK);
235 if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not ""
236 if (strchr(*argv, '/') != NULL) {
237 // goto default fonts location. don't die if doesn't exist
238 chdir(CONFIG_DEFAULT_SETFONT_DIR "/consolefonts");
239 // buglet: we don't return to current dir...
240 // affects "setfont FONT -m ./MAP" case
244 len = 32*1024; // can't be larger
245 psfhdr = (struct psf_header *) xmalloc_open_zipped_read_close(*argv, &len);
246 do_load(fd, psfhdr, len);
248 // load the screen map, if any
249 if (opts & 1) { // -m
250 unsigned mode = PIO_SCRNMAP;
253 if (sizeof(CONFIG_DEFAULT_SETFONT_DIR) > 1) { // if not ""
254 if (strchr(mapfilename, '/') != NULL) {
255 // goto default keymaps location
256 chdir(CONFIG_DEFAULT_SETFONT_DIR "/consoletrans");
260 map = xmalloc_open_zipped_read_close(mapfilename, &len);
262 bb_simple_perror_msg_and_die(mapfilename);
263 // file size is 256 or 512 bytes? -> assume binary map
264 if (len == E_TABSZ || len == 2*E_TABSZ) {
265 if (len == 2*E_TABSZ)
266 mode = PIO_UNISCRNMAP;
268 #if ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
269 // assume textual Unicode console maps:
270 // 0x00 U+0000 # NULL (NUL)
271 // 0x01 U+0001 # START OF HEADING (SOH)
272 // 0x02 U+0002 # START OF TEXT (STX)
273 // 0x03 U+0003 # END OF TEXT (ETX)
279 if (ENABLE_FEATURE_CLEAN_UP)
281 map = xmalloc(E_TABSZ * sizeof(unsigned short));
283 #define unicodes ((unsigned short *)map)
285 for (i = 0; i < E_TABSZ; i++)
286 unicodes[i] = 0xf000 + i;
288 parser = config_open(mapfilename);
289 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) {
290 // parse code/value pair
291 int a = ctoi(token[0]);
292 int b = ctoi(token[1]);
293 if (a < 0 || a >= E_TABSZ
294 || b < 0 || b > 65535
296 bb_error_msg_and_die("map format");
300 // unicode character is met?
302 mode = PIO_UNISCRNMAP;
304 if (ENABLE_FEATURE_CLEAN_UP)
305 config_close(parser);
307 if (mode != PIO_UNISCRNMAP) {
308 #define asciis ((unsigned char *)map)
309 for (i = 0; i < E_TABSZ; i++)
310 asciis[i] = unicodes[i];
315 #endif // ENABLE_FEATURE_SETFONT_TEXTUAL_MAP
318 xioctl(fd, mode, map);
320 if (ENABLE_FEATURE_CLEAN_UP)