Annotation of /trunk/linterm_tools/fw_builder/bootsplash/splash.c
Parent Directory | Revision Log
Revision 658 -
(hide annotations)
(download)
Mon Jan 14 16:57:24 2008 UTC (16 years, 4 months ago) by niro
File MIME type: text/plain
File size: 11953 byte(s)
Mon Jan 14 16:57:24 2008 UTC (16 years, 4 months ago) by niro
File MIME type: text/plain
File size: 11953 byte(s)
initial import
1 | niro | 658 | /* 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 | } |