Annotation of /trunk/mkinitrd-magellan/busybox/console-tools/loadfont.c
Parent Directory | Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 4550 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 4550 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | niro | 532 | /* vi: set sw=4 ts=4: */ |
2 | /* | ||
3 | * loadfont.c - Eugene Crosser & Andries Brouwer | ||
4 | * | ||
5 | * Version 0.96bb | ||
6 | * | ||
7 | * Loads the console font, and possibly the corresponding screen map(s). | ||
8 | * (Adapted for busybox by Matej Vela.) | ||
9 | */ | ||
10 | #include "busybox.h" | ||
11 | #include <sys/kd.h> | ||
12 | |||
13 | enum { | ||
14 | PSF_MAGIC1 = 0x36, | ||
15 | PSF_MAGIC2 = 0x04, | ||
16 | |||
17 | PSF_MODE512 = 0x01, | ||
18 | PSF_MODEHASTAB = 0x02, | ||
19 | PSF_MAXMODE = 0x03, | ||
20 | PSF_SEPARATOR = 0xFFFF | ||
21 | }; | ||
22 | |||
23 | struct psf_header { | ||
24 | unsigned char magic1, magic2; /* Magic number */ | ||
25 | unsigned char mode; /* PSF font mode */ | ||
26 | unsigned char charsize; /* Character size */ | ||
27 | }; | ||
28 | |||
29 | #define PSF_MAGIC_OK(x) ((x).magic1 == PSF_MAGIC1 && (x).magic2 == PSF_MAGIC2) | ||
30 | |||
31 | static void loadnewfont(int fd); | ||
32 | |||
33 | int loadfont_main(int argc, char **argv) | ||
34 | { | ||
35 | int fd; | ||
36 | |||
37 | if (argc != 1) | ||
38 | bb_show_usage(); | ||
39 | |||
40 | fd = xopen(CURRENT_VC, O_RDWR); | ||
41 | loadnewfont(fd); | ||
42 | |||
43 | return EXIT_SUCCESS; | ||
44 | } | ||
45 | |||
46 | static void do_loadfont(int fd, unsigned char *inbuf, int unit, int fontsize) | ||
47 | { | ||
48 | char buf[16384]; | ||
49 | int i; | ||
50 | |||
51 | memset(buf, 0, sizeof(buf)); | ||
52 | |||
53 | if (unit < 1 || unit > 32) | ||
54 | bb_error_msg_and_die("bad character size %d", unit); | ||
55 | |||
56 | for (i = 0; i < fontsize; i++) | ||
57 | memcpy(buf + (32 * i), inbuf + (unit * i), unit); | ||
58 | |||
59 | #if defined( PIO_FONTX ) && !defined( __sparc__ ) | ||
60 | { | ||
61 | struct consolefontdesc cfd; | ||
62 | |||
63 | cfd.charcount = fontsize; | ||
64 | cfd.charheight = unit; | ||
65 | cfd.chardata = buf; | ||
66 | |||
67 | if (ioctl(fd, PIO_FONTX, &cfd) == 0) | ||
68 | return; /* success */ | ||
69 | bb_perror_msg("PIO_FONTX ioctl error (trying PIO_FONT)"); | ||
70 | } | ||
71 | #endif | ||
72 | if (ioctl(fd, PIO_FONT, buf)) | ||
73 | bb_perror_msg_and_die("PIO_FONT ioctl error"); | ||
74 | } | ||
75 | |||
76 | static void | ||
77 | do_loadtable(int fd, unsigned char *inbuf, int tailsz, int fontsize) | ||
78 | { | ||
79 | struct unimapinit advice; | ||
80 | struct unimapdesc ud; | ||
81 | struct unipair *up; | ||
82 | int ct = 0, maxct; | ||
83 | int glyph; | ||
84 | uint16_t unicode; | ||
85 | |||
86 | maxct = tailsz; /* more than enough */ | ||
87 | up = xmalloc(maxct * sizeof(struct unipair)); | ||
88 | |||
89 | for (glyph = 0; glyph < fontsize; glyph++) { | ||
90 | while (tailsz >= 2) { | ||
91 | unicode = (((uint16_t) inbuf[1]) << 8) + inbuf[0]; | ||
92 | tailsz -= 2; | ||
93 | inbuf += 2; | ||
94 | if (unicode == PSF_SEPARATOR) | ||
95 | break; | ||
96 | up[ct].unicode = unicode; | ||
97 | up[ct].fontpos = glyph; | ||
98 | ct++; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | /* Note: after PIO_UNIMAPCLR and before PIO_UNIMAP | ||
103 | this printf did not work on many kernels */ | ||
104 | |||
105 | advice.advised_hashsize = 0; | ||
106 | advice.advised_hashstep = 0; | ||
107 | advice.advised_hashlevel = 0; | ||
108 | if (ioctl(fd, PIO_UNIMAPCLR, &advice)) { | ||
109 | #ifdef ENOIOCTLCMD | ||
110 | if (errno == ENOIOCTLCMD) { | ||
111 | bb_error_msg("it seems this kernel is older than 1.1.92"); | ||
112 | bb_error_msg_and_die("no Unicode mapping table loaded"); | ||
113 | } else | ||
114 | #endif | ||
115 | bb_perror_msg_and_die("PIO_UNIMAPCLR"); | ||
116 | } | ||
117 | ud.entry_ct = ct; | ||
118 | ud.entries = up; | ||
119 | if (ioctl(fd, PIO_UNIMAP, &ud)) { | ||
120 | bb_perror_msg_and_die("PIO_UNIMAP"); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static void loadnewfont(int fd) | ||
125 | { | ||
126 | int unit; | ||
127 | unsigned char inbuf[32768]; /* primitive */ | ||
128 | unsigned int inputlth, offset; | ||
129 | |||
130 | /* | ||
131 | * We used to look at the length of the input file | ||
132 | * with stat(); now that we accept compressed files, | ||
133 | * just read the entire file. | ||
134 | */ | ||
135 | inputlth = fread(inbuf, 1, sizeof(inbuf), stdin); | ||
136 | if (ferror(stdin)) | ||
137 | bb_perror_msg_and_die("error reading input font"); | ||
138 | /* use malloc/realloc in case of giant files; | ||
139 | maybe these do not occur: 16kB for the font, | ||
140 | and 16kB for the map leaves 32 unicode values | ||
141 | for each font position */ | ||
142 | if (!feof(stdin)) | ||
143 | bb_perror_msg_and_die("font too large"); | ||
144 | |||
145 | /* test for psf first */ | ||
146 | { | ||
147 | struct psf_header psfhdr; | ||
148 | int fontsize; | ||
149 | int hastable; | ||
150 | unsigned int head0, head; | ||
151 | |||
152 | if (inputlth < sizeof(struct psf_header)) | ||
153 | goto no_psf; | ||
154 | |||
155 | psfhdr = *(struct psf_header *) &inbuf[0]; | ||
156 | |||
157 | if (!PSF_MAGIC_OK(psfhdr)) | ||
158 | goto no_psf; | ||
159 | |||
160 | if (psfhdr.mode > PSF_MAXMODE) | ||
161 | bb_error_msg_and_die("unsupported psf file mode"); | ||
162 | fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); | ||
163 | #if !defined( PIO_FONTX ) || defined( __sparc__ ) | ||
164 | if (fontsize != 256) | ||
165 | bb_error_msg_and_die("only fontsize 256 supported"); | ||
166 | #endif | ||
167 | hastable = (psfhdr.mode & PSF_MODEHASTAB); | ||
168 | unit = psfhdr.charsize; | ||
169 | head0 = sizeof(struct psf_header); | ||
170 | |||
171 | head = head0 + fontsize * unit; | ||
172 | if (head > inputlth || (!hastable && head != inputlth)) | ||
173 | bb_error_msg_and_die("input file: bad length"); | ||
174 | do_loadfont(fd, inbuf + head0, unit, fontsize); | ||
175 | if (hastable) | ||
176 | do_loadtable(fd, inbuf + head, inputlth - head, fontsize); | ||
177 | return; | ||
178 | } | ||
179 | no_psf: | ||
180 | |||
181 | /* file with three code pages? */ | ||
182 | if (inputlth == 9780) { | ||
183 | offset = 40; | ||
184 | unit = 16; | ||
185 | } else { | ||
186 | /* bare font */ | ||
187 | if (inputlth & 0377) | ||
188 | bb_error_msg_and_die("bad input file size"); | ||
189 | offset = 0; | ||
190 | unit = inputlth / 256; | ||
191 | } | ||
192 | do_loadfont(fd, inbuf + offset, unit, 256); | ||
193 | } |