Contents of /trunk/linterm_tools/fw_builder/bootsplash/splash.c
Parent Directory | Revision Log
Revision 658 -
(show annotations)
(download)
Mon Jan 14 16:57:24 2008 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 11953 byte(s)
Mon Jan 14 16:57:24 2008 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 11953 byte(s)
initial import
1 | /* Splash control program. |
2 | * |
3 | * (c) 2001, 2002, 2003 by Stefan Reinauer <stepan@suse.de> |
4 | * |
5 | * This program is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU General Public License |
7 | * as published by the Free Software Foundation; either version |
8 | * 2 of the License, or (at your option) any later version. |
9 | * |
10 | */ |
11 | |
12 | #include <sys/types.h> |
13 | #include <sys/stat.h> |
14 | #include <fcntl.h> |
15 | #include <unistd.h> |
16 | #include <errno.h> |
17 | #include <stdio.h> |
18 | #include <string.h> |
19 | #include <stdlib.h> |
20 | #include <libgen.h> |
21 | #include <getopt.h> |
22 | |
23 | |
24 | #define PROCSPLASH "/proc/splash" |
25 | #define BUFSIZE 4096 |
26 | #if 1 |
27 | #define DEBUG(x...) |
28 | #else |
29 | #define DEBUG(x...) printf(x) |
30 | #endif |
31 | |
32 | long unit = 0; |
33 | long version = 1; |
34 | long state = -1; |
35 | long fgcolor = -1; |
36 | long bgcolor = -1; |
37 | long tx = -1; |
38 | long ty = -1; |
39 | long tw = -1; |
40 | long th = -1; |
41 | long px = 0; |
42 | long py = 0; |
43 | long pw = 0; |
44 | long ph = 0; |
45 | long pr = 0; |
46 | long pg = 0; |
47 | long pb = 0; |
48 | long pa = 160; |
49 | long pf = 1; |
50 | long pc = 0x141464; |
51 | long ptl = 0xffff; |
52 | long pbr = 0x00; |
53 | long ax = 0; |
54 | long ay = 0; |
55 | long progress = 0; |
56 | long overpaintok = 0; |
57 | long percent = 0; |
58 | long text = 0; |
59 | char *jpgfile = 0; |
60 | char *silentjpgfile = 0; |
61 | char splashdscname[512]; |
62 | |
63 | int boxcount; |
64 | unsigned char boxes[12 * 256]; |
65 | int sboxcount; |
66 | unsigned char sboxes[12 * 256]; |
67 | |
68 | struct parstab { |
69 | char *name; |
70 | long *val; |
71 | char **str; |
72 | } parstab[] = { |
73 | { "unit", &unit }, |
74 | { "version", &version }, |
75 | { "state", &state }, |
76 | { "fgcolor", &fgcolor }, |
77 | { "bgcolor", &bgcolor }, |
78 | /* v1+ */ |
79 | { "tx", &tx }, |
80 | { "ty", &ty }, |
81 | { "tw", &tw }, |
82 | { "th", &th }, |
83 | /* v2+ */ |
84 | { "px", &px }, |
85 | { "py", &py }, |
86 | { "pw", &pw }, |
87 | { "ph", &ph }, |
88 | { "pr", &pr }, |
89 | { "pg", &pg }, |
90 | { "pb", &pb }, |
91 | { "ax", &ax }, |
92 | { "ay", &ay }, |
93 | /* v3+ */ |
94 | /* independant */ |
95 | { "progress_enable", &progress }, |
96 | { "progress_x", &progress }, |
97 | { "progress_y", &progress }, |
98 | { "progress_width", &progress }, |
99 | { "progress_height", &progress }, |
100 | { "progress_fgcolor", &progress }, |
101 | { "progress_bgcolor", &progress }, |
102 | { "text_size", &text }, |
103 | { "text_color", &text }, |
104 | { "text_x", &text }, |
105 | { "text_y", &text }, |
106 | { "text_font", (long *) 0 }, |
107 | { "silentjpeg", (long *) 0, &silentjpgfile }, |
108 | { "percent", &percent }, |
109 | { "overpaintok", &overpaintok }, |
110 | { "jpeg", (long *) 0, &jpgfile }, |
111 | { (char *) 0, (long *) 0 } |
112 | }; |
113 | |
114 | void parsebox(char *pl) |
115 | { |
116 | int co[4]; |
117 | int i, j, c, d = 0; |
118 | char cols[16]; |
119 | unsigned char *bp; |
120 | int boxcnt; |
121 | int isibox = 0; |
122 | int *boxcntp; |
123 | unsigned char *boxptr; |
124 | char *p = pl + 3; |
125 | int noover = 0; |
126 | int hidemax = 0; |
127 | |
128 | boxcntp = &boxcount; |
129 | boxptr = boxes; |
130 | for (i = 0; i < 4; i++) { |
131 | if (*p != ' ' && *p != '\t' && *p != '=') { |
132 | fprintf(stderr, "syntax error: '%c' %s\n", *p, pl); |
133 | exit(1); |
134 | } |
135 | while (*p == ' ' || *p == '\t' || *p == '=') |
136 | p++; |
137 | if (i == 0 && !strncmp(p, "silent", 6)) { |
138 | i--; |
139 | boxcntp = &sboxcount; |
140 | boxptr = sboxes; |
141 | p += 6; |
142 | continue; |
143 | } |
144 | if (i == 0 && !strncmp(p, "inter", 5)) { |
145 | i--; |
146 | isibox = 1; |
147 | p += 5; |
148 | continue; |
149 | } |
150 | if (i == 0 && !strncmp(p, "noover", 6)) { |
151 | i--; |
152 | noover = 1; |
153 | p += 6; |
154 | continue; |
155 | } |
156 | if (i == 0 && !strncmp(p, "hidemax", 7)) { |
157 | i--; |
158 | hidemax = 1; |
159 | p += 7; |
160 | continue; |
161 | } |
162 | co[i] = strtol(p, (char **) NULL, 0); |
163 | while (*p == 'x' || (*p >= '0' && *p <= '9') |
164 | || (*p >= 'a' && *p <= 'f') || (*p >= 'A' |
165 | && *p <= 'F')) |
166 | p++; |
167 | } |
168 | for (i = 0; i < 4; i++) { |
169 | if (*p != ' ' && *p != '\t') { |
170 | fprintf(stderr, "syntax error: %s\n", pl); |
171 | exit(1); |
172 | } |
173 | while (*p == ' ' || *p == '\t') |
174 | p++; |
175 | if (i == 1 && *p == 0) |
176 | break; |
177 | if (*p++ != '#') { |
178 | fprintf(stderr, "syntax error: %s\n", pl); |
179 | exit(1); |
180 | } |
181 | for (j = 0; j < 8; j++) { |
182 | c = *p++; |
183 | if (c >= '0' && c <= '9') |
184 | c -= '0'; |
185 | else if (c >= 'a' && c <= 'f') |
186 | c -= 'a' - 10; |
187 | else if (c >= 'A' && c <= 'F') |
188 | c -= 'A' - 10; |
189 | else { |
190 | fprintf(stderr, "syntax error: %s\n", pl); |
191 | exit(1); |
192 | } |
193 | if (!(j & 1)) { |
194 | d = c; |
195 | continue; |
196 | } |
197 | c += d << 4; |
198 | cols[i * 4 + (j >> 1)] = c; |
199 | if (j == 5 && (*p == 0 || *p == ' ' || *p == '\t')) { |
200 | cols[i * 4 + 3] = 255; |
201 | break; |
202 | } |
203 | } |
204 | if (*p == 0 && i == 0) { |
205 | i = 1; |
206 | break; |
207 | } |
208 | } |
209 | while (*p == ' ' || *p == '\t') |
210 | p++; |
211 | if (*p) { |
212 | fprintf(stderr, "syntax error: %s\n", pl); |
213 | exit(1); |
214 | } |
215 | boxcnt = *boxcntp; |
216 | if (boxcnt >= 254) { |
217 | fprintf(stderr, "too many boxes\n"); |
218 | exit(1); |
219 | } |
220 | bp = boxptr + 12 * boxcnt++; |
221 | if (isibox) |
222 | co[0] = ~co[0]; |
223 | if (i > 1) { |
224 | co[1] = ~co[1]; |
225 | boxcnt++; |
226 | } |
227 | if (noover) |
228 | co[2] = ~co[2]; |
229 | if (hidemax) |
230 | co[3] = ~co[3]; |
231 | *bp++ = co[0] & 255; |
232 | *bp++ = co[0] >> 8; |
233 | *bp++ = co[1] & 255; |
234 | *bp++ = co[1] >> 8; |
235 | *bp++ = co[2] & 255; |
236 | *bp++ = co[2] >> 8; |
237 | *bp++ = co[3] & 255; |
238 | *bp++ = co[3] >> 8; |
239 | for (j = 0; j < i * 4; j++) |
240 | *bp++ = cols[j]; |
241 | *boxcntp = boxcnt; |
242 | } |
243 | |
244 | void setsplash(char *cfgfile, int filterflag, int verbose_only) |
245 | { |
246 | struct stat stb; |
247 | char buf[256]; |
248 | char *p; |
249 | int l, size, fd; |
250 | FILE *fp = 0; |
251 | FILE *sfp = 0; |
252 | struct parstab *pt; |
253 | unsigned char *pic; |
254 | int silentl = 0; |
255 | |
256 | if (cfgfile) { |
257 | if ((fp = fopen(cfgfile, "r")) == 0) { |
258 | perror(cfgfile); |
259 | exit(1); |
260 | } |
261 | while (fgets(buf, sizeof(buf), fp)) { |
262 | l = strlen(buf); |
263 | if (l == 0) |
264 | continue; |
265 | if (l == sizeof(buf) - 1) { |
266 | fprintf(stderr, "line too long\n"); |
267 | exit(1); |
268 | } |
269 | buf[--l] = 0; |
270 | while (l |
271 | && (buf[l - 1] == ' ' |
272 | || (buf[l - 1] == '\t'))) |
273 | buf[--l] = 0; |
274 | for (p = buf; *p == ' ' || *p == '\t'; p++); |
275 | if (*p == 0 || *p == '#') |
276 | continue; |
277 | if (!strncmp(p, "box", 3)) { |
278 | parsebox(p); |
279 | continue; |
280 | } |
281 | for (pt = parstab; pt->name; pt++) { |
282 | l = strlen(pt->name); |
283 | if (!strncmp(p, pt->name, l) |
284 | && (p[l] == ' ' || p[l] == '\t' |
285 | || p[l] == '=')) |
286 | break; |
287 | } |
288 | if (!pt->name) { |
289 | fprintf(stderr, "syntax error: %s\n", p); |
290 | exit(1); |
291 | } |
292 | while (p[l] == ' ' || p[l] == '\t') |
293 | l++; |
294 | if (p[l++] != '=') { |
295 | fprintf(stderr, "syntax error: %s\n", p); |
296 | exit(1); |
297 | } |
298 | while (p[l] == ' ' || p[l] == '\t') |
299 | l++; |
300 | if (pt->val) |
301 | *pt->val = |
302 | strtol(p + l, (char **) NULL, 0); |
303 | else |
304 | *pt->str = strdup(p + l); |
305 | } |
306 | fclose(fp); |
307 | if (!jpgfile) { |
308 | l = strlen(cfgfile); |
309 | if (l > 4 && !strcmp(cfgfile + l - 4, ".cfg")) { |
310 | jpgfile = strdup(cfgfile); |
311 | strcpy(jpgfile + l - 4, ".jpg"); |
312 | p = strstr(jpgfile, "config"); |
313 | if (p) |
314 | strncpy(p, "images", 6); |
315 | } |
316 | } |
317 | |
318 | if (tx == 0 && ty == 0 && tw == 0 && th == 0) { |
319 | tx = px + 8; |
320 | ty = py + 4; |
321 | tw = pw - 16; |
322 | th = ph - 8; |
323 | } |
324 | |
325 | if (jpgfile |
326 | && (*jpgfile == 0 || tx < 0 || ty < 0 || tw <= 0 |
327 | || th <= 0)) { |
328 | free(jpgfile); |
329 | jpgfile = 0; |
330 | } |
331 | } |
332 | |
333 | if (verbose_only) |
334 | silentjpgfile = NULL; |
335 | |
336 | |
337 | if (silentjpgfile && jpgfile) { |
338 | if ((sfp = fopen(silentjpgfile, "r")) == 0) { |
339 | perror(silentjpgfile); |
340 | exit(1); |
341 | } |
342 | if (fstat(fileno(sfp), &stb) == -1) { |
343 | perror("fstat"); |
344 | exit(1); |
345 | } |
346 | silentl = stb.st_size; |
347 | } |
348 | |
349 | if (jpgfile) { |
350 | if ((fp = fopen(jpgfile, "r")) == 0) { |
351 | perror(jpgfile); |
352 | exit(1); |
353 | } |
354 | if (fstat(fileno(fp), &stb) == -1) { |
355 | perror("fstat"); |
356 | exit(1); |
357 | } |
358 | l = stb.st_size; |
359 | pic = |
360 | calloc(47 + l + silentl + boxcount * 12 + |
361 | sboxcount * 12, 1); |
362 | if (pic == 0) { |
363 | fprintf(stderr, "Out of memory.\n"); |
364 | exit(1); |
365 | } |
366 | if (fread(pic + 47 + boxcount * 12, l, 1, fp) != 1) { |
367 | perror("fread"); |
368 | exit(1); |
369 | } |
370 | if (silentjpgfile) { |
371 | if (fread |
372 | (pic + 47 + l + boxcount * 12 + sboxcount * 12, |
373 | silentl, 1, sfp) != 1) { |
374 | perror("fread"); |
375 | exit(1); |
376 | } |
377 | fclose(sfp); |
378 | if (sboxcount) |
379 | memmove(pic + 47 + l + boxcount * 12, |
380 | sboxes, sboxcount * 12); |
381 | silentl += sboxcount * 12; |
382 | l += silentl; |
383 | } |
384 | fclose(fp); |
385 | } else { |
386 | l = 0; |
387 | pic = calloc(47, 1); |
388 | if (pic == 0) { |
389 | fprintf(stderr, "Out of memory.\n"); |
390 | exit(1); |
391 | } |
392 | } |
393 | size = l; |
394 | if (version < 1 || version > 3) { |
395 | fprintf(stderr, "Illegal version: %ld\n", version); |
396 | exit(1); |
397 | } |
398 | if (version == 1 && unit != 0) { |
399 | /* convert to version 2 */ |
400 | tx *= 8; |
401 | ty *= 16; |
402 | tw *= 8; |
403 | th *= 16; |
404 | px = tx + 10; |
405 | py = ty + 10; |
406 | pw = tw - 20; |
407 | ph = th - 20; |
408 | pr = pg = pb = 240; |
409 | state = 1; |
410 | fgcolor = 0; |
411 | bgcolor = 15; |
412 | version = 2; |
413 | } |
414 | if (version == 1) { |
415 | /* write version 1 file */ |
416 | strcpy(pic, "BOOTSPL1"); |
417 | pic[8] = tx; |
418 | pic[9] = tx >> 8; |
419 | pic[10] = ty; |
420 | pic[11] = ty >> 8; |
421 | pic[12] = tw; |
422 | pic[13] = tw >> 8; |
423 | pic[14] = th; |
424 | pic[15] = th >> 8; |
425 | pic[16] = size; |
426 | pic[17] = size >> 8; |
427 | pic[18] = size >> 16; |
428 | pic[19] = size >> 24; |
429 | if (l > 0) |
430 | memmove(pic + 20, pic + 47, l); |
431 | l += 20; |
432 | } else if (version == 2) { |
433 | /* write version 2 file */ |
434 | strcpy(pic, "BOOTSPL2"); |
435 | pic[8] = unit; |
436 | pic[9] = state; |
437 | pic[10] = fgcolor; |
438 | pic[11] = bgcolor; |
439 | if (cfgfile && size == 0 |
440 | && (state != -1 || fgcolor != -1 || bgcolor != -1)) |
441 | size = -1; |
442 | pic[12] = size; |
443 | pic[13] = size >> 8; |
444 | pic[14] = size >> 16; |
445 | pic[15] = size >> 24; |
446 | pic[16] = tx; |
447 | pic[17] = tx >> 8; |
448 | pic[18] = ty; |
449 | pic[19] = ty >> 8; |
450 | pic[20] = tw; |
451 | pic[21] = tw >> 8; |
452 | pic[22] = th; |
453 | pic[23] = th >> 8; |
454 | pic[24] = px; |
455 | pic[25] = px >> 8; |
456 | pic[26] = py; |
457 | pic[27] = py >> 8; |
458 | pic[28] = pw; |
459 | pic[29] = pw >> 8; |
460 | pic[30] = ph; |
461 | pic[31] = ph >> 8; |
462 | pic[32] = pr; |
463 | pic[33] = pg; |
464 | pic[34] = pb; |
465 | if (l > 0) |
466 | memmove(pic + 35, pic + 47, l); |
467 | l += 35; |
468 | } else { /* version 3 */ |
469 | strcpy(pic, "BOOTSPL3"); |
470 | pic[8] = unit; |
471 | pic[9] = state; |
472 | pic[10] = fgcolor; |
473 | pic[11] = bgcolor; |
474 | size += boxcount * 12; |
475 | if (cfgfile && size == 0 |
476 | && (state != -1 || fgcolor != -1 || bgcolor != -1)) |
477 | size = -1; |
478 | pic[12] = size; |
479 | pic[13] = size >> 8; |
480 | pic[14] = size >> 16; |
481 | pic[15] = size >> 24; |
482 | pic[16] = tx; |
483 | pic[17] = tx >> 8; |
484 | pic[18] = ty; |
485 | pic[19] = ty >> 8; |
486 | pic[20] = tw; |
487 | pic[21] = tw >> 8; |
488 | pic[22] = th; |
489 | pic[23] = th >> 8; |
490 | pic[24] = boxcount; |
491 | pic[25] = boxcount >> 8; |
492 | pic[28] = silentl; |
493 | pic[29] = silentl >> 8; |
494 | pic[30] = silentl >> 16; |
495 | pic[31] = silentl >> 24; |
496 | pic[32] = sboxcount; |
497 | pic[33] = sboxcount >> 8; |
498 | pic[34] = percent; |
499 | pic[35] = percent >> 8; |
500 | pic[36] = overpaintok; |
501 | pic[37] = 0; /* numpalette */ |
502 | if (l > 0) |
503 | memmove(pic + 38 + boxcount * 12, |
504 | pic + 47 + boxcount * 12, l); |
505 | if (boxcount) |
506 | memmove(pic + 38, boxes, boxcount * 12); |
507 | l += 38 + boxcount * 12; |
508 | } |
509 | |
510 | if (filterflag) |
511 | fd = 1; |
512 | else if ((fd = open(PROCSPLASH, O_WRONLY)) == -1) { |
513 | perror(PROCSPLASH); |
514 | exit(1); |
515 | } |
516 | if (write(fd, pic, l) != l) { |
517 | perror("write"); |
518 | exit(1); |
519 | } |
520 | if (!filterflag) |
521 | close(fd); |
522 | free(pic); |
523 | } |
524 | |
525 | int main(int argc, char *argv[]) |
526 | { |
527 | int procsplash, c; |
528 | int setflag = 0; |
529 | int errflag = 0; |
530 | int filterflag = 0; |
531 | int verbose_only = 0; |
532 | unsigned char *readbuffer; |
533 | |
534 | while ((c = getopt(argc, argv, "fsu:n")) != EOF) { |
535 | switch (c) { |
536 | case 's': |
537 | setflag = 1; |
538 | break; |
539 | case 'f': |
540 | filterflag = 1; |
541 | break; |
542 | case 'u': |
543 | unit = atoi(optarg); |
544 | break; |
545 | case 'n': |
546 | verbose_only = 1; |
547 | break; |
548 | case '?': |
549 | errflag = 1; |
550 | break; |
551 | } |
552 | } |
553 | |
554 | if (errflag |
555 | || (argc != optind + 1 && (argc != optind || !setflag))) { |
556 | printf("Usage: %s -s [-u unit] -n [cfgfile]\n", argv[0]); |
557 | return 0; |
558 | } |
559 | |
560 | readbuffer = malloc(BUFSIZE); |
561 | |
562 | if (!readbuffer) { |
563 | DEBUG("splash: Not enough memory.\n"); |
564 | return -ENOMEM; |
565 | } |
566 | |
567 | if (!setflag || !filterflag) { |
568 | procsplash = open(PROCSPLASH, O_RDONLY); |
569 | if (procsplash < 0) { |
570 | if (setflag) { |
571 | perror(PROCSPLASH); |
572 | exit(1); |
573 | } |
574 | DEBUG("splash: File %s not available.\n", |
575 | PROCSPLASH); |
576 | return 0; |
577 | } |
578 | |
579 | if (read(procsplash, readbuffer, BUFSIZE) < 0) { |
580 | if (setflag) |
581 | perror("read"); |
582 | DEBUG("splash: Read error in file %s.\n", |
583 | PROCSPLASH); |
584 | return -EBUSY; |
585 | } |
586 | close(procsplash); |
587 | } |
588 | if (setflag) { |
589 | if (!filterflag |
590 | && !strncmp(readbuffer, "Splash screen v0", 16)) { |
591 | fprintf(stderr, |
592 | "Your kernel support for the bootsplash is too old. Get the new version from http://www.bootsplash.org/\n"); |
593 | exit(1); |
594 | } |
595 | setsplash(argc > optind ? argv[optind] : 0, filterflag, |
596 | verbose_only); |
597 | exit(0); |
598 | } |
599 | |
600 | return 0; |
601 | } |