Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/console-tools/loadfont.c

Parent Directory Parent Directory | Revision Log 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)
-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     }