2 * linux/drivers/video/bootsplash/bootsplash.c -
3 * splash screen handling functions.
5 * (w) 2001-2004 by Volker Poplawski, <volker@poplawski.de>,
6 * Stefan Reinauer, <stepan@suse.de>,
7 * Steffen Winterfeldt, <snwint@suse.de>,
8 * Michael Schroeder <mls@suse.de>
9 * 2009-2011 Egbert Eich <eich@suse.de>
11 * Ideas & SuSE screen work by Ken Wimer, <wimer@suse.de>
13 * For more information on this code check http://www.bootsplash.org/
16 #include <linux/module.h>
17 #include <linux/types.h>
19 #include <linux/vt_kern.h>
20 #include <linux/vmalloc.h>
21 #include <linux/unistd.h>
22 #include <linux/syscalls.h>
23 #include <linux/console.h>
24 #include <linux/workqueue.h>
25 #include <linux/slab.h>
29 #include "../console/fbcon.h"
30 #include <linux/bootsplash.h>
31 #include "decode-jpg.h"
34 # define SPLASH_DEBUG(fmt, args...)
36 # define SPLASH_DEBUG(fmt, args...) \
37 printk(KERN_WARNING "%s: " fmt "\n", __func__, ##args)
39 extern signed char con2fb_map[MAX_NR_CONSOLES];
41 #define SPLASH_VERSION "3.2.0-2010/03/31"
43 /* These errors have to match fbcon-jpegdec.h */
44 static unsigned char *jpg_errors[] = {
49 "bad width or height",
52 "quant table selector",
53 "picture is not YCBCR 221111",
64 static int splash_usesilent;
65 static unsigned long splash_default = 0xf01;
67 static int jpeg_get(unsigned char *buf, unsigned char *pic,
68 int width, int height, enum splash_color_format cf,
69 struct jpeg_decdata *decdata);
70 static int splash_look_for_jpeg(struct vc_data *vc, int width, int height);
72 static int __init splash_setup(char *options)
76 if (!strncmp("silent", options, 6)) {
77 printk(KERN_INFO "bootsplash: silent mode.\n");
80 if (strlen(options) == 6)
84 if (!strncmp("verbose", options, 7)) {
85 printk(KERN_INFO "bootsplash: verbose mode.\n");
87 if (strlen(options) == 7)
91 if (strict_strtoul(options, 0, &splash_default) == -EINVAL)
97 __setup("splash=", splash_setup);
100 static int splash_hasinter(unsigned char *buf, int num)
102 unsigned char *bufend = buf + num * 12;
103 while (buf < bufend) {
104 if (buf[1] > 127) /* inter? */
106 buf += buf[3] > 127 ? 24 : 12; /* blend? */
111 static int boxextract(unsigned char *buf, unsigned short *dp,
112 unsigned char *cols, int *blendp)
114 dp[0] = buf[0] | buf[1] << 8;
115 dp[1] = buf[2] | buf[3] << 8;
116 dp[2] = buf[4] | buf[5] << 8;
117 dp[3] = buf[6] | buf[7] << 8;
118 *(unsigned int *)(cols + 0) =
119 *(unsigned int *)(cols + 4) =
120 *(unsigned int *)(cols + 8) =
121 *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 8);
124 *(unsigned int *)(cols + 4) = *(unsigned int *)(buf + 12);
125 *(unsigned int *)(cols + 8) = *(unsigned int *)(buf + 16);
126 *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 20);
133 static void boxit(unsigned char *pic, int bytes, unsigned char *buf, int num,
134 int percent, int xoff, int yoff, int overpaint,
135 enum splash_color_format cf)
137 int x, y, p, doblend, r, g, b, a, add;
139 unsigned short data1[4];
140 unsigned char cols1[16];
141 unsigned short data2[4];
142 unsigned char cols2[16];
143 unsigned char *bufend;
145 unsigned int stipple[32], sti, stin, stinn, stixs, stixe, stiys, stiye;
146 int xs, xe, ys, ye, xo, yo;
147 int octpp = splash_octpp(cf);
150 if (num == 0 || percent < -1)
152 bufend = buf + num * 12;
153 stipple[0] = 0xffffffff;
158 while (buf < bufend) {
160 buf += boxextract(buf, data1, cols1, &doblend);
161 if (data1[0] == 32767 && data1[1] == 32767) {
169 } else if (stinn == 4) {
173 stipple[stinn++] = (cols1[0] << 24) |
177 stipple[stinn++] = (cols1[4] << 24) |
181 stipple[stinn++] = (cols1[8] << 24) |
185 stipple[stinn++] = (cols1[12] << 24) |
193 if (data1[0] > 32767)
194 buf += boxextract(buf, data2, cols2, &doblend);
195 if (data1[0] == 32767 && data1[1] == 32766) {
197 i = 12 * (short)data1[3];
199 i += boxextract(buf + i, data1, cols1, &doblend);
200 if (data1[0] > 32767)
201 boxextract(buf + i, data2, cols2, &doblend);
203 if (data1[0] == 32767)
205 if (data1[2] > 32767) {
208 data1[2] = ~data1[2];
210 if (data1[3] > 32767) {
211 if (percent == 65536)
213 data1[3] = ~data1[3];
215 if (data1[0] > 32767) {
218 data1[0] = ~data1[0];
219 for (i = 0; i < 4; i++)
220 data1[i] = (data1[i] * (65536 - percent)
221 + data2[i] * percent) >> 16;
222 for (i = 0; i < 16; i++)
223 cols1[i] = (cols1[i] * (65536 - percent)
224 + cols2[i] * percent) >> 16;
226 *(unsigned int *)cols2 = *(unsigned int *)cols1;
228 if (a == 0 && !doblend)
231 if (stixs >= 32768) {
232 xo = xs = (stixs ^ 65535) + data1[0];
233 xe = stixe ? stixe + data1[0] : data1[2];
234 } else if (stixe >= 32768) {
235 xs = stixs ? data1[2] - stixs : data1[0];
236 xe = data1[2] - (stixe ^ 65535);
240 xe = stixe ? stixe : data1[2];
242 if (stiys >= 32768) {
243 yo = ys = (stiys ^ 65535) + data1[1];
244 ye = stiye ? stiye + data1[1] : data1[3];
245 } else if (stiye >= 32768) {
246 ys = stiys ? data1[3] - stiys : data1[1];
247 ye = data1[3] - (stiye ^ 65535);
251 ye = stiye ? stiye : data1[3];
254 yo = stin - (yo % stin);
264 for (y = ys; y <= ye; y++) {
265 sti = stipple[(y + yo) % stin];
268 sti = (sti << x) | (sti >> (32 - x));
270 p = data1[3] - data1[1];
272 p = ((y - data1[1]) << 16) / p;
273 for (i = 0; i < 8; i++)
274 cols2[i + 8] = (cols1[i] * (65536 - p)
279 add ^= (add ^ y) & 1 ? 1 : 3; /*2x2 ordered dithering*/
280 picp.ub = (pic + (xs + xoff) * octpp
281 + (y + yoff) * bytes);
282 for (x = xs; x <= xe; x++) {
283 if (!(sti & 0x80000000)) {
299 sti = (sti << 1) | 1;
301 p = data1[2] - data1[0];
303 p = ((x - data1[0]) << 16) / p;
304 for (i = 0; i < 4; i++)
305 cols2[i] = (cols2[i + 8] * (65536 - p)
313 #define CLAMP(x) ((x) >= 256 ? 255 : (x))
314 #define BLEND(x, v, a) ((x * (255 - a) + v * a) / 255)
316 case SPLASH_DEPTH_15:
319 r = BLEND((i>>7 & 0xf8), r, a);
320 g = BLEND((i>>2 & 0xf8), g, a);
321 b = BLEND((i<<3 & 0xf8), b, a);
326 i = ((CLAMP(r) & 0xf8) << 7) |
327 ((CLAMP(g) & 0xf8) << 2) |
331 case SPLASH_DEPTH_16:
334 r = BLEND((i>>8 & 0xf8), r, a);
335 g = BLEND((i>>3 & 0xfc), g, a);
336 b = BLEND((i<<3 & 0xf8), b, a);
341 i = ((CLAMP(r) & 0xf8) << 8) |
342 ((CLAMP(g) & 0xfc) << 3) |
346 case SPLASH_DEPTH_24_PACKED:
349 r = BLEND((i & 0xff), r, a);
351 g = BLEND((i & 0xff), g, a);
353 b = BLEND((i & 0xff), b, a);
355 *(picp.ub++) = CLAMP(r);
356 *(picp.ub++) = CLAMP(g);
357 *(picp.ub++) = CLAMP(b);
359 case SPLASH_DEPTH_24:
362 r = BLEND((i>>16 & 0xff), r, a);
363 g = BLEND((i>>8 & 0xff), g, a);
364 b = BLEND((i & 0xff), b, a);
366 i = ((CLAMP(r) << 16)
380 static void box_offsets(unsigned char *buf, int num,
381 int screen_w, int screen_h, int pic_w, int pic_h,
382 int *x_off, int *y_off)
385 int x_min = pic_w, x_max = 0;
386 int y_min = pic_h, y_max = 0;
388 unsigned short data1[4];
389 unsigned char cols1[16];
390 unsigned short data2[4];
391 unsigned char cols2[16];
392 unsigned char *bufend;
393 unsigned int stin, stinn, stixs, stixe, stiys, stiye;
398 if ((screen_w == pic_w && screen_h == pic_h) || num == 0)
401 bufend = buf + num * 12;
407 while (buf < bufend) {
409 buf += boxextract(buf, data1, cols1, &doblend);
410 if (data1[0] == 32767 && data1[1] == 32767) {
418 } else if (stinn == 4) {
426 if (data1[0] > 32767)
427 buf += boxextract(buf, data2, cols2, &doblend);
428 if (data1[0] == 32767 && data1[1] == 32766) {
430 i = 12 * (short)data1[3];
432 i += boxextract(buf + i, data1, cols1, &doblend);
433 if (data1[0] > 32767)
434 boxextract(buf + i, data2, cols2, &doblend);
436 if (data1[0] == 32767)
438 if (data1[2] > 32767)
439 data1[2] = ~data1[2];
440 if (data1[3] > 32767)
441 data1[3] = ~data1[3];
442 if (data1[0] > 32767) {
443 data1[0] = ~data1[0];
444 for (i = 0; i < 4; i++)
445 data1[i] = (data1[i] * (65536 - 1)
446 + data2[i] * 1) >> 16;
448 *(unsigned int *)cols2 = *(unsigned int *)cols1;
450 if (a == 0 && !doblend)
453 if (stixs >= 32768) {
454 xs = (stixs ^ 65535) + data1[0];
455 xe = stixe ? stixe + data1[0] : data1[2];
456 } else if (stixe >= 32768) {
457 xs = stixs ? data1[2] - stixs : data1[0];
458 xe = data1[2] - (stixe ^ 65535);
461 xe = stixe ? stixe : data1[2];
463 if (stiys >= 32768) {
464 ys = (stiys ^ 65535) + data1[1];
465 ye = stiye ? stiye + data1[1] : data1[3];
466 } else if (stiye >= 32768) {
467 ys = stiys ? data1[3] - stiys : data1[1];
468 ye = data1[3] - (stiye ^ 65535);
471 ye = stiye ? stiye : data1[3];
492 int x_center = (x_min + x_max) / 2;
493 int y_center = (y_min + y_max) / 2;
495 if (screen_w == pic_w)
498 if (x_center < (pic_w + pic_w / 5) >> 1 &&
499 x_center > (pic_w - pic_w / 5) >> 1) {
500 *x_off = (screen_w - pic_w) >> 1;
502 int x = x_center * screen_w / pic_w;
503 *x_off = x - x_center;
504 if (x_min + *x_off < 0)
506 if (x_max + *x_off > screen_w)
507 *x_off = screen_w - pic_w;
510 if (screen_h == pic_h)
513 if (y_center < (pic_h + pic_h / 5) >> 1 &&
514 y_center > (pic_h - pic_h / 5) >> 1)
515 *y_off = (screen_h - pic_h) >> 1;
517 int x = y_center * screen_h / pic_h;
518 *y_off = x - y_center;
519 if (y_min + *y_off < 0)
521 if (y_max + *x_off > screen_h)
522 *y_off = screen_h - pic_h;
528 static int splash_check_jpeg(unsigned char *jpeg,
529 int width, int height)
533 struct jpeg_decdata *decdata; /* private decoder data */
536 size = ((width + 15) & ~15) * ((height + 15) & ~15) * 2;
539 printk(KERN_INFO "bootsplash: no memory for decoded picture.\n");
542 decdata = vmalloc(sizeof(*decdata));
544 printk(KERN_INFO "bootsplash: not enough memory.\n");
548 /* test decode: use fixed depth of 16 */
549 err = jpeg_decode(jpeg, mem,
550 ((width + 15) & ~15), ((height + 15) & ~15),
554 printk(KERN_INFO "bootsplash: "
555 "error while decompressing picture: %s (%d)\n",
556 jpg_errors[err - 1], err);
562 static void splash_free(struct vc_data *vc, struct fb_info *info)
564 struct splash_data *sd;
565 struct splash_data *next;
567 for (sd = vc->vc_splash_data; sd; sd = next) {
570 if (!sd->pic->ref_cnt) {
571 vfree(sd->pic->splash_pic);
575 if (!sd->imgd->ref_cnt) {
576 vfree(sd->imgd->splash_sboxes);
581 vc->vc_splash_data = 0;
583 info->splash_data = 0;
586 static int splash_mkpenguin(struct splash_data *data,
587 int pxo, int pyo, int pwi, int phe,
588 int pr, int pg, int pb)
593 if (pwi == 0 || phe == 0)
596 buf = (unsigned char *)data + sizeof(*data);
614 for (i = 0; i < 12; i++, buf++)
624 static const int splash_offsets[3][16] = {
625 /* len, unit, size, state, fgcol, col, xo, yo, wi, he
626 boxcnt, ssize, sboxcnt, percent, overok, palcnt */
628 { 20, -1, 16, -1, -1, -1, 8, 10, 12, 14,
629 -1, -1, -1, -1, -1, -1 },
631 { 35, 8, 12, 9, 10, 11, 16, 18, 20, 22,
632 -1, -1, -1, -1, -1, -1 },
634 { 38, 8, 12, 9, 10, 11, 16, 18, 20, 22,
635 24, 28, 32, 34, 36, 37 },
638 #define SPLASH_OFF_LEN offsets[0]
639 #define SPLASH_OFF_UNIT offsets[1]
640 #define SPLASH_OFF_SIZE offsets[2]
641 #define SPLASH_OFF_STATE offsets[3]
642 #define SPLASH_OFF_FGCOL offsets[4]
643 #define SPLASH_OFF_COL offsets[5]
644 #define SPLASH_OFF_XO offsets[6]
645 #define SPLASH_OFF_YO offsets[7]
646 #define SPLASH_OFF_WI offsets[8]
647 #define SPLASH_OFF_HE offsets[9]
648 #define SPLASH_OFF_BOXCNT offsets[10]
649 #define SPLASH_OFF_SSIZE offsets[11]
650 #define SPLASH_OFF_SBOXCNT offsets[12]
651 #define SPLASH_OFF_PERCENT offsets[13]
652 #define SPLASH_OFF_OVEROK offsets[14]
653 #define SPLASH_OFF_PALCNT offsets[15]
655 static inline int splash_getb(unsigned char *pos, int off)
657 return off == -1 ? 0 : pos[off];
660 static inline int splash_gets(unsigned char *pos, int off)
662 return off == -1 ? 0 : pos[off] | pos[off + 1] << 8;
665 static inline int splash_geti(unsigned char *pos, int off)
667 return off == -1 ? 0 : (pos[off] |
673 /* move the given splash_data to the current one */
674 static void splash_pivot_current(struct vc_data *vc, struct splash_data *new)
676 struct splash_data *sd;
677 struct splash_pic_data *pic;
678 int state, percent, silent;
680 sd = vc->vc_splash_data;
681 if (!sd || sd == new)
684 state = sd->splash_state;
685 percent = sd->splash_percent;
686 silent = sd->splash_dosilent;
687 if (sd->pic->ref_cnt > 1) {
688 pic = kzalloc(sizeof(struct splash_pic_data), GFP_KERNEL);
693 sd->pic->ref_cnt = 1;
694 sd->pic->splash_pic_size = 0;
695 sd->pic->splash_pic = NULL;
696 sd->splash_vc_text_wi = sd->imgd->splash_text_wi;
697 sd->splash_vc_text_he = sd->imgd->splash_text_he;
698 for (; sd->next; sd = sd->next) {
699 if (sd->next == new) {
700 sd->next = new->next;
701 new->next = vc->vc_splash_data;
702 vc->vc_splash_data = new;
703 /* copy the current states */
704 new->splash_state = state;
705 new->splash_percent = percent;
706 new->splash_dosilent = silent;
707 new->splash_vc_text_wi = new->imgd->splash_text_wi;
708 new->splash_vc_text_he = new->imgd->splash_text_he;
710 new->splash_boxes_xoff = 0;
711 new->splash_boxes_yoff = 0;
712 new->splash_sboxes_xoff = 0;
713 new->splash_sboxes_yoff = 0;
715 if (new->pic->ref_cnt > 1) {
716 struct splash_pic_data *pic;
717 pic = kzalloc(sizeof(struct splash_pic_data),
724 new->pic->ref_cnt = 1;
725 new->pic->splash_pic_size = 0;
726 new->pic->splash_pic = NULL;
733 static int update_boxes(struct vc_data *vc,
735 unsigned char *ndata, int len, unsigned char * end,
740 struct splash_data *sd;
741 struct splash_img_data *imgd;
744 sd = vc->vc_splash_data;
748 i = splash_getb(ndata, SPLASH_OFF_STATE);
750 sd->splash_state = i; /*@!@*/
753 i = splash_getb(ndata, SPLASH_OFF_FGCOL);
755 imgd->splash_fg_color = i;
758 i = splash_getb(ndata, SPLASH_OFF_COL);
760 imgd->splash_color = i;
763 boxcnt = sboxcnt = 0;
764 if (ndata + len <= end) {
765 boxcnt = splash_gets(ndata, SPLASH_OFF_BOXCNT);
766 sboxcnt = splash_gets(ndata, SPLASH_OFF_SBOXCNT);
769 i = splash_gets(ndata, len);
771 <= imgd->splash_boxcount &&
772 ndata + len + 2 + boxcnt * 12
774 if (splash_geti(ndata, len + 2)
776 !memcmp(ndata + len + 2,
777 imgd->splash_boxes + i * 12,
779 memcpy(imgd->splash_boxes + i * 12,
785 len += boxcnt * 12 + 2;
788 i = splash_gets(ndata, len);
789 if ((sboxcnt + i <= imgd->splash_sboxcount) &&
790 (ndata + len + 2 + sboxcnt * 12 <= end)) {
791 if ((splash_geti(ndata, len + 2) != 0x7ffd7fff)
792 || !memcmp(ndata + len + 2,
793 imgd->splash_sboxes + i * 12,
795 memcpy(imgd->splash_sboxes + i * 12,
808 static int splash_getraw(unsigned char *start, unsigned char *end, int *update)
810 unsigned char *ndata;
821 struct vc_data *vc = NULL;
822 struct fb_info *info = NULL;
823 struct splash_data *sd;
824 struct splash_img_data *imgd;
825 struct splash_pic_data *pic;
826 struct splash_data *splash_found = NULL;
828 int oldpercent, oldsilent;
836 splash_geti(start, 12) != (int)0xffffffff)
837 printk(KERN_INFO "bootsplash %s: looking for picture...\n",
842 for (ndata = start; ndata < end; ndata++) {
843 if (ndata[0] != 'B' ||
848 if (ndata[4] != 'S' ||
855 version = ndata[7] - '0';
856 offsets = splash_offsets[version - 1];
857 len = SPLASH_OFF_LEN;
859 unit = splash_getb(ndata, SPLASH_OFF_UNIT);
860 if (unit >= MAX_NR_CONSOLES)
866 vc = vc_cons[unit].d;
870 info = registered_fb[(int)con2fb_map[unit]];
872 splash_size = splash_geti(ndata, SPLASH_OFF_SIZE);
875 * Update. Wonder what should happen here now
876 * since we can have multiple splash_data records
878 if (splash_size == (int)0xffffffff && version > 1) {
879 if (update_boxes(vc, offsets, ndata, len, end, update) < 0)
885 if (splash_size == 0) {
887 "bootsplash: ...found, freeing memory.\n");
888 if (vc->vc_splash_data)
889 splash_free(vc, info);
892 boxcnt = splash_gets(ndata, SPLASH_OFF_BOXCNT);
893 palcnt = 3 * splash_getb(ndata, SPLASH_OFF_PALCNT);
894 if (ndata + len + splash_size > end) {
896 "bootsplash: ...found, but truncated!\n");
899 silentsize = splash_geti(ndata, SPLASH_OFF_SSIZE);
902 "bootsplash: silentjpeg size %d bytes\n",
904 if (silentsize >= splash_size) {
905 printk(KERN_ERR "bootsplash: bigger than splashsize!\n");
908 splash_size -= silentsize;
909 if (!splash_usesilent)
912 sboxcnt = splash_gets(ndata, SPLASH_OFF_SBOXCNT);
913 if (vc->vc_splash_data) {
914 oldpercent = vc->vc_splash_data->splash_percent;/*@!@*/
915 oldsilent = vc->vc_splash_data->splash_dosilent;/*@!@*/
917 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
920 imgd = vmalloc(sizeof(*imgd)
921 + splash_size + (version < 3 ? 2 * 12 : 0));
926 pic = kzalloc(sizeof(*pic), GFP_KERNEL);
932 memset(imgd, 0, sizeof(*imgd));
937 jpeg_get_size(ndata + len + boxcnt * 12 + palcnt,
938 &imgd->splash_width, &imgd->splash_height);
939 if (splash_check_jpeg(ndata + len + boxcnt * 12 + palcnt,
941 imgd->splash_height)) {
942 ndata += len + splash_size - 1;
948 imgd->splash_silentjpeg = vmalloc(silentsize);
949 if (imgd->splash_silentjpeg) {
950 memcpy(imgd->splash_silentjpeg,
951 ndata + len + splash_size, silentsize);
952 imgd->splash_sboxes = imgd->splash_silentjpeg;
953 imgd->splash_silentjpeg += 12 * sboxcnt;
954 imgd->splash_sboxcount = sboxcnt;
957 imgd->splash_fg_color = splash_getb(ndata, SPLASH_OFF_FGCOL);
958 imgd->splash_color = splash_getb(ndata, SPLASH_OFF_COL);
959 imgd->splash_overpaintok = splash_getb(ndata, SPLASH_OFF_OVEROK);
960 imgd->splash_text_xo = splash_gets(ndata, SPLASH_OFF_XO);
961 imgd->splash_text_yo = splash_gets(ndata, SPLASH_OFF_YO);
962 imgd->splash_text_wi = splash_gets(ndata, SPLASH_OFF_WI);
963 imgd->splash_text_he = splash_gets(ndata, SPLASH_OFF_HE);
965 imgd->splash_text_xo *= 8;
966 imgd->splash_text_wi *= 8;
967 imgd->splash_text_yo *= 16;
968 imgd->splash_text_he *= 16;
969 imgd->splash_color = (splash_default >> 8) & 0x0f;
970 imgd->splash_fg_color = (splash_default >> 4) & 0x0f;
973 /* fake penguin box for older formats */
975 boxcnt = splash_mkpenguin(sd, imgd->splash_text_xo + 10,
976 imgd->splash_text_yo + 10,
977 imgd->splash_text_wi - 20,
978 imgd->splash_text_he - 20,
980 else if (version == 2)
981 boxcnt = splash_mkpenguin(sd,
982 splash_gets(ndata, 24),
983 splash_gets(ndata, 26),
984 splash_gets(ndata, 28),
985 splash_gets(ndata, 30),
986 splash_getb(ndata, 32),
987 splash_getb(ndata, 33),
988 splash_getb(ndata, 34));
991 + sizeof(*imgd) + (version < 3 ? boxcnt * 12 : 0),
994 imgd->splash_boxcount = boxcnt;
995 imgd->splash_boxes = (unsigned char *)imgd + sizeof(*imgd);
996 imgd->splash_palette = imgd->splash_boxes + boxcnt * 12;
997 imgd->splash_jpeg = imgd->splash_palette + palcnt;
999 sd->splash_state = splash_getb(ndata, SPLASH_OFF_STATE);/*@!@*/
1000 sd->splash_percent = oldpercent == -3 ?
1001 splash_gets(ndata, SPLASH_OFF_PERCENT) :
1003 sd->pic->splash_pic = NULL;
1004 sd->pic->splash_pic_size = 0;
1006 sd->splash_dosilent = imgd->splash_silentjpeg != 0 ?
1007 (oldsilent == -1 ? 1 : oldsilent) :
1010 sd->splash_vc_text_wi = imgd->splash_text_wi;
1011 sd->splash_vc_text_he = imgd->splash_text_he;
1013 sd->next = vc->vc_splash_data;
1014 vc->vc_splash_data = sd;
1017 width = info->var.xres;
1018 height = info->var.yres;
1019 if (imgd->splash_width != width ||
1020 imgd->splash_height != height) {
1021 ndata += len + splash_size - 1;
1026 "bootsplash: ...found (%dx%d, %d bytes, v%d).\n",
1027 imgd->splash_width, imgd->splash_height,
1028 splash_size, version);
1031 "bootsplash: Using deprecated v1 header. "
1032 "Updating your splash utility recommended.\n");
1034 "bootsplash: Find the latest version at "
1035 "http://www.bootsplash.org/\n");
1043 splash_pivot_current(vc, splash_found);
1048 info = registered_fb[(int)con2fb_map[0]];
1050 width = info->var.xres;
1051 height = info->var.yres;
1054 if (!splash_look_for_jpeg(vc, width, height))
1060 printk(KERN_ERR "bootsplash: ...no good signature found.\n");
1064 static void splash_update_redraw(struct vc_data *vc, struct fb_info *info)
1067 vc->vc_origin + vc->vc_size_row * vc->vc_top,
1068 vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
1069 splash_clear_margins(vc, info, 0);
1072 int splash_do_verbose(void)
1075 struct fb_info *info;
1079 if (!oops_in_progress)
1082 if (!splash_usesilent)
1087 if (!vc || !vc->vc_splash_data || !vc->vc_splash_data->splash_state)
1089 if (!vc->vc_splash_data->imgd->splash_silentjpeg)
1092 if (!vc->vc_splash_data->splash_dosilent)
1094 vc->vc_splash_data->splash_dosilent = 0;
1095 if (fg_console != vc->vc_num)
1098 info = registered_fb[(int)con2fb_map[0]];
1100 if (!info || !info->splash_data)
1103 splash_update_redraw(vc, info);
1107 if (!oops_in_progress)
1113 static void splash_verbose_callback(struct work_struct *ignored)
1115 splash_do_verbose();
1118 static DECLARE_WORK(splash_work, splash_verbose_callback);
1120 int splash_verbose(void)
1122 if (!oops_in_progress)
1123 schedule_work(&splash_work);
1125 return splash_do_verbose();
1129 static void splash_off(struct vc_data *vc, struct fb_info *info)
1131 int rows = info->var.xres / vc->vc_font.width;
1132 int cols = info->var.yres / vc->vc_font.height;
1135 info->splash_data = 0;
1136 if (rows != vc->vc_rows || cols != vc->vc_cols)
1137 vc_resize(vc, rows, cols);
1140 /* look for the splash with the matching size and set it as the current */
1141 static int splash_look_for_jpeg(struct vc_data *vc, int width, int height)
1143 struct splash_data *sd, *found = NULL;
1144 int found_delta_x = INT_MAX, found_delta_y = INT_MAX;
1146 for (sd = vc->vc_splash_data; sd; sd = sd->next) {
1147 int delta_x = abs(sd->imgd->splash_width - width) * height;
1148 int delta_y = abs(sd->imgd->splash_height - height) * width;
1150 (found_delta_x + found_delta_y > delta_x + delta_y)) {
1152 found_delta_x = delta_x;
1153 found_delta_y = delta_y;
1158 SPLASH_DEBUG("bootsplash: "
1159 "scalable image found (%dx%d scaled to %dx%d).",
1160 found->imgd->splash_width,
1161 found->imgd->splash_height,
1164 splash_pivot_current(vc, found);
1166 /* textarea margins are constant independent from image size */
1167 if (found->imgd->splash_height != height)
1168 found->splash_vc_text_he = height
1169 - (found->imgd->splash_height
1170 - found->imgd->splash_text_he);
1172 found->splash_vc_text_he = found->imgd->splash_text_he;
1173 if (found->imgd->splash_width != width)
1174 found->splash_vc_text_wi =
1176 - (found->imgd->splash_width
1177 - found->imgd->splash_text_wi);
1179 found->splash_vc_text_wi = found->imgd->splash_text_wi;
1181 if (found->imgd->splash_width != width
1182 || found->imgd->splash_height != height) {
1183 box_offsets(found->imgd->splash_boxes,
1184 found->imgd->splash_boxcount,
1186 found->imgd->splash_width,
1187 found->imgd->splash_height,
1188 &found->splash_boxes_xoff,
1189 &found->splash_boxes_yoff);
1190 SPLASH_DEBUG("bootsplash: offsets for boxes: x=%d y=%d",
1191 found->splash_boxes_xoff,
1192 found->splash_boxes_yoff);
1194 if (found->imgd->splash_sboxes) {
1195 box_offsets(found->imgd->splash_sboxes,
1196 found->imgd->splash_sboxcount,
1198 found->imgd->splash_width,
1199 found->imgd->splash_height,
1200 &found->splash_sboxes_xoff,
1201 &found->splash_sboxes_yoff);
1202 SPLASH_DEBUG("bootsplash: "
1203 "offsets sboxes: x=%d y=%d",
1204 found->splash_sboxes_xoff,
1205 found->splash_sboxes_yoff);
1208 found->splash_sboxes_xoff = 0;
1209 found->splash_sboxes_yoff = 0;
1216 static int splash_recolor(struct vc_data *vc, struct fb_info *info)
1221 if (!vc->vc_splash_data)
1223 if (!vc->vc_splash_data->splash_state)
1225 color = vc->vc_splash_data->imgd->splash_color << 4 |
1226 vc->vc_splash_data->imgd->splash_fg_color;
1227 if (vc->vc_def_color != color)
1228 con_remap_def_color(vc, color);
1229 if (info && info->splash_data && fg_console == vc->vc_num)
1230 splash_update_redraw(vc, info);
1231 vc->vc_splash_data->color_set = 1;
1235 int splash_prepare(struct vc_data *vc, struct fb_info *info)
1238 int width, height, octpp, size, sbytes;
1239 enum splash_color_format cf = SPLASH_DEPTH_UNKNOWN;
1241 struct jpeg_decdata *decdata; /* private decoder data */
1243 SPLASH_DEBUG("vc_num: %i", vc->vc_num);
1245 #if 0 /* Nouveau fb sets a different ops, so we can't use the condition */
1246 if (info->fbops->fb_imageblit != cfb_imageblit) {
1247 printk(KERN_ERR "bootsplash: "
1248 "found, but framebuffer can't "
1254 if (!vc->vc_splash_data || !vc->vc_splash_data->splash_state) {
1255 splash_off(vc, info);
1259 width = info->var.xres;
1260 height = info->var.yres;
1261 switch (info->var.bits_per_pixel) {
1263 if ((info->var.red.length +
1264 info->var.green.length +
1265 info->var.blue.length) == 15)
1266 cf = SPLASH_DEPTH_15;
1268 cf = SPLASH_DEPTH_16;
1271 cf = SPLASH_DEPTH_24_PACKED;
1274 cf = SPLASH_DEPTH_24;
1277 if (cf == SPLASH_DEPTH_UNKNOWN) {
1278 printk(KERN_INFO "bootsplash: unsupported pixel format: %i\n",
1279 info->var.bits_per_pixel);
1280 splash_off(vc, info);
1283 octpp = splash_octpp(cf);
1285 if (splash_look_for_jpeg(vc, width, height) < 0) {
1286 printk(KERN_INFO "bootsplash: no matching splash %dx%d\n",
1288 splash_off(vc, info);
1292 sbytes = ((width + 15) & ~15) * octpp;
1293 size = sbytes * ((height + 15) & ~15);
1295 if (size != vc->vc_splash_data->pic->splash_pic_size) {
1296 if (vc->vc_splash_data->pic->ref_cnt > 1) {
1297 struct splash_pic_data *pic;
1298 pic = kzalloc(sizeof(struct splash_pic_data),
1302 vc->vc_splash_data->pic = pic;
1304 vc->vc_splash_data->pic->ref_cnt = 1;
1305 vc->vc_splash_data->pic->splash_pic = NULL;
1306 vc->vc_splash_data->pic->splash_pic_size = 0;
1308 if (!vc->vc_splash_data->pic->splash_pic) {
1309 vc->vc_splash_data->pic->splash_pic = vmalloc(size);
1312 if (!vc->vc_splash_data->pic->splash_pic) {
1313 printk(KERN_INFO "bootsplash: not enough memory.\n");
1314 splash_off(vc, info);
1318 decdata = vmalloc(sizeof(*decdata));
1320 printk(KERN_INFO "bootsplash: not enough memory.\n");
1321 splash_off(vc, info);
1325 if (vc->vc_splash_data->imgd->splash_silentjpeg &&
1326 vc->vc_splash_data->splash_dosilent) {
1328 err = jpeg_get(vc->vc_splash_data->imgd->splash_silentjpeg,
1329 vc->vc_splash_data->pic->splash_pic,
1330 width, height, cf, decdata);
1332 printk(KERN_INFO "bootsplash: "
1333 "error while decompressing silent picture: "
1335 jpg_errors[err - 1], err);
1336 vc->vc_splash_data->splash_dosilent = 0;
1338 if (vc->vc_splash_data->imgd->splash_sboxcount)
1339 boxit(vc->vc_splash_data->pic->splash_pic,
1341 vc->vc_splash_data->imgd->splash_sboxes,
1342 vc->vc_splash_data->imgd->splash_sboxcount,
1343 vc->vc_splash_data->splash_percent,
1344 vc->vc_splash_data->splash_sboxes_xoff,
1345 vc->vc_splash_data->splash_sboxes_yoff,
1346 vc->vc_splash_data->splash_percent < 0 ?
1349 splashcopy(info->screen_base,
1350 vc->vc_splash_data->pic->splash_pic,
1353 info->fix.line_length, sbytes,
1357 vc->vc_splash_data->splash_dosilent = 0;
1360 err = jpeg_get(vc->vc_splash_data->imgd->splash_jpeg,
1361 vc->vc_splash_data->pic->splash_pic,
1362 width, height, cf, decdata);
1364 printk(KERN_INFO "bootsplash: "
1365 "error while decompressing picture: %s (%d) .\n",
1366 jpg_errors[err - 1], err);
1367 splash_off(vc, info);
1374 vc->vc_splash_data->pic->splash_pic_size = size;
1375 vc->vc_splash_data->pic->splash_pic_stride = sbytes;
1377 if (vc->vc_splash_data->imgd->splash_boxcount)
1378 boxit(vc->vc_splash_data->pic->splash_pic,
1380 vc->vc_splash_data->imgd->splash_boxes,
1381 vc->vc_splash_data->imgd->splash_boxcount,
1382 vc->vc_splash_data->splash_percent,
1383 vc->vc_splash_data->splash_boxes_xoff,
1384 vc->vc_splash_data->splash_boxes_yoff,
1387 if (vc->vc_splash_data->splash_state) {
1388 int cols = vc->vc_splash_data->splash_vc_text_wi
1389 / vc->vc_font.width;
1390 int rows = vc->vc_splash_data->splash_vc_text_he
1391 / vc->vc_font.height;
1393 info->splash_data = vc->vc_splash_data;
1395 info->splash_data->need_sync = 0;
1396 /* XEN fb needs some sync after the direct modification of
1397 * fb area; maybe other FBs would need similar hack, but
1398 * so far I don't care.
1400 if (!strcmp(info->fix.id, "xen")) {
1401 info->splash_data->need_sync = 1;
1402 /* sync the whole splash once */
1403 splash_sync_region(info, 0, 0,
1404 info->var.xres, info->var.yres);
1407 /* vc_resize also calls con_switch which resets yscroll */
1408 if (rows != vc->vc_rows || cols != vc->vc_cols)
1409 vc_resize(vc, cols, rows);
1410 if (!vc->vc_splash_data->color_set)
1411 splash_recolor(vc, NULL);
1413 SPLASH_DEBUG("Splash Status is off\n");
1414 splash_off(vc, info);
1421 #ifdef CONFIG_PROC_FS
1423 #include <linux/proc_fs.h>
1425 static int splash_read_proc(char *buffer, char **start, off_t offset, int size,
1426 int *eof, void *data);
1427 static int splash_write_proc(struct file *file, const char *buffer,
1428 unsigned long count, void *data);
1429 static int splash_status(struct vc_data *vc);
1430 static int splash_proc_register(void);
1432 static struct proc_dir_entry *proc_splash;
1434 static int splash_status(struct vc_data *vc)
1436 struct fb_info *info;
1438 printk(KERN_INFO "bootsplash: status on console %d changed to %s\n",
1440 vc->vc_splash_data &&
1441 vc->vc_splash_data->splash_state ? "on" : "off");
1443 info = registered_fb[(int) con2fb_map[vc->vc_num]];
1447 if (fg_console == vc->vc_num)
1448 splash_prepare(vc, info);
1449 if (vc->vc_splash_data && vc->vc_splash_data->splash_state)
1450 splash_recolor(vc, info);
1452 splash_off(vc, info);
1453 if (vc->vc_def_color != 0x07)
1454 con_remap_def_color(vc, 0x07);
1460 int splash_copy_current_img(int unit_s, int unit_t)
1462 struct fb_info *info;
1463 struct vc_data *vc_s;
1464 struct vc_data *vc_t;
1465 struct splash_data *sd_s;
1466 struct splash_data *sd_t;
1469 if (unit_s >= MAX_NR_CONSOLES || unit_t >= MAX_NR_CONSOLES)
1472 vc_s = vc_cons[unit_s].d;
1474 printk(KERN_WARNING "bootsplash: "
1475 "copy: source (%i) is invalid.\n", unit_s);
1478 sd_s = vc_s->vc_splash_data;
1479 if (!sd_s || !sd_s->imgd) {
1480 printk(KERN_INFO "bootsplash: "
1481 "copy: source_vc (%i) doesn't have valid splash data.\n",
1485 vc_allocate(unit_t);
1486 vc_t = vc_cons[unit_t].d;
1488 printk(KERN_WARNING "bootsplash: copy: dest (%i) is invalid.\n",
1492 sd_t = kzalloc(sizeof(*sd_t), GFP_KERNEL);
1495 vc_t->vc_splash_data = sd_t;
1497 sd_t->imgd = sd_s->imgd;
1498 sd_t->imgd->ref_cnt++;
1500 /* now recreate all the rest */
1501 sd_t->splash_state = sd_s->splash_state;
1502 sd_t->splash_percent = sd_s->splash_percent;
1503 sd_t->splash_dosilent = sd_s->splash_dosilent;
1504 sd_t->splash_vc_text_wi = sd_s->imgd->splash_text_wi;
1505 sd_t->splash_vc_text_he = sd_s->imgd->splash_text_he;
1507 sd_t->splash_boxes_xoff = 0;
1508 sd_t->splash_boxes_yoff = 0;
1509 sd_t->splash_sboxes_xoff = 0;
1510 sd_t->splash_sboxes_yoff = 0;
1512 info = registered_fb[(int) con2fb_map[vc_t->vc_num]];
1513 size = (((info->var.xres + 15) & ~15)
1514 * ((info->var.bits_per_pixel + 1) >> 3))
1515 * ((info->var.yres + 15) & ~15);
1516 if (size != vc_s->vc_splash_data->pic->splash_pic_size) {
1517 sd_t->pic = kzalloc(sizeof(struct splash_pic_data), GFP_KERNEL);
1520 sd_t->pic->ref_cnt = 1;
1522 sd_t->pic = sd_s->pic;
1523 sd_t->pic->ref_cnt++;
1526 splash_status(vc_t);
1531 static int splash_read_proc(char *buffer, char **start, off_t offset, int size,
1532 int *eof, void *data)
1536 struct vc_data *vc = vc_cons[0].d;
1537 struct fb_info *info = registered_fb[(int)con2fb_map[0]];
1538 int color = vc->vc_splash_data ?
1539 vc->vc_splash_data->imgd->splash_color << 4 |
1540 vc->vc_splash_data->imgd->splash_fg_color : splash_default >> 4;
1541 int status = vc->vc_splash_data ?
1542 vc->vc_splash_data->splash_state & 1 : 0;
1545 xres = info->var.xres;
1546 yres = info->var.yres;
1550 len = sprintf(buffer, "Splash screen v%s (0x%02x, %dx%d%s): %s\n",
1551 SPLASH_VERSION, color, xres, yres,
1552 (vc->vc_splash_data ?
1553 vc->vc_splash_data->splash_dosilent : 0) ? ", silent" :
1555 status ? "on" : "off");
1559 *start = buffer - offset;
1561 return (size < len - offset ? size : len - offset);
1564 void splash_set_percent(struct vc_data *vc, int pe)
1566 struct fb_info *info;
1567 struct fbcon_ops *ops;
1568 struct splash_data *vc_splash_data;
1571 SPLASH_DEBUG(" console: %d val: %d\n", vc->vc_num, pe);
1579 vc_splash_data = vc->vc_splash_data;
1580 if (!vc_splash_data || vc_splash_data->splash_percent == pe)
1583 oldpe = vc_splash_data->splash_percent;
1584 vc_splash_data->splash_percent = pe;
1585 if (fg_console != vc->vc_num ||
1586 !vc_splash_data->splash_state) {
1589 info = registered_fb[(int) con2fb_map[vc->vc_num]];
1593 ops = info->fbcon_par;
1594 if (ops->blank_state)
1596 if (!vc_splash_data->imgd->splash_overpaintok
1599 if (splash_hasinter(vc_splash_data->imgd->splash_boxes,
1600 vc_splash_data->imgd->splash_boxcount)) {
1603 splash_prepare(vc, info);
1605 struct splash_data *splash_data = info->splash_data;
1606 enum splash_color_format cf = SPLASH_DEPTH_UNKNOWN;
1607 switch (info->var.bits_per_pixel) {
1609 if ((info->var.red.length +
1610 info->var.green.length +
1611 info->var.blue.length) == 15)
1612 cf = SPLASH_DEPTH_15;
1614 cf = SPLASH_DEPTH_16;
1617 cf = SPLASH_DEPTH_24_PACKED;
1620 cf = SPLASH_DEPTH_24;
1623 if (cf == SPLASH_DEPTH_UNKNOWN)
1626 if (splash_data->imgd->splash_silentjpeg
1627 && splash_data->splash_dosilent) {
1628 boxit(info->screen_base,
1629 info->fix.line_length,
1630 splash_data->imgd->splash_sboxes,
1631 splash_data->imgd->splash_sboxcount,
1632 splash_data->splash_percent,
1633 splash_data->splash_sboxes_xoff,
1634 splash_data->splash_sboxes_yoff,
1637 /* FIXME: get a proper width/height */
1638 splash_sync_region(info,
1639 splash_data->splash_sboxes_xoff,
1640 splash_data->splash_sboxes_yoff,
1642 splash_data->splash_sboxes_xoff,
1649 static const char *get_unit(const char *buffer, int *unit)
1653 if (buffer[0] >= '0' && buffer[0] <= '9') {
1654 *unit = buffer[0] - '0';
1656 if (buffer[0] >= '0' && buffer[0] <= '9') {
1657 *unit = *unit * 10 + buffer[0] - '0';
1666 static int splash_write_proc(struct file *file, const char *buffer,
1667 unsigned long count, void *data)
1672 struct splash_data *vc_splash_data;
1676 if (!buffer || !splash_default)
1681 if (buffer[0] == '@') {
1683 buffer = get_unit(buffer, &unit);
1684 if (unit < 0 || unit >= MAX_NR_CONSOLES || !vc_cons[unit].d) {
1689 SPLASH_DEBUG(" unit: %i", unit);
1690 vc = vc_cons[unit].d;
1691 vc_splash_data = vc->vc_splash_data;
1693 if (!strncmp(buffer, "redraw", 6)) {
1694 SPLASH_DEBUG(" redraw");
1700 if (!strncmp(buffer, "show", 4) || !strncmp(buffer, "hide", 4)) {
1703 SPLASH_DEBUG("show/hide");
1704 if (buffer[4] == ' ' && buffer[5] == 'p')
1706 else if (buffer[4] == '\n')
1708 else if (strict_strtol(buffer + 5, 0, &pe) == -EINVAL)
1716 splash_set_percent(vc, pe);
1721 if (!strncmp(buffer, "copy", 4)) {
1723 if (buffer[0] == ' ')
1725 buffer = get_unit(buffer, &unit);
1726 if (unit < 0 || unit >= MAX_NR_CONSOLES) {
1730 buffer = get_unit(buffer, &new);
1731 if (new < 0 || new >= MAX_NR_CONSOLES) {
1735 splash_copy_current_img(unit, new);
1740 if (!strncmp(buffer, "silent\n", 7)
1741 || !strncmp(buffer, "verbose\n", 8)) {
1742 SPLASH_DEBUG(" silent/verbose");
1744 if (vc_splash_data &&
1745 vc_splash_data->imgd->splash_silentjpeg) {
1746 if (vc_splash_data->splash_dosilent !=
1747 (buffer[0] == 's')) {
1748 vc_splash_data->splash_dosilent =
1757 if (!strncmp(buffer, "freesilent\n", 11)) {
1758 SPLASH_DEBUG(" freesilent");
1760 if (vc_splash_data &&
1761 vc_splash_data->imgd->splash_silentjpeg) {
1762 struct splash_data *sd;
1763 printk(KERN_INFO "bootsplash: freeing silent jpeg\n");
1764 for (sd = vc_splash_data; sd; sd = sd->next) {
1765 sd->imgd->splash_silentjpeg = 0;
1766 vfree(sd->imgd->splash_sboxes);
1767 sd->imgd->splash_sboxes = 0;
1768 sd->imgd->splash_sboxcount = 0;
1770 if (vc_splash_data->splash_dosilent)
1773 vc->vc_splash_data->splash_dosilent = 0;
1779 if (!strncmp(buffer, "BOOTSPL", 7)) {
1782 SPLASH_DEBUG(" BOOTSPL");
1783 unit = splash_getraw((unsigned char *)buffer,
1784 (unsigned char *)buffer + count,
1786 SPLASH_DEBUG(" unit: %i up: %i", unit, up);
1788 struct fb_info *info;
1790 vc = vc_cons[unit].d;
1791 info = registered_fb[(int) con2fb_map[vc->vc_num]];
1800 struct splash_data *vc_splash_data
1801 = vc->vc_splash_data;
1802 struct splash_data *splash_data
1803 = info->splash_data;
1804 struct fbcon_ops *ops = info->fbcon_par;
1805 enum splash_color_format cf = SPLASH_DEPTH_UNKNOWN;
1807 switch (info->var.bits_per_pixel) {
1809 if ((info->var.red.length +
1810 info->var.green.length +
1811 info->var.blue.length) == 15)
1812 cf = SPLASH_DEPTH_15;
1814 cf = SPLASH_DEPTH_16;
1817 cf = SPLASH_DEPTH_24_PACKED;
1820 cf = SPLASH_DEPTH_24;
1823 if (cf == SPLASH_DEPTH_UNKNOWN)
1825 if (ops->blank_state ||
1830 && splash_data->imgd->splash_silentjpeg
1831 && splash_data->splash_dosilent) {
1832 boxit(info->screen_base,
1833 info->fix.line_length,
1834 splash_data->imgd->splash_sboxes,
1835 splash_data->imgd->splash_sboxcount,
1836 splash_data->splash_percent,
1837 splash_data->splash_sboxes_xoff,
1838 splash_data->splash_sboxes_yoff,
1841 } else if ((up & 1) != 0) {
1842 boxit(info->screen_base,
1843 info->fix.line_length,
1844 splash_data->imgd->splash_boxes,
1845 splash_data->imgd->splash_boxcount,
1846 splash_data->splash_percent,
1847 splash_data->splash_boxes_xoff,
1848 splash_data->splash_boxes_yoff,
1858 if (!vc_splash_data) {
1863 if (buffer[0] == 't') {
1864 vc_splash_data->splash_state ^= 1;
1870 if (strict_strtoul(buffer, 0, &uval) == -EINVAL)
1874 vc_splash_data->imgd->splash_color = uval >> 8 & 0xff;
1875 vc_splash_data->imgd->splash_fg_color = uval >> 4 & 0x0f;
1877 if ((uval & 1) == vc_splash_data->splash_state)
1878 splash_recolor(vc, NULL);
1880 vc_splash_data->splash_state = uval & 1;
1887 static int splash_proc_register(void)
1889 proc_splash = create_proc_entry("splash", 0, 0);
1891 proc_splash->read_proc = splash_read_proc;
1892 proc_splash->write_proc = splash_write_proc;
1898 #endif /* CONFIG_PROC_FS */
1900 #define INIT_CONSOLE 0
1902 void splash_init(void)
1904 static bool splash_not_initialized = true;
1905 struct fb_info *info;
1910 int max_len = 1024*1024*2;
1913 if (splash_not_initialized == false)
1915 vc = vc_cons[INIT_CONSOLE].d;
1916 info = registered_fb[(int)con2fb_map[INIT_CONSOLE]];
1919 || info->var.bits_per_pixel < 16) /* not supported */
1921 #ifdef CONFIG_PROC_FS
1922 splash_proc_register();
1924 splash_not_initialized = false;
1925 if (vc->vc_splash_data)
1927 fd = sys_open("/bootsplash", O_RDONLY, 0);
1930 fd = sys_open("/initrd.image", O_RDONLY, 0);
1934 len = (int)sys_lseek(fd, (off_t)0, 2);
1939 /* Don't look for more than the last 2MB */
1940 if (len > max_len) {
1941 printk(KERN_INFO "bootsplash: "
1942 "scanning last %dMB of initrd for signature\n",
1944 sys_lseek(fd, (off_t)(len - max_len), 0);
1947 sys_lseek(fd, (off_t)0, 0);
1953 if ((int)sys_read(fd, mem, len) == len
1954 && (splash_getraw((unsigned char *)mem,
1955 (unsigned char *)mem + len, (int *)0)
1957 && vc->vc_splash_data)
1958 vc->vc_splash_data->splash_state = splash_default & 1;
1964 sys_unlink("/bootsplash");
1968 #define SPLASH_ALIGN 15
1970 static u32 *do_coefficients(u32 from, u32 to, u32 *shift)
1979 u32 rnd = from >> 1;
1986 if ((1 << upper) & from)
1992 *shift = 32 - 8 - 1 - upper;
1994 coefficients = vmalloc(sizeof(u32) * (from / to + 2) * from + 1);
2003 while (sum < from) {
2005 ((left << *shift) + rnd) / from;
2012 (((to - left) << *shift) + rnd) / from;
2014 coefficients[m] = col_cnt;
2017 coefficients[0] = row_cnt;
2018 return coefficients;
2026 if ((1 << upper) & to)
2032 *shift = 32 - 8 - 1 - upper;
2034 coefficients = vmalloc(sizeof(u32) * 3 * from + 1);
2050 coefficients[n] = col_cnt;
2051 coefficients[0] = row_cnt;
2052 return coefficients;
2054 coefficients[n++] = col_cnt - 1;
2055 coefficients[n++] = ((diff << *shift) + rnd) / from;
2056 coefficients[n++] = ((left << *shift) + rnd) / from;
2068 #define put_pixel(pix, buf, cf) \
2070 case SPLASH_DEPTH_15: \
2071 *(u16 *)(buf) = (u16)((pix).red << 10 | \
2072 (pix).green << 5 | (pix).blue); \
2075 case SPLASH_DEPTH_16: \
2076 *(u16 *)(buf) = (u16)((pix).red << 11 | \
2077 (pix).green << 5 | (pix).blue); \
2080 case SPLASH_DEPTH_24_PACKED: \
2081 *(u16 *)(buf) = (u16)((pix).red << 8 | (pix).green); \
2083 *((buf)++) = (pix).blue; \
2085 case SPLASH_DEPTH_24: \
2086 *(u32 *)(buf) = (u32)((pix).red << 16 | \
2087 (pix).green << 8 | (pix).blue); \
2090 case SPLASH_DEPTH_UNKNOWN: \
2094 #define get_pixel(pix, buf, depth) \
2096 case SPLASH_DEPTH_15: \
2097 (pix).red = ((*(u16 *)(buf)) >> 10) & 0x1f; \
2098 (pix).green = ((*(u16 *)(buf)) >> 5) & 0x1f; \
2099 (pix).blue = (*(u16 *)(buf)) & 0x1f; \
2102 case SPLASH_DEPTH_16: \
2103 (pix).red = ((*(u16 *)(buf)) >> 11) & 0x1f; \
2104 (pix).green = ((*(u16 *)(buf)) >> 5) & 0x3f; \
2105 (pix).blue = (*(u16 *)(buf)) & 0x1f; \
2108 case SPLASH_DEPTH_24_PACKED: \
2109 (pix).blue = *(((buf))++); \
2110 (pix).green = *(((buf))++); \
2111 (pix).red = *(((buf))++); \
2113 case SPLASH_DEPTH_24: \
2114 (pix).blue = *(((buf))++); \
2115 (pix).green = *(((buf))++); \
2116 (pix).red = *(((buf))++); \
2119 case SPLASH_DEPTH_UNKNOWN: \
2124 scale_x_down(enum splash_color_format cf, int src_w,
2125 unsigned char **src_p, u32 *x_coeff,
2126 u32 x_shift, u32 y_coeff, struct pixel *row_buffer)
2128 u32 curr_x_coeff = 1;
2129 struct pixel curr_pixel, tmp_pixel;
2130 u32 x_array_size = x_coeff[0];
2135 u32 rnd = (1 << (x_shift - 1));
2137 for (i = 0; i < src_w; ) {
2139 get_pixel(tmp_pixel, *src_p, cf);
2141 for (l = 0; l < x_array_size; l++) {
2142 x_column_num = x_coeff[curr_x_coeff++];
2144 curr_pixel.green = 0;
2145 curr_pixel.blue = 0;
2146 for (m = 0; m < x_column_num - 1; m++) {
2147 curr_pixel.red += tmp_pixel.red
2148 * x_coeff[curr_x_coeff];
2149 curr_pixel.green += tmp_pixel.green
2150 * x_coeff[curr_x_coeff];
2151 curr_pixel.blue += tmp_pixel.blue
2152 * x_coeff[curr_x_coeff];
2154 get_pixel(tmp_pixel, *src_p, cf);
2157 curr_pixel.red += tmp_pixel.red * x_coeff[curr_x_coeff];
2158 curr_pixel.green += tmp_pixel.green
2159 * x_coeff[curr_x_coeff];
2160 curr_pixel.blue += tmp_pixel.blue
2161 * x_coeff[curr_x_coeff];
2163 curr_pixel.red = (curr_pixel.red + rnd) >> x_shift;
2164 curr_pixel.green = (curr_pixel.green + rnd) >> x_shift;
2165 curr_pixel.blue = (curr_pixel.blue + rnd) >> x_shift;
2166 row_buffer[k].red += curr_pixel.red * y_coeff;
2167 row_buffer[k].green += curr_pixel.green * y_coeff;
2168 row_buffer[k].blue += curr_pixel.blue * y_coeff;
2175 scale_x_up(enum splash_color_format cf, int src_w,
2176 unsigned char **src_p, u32 *x_coeff,
2177 u32 x_shift, u32 y_coeff, struct pixel *row_buffer)
2179 u32 curr_x_coeff = 1;
2180 struct pixel curr_pixel, tmp_pixel;
2181 u32 x_array_size = x_coeff[0];
2186 u32 rnd = (1 << (x_shift - 1));
2188 for (i = 0; i < src_w;) {
2190 get_pixel(tmp_pixel, *src_p, cf);
2192 for (l = 0; l < x_array_size - 1; l++) {
2193 x_column_num = x_coeff[curr_x_coeff++];
2194 for (m = 0; m < x_column_num; m++) {
2195 row_buffer[k].red += tmp_pixel.red * y_coeff;
2196 row_buffer[k].green += tmp_pixel.green * y_coeff;
2197 row_buffer[k].blue += tmp_pixel.blue * y_coeff;
2200 curr_pixel.red = tmp_pixel.red * x_coeff[curr_x_coeff];
2201 curr_pixel.green = tmp_pixel.green
2202 * x_coeff[curr_x_coeff];
2203 curr_pixel.blue = tmp_pixel.blue * x_coeff[curr_x_coeff];
2205 get_pixel(tmp_pixel, *src_p, cf);
2207 row_buffer[k].red += ((curr_pixel.red
2209 * x_coeff[curr_x_coeff])
2210 + rnd) >> x_shift) * y_coeff;
2211 row_buffer[k].green += ((curr_pixel.green
2213 * x_coeff[curr_x_coeff])
2214 + rnd) >> x_shift) * y_coeff;
2215 row_buffer[k].blue += ((curr_pixel.blue
2217 * x_coeff[curr_x_coeff])
2218 + rnd) >> x_shift) * y_coeff;
2222 for (m = 0; m < x_coeff[curr_x_coeff]; m++) {
2223 row_buffer[k].red += tmp_pixel.red * y_coeff;
2224 row_buffer[k].green += tmp_pixel.green * y_coeff;
2225 row_buffer[k].blue += tmp_pixel.blue * y_coeff;
2231 static int scale_y_down(unsigned char *src, unsigned char *dst,
2232 enum splash_color_format cf,
2233 int src_w, int src_h, int dst_w, int dst_h)
2235 int octpp = splash_octpp(cf);
2236 int src_x_bytes = octpp * ((src_w + SPLASH_ALIGN) & ~SPLASH_ALIGN);
2237 int dst_x_bytes = octpp * ((dst_w + SPLASH_ALIGN) & ~SPLASH_ALIGN);
2239 struct pixel *row_buffer;
2240 u32 x_shift, y_shift;
2243 u32 curr_y_coeff = 1;
2244 unsigned char *src_p;
2245 unsigned char *src_p_line = src;
2254 row_buffer = vmalloc(sizeof(struct pixel)
2256 x_coeff = do_coefficients(src_w, dst_w, &x_shift);
2257 y_coeff = do_coefficients(src_h, dst_h, &y_shift);
2258 if (!row_buffer || !x_coeff || !y_coeff) {
2264 y_array_rows = y_coeff[0];
2265 rnd = (1 << (y_shift - 1));
2266 xup = (src_w <= dst_w) ? 1 : 0;
2270 for (j = 0; j < src_h;) {
2272 for (r = 0; r < y_array_rows; r++) {
2273 y_column_num = y_coeff[curr_y_coeff++];
2274 for (k = 0; k < dst_w + 1; k++) {
2275 row_buffer[k].red = 0;
2276 row_buffer[k].green = 0;
2277 row_buffer[k].blue = 0;
2281 scale_x_up(cf, src_w, &src_p, x_coeff,
2282 x_shift, y_coeff[curr_y_coeff],
2285 scale_x_down(cf, src_w, &src_p, x_coeff,
2286 x_shift, y_coeff[curr_y_coeff],
2289 for (s = 1; s < y_column_num; s++) {
2290 src_p = src_p_line = src_p_line + src_x_bytes;
2293 scale_x_up(cf, src_w, &src_p,
2295 y_coeff[curr_y_coeff],
2298 scale_x_down(cf, src_w, &src_p,
2300 y_coeff[curr_y_coeff],
2304 for (k = 0; k < dst_w; k++) {
2305 row_buffer[k].red = (row_buffer[k].red + rnd)
2307 row_buffer[k].green = (row_buffer[k].green
2310 row_buffer[k].blue = (row_buffer[k].blue + rnd)
2312 put_pixel(row_buffer[k], dst, cf);
2314 dst = dst_p_line = dst_p_line + dst_x_bytes;
2316 src_p_line = src_p_line + src_x_bytes;
2325 static int scale_y_up(unsigned char *src, unsigned char *dst,
2326 enum splash_color_format cf,
2327 int src_w, int src_h, int dst_w, int dst_h)
2329 int octpp = splash_octpp(cf);
2330 int src_x_bytes = octpp * ((src_w + SPLASH_ALIGN) & ~SPLASH_ALIGN);
2331 int dst_x_bytes = octpp * ((dst_w + SPLASH_ALIGN) & ~SPLASH_ALIGN);
2333 u32 x_shift, y_shift;
2336 struct pixel *row_buf_list[2];
2337 struct pixel *row_buffer;
2338 u32 curr_y_coeff = 1;
2339 unsigned char *src_p;
2340 unsigned char *src_p_line = src;
2351 x_coeff = do_coefficients(src_w, dst_w, &x_shift);
2352 y_coeff = do_coefficients(src_h, dst_h, &y_shift);
2353 row_buf_list[0] = vmalloc(2 * sizeof(struct pixel)
2355 if (!row_buf_list[0] || !x_coeff || !y_coeff) {
2356 vfree(row_buf_list[0]);
2361 row_buf_list[1] = row_buf_list[0] + (dst_w + 1);
2363 y_array_rows = y_coeff[0];
2364 rnd = (1 << (y_shift - 1));
2366 xup = (src_w <= dst_w) ? 1 : 0;
2372 row_buffer = row_buf_list[0];
2374 for (j = 0; j < src_h;) {
2375 memset(row_buf_list[0], 0, (2 * sizeof(struct pixel)
2379 scale_x_up(cf, src_w, &src_p, x_coeff,
2380 x_shift, 1, row_buffer);
2382 scale_x_down(cf, src_w, &src_p, x_coeff, x_shift, 1,
2384 src_p = src_p_line = src_p_line + src_x_bytes;
2386 for (r = 0; r < y_array_rows - 1; r++) {
2387 struct pixel *old_row_buffer = row_buffer;
2388 u32 prev_y_coeff_val;
2390 y_column_num = y_coeff[curr_y_coeff];
2391 for (s = 0; s < y_column_num; s++) {
2392 for (k = 0; k < dst_w; k++)
2393 put_pixel(row_buffer[k], dst, cf);
2394 dst = dst_p_line = dst_p_line + dst_x_bytes;
2398 row_buffer = row_buf_list[(bi++) % 2];
2399 prev_y_coeff_val = y_coeff[curr_y_coeff++];
2401 scale_x_up(cf, src_w, &src_p, x_coeff,
2402 x_shift, 1, row_buffer);
2404 scale_x_down(cf, src_w, &src_p, x_coeff,
2405 x_shift, 1, row_buffer);
2406 src_p = src_p_line = src_p_line + src_x_bytes;
2408 for (k = 0; k < dst_w; k++) {
2410 pix.red = ((old_row_buffer[k].red
2412 + (row_buffer[k].red
2413 * y_coeff[curr_y_coeff])
2415 pix.green = ((old_row_buffer[k].green
2417 + (row_buffer[k].green
2418 * y_coeff[curr_y_coeff])
2420 pix.blue = ((old_row_buffer[k].blue
2422 + (row_buffer[k].blue
2423 * y_coeff[curr_y_coeff])
2425 old_row_buffer[k].red = 0;
2426 old_row_buffer[k].green = 0;
2427 old_row_buffer[k].blue = 0;
2428 put_pixel(pix, dst, cf);
2430 dst = dst_p_line = dst_p_line + dst_x_bytes;
2434 for (r = 0; r < y_coeff[curr_y_coeff]; r++) {
2435 for (k = 0; k < dst_w; k++)
2436 put_pixel(row_buffer[k], dst, cf);
2438 dst = dst_p_line = dst_p_line + dst_x_bytes;
2442 vfree(row_buf_list[0]);
2449 static int jpeg_get(unsigned char *buf, unsigned char *pic,
2450 int width, int height, enum splash_color_format cf,
2451 struct jpeg_decdata *decdata)
2453 int my_width, my_height;
2455 int octpp = splash_octpp(cf);
2457 jpeg_get_size(buf, &my_width, &my_height);
2459 if (my_height != height || my_width != width) {
2460 int my_size = ((my_width + 15) & ~15)
2461 * ((my_height + 15) & ~15) * octpp;
2462 unsigned char *mem = vmalloc(my_size);
2465 err = jpeg_decode(buf, mem, ((my_width + 15) & ~15),
2466 ((my_height + 15) & ~15), cf, decdata);
2472 "bootsplash: scaling image from %dx%d to %dx%d\n",
2473 my_width, my_height, width, height);
2474 if (my_height <= height)
2475 err = scale_y_up(mem, pic, cf, my_width, my_height,
2476 ((width + 15) & ~15),
2477 ((height + 15) & ~15));
2479 err = scale_y_down(mem, pic, cf, my_width, my_height,
2480 ((width + 15) & ~15),
2481 ((height + 15) & ~15));
2486 err = jpeg_decode(buf, pic, ((width + 15) & ~15),
2487 ((height + 15) & ~15), cf, decdata);