- Updated to 3.4-rc1.
[linux-flexiantxendom0-3.2.10.git] / drivers / video / bootsplash / bootsplash.c
1 /*
2  *           linux/drivers/video/bootsplash/bootsplash.c -
3  *                 splash screen handling functions.
4  *
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>
10  *
11  *        Ideas & SuSE screen work by Ken Wimer, <wimer@suse.de>
12  *
13  *  For more information on this code check http://www.bootsplash.org/
14  */
15
16 #include <linux/module.h>
17 #include <linux/types.h>
18 #include <linux/fb.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>
26
27 #include <asm/irq.h>
28
29 #include "../console/fbcon.h"
30 #include <linux/bootsplash.h>
31 #include "decode-jpg.h"
32
33 #ifndef DEBUG
34 # define SPLASH_DEBUG(fmt, args...)
35 #else
36 # define SPLASH_DEBUG(fmt, args...) \
37         printk(KERN_WARNING "%s: " fmt "\n", __func__, ##args)
38 #endif
39 extern signed char con2fb_map[MAX_NR_CONSOLES];
40
41 #define SPLASH_VERSION "3.2.0-2010/03/31"
42
43 /* These errors have to match fbcon-jpegdec.h */
44 static unsigned char *jpg_errors[] = {
45         "no SOI found",
46         "not 8 bit",
47         "height mismatch",
48         "width mismatch",
49         "bad width or height",
50         "too many COMPPs",
51         "illegal HV",
52         "quant table selector",
53         "picture is not YCBCR 221111",
54         "unknow CID in scan",
55         "dct not sequential",
56         "wrong marker",
57         "no EOI",
58         "bad tables",
59         "depth mismatch",
60         "scale error",
61         "out of memory"
62 };
63
64 static int splash_usesilent;
65 static unsigned long splash_default = 0xf01;
66
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);
71
72 static int __init splash_setup(char *options)
73 {
74         splash_usesilent = 0;
75
76         if (!strncmp("silent", options, 6)) {
77                 printk(KERN_INFO "bootsplash: silent mode.\n");
78                 splash_usesilent = 1;
79                 /* skip "silent," */
80                 if (strlen(options) == 6)
81                         return 0;
82                 options += 7;
83         }
84         if (!strncmp("verbose", options, 7)) {
85                 printk(KERN_INFO "bootsplash: verbose mode.\n");
86                 splash_usesilent = 0;
87                 if (strlen(options) == 7)
88                         return 0;
89                 options += 8;
90         }
91         if (strict_strtoul(options, 0, &splash_default) == -EINVAL)
92                 splash_default = 0;
93
94         return 0;
95 }
96
97 __setup("splash=", splash_setup);
98
99
100 static int splash_hasinter(unsigned char *buf, int num)
101 {
102         unsigned char *bufend = buf + num * 12;
103         while (buf < bufend) {
104                 if (buf[1] > 127)               /* inter? */
105                         return 1;
106                 buf += buf[3] > 127 ? 24 : 12;  /* blend? */
107         }
108         return 0;
109 }
110
111 static int boxextract(unsigned char *buf, unsigned short *dp,
112                       unsigned char *cols, int *blendp)
113 {
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);
122         if (dp[1] > 32767) {
123                 dp[1] = ~dp[1];
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);
127                 *blendp = 1;
128                 return 24;
129         }
130         return 12;
131 }
132
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)
136 {
137         int x, y, p, doblend, r, g, b, a, add;
138         unsigned int i = 0;
139         unsigned short data1[4];
140         unsigned char cols1[16];
141         unsigned short data2[4];
142         unsigned char cols2[16];
143         unsigned char *bufend;
144         union pt picp;
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);
148
149         SPLASH_DEBUG();
150         if (num == 0 || percent < -1)
151                 return;
152         bufend = buf + num * 12;
153         stipple[0] = 0xffffffff;
154         stin = 1;
155         stinn = 0;
156         stixs = stixe = 0;
157         stiys = stiye = 0;
158         while (buf < bufend) {
159                 doblend = 0;
160                 buf += boxextract(buf, data1, cols1, &doblend);
161                 if (data1[0] == 32767 && data1[1] == 32767) {
162                         /* box stipple */
163                         if (stinn == 32)
164                                 continue;
165                         if (stinn == 0) {
166                                 stixs = data1[2];
167                                 stixe = data1[3];
168                                 stiys = stiye = 0;
169                         } else if (stinn == 4) {
170                                 stiys = data1[2];
171                                 stiye = data1[3];
172                         }
173                         stipple[stinn++] = (cols1[0]  << 24) |
174                                 (cols1[1]  << 16) |
175                                 (cols1[2]  << 8)  |
176                                 cols1[3] ;
177                         stipple[stinn++] = (cols1[4]  << 24) |
178                                 (cols1[5]  << 16) |
179                                 (cols1[6]  << 8)  |
180                                 cols1[7] ;
181                         stipple[stinn++] = (cols1[8]  << 24) |
182                                 (cols1[9]  << 16) |
183                                 (cols1[10] << 8)  |
184                                 cols1[11] ;
185                         stipple[stinn++] = (cols1[12] << 24) |
186                                 (cols1[13] << 16) |
187                                 (cols1[14] << 8)  |
188                                 cols1[15] ;
189                         stin = stinn;
190                         continue;
191                 }
192                 stinn = 0;
193                 if (data1[0] > 32767)
194                         buf += boxextract(buf, data2, cols2, &doblend);
195                 if (data1[0] == 32767 && data1[1] == 32766) {
196                         /* box copy */
197                         i = 12 * (short)data1[3];
198                         doblend = 0;
199                         i += boxextract(buf + i, data1, cols1, &doblend);
200                         if (data1[0] > 32767)
201                                 boxextract(buf + i, data2, cols2, &doblend);
202                 }
203                 if (data1[0] == 32767)
204                         continue;
205                 if (data1[2] > 32767) {
206                         if (overpaint)
207                                 continue;
208                         data1[2] = ~data1[2];
209                 }
210                 if (data1[3] > 32767) {
211                         if (percent == 65536)
212                                 continue;
213                         data1[3] = ~data1[3];
214                 }
215                 if (data1[0] > 32767) {
216                         if (percent < 0)
217                                 continue;
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;
225                 }
226                 *(unsigned int *)cols2 = *(unsigned int *)cols1;
227                 a = cols2[3];
228                 if (a == 0 && !doblend)
229                         continue;
230
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);
237                         xo = xe + 1;
238                 } else {
239                         xo = xs = stixs;
240                         xe = stixe ? stixe : data1[2];
241                 }
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);
248                         yo = ye + 1;
249                 } else {
250                         yo = ys = stiys;
251                         ye = stiye ? stiye : data1[3];
252                 }
253                 xo = 32 - (xo & 31);
254                 yo = stin - (yo % stin);
255                 if (xs < data1[0])
256                         xs = data1[0];
257                 if (xe > data1[2])
258                         xe = data1[2];
259                 if (ys < data1[1])
260                         ys = data1[1];
261                 if (ye > data1[3])
262                         ye = data1[3];
263
264                 for (y = ys; y <= ye; y++) {
265                         sti = stipple[(y + yo) % stin];
266                         x = (xs + xo) & 31;
267                         if (x)
268                                 sti = (sti << x) | (sti >> (32 - x));
269                         if (doblend) {
270                                 p = data1[3] - data1[1];
271                                 if (p != 0)
272                                         p = ((y - data1[1]) << 16) / p;
273                                 for (i = 0; i < 8; i++)
274                                         cols2[i + 8] = (cols1[i] * (65536 - p)
275                                                         + cols1[i + 8] * p)
276                                                 >> 16;
277                         }
278                         add = (xs & 1);
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)) {
284                                         sti <<= 1;
285                                         switch (octpp) {
286                                         case 2:
287                                                 picp.us++;
288                                                 break;
289                                         case 3:
290                                                 picp.ub += 3;
291                                                 break;
292                                         case 4:
293                                                 picp.ul++;
294                                                 break;
295                                         }
296                                         add ^= 3;
297                                         continue;
298                                 }
299                                 sti = (sti << 1) | 1;
300                                 if (doblend) {
301                                         p = data1[2] - data1[0];
302                                         if (p != 0)
303                                                 p = ((x - data1[0]) << 16) / p;
304                                         for (i = 0; i < 4; i++)
305                                                 cols2[i] = (cols2[i + 8] * (65536 - p)
306                                                             + cols2[i + 12] * p)
307                                                         >> 16;
308                                         a = cols2[3];
309                                 }
310                                 r = cols2[0];
311                                 g = cols2[1];
312                                 b = cols2[2];
313 #define CLAMP(x) ((x) >= 256 ? 255 : (x))
314 #define BLEND(x, v, a) ((x * (255 - a) + v * a) / 255)
315                                 switch (cf) {
316                                 case SPLASH_DEPTH_15:
317                                         if (a != 255) {
318                                                 i = *picp.us;
319                                                 r = BLEND((i>>7 & 0xf8), r, a);
320                                                 g = BLEND((i>>2 & 0xf8), g, a);
321                                                 b = BLEND((i<<3 & 0xf8), b, a);
322                                         }
323                                         r += add * 2 + 1;
324                                         g += add;
325                                         b += add * 2 + 1;
326                                         i =     ((CLAMP(r) & 0xf8) <<  7) |
327                                                 ((CLAMP(g) & 0xf8) <<  2) |
328                                                 ((CLAMP(b))        >>  3);
329                                         *(picp.us++) = i;
330                                         break;
331                                 case SPLASH_DEPTH_16:
332                                         if (a != 255) {
333                                                 i = *picp.us;
334                                                 r = BLEND((i>>8 & 0xf8), r, a);
335                                                 g = BLEND((i>>3 & 0xfc), g, a);
336                                                 b = BLEND((i<<3 & 0xf8), b, a);
337                                         }
338                                         r += add * 2 + 1;
339                                         g += add;
340                                         b += add * 2 + 1;
341                                                 i = ((CLAMP(r) & 0xf8) <<  8) |
342                                                     ((CLAMP(g) & 0xfc) <<  3) |
343                                                     ((CLAMP(b))        >>  3);
344                                         *(picp.us++) = i;
345                                         break;
346                                 case SPLASH_DEPTH_24_PACKED:
347                                         if (a != 255) {
348                                                 i = *picp.ub;
349                                                 r = BLEND((i & 0xff), r, a);
350                                                 i = *(picp.ub + 1);
351                                                 g = BLEND((i & 0xff), g, a);
352                                                 i = *(picp.ub + 2);
353                                                 b = BLEND((i & 0xff), b, a);
354                                         }
355                                         *(picp.ub++) = CLAMP(r);
356                                         *(picp.ub++) = CLAMP(g);
357                                         *(picp.ub++) = CLAMP(b);
358                                         break;
359                                 case SPLASH_DEPTH_24:
360                                         if (a != 255) {
361                                                 i = *picp.ul;
362                                                 r = BLEND((i>>16 & 0xff), r, a);
363                                                 g = BLEND((i>>8  & 0xff), g, a);
364                                                 b = BLEND((i     & 0xff), b, a);
365                                         }
366                                         i = ((CLAMP(r) << 16)
367                                              | (CLAMP(g) << 8)
368                                              | (CLAMP(b)));
369                                         *(picp.ul++) = i;
370                                         break;
371                                 default:
372                                         break;
373                                 }
374                                 add ^= 3;
375                         }
376                 }
377         }
378 }
379
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)
383 {
384         int a, doblend;
385         int x_min = pic_w, x_max = 0;
386         int y_min = pic_h, y_max = 0;
387         unsigned int i = 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;
394         int xs, xe, ys, ye;
395
396         SPLASH_DEBUG();
397
398         if ((screen_w == pic_w && screen_h == pic_h) || num == 0)
399                 *x_off = *y_off = 0;
400
401         bufend = buf + num * 12;
402         stin = 1;
403         stinn = 0;
404         stixs = stixe = 0;
405         stiys = stiye = 0;
406
407         while (buf < bufend) {
408                 doblend = 0;
409                 buf += boxextract(buf, data1, cols1, &doblend);
410                 if (data1[0] == 32767 && data1[1] == 32767) {
411                         /* box stipple */
412                         if (stinn == 32)
413                                 continue;
414                         if (stinn == 0) {
415                                 stixs = data1[2];
416                                 stixe = data1[3];
417                                 stiys = stiye = 0;
418                         } else if (stinn == 4) {
419                                 stiys = data1[2];
420                                 stiye = data1[3];
421                         }
422                         stin = stinn;
423                         continue;
424                 }
425                 stinn = 0;
426                 if (data1[0] > 32767)
427                         buf += boxextract(buf, data2, cols2, &doblend);
428                 if (data1[0] == 32767 && data1[1] == 32766) {
429                         /* box copy */
430                         i = 12 * (short)data1[3];
431                         doblend = 0;
432                         i += boxextract(buf + i, data1, cols1, &doblend);
433                         if (data1[0] > 32767)
434                                 boxextract(buf + i, data2, cols2, &doblend);
435                 }
436                 if (data1[0] == 32767)
437                         continue;
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;
447                 }
448                 *(unsigned int *)cols2 = *(unsigned int *)cols1;
449                 a = cols2[3];
450                 if (a == 0 && !doblend)
451                         continue;
452
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);
459                 } else {
460                         xs = stixs;
461                         xe = stixe ? stixe : data1[2];
462                 }
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);
469                 } else {
470                         ys = stiys;
471                         ye = stiye ? stiye : data1[3];
472                 }
473                 if (xs < data1[0])
474                         xs = data1[0];
475                 if (xe > data1[2])
476                         xe = data1[2];
477                 if (ys < data1[1])
478                         ys = data1[1];
479                 if (ye > data1[3])
480                         ye = data1[3];
481
482                 if (xs < x_min)
483                         x_min = xs;
484                 if (xe > x_max)
485                         x_max = xe;
486                 if (ys < y_min)
487                         y_min = ys;
488                 if (ye > y_max)
489                         y_max = ye;
490         }
491         {
492                 int x_center = (x_min + x_max) / 2;
493                 int y_center = (y_min + y_max) / 2;
494
495                 if (screen_w == pic_w)
496                         *x_off = 0;
497                 else {
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;
501                         } else {
502                                 int x = x_center * screen_w / pic_w;
503                                 *x_off = x - x_center;
504                                 if (x_min + *x_off < 0)
505                                         *x_off = 0;
506                                 if (x_max + *x_off > screen_w)
507                                         *x_off = screen_w - pic_w;
508                         }
509                 }
510                 if (screen_h == pic_h)
511                         *y_off = 0;
512                 else {
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;
516                         else {
517                                 int x = y_center * screen_h / pic_h;
518                                 *y_off = x - y_center;
519                                 if (y_min + *y_off < 0)
520                                         *y_off = 0;
521                                 if (y_max + *x_off > screen_h)
522                                         *y_off = screen_h - pic_h;
523                         }
524                 }
525         }
526 }
527
528 static int splash_check_jpeg(unsigned char *jpeg,
529                              int width, int height)
530 {
531         int size, err;
532         unsigned char *mem;
533         struct jpeg_decdata *decdata; /* private decoder data */
534
535
536         size = ((width + 15) & ~15) * ((height + 15) & ~15) * 2;
537         mem = vmalloc(size);
538         if (!mem) {
539                 printk(KERN_INFO "bootsplash: no memory for decoded picture.\n");
540                 return -1;
541         }
542         decdata = vmalloc(sizeof(*decdata));
543         if (!decdata) {
544                 printk(KERN_INFO "bootsplash: not enough memory.\n");
545                 vfree(mem);
546                 return -1;
547         }
548         /* test decode: use fixed depth of 16 */
549         err = jpeg_decode(jpeg, mem,
550                           ((width + 15) & ~15), ((height + 15) & ~15),
551                           SPLASH_DEPTH_16,
552                           decdata);
553         if (err)
554                 printk(KERN_INFO "bootsplash: "
555                        "error while decompressing picture: %s (%d)\n",
556                        jpg_errors[err - 1], err);
557         vfree(decdata);
558         vfree(mem);
559         return err ? -1 : 0;
560 }
561
562 static void splash_free(struct vc_data *vc, struct fb_info *info)
563 {
564         struct splash_data *sd;
565         struct splash_data *next;
566         SPLASH_DEBUG();
567         for (sd = vc->vc_splash_data; sd; sd = next) {
568                 next = sd->next;
569                 sd->pic->ref_cnt--;
570                 if (!sd->pic->ref_cnt) {
571                         vfree(sd->pic->splash_pic);
572                         vfree(sd->pic);
573                 }
574                 sd->imgd->ref_cnt--;
575                 if (!sd->imgd->ref_cnt) {
576                         vfree(sd->imgd->splash_sboxes);
577                         vfree(sd->imgd);
578                 }
579                 vfree(sd);
580         }
581         vc->vc_splash_data = 0;
582         if (info)
583                 info->splash_data = 0;
584 }
585
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)
589 {
590         unsigned char *buf;
591         int i;
592
593         if (pwi == 0 || phe == 0)
594                 return 0;
595
596         buf = (unsigned char *)data + sizeof(*data);
597
598         pwi += pxo - 1;
599         phe += pyo - 1;
600
601         *buf++ = pxo;
602         *buf++ = pxo >> 8;
603         *buf++ = pyo;
604         *buf++ = pyo >> 8;
605         *buf++ = pwi;
606         *buf++ = pwi >> 8;
607         *buf++ = phe;
608         *buf++ = phe >> 8;
609         *buf++ = pr;
610         *buf++ = pg;
611         *buf++ = pb;
612         *buf++ = 0;
613
614         for (i = 0; i < 12; i++, buf++)
615                 *buf = buf[-12];
616
617         buf[-24] ^= 0xff;
618         buf[-23] ^= 0xff;
619         buf[-1] = 0xff;
620
621         return 2;
622 }
623
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 */
627     /* V1 */
628         {   20,   -1,   16,    -1,    -1,  -1,  8, 10, 12, 14,
629             -1,    -1,      -1,      -1,     -1,     -1 },
630         /* V2 */
631         {   35,    8,   12,     9,    10,  11, 16, 18, 20, 22,
632             -1,    -1,      -1,      -1,     -1,     -1 },
633         /* V3 */
634         {   38,    8,   12,     9,    10,  11, 16, 18, 20, 22,
635             24,    28,      32,      34,     36,     37 },
636 };
637
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]
654
655 static inline int splash_getb(unsigned char *pos, int off)
656 {
657         return off == -1 ? 0 : pos[off];
658 }
659
660 static inline int splash_gets(unsigned char *pos, int off)
661 {
662         return off == -1 ? 0 : pos[off] | pos[off + 1] << 8;
663 }
664
665 static inline int splash_geti(unsigned char *pos, int off)
666 {
667         return off == -1 ? 0 : (pos[off] |
668                                 pos[off + 1] << 8 |
669                                 pos[off + 2] << 16 |
670                                 pos[off + 3] << 24);
671 }
672
673 /* move the given splash_data to the current one */
674 static void splash_pivot_current(struct vc_data *vc, struct splash_data *new)
675 {
676         struct splash_data *sd;
677         struct splash_pic_data *pic;
678         int state, percent, silent;
679
680         sd = vc->vc_splash_data;
681         if (!sd || sd == new)
682                 return;
683
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);
689                 if (!pic)
690                         return;
691                 sd->pic = pic;
692         }
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;
709
710                         new->splash_boxes_xoff = 0;
711                         new->splash_boxes_yoff = 0;
712                         new->splash_sboxes_xoff = 0;
713                         new->splash_sboxes_yoff = 0;
714
715                         if (new->pic->ref_cnt > 1) {
716                                 struct splash_pic_data *pic;
717                                 pic = kzalloc(sizeof(struct splash_pic_data),
718                                               GFP_KERNEL);
719                                 if (!pic)
720                                         return;
721
722                                 new->pic = pic;
723                         }
724                         new->pic->ref_cnt = 1;
725                         new->pic->splash_pic_size = 0;
726                         new->pic->splash_pic = NULL;
727
728                         return;
729                 }
730         }
731 }
732
733 static int update_boxes(struct vc_data *vc,
734                const int *offsets,
735                unsigned char *ndata, int len, unsigned char * end,
736                int *update)
737 {
738         int boxcnt;
739         int sboxcnt;
740         struct splash_data *sd;
741         struct splash_img_data *imgd;
742         int i;
743
744         sd = vc->vc_splash_data;
745         if (sd != 0) {
746                 int up = 0;
747                 imgd = sd->imgd;
748                 i = splash_getb(ndata, SPLASH_OFF_STATE);
749                 if (i != 255) {
750                         sd->splash_state = i; /*@!@*/
751                         up = -1;
752                 }
753                 i = splash_getb(ndata, SPLASH_OFF_FGCOL);
754                 if (i != 255) {
755                         imgd->splash_fg_color = i;
756                         up = -1;
757                 }
758                 i = splash_getb(ndata, SPLASH_OFF_COL);
759                 if (i != 255) {
760                         imgd->splash_color = i;
761                         up = -1;
762                 }
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);
767                 }
768                 if (boxcnt) {
769                         i = splash_gets(ndata, len);
770                         if (boxcnt + i
771                             <= imgd->splash_boxcount &&
772                             ndata + len + 2 + boxcnt * 12
773                             <= end) {
774                                 if (splash_geti(ndata, len + 2)
775                                     != 0x7ffd7fff ||
776                                     !memcmp(ndata + len + 2,
777                                             imgd->splash_boxes + i * 12,
778                                             8)) {
779                                         memcpy(imgd->splash_boxes + i * 12,
780                                                ndata + len + 2,
781                                                boxcnt * 12);
782                                         up |= 1;
783                                 }
784                         }
785                         len += boxcnt * 12 + 2;
786                 }
787                 if (sboxcnt) {
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,
794                                                8)) {
795                                         memcpy(imgd->splash_sboxes + i * 12,
796                                                ndata + len + 2,
797                                                sboxcnt * 12);
798                                         up |= 2;
799                                 }
800                         }
801                 }
802                 if (update)
803                         *update = up;
804         }
805         return 0;
806 }
807
808 static int splash_getraw(unsigned char *start, unsigned char *end, int *update)
809 {
810         unsigned char *ndata;
811         int version;
812         int splash_size;
813         int unit;
814         int width, height;
815         int silentsize;
816         int boxcnt;
817         int sboxcnt;
818         int palcnt;
819         int len;
820         const int *offsets;
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;
827         int unit_found = -1;
828         int oldpercent, oldsilent;
829
830         if (update)
831                 *update = -1;
832
833         if (!update ||
834             start[7] < '2' ||
835             start[7] > '3' ||
836             splash_geti(start, 12) != (int)0xffffffff)
837                 printk(KERN_INFO "bootsplash %s: looking for picture...\n",
838                        SPLASH_VERSION);
839
840         oldpercent = -3;
841         oldsilent = -1;
842         for (ndata = start; ndata < end; ndata++) {
843                 if (ndata[0] != 'B' ||
844                     ndata[1] != 'O' ||
845                     ndata[2] != 'O' ||
846                     ndata[3] != 'T')
847                         continue;
848                 if (ndata[4] != 'S' ||
849                     ndata[5] != 'P' ||
850                     ndata[6] != 'L' ||
851                     ndata[7]  < '1' ||
852                     ndata[7]  > '3')
853                         continue;
854
855                 version = ndata[7] - '0';
856                 offsets = splash_offsets[version - 1];
857                 len = SPLASH_OFF_LEN;
858
859                 unit = splash_getb(ndata, SPLASH_OFF_UNIT);
860                 if (unit >= MAX_NR_CONSOLES)
861                         continue;
862
863                 if (unit)
864                         vc_allocate(unit);
865
866                 vc = vc_cons[unit].d;
867                 if (!vc)
868                         continue;
869
870                 info = registered_fb[(int)con2fb_map[unit]];
871
872                 splash_size = splash_geti(ndata, SPLASH_OFF_SIZE);
873
874                 /*
875                  * Update. Wonder what should happen here now
876                  * since we can have multiple splash_data records
877                  */
878                 if (splash_size == (int)0xffffffff && version > 1) {
879                         if (update_boxes(vc, offsets, ndata, len, end, update) < 0)
880                                 return -1;
881
882                         return unit;
883                 }
884
885                 if (splash_size == 0) {
886                         printk(KERN_INFO
887                                "bootsplash: ...found, freeing memory.\n");
888                         if (vc->vc_splash_data)
889                                 splash_free(vc, info);
890                         return unit;
891                 }
892                 boxcnt = splash_gets(ndata, SPLASH_OFF_BOXCNT);
893                 palcnt = 3 * splash_getb(ndata, SPLASH_OFF_PALCNT);
894                 if (ndata + len + splash_size > end) {
895                         printk(KERN_ERR
896                                "bootsplash: ...found, but truncated!\n");
897                         return -1;
898                 }
899                 silentsize = splash_geti(ndata, SPLASH_OFF_SSIZE);
900                 if (silentsize)
901                         printk(KERN_INFO
902                                "bootsplash: silentjpeg size %d bytes\n",
903                                silentsize);
904                 if (silentsize >= splash_size) {
905                         printk(KERN_ERR "bootsplash: bigger than splashsize!\n");
906                         return -1;
907                 }
908                 splash_size -= silentsize;
909                 if (!splash_usesilent)
910                         silentsize = 0;
911
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;/*@!@*/
916                 }
917                 sd = kzalloc(sizeof(*sd), GFP_KERNEL);
918                 if (!sd)
919                         break;
920                 imgd = vmalloc(sizeof(*imgd)
921                                + splash_size + (version < 3 ? 2 * 12 : 0));
922                 if (!imgd) {
923                         vfree(sd);
924                         break;
925                 }
926                 pic = kzalloc(sizeof(*pic), GFP_KERNEL);
927                 if (!pic) {
928                         vfree(sd);
929                         vfree(pic);
930                         break;
931                 }
932                 memset(imgd, 0, sizeof(*imgd));
933                 sd->imgd = imgd;
934                 sd->pic = pic;
935                 imgd->ref_cnt = 1;
936                 pic->ref_cnt = 1;
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,
940                                       imgd->splash_width,
941                                       imgd->splash_height)) {
942                         ndata += len + splash_size - 1;
943                         vfree(imgd);
944                         vfree(sd);
945                         continue;
946                 }
947                 if (silentsize) {
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;
955                         }
956                 }
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);
964                 if (version == 1) {
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;
971                 }
972
973                 /* fake penguin box for older formats */
974                 if (version == 1)
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,
979                                                   0xf0, 0xf0, 0xf0);
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));
989
990                 memcpy((char *)imgd
991                        + sizeof(*imgd) + (version < 3 ? boxcnt * 12 : 0),
992                        ndata + len,
993                        splash_size);
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;
998
999                 sd->splash_state = splash_getb(ndata, SPLASH_OFF_STATE);/*@!@*/
1000                 sd->splash_percent = oldpercent == -3 ?
1001                         splash_gets(ndata, SPLASH_OFF_PERCENT) :
1002                         oldpercent; /*@!@*/
1003                 sd->pic->splash_pic = NULL;
1004                 sd->pic->splash_pic_size = 0;
1005
1006                 sd->splash_dosilent = imgd->splash_silentjpeg != 0 ?
1007                         (oldsilent == -1 ? 1 : oldsilent) :
1008                         0; /* @!@ */
1009
1010                 sd->splash_vc_text_wi = imgd->splash_text_wi;
1011                 sd->splash_vc_text_he = imgd->splash_text_he;
1012
1013                 sd->next = vc->vc_splash_data;
1014                 vc->vc_splash_data = sd;
1015
1016                 if (info) {
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;
1022                                 continue;
1023                         }
1024                 }
1025                 printk(KERN_INFO
1026                        "bootsplash: ...found (%dx%d, %d bytes, v%d).\n",
1027                        imgd->splash_width, imgd->splash_height,
1028                        splash_size, version);
1029                 if (version == 1) {
1030                         printk(KERN_WARNING
1031                                "bootsplash: Using deprecated v1 header. "
1032                                "Updating your splash utility recommended.\n");
1033                         printk(KERN_INFO
1034                                "bootsplash: Find the latest version at "
1035                        "http://www.bootsplash.org/\n");
1036                 }
1037
1038                 splash_found = sd;
1039                 unit_found = unit;
1040         }
1041
1042         if (splash_found) {
1043                 splash_pivot_current(vc, splash_found);
1044                 return unit_found;
1045         } else {
1046                 vc = vc_cons[0].d;
1047                 if (vc) {
1048                         info = registered_fb[(int)con2fb_map[0]];
1049                         if (info) {
1050                                 width = info->var.xres;
1051                                 height = info->var.yres;
1052                         } else
1053                                 width = height = 0;
1054                         if (!splash_look_for_jpeg(vc, width, height))
1055                                 return -1;
1056                         return 0;
1057                 }
1058         }
1059
1060         printk(KERN_ERR "bootsplash: ...no good signature found.\n");
1061         return -1;
1062 }
1063
1064 static void splash_update_redraw(struct vc_data *vc, struct fb_info *info)
1065 {
1066         update_region(vc,
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);
1070 }
1071
1072 int splash_do_verbose(void)
1073 {
1074         struct vc_data *vc;
1075         struct fb_info *info;
1076         int ret = 0;
1077
1078         SPLASH_DEBUG();
1079         if (!oops_in_progress)
1080                 console_lock();
1081
1082         if (!splash_usesilent)
1083                 goto done;
1084
1085         vc = vc_cons[0].d;
1086
1087         if (!vc || !vc->vc_splash_data || !vc->vc_splash_data->splash_state)
1088                 goto done;
1089         if (!vc->vc_splash_data->imgd->splash_silentjpeg)
1090                 goto done;
1091
1092         if (!vc->vc_splash_data->splash_dosilent)
1093                 goto done;
1094         vc->vc_splash_data->splash_dosilent = 0;
1095         if (fg_console != vc->vc_num)
1096                 goto done;
1097
1098         info = registered_fb[(int)con2fb_map[0]];
1099
1100         if (!info || !info->splash_data)
1101                 goto done;
1102
1103         splash_update_redraw(vc, info);
1104         ret = 0;
1105
1106  done:
1107         if (!oops_in_progress)
1108                 console_unlock();
1109
1110         return ret;
1111 }
1112
1113 static void splash_verbose_callback(struct work_struct *ignored)
1114 {
1115         splash_do_verbose();
1116 }
1117
1118 static DECLARE_WORK(splash_work, splash_verbose_callback);
1119
1120 int splash_verbose(void)
1121 {
1122         if (!oops_in_progress)
1123                 schedule_work(&splash_work);
1124         else
1125                 return splash_do_verbose();
1126         return 0;
1127 }
1128
1129 static void splash_off(struct vc_data *vc, struct fb_info *info)
1130 {
1131         int rows = info->var.xres / vc->vc_font.width;
1132         int cols = info->var.yres / vc->vc_font.height;
1133         SPLASH_DEBUG();
1134
1135         info->splash_data = 0;
1136         if (rows != vc->vc_rows || cols != vc->vc_cols)
1137                 vc_resize(vc, rows, cols);
1138 }
1139
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)
1142 {
1143         struct splash_data *sd, *found = NULL;
1144         int found_delta_x = INT_MAX, found_delta_y = INT_MAX;
1145
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;
1149                 if (!found ||
1150                     (found_delta_x + found_delta_y > delta_x + delta_y)) {
1151                         found = sd;
1152                         found_delta_x = delta_x;
1153                         found_delta_y = delta_y;
1154                 }
1155         }
1156
1157         if (found) {
1158                 SPLASH_DEBUG("bootsplash: "
1159                              "scalable image found (%dx%d scaled to %dx%d).",
1160                              found->imgd->splash_width,
1161                              found->imgd->splash_height,
1162                              width, height);
1163
1164                 splash_pivot_current(vc, found);
1165
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);
1171                 else
1172                         found->splash_vc_text_he = found->imgd->splash_text_he;
1173                 if (found->imgd->splash_width != width)
1174                         found->splash_vc_text_wi =
1175                                 width
1176                                 - (found->imgd->splash_width
1177                                    - found->imgd->splash_text_wi);
1178                 else
1179                         found->splash_vc_text_wi = found->imgd->splash_text_wi;
1180
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,
1185                                     width, height,
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);
1193
1194                         if (found->imgd->splash_sboxes) {
1195                                 box_offsets(found->imgd->splash_sboxes,
1196                                             found->imgd->splash_sboxcount,
1197                                             width, height,
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);
1206                         }
1207                 } else {
1208                         found->splash_sboxes_xoff = 0;
1209                         found->splash_sboxes_yoff = 0;
1210                 }
1211                 return 0;
1212         }
1213         return -1;
1214 }
1215
1216 static int splash_recolor(struct vc_data *vc, struct fb_info *info)
1217 {
1218         int color;
1219
1220         SPLASH_DEBUG();
1221         if (!vc->vc_splash_data)
1222                 return -1;
1223         if (!vc->vc_splash_data->splash_state)
1224                 return 0;
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;
1232         return 0;
1233 }
1234
1235 int splash_prepare(struct vc_data *vc, struct fb_info *info)
1236 {
1237         int err;
1238         int width, height, octpp, size, sbytes;
1239         enum splash_color_format cf = SPLASH_DEPTH_UNKNOWN;
1240         int pic_update = 0;
1241         struct jpeg_decdata *decdata; /* private decoder data */
1242
1243         SPLASH_DEBUG("vc_num: %i", vc->vc_num);
1244
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 "
1249                        "handle it!\n");
1250                 return -1;
1251         }
1252 #endif
1253
1254         if (!vc->vc_splash_data || !vc->vc_splash_data->splash_state) {
1255                 splash_off(vc, info);
1256                 return -1;
1257         }
1258
1259         width = info->var.xres;
1260         height = info->var.yres;
1261         switch (info->var.bits_per_pixel) {
1262         case 16:
1263                 if ((info->var.red.length +
1264                      info->var.green.length +
1265                      info->var.blue.length) == 15)
1266                         cf = SPLASH_DEPTH_15;
1267                 else
1268                         cf = SPLASH_DEPTH_16;
1269                 break;
1270         case 24:
1271                 cf = SPLASH_DEPTH_24_PACKED;
1272                 break;
1273         case 32:
1274                 cf = SPLASH_DEPTH_24;
1275                 break;
1276         }
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);
1281                 return -2;
1282         }
1283         octpp = splash_octpp(cf);
1284
1285         if (splash_look_for_jpeg(vc, width, height) < 0) {
1286                 printk(KERN_INFO "bootsplash: no matching splash %dx%d\n",
1287                        width, height);
1288                 splash_off(vc, info);
1289                 return -2;
1290         }
1291
1292         sbytes = ((width + 15) & ~15) * octpp;
1293         size = sbytes * ((height + 15) & ~15);
1294
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),
1299                                       GFP_KERNEL);
1300                         if (!pic)
1301                                 return -2;
1302                         vc->vc_splash_data->pic = pic;
1303                 }
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;
1307         }
1308         if (!vc->vc_splash_data->pic->splash_pic) {
1309                 vc->vc_splash_data->pic->splash_pic = vmalloc(size);
1310                 pic_update = 1;
1311         }
1312         if (!vc->vc_splash_data->pic->splash_pic) {
1313                 printk(KERN_INFO "bootsplash: not enough memory.\n");
1314                 splash_off(vc, info);
1315                 return -3;
1316         }
1317
1318         decdata = vmalloc(sizeof(*decdata));
1319         if (!decdata) {
1320                 printk(KERN_INFO "bootsplash: not enough memory.\n");
1321                 splash_off(vc, info);
1322                 return -3;
1323         }
1324
1325         if (vc->vc_splash_data->imgd->splash_silentjpeg &&
1326             vc->vc_splash_data->splash_dosilent) {
1327                 pic_update = 1;
1328                 err = jpeg_get(vc->vc_splash_data->imgd->splash_silentjpeg,
1329                                vc->vc_splash_data->pic->splash_pic,
1330                                width, height, cf, decdata);
1331                 if (err) {
1332                         printk(KERN_INFO "bootsplash: "
1333                                "error while decompressing silent picture: "
1334                                "%s (%d)\n",
1335                                jpg_errors[err - 1], err);
1336                         vc->vc_splash_data->splash_dosilent = 0;
1337                 } else {
1338                         if (vc->vc_splash_data->imgd->splash_sboxcount)
1339                                 boxit(vc->vc_splash_data->pic->splash_pic,
1340                                       sbytes,
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 ?
1347                                       1 : 0,
1348                                       cf);
1349                         splashcopy(info->screen_base,
1350                                    vc->vc_splash_data->pic->splash_pic,
1351                                    info->var.yres,
1352                                    info->var.xres,
1353                                    info->fix.line_length, sbytes,
1354                                    octpp);
1355                 }
1356         } else
1357                 vc->vc_splash_data->splash_dosilent = 0;
1358
1359         if (pic_update) {
1360                 err = jpeg_get(vc->vc_splash_data->imgd->splash_jpeg,
1361                                vc->vc_splash_data->pic->splash_pic,
1362                                width, height, cf, decdata);
1363                 if (err) {
1364                         printk(KERN_INFO "bootsplash: "
1365                                "error while decompressing picture: %s (%d) .\n",
1366                                jpg_errors[err - 1], err);
1367                         splash_off(vc, info);
1368                         return -4;
1369                 }
1370         }
1371
1372         vfree(decdata);
1373
1374         vc->vc_splash_data->pic->splash_pic_size = size;
1375         vc->vc_splash_data->pic->splash_pic_stride = sbytes;
1376
1377         if (vc->vc_splash_data->imgd->splash_boxcount)
1378                 boxit(vc->vc_splash_data->pic->splash_pic,
1379                       sbytes,
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,
1385                       0,
1386                       cf);
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;
1392
1393                 info->splash_data = vc->vc_splash_data;
1394
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.
1399                  */
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);
1405                 }
1406
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);
1412         } else {
1413                 SPLASH_DEBUG("Splash Status is off\n");
1414                 splash_off(vc, info);
1415                 return -5;
1416         }
1417         return 0;
1418 }
1419
1420
1421 #ifdef CONFIG_PROC_FS
1422
1423 #include <linux/proc_fs.h>
1424
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);
1431
1432 static struct proc_dir_entry *proc_splash;
1433
1434 static int splash_status(struct vc_data *vc)
1435 {
1436         struct fb_info *info;
1437
1438         printk(KERN_INFO "bootsplash: status on console %d changed to %s\n",
1439                vc->vc_num,
1440                vc->vc_splash_data &&
1441                vc->vc_splash_data->splash_state ? "on" : "off");
1442
1443         info = registered_fb[(int) con2fb_map[vc->vc_num]];
1444         if (!info)
1445                 return 0;
1446
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);
1451         else {
1452                 splash_off(vc, info);
1453                 if (vc->vc_def_color != 0x07)
1454                         con_remap_def_color(vc, 0x07);
1455         }
1456
1457         return 0;
1458 }
1459
1460 int splash_copy_current_img(int unit_s, int unit_t)
1461 {
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;
1467         int size;
1468
1469         if (unit_s >= MAX_NR_CONSOLES || unit_t >= MAX_NR_CONSOLES)
1470                 return -1;
1471
1472         vc_s = vc_cons[unit_s].d;
1473         if (!vc_s) {
1474                 printk(KERN_WARNING "bootsplash: "
1475                        "copy: source (%i) is invalid.\n", unit_s);
1476                 return -1;
1477         }
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",
1482                        unit_s);
1483                 return -1;
1484         }
1485         vc_allocate(unit_t);
1486         vc_t = vc_cons[unit_t].d;
1487         if (!vc_t) {
1488                 printk(KERN_WARNING "bootsplash: copy: dest (%i) is invalid.\n",
1489                        unit_t);
1490                 return -1;
1491         }
1492         sd_t = kzalloc(sizeof(*sd_t), GFP_KERNEL);
1493         if (!sd_t)
1494                 return -1;
1495         vc_t->vc_splash_data = sd_t;
1496
1497         sd_t->imgd = sd_s->imgd;
1498         sd_t->imgd->ref_cnt++;
1499
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;
1506
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;
1511
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);
1518                 if (!sd_t->pic)
1519                         return -1;
1520                 sd_t->pic->ref_cnt = 1;
1521         } else {
1522                 sd_t->pic = sd_s->pic;
1523                 sd_t->pic->ref_cnt++;
1524         }
1525
1526         splash_status(vc_t);
1527
1528         return 0;
1529 }
1530
1531 static int splash_read_proc(char *buffer, char **start, off_t offset, int size,
1532                         int *eof, void *data)
1533 {
1534         int len;
1535         int xres, yres;
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;
1543
1544         if (info) {
1545                 xres = info->var.xres;
1546                 yres = info->var.yres;
1547         } else
1548                 xres = yres = 0;
1549
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" :
1554                       "",
1555                       status ? "on" : "off");
1556         if (offset >= len)
1557                 return 0;
1558
1559         *start = buffer - offset;
1560
1561         return (size < len - offset ? size : len - offset);
1562 }
1563
1564 void splash_set_percent(struct vc_data *vc, int pe)
1565 {
1566         struct fb_info *info;
1567         struct fbcon_ops *ops;
1568         struct splash_data *vc_splash_data;
1569         int oldpe;
1570
1571         SPLASH_DEBUG(" console: %d val: %d\n", vc->vc_num, pe);
1572
1573         if (pe < -2)
1574                 pe = 0;
1575         if (pe > 65535)
1576                 pe = 65535;
1577         pe += pe > 32767;
1578
1579         vc_splash_data = vc->vc_splash_data;
1580         if (!vc_splash_data || vc_splash_data->splash_percent == pe)
1581                 return;
1582
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) {
1587                 return;
1588         }
1589         info = registered_fb[(int) con2fb_map[vc->vc_num]];
1590         if (!info)
1591                 return;
1592
1593         ops = info->fbcon_par;
1594         if (ops->blank_state)
1595                 return;
1596         if (!vc_splash_data->imgd->splash_overpaintok
1597             || pe == 65536
1598             || pe < oldpe) {
1599                 if (splash_hasinter(vc_splash_data->imgd->splash_boxes,
1600                                     vc_splash_data->imgd->splash_boxcount)) {
1601                         splash_status(vc);
1602                 } else
1603                         splash_prepare(vc, info);
1604         } else {
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) {
1608                 case 16:
1609                         if ((info->var.red.length +
1610                              info->var.green.length +
1611                              info->var.blue.length) == 15)
1612                                 cf = SPLASH_DEPTH_15;
1613                         else
1614                                 cf = SPLASH_DEPTH_16;
1615                         break;
1616                 case 24:
1617                         cf = SPLASH_DEPTH_24_PACKED;
1618                         break;
1619                 case 32:
1620                         cf = SPLASH_DEPTH_24;
1621                         break;
1622                 }
1623                 if (cf == SPLASH_DEPTH_UNKNOWN)
1624                         return;
1625                 if (splash_data) {
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,
1635                                       1,
1636                                       cf);
1637                                 /* FIXME: get a proper width/height */
1638                                 splash_sync_region(info,
1639                                         splash_data->splash_sboxes_xoff,
1640                                         splash_data->splash_sboxes_yoff,
1641                                         info->var.xres -
1642                                         splash_data->splash_sboxes_xoff,
1643                                         8);
1644                         }
1645                 }
1646         }
1647 }
1648
1649 static const char *get_unit(const char *buffer, int *unit)
1650 {
1651
1652         *unit = -1;
1653         if (buffer[0] >= '0' && buffer[0] <= '9') {
1654                 *unit = buffer[0] - '0';
1655                 buffer++;
1656                 if (buffer[0] >= '0' && buffer[0] <= '9') {
1657                         *unit = *unit * 10 + buffer[0] - '0';
1658                         buffer++;
1659                 }
1660                 if (*buffer == ' ')
1661                         buffer++;
1662         }
1663         return buffer;
1664 }
1665
1666 static int splash_write_proc(struct file *file, const char *buffer,
1667                              unsigned long count, void *data)
1668 {
1669         int new, unit;
1670         unsigned long uval;
1671         struct vc_data *vc;
1672         struct splash_data *vc_splash_data;
1673
1674         SPLASH_DEBUG();
1675
1676         if (!buffer || !splash_default)
1677                 return count;
1678
1679         console_lock();
1680         unit = 0;
1681         if (buffer[0] == '@') {
1682                 buffer++;
1683                 buffer = get_unit(buffer, &unit);
1684                 if (unit < 0 || unit >= MAX_NR_CONSOLES || !vc_cons[unit].d) {
1685                         console_unlock();
1686                         return count;
1687                 }
1688         }
1689         SPLASH_DEBUG(" unit: %i", unit);
1690         vc = vc_cons[unit].d;
1691         vc_splash_data = vc->vc_splash_data;
1692
1693         if (!strncmp(buffer, "redraw", 6)) {
1694                 SPLASH_DEBUG(" redraw");
1695                 splash_status(vc);
1696                 console_unlock();
1697                 return count;
1698         }
1699
1700         if (!strncmp(buffer, "show", 4) || !strncmp(buffer, "hide", 4)) {
1701                 long int pe;
1702
1703                 SPLASH_DEBUG("show/hide");
1704                 if (buffer[4] == ' ' && buffer[5] == 'p')
1705                         pe = 0;
1706                 else if (buffer[4] == '\n')
1707                         pe = 65535;
1708                 else if (strict_strtol(buffer + 5, 0, &pe) == -EINVAL)
1709                         pe = 0;
1710                 if (pe < -2)
1711                         pe = 0;
1712                 if (pe > 65535)
1713                         pe = 65535;
1714                 if (*buffer == 'h')
1715                         pe = 65535 - pe;
1716                 splash_set_percent(vc, pe);
1717                 console_unlock();
1718                 return count;
1719         }
1720
1721         if (!strncmp(buffer, "copy", 4)) {
1722                 buffer += 4;
1723                 if (buffer[0] == ' ')
1724                         buffer++;
1725                 buffer = get_unit(buffer, &unit);
1726                 if (unit < 0 || unit >= MAX_NR_CONSOLES) {
1727                         console_unlock();
1728                         return count;
1729                 }
1730                 buffer = get_unit(buffer, &new);
1731                 if (new < 0 || new >= MAX_NR_CONSOLES) {
1732                         console_unlock();
1733                         return count;
1734                 }
1735                 splash_copy_current_img(unit, new);
1736                 console_unlock();
1737                 return count;
1738         }
1739
1740         if (!strncmp(buffer, "silent\n", 7)
1741             || !strncmp(buffer, "verbose\n", 8)) {
1742                 SPLASH_DEBUG(" silent/verbose");
1743
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 =
1749                                         buffer[0] == 's';
1750                                 splash_status(vc);
1751                         }
1752                 }
1753                 console_unlock();
1754                 return count;
1755         }
1756
1757         if (!strncmp(buffer, "freesilent\n", 11)) {
1758                 SPLASH_DEBUG(" freesilent");
1759
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;
1769                         }
1770                         if (vc_splash_data->splash_dosilent)
1771                                 splash_status(vc);
1772
1773                         vc->vc_splash_data->splash_dosilent = 0;
1774                 }
1775                 console_unlock();
1776                 return count;
1777         }
1778
1779         if (!strncmp(buffer, "BOOTSPL", 7)) {
1780                 int up = -1;
1781
1782                 SPLASH_DEBUG(" BOOTSPL");
1783                 unit = splash_getraw((unsigned char *)buffer,
1784                                      (unsigned char *)buffer + count,
1785                                      &up);
1786                 SPLASH_DEBUG(" unit: %i up: %i", unit, up);
1787                 if (unit >= 0) {
1788                         struct fb_info *info;
1789
1790                         vc = vc_cons[unit].d;
1791                         info = registered_fb[(int) con2fb_map[vc->vc_num]];
1792                         if (!info) {
1793                                 console_unlock();
1794                                 return count;
1795                         }
1796
1797                         if (up == -1) {
1798                                 splash_status(vc);
1799                         } else {
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;
1806
1807                                 switch (info->var.bits_per_pixel) {
1808                                 case 16:
1809                                         if ((info->var.red.length +
1810                                              info->var.green.length +
1811                                              info->var.blue.length) == 15)
1812                                                 cf = SPLASH_DEPTH_15;
1813                                         else
1814                                                 cf = SPLASH_DEPTH_16;
1815                                         break;
1816                                 case 24:
1817                                         cf = SPLASH_DEPTH_24_PACKED;
1818                                         break;
1819                                 case 32:
1820                                         cf = SPLASH_DEPTH_24;
1821                                         break;
1822                                 }
1823                                 if (cf == SPLASH_DEPTH_UNKNOWN)
1824                                         up = 0;
1825                                 if (ops->blank_state ||
1826                                     !vc_splash_data ||
1827                                     !splash_data)
1828                                         up = 0;
1829                                 if ((up & 2) != 0
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,
1839                                               1,
1840                                               cf);
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,
1849                                               1,
1850                                               cf);
1851                                 }
1852                         }
1853                 }
1854                 console_unlock();
1855                 return count;
1856         }
1857
1858         if (!vc_splash_data) {
1859                 console_unlock();
1860                 return count;
1861         }
1862
1863         if (buffer[0] == 't') {
1864                 vc_splash_data->splash_state ^= 1;
1865                 SPLASH_DEBUG(" t");
1866                 splash_status(vc);
1867                 console_unlock();
1868                 return count;
1869         }
1870         if (strict_strtoul(buffer, 0, &uval) == -EINVAL)
1871                 uval = 1;
1872         if (uval > 1) {
1873                 /* expert user */
1874                 vc_splash_data->imgd->splash_color    = uval >> 8 & 0xff;
1875                 vc_splash_data->imgd->splash_fg_color = uval >> 4 & 0x0f;
1876         }
1877         if ((uval & 1) == vc_splash_data->splash_state)
1878                 splash_recolor(vc, NULL);
1879         else {
1880                 vc_splash_data->splash_state = uval & 1;
1881                 splash_status(vc);
1882         }
1883         console_unlock();
1884         return count;
1885 }
1886
1887 static int splash_proc_register(void)
1888 {
1889         proc_splash = create_proc_entry("splash", 0, 0);
1890         if (proc_splash) {
1891                 proc_splash->read_proc = splash_read_proc;
1892                 proc_splash->write_proc = splash_write_proc;
1893                 return 0;
1894         }
1895         return 1;
1896 }
1897
1898 #endif  /* CONFIG_PROC_FS */
1899
1900 #define INIT_CONSOLE 0
1901
1902 void splash_init(void)
1903 {
1904         static bool splash_not_initialized = true;
1905         struct fb_info *info;
1906         struct vc_data *vc;
1907         int isramfs = 1;
1908         int fd;
1909         int len;
1910         int max_len = 1024*1024*2;
1911         char *mem;
1912
1913         if (splash_not_initialized == false)
1914                 return;
1915         vc = vc_cons[INIT_CONSOLE].d;
1916         info = registered_fb[(int)con2fb_map[INIT_CONSOLE]];
1917         if (!vc
1918             || !info
1919             || info->var.bits_per_pixel < 16) /* not supported */
1920                 return;
1921 #ifdef CONFIG_PROC_FS
1922         splash_proc_register();
1923 #endif
1924         splash_not_initialized = false;
1925         if (vc->vc_splash_data)
1926                 return;
1927         fd = sys_open("/bootsplash", O_RDONLY, 0);
1928         if (fd < 0) {
1929                 isramfs = 0;
1930                 fd = sys_open("/initrd.image", O_RDONLY, 0);
1931         }
1932         if (fd < 0)
1933                 return;
1934         len = (int)sys_lseek(fd, (off_t)0, 2);
1935         if (len <= 0) {
1936                 sys_close(fd);
1937                 return;
1938         }
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",
1943                        max_len>>20);
1944                 sys_lseek(fd, (off_t)(len - max_len), 0);
1945                 len = max_len;
1946         } else {
1947                 sys_lseek(fd, (off_t)0, 0);
1948         }
1949
1950         mem = vmalloc(len);
1951         if (mem) {
1952                 console_lock();
1953                 if ((int)sys_read(fd, mem, len) == len
1954                     && (splash_getraw((unsigned char *)mem,
1955                                       (unsigned char *)mem + len, (int *)0)
1956                         == INIT_CONSOLE)
1957                     && vc->vc_splash_data)
1958                         vc->vc_splash_data->splash_state = splash_default & 1;
1959                 console_unlock();
1960                 vfree(mem);
1961         }
1962         sys_close(fd);
1963         if (isramfs)
1964                 sys_unlink("/bootsplash");
1965         return;
1966 }
1967
1968 #define SPLASH_ALIGN 15
1969
1970 static u32 *do_coefficients(u32 from, u32 to, u32 *shift)
1971 {
1972         u32 *coefficients;
1973         u32 left = to;
1974         int n = 1;
1975         u32 upper = 31;
1976         int col_cnt = 0;
1977         int row_cnt = 0;
1978         int m;
1979         u32 rnd = from >> 1;
1980
1981         if (from > to) {
1982                 left = to;
1983                 rnd = from >> 1;
1984
1985                 while (upper > 0) {
1986                         if ((1 << upper) & from)
1987                                 break;
1988                         upper--;
1989                 }
1990                 upper++;
1991
1992                 *shift = 32 - 8 - 1 - upper;
1993
1994                 coefficients = vmalloc(sizeof(u32) * (from / to + 2) * from + 1);
1995                 if (!coefficients)
1996                         return NULL;
1997
1998                 n = 1;
1999                 while (1) {
2000                         u32 sum = left;
2001                         col_cnt = 0;
2002                         m = n++;
2003                         while (sum < from) {
2004                                 coefficients[n++] =
2005                                         ((left << *shift) + rnd) / from;
2006                                 col_cnt++;
2007                                 left = to;
2008                                 sum += left;
2009                         }
2010                         left = sum - from;
2011                         coefficients[n++] =
2012                                 (((to - left) << *shift) + rnd) / from;
2013                         col_cnt++;
2014                         coefficients[m] = col_cnt;
2015                         row_cnt++;
2016                         if (!left) {
2017                                 coefficients[0] = row_cnt;
2018                                 return coefficients;
2019                         }
2020                 }
2021         } else {
2022                 left = 0;
2023                 rnd = to >> 1;
2024
2025                 while (upper > 0) {
2026                         if ((1 << upper) & to)
2027                                 break;
2028                         upper--;
2029                 }
2030                 upper++;
2031
2032                 *shift = 32 - 8 - 1 - upper;
2033
2034                 coefficients = vmalloc(sizeof(u32) * 3 * from + 1);
2035                 if (!coefficients)
2036                         return NULL;
2037
2038                 while (1) {
2039                         u32 diff;
2040                         u32 sum = left;
2041                         col_cnt = 0;
2042                         row_cnt++;
2043                         while (sum < to) {
2044                                 col_cnt++;
2045                                 sum += from;
2046                         }
2047                         left = sum - to;
2048                         diff = from - left;
2049                         if (!left) {
2050                                 coefficients[n] = col_cnt;
2051                                 coefficients[0] = row_cnt;
2052                                 return coefficients;
2053                         }
2054                         coefficients[n++] = col_cnt - 1;
2055                         coefficients[n++] = ((diff << *shift) + rnd) / from;
2056                         coefficients[n++] = ((left << *shift) + rnd) / from;
2057                 }
2058         }
2059 }
2060
2061
2062 struct pixel {
2063         u32 red;
2064         u32 green;
2065         u32 blue;
2066 };
2067
2068 #define put_pixel(pix, buf, cf)                                         \
2069         switch (cf) {                                                   \
2070         case SPLASH_DEPTH_15:                                           \
2071                 *(u16 *)(buf) = (u16)((pix).red << 10 |                 \
2072                                       (pix).green << 5 | (pix).blue);   \
2073         (buf) += 2;                                                     \
2074         break;                                                          \
2075         case SPLASH_DEPTH_16:                                           \
2076                 *(u16 *)(buf) = (u16)((pix).red << 11 |                 \
2077                                       (pix).green << 5 | (pix).blue);   \
2078                 (buf) += 2;                                             \
2079                 break;                                                  \
2080         case SPLASH_DEPTH_24_PACKED:                                    \
2081                 *(u16 *)(buf) = (u16)((pix).red << 8 | (pix).green);    \
2082                 buf += 2;                                               \
2083                 *((buf)++) = (pix).blue;                                \
2084                 break;                                                  \
2085         case SPLASH_DEPTH_24:                                           \
2086                 *(u32 *)(buf) = (u32)((pix).red << 16 |                 \
2087                                       (pix).green << 8 | (pix).blue);   \
2088                 (buf) += 4;                                             \
2089                 break;                                                  \
2090         case SPLASH_DEPTH_UNKNOWN:                                      \
2091                 break;                                                  \
2092         }
2093
2094 #define get_pixel(pix, buf, depth)                                     \
2095         switch (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;                   \
2100                 (buf) += 2;                                            \
2101                 break;                                                 \
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;                   \
2106                 (buf) += 2;                                            \
2107                 break;                                                 \
2108         case SPLASH_DEPTH_24_PACKED:                                   \
2109                 (pix).blue = *(((buf))++);                             \
2110                 (pix).green = *(((buf))++);                            \
2111                 (pix).red = *(((buf))++);                              \
2112                 break;                                                 \
2113         case SPLASH_DEPTH_24:                                          \
2114                 (pix).blue = *(((buf))++);                             \
2115                 (pix).green = *(((buf))++);                            \
2116                 (pix).red = *(((buf))++);                              \
2117                 (buf)++;                                               \
2118                 break;                                                 \
2119          case SPLASH_DEPTH_UNKNOWN:                                    \
2120                 break;                                                 \
2121         }
2122
2123 static inline void
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)
2127 {
2128         u32 curr_x_coeff = 1;
2129         struct pixel curr_pixel, tmp_pixel;
2130         u32 x_array_size = x_coeff[0];
2131         int x_column_num;
2132         int i;
2133         int l, m;
2134         int k = 0;
2135         u32 rnd = (1 << (x_shift - 1));
2136
2137         for (i = 0; i < src_w; ) {
2138                 curr_x_coeff = 1;
2139                 get_pixel(tmp_pixel, *src_p, cf);
2140                 i++;
2141                 for (l = 0; l < x_array_size; l++) {
2142                         x_column_num = x_coeff[curr_x_coeff++];
2143                         curr_pixel.red = 0;
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];
2153                                 curr_x_coeff++;
2154                                 get_pixel(tmp_pixel, *src_p, cf);
2155                                 i++;
2156                         }
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];
2162                         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;
2169                         k++;
2170                 }
2171         }
2172 }
2173
2174 static inline void
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)
2178 {
2179         u32 curr_x_coeff = 1;
2180         struct pixel curr_pixel, tmp_pixel;
2181         u32 x_array_size = x_coeff[0];
2182         int x_column_num;
2183         int i;
2184         int l, m;
2185         int k = 0;
2186         u32 rnd = (1 << (x_shift - 1));
2187
2188         for (i = 0; i < src_w;) {
2189                 curr_x_coeff = 1;
2190                 get_pixel(tmp_pixel, *src_p, cf);
2191                 i++;
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;
2198                                 k++;
2199                         }
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];
2204                         curr_x_coeff++;
2205                         get_pixel(tmp_pixel, *src_p, cf);
2206                         i++;
2207                         row_buffer[k].red += ((curr_pixel.red
2208                                                + (tmp_pixel.red
2209                                                   * x_coeff[curr_x_coeff])
2210                                                + rnd) >> x_shift) * y_coeff;
2211                         row_buffer[k].green += ((curr_pixel.green
2212                                                  + (tmp_pixel.green
2213                                                     * x_coeff[curr_x_coeff])
2214                                                  + rnd) >> x_shift) * y_coeff;
2215                         row_buffer[k].blue += ((curr_pixel.blue
2216                                                 + (tmp_pixel.blue
2217                                                    * x_coeff[curr_x_coeff])
2218                                                 + rnd) >> x_shift) * y_coeff;
2219                         k++;
2220                         curr_x_coeff++;
2221                 }
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;
2226                         k++;
2227                 }
2228         }
2229 }
2230
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)
2234 {
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);
2238         int j;
2239         struct pixel *row_buffer;
2240         u32 x_shift, y_shift;
2241         u32 *x_coeff;
2242         u32 *y_coeff;
2243         u32 curr_y_coeff = 1;
2244         unsigned char *src_p;
2245         unsigned char *src_p_line = src;
2246         char *dst_p_line;
2247         int r, s;
2248         int y_array_rows;
2249         int y_column_num;
2250         int k;
2251         u32 rnd;
2252         int xup;
2253
2254         row_buffer = vmalloc(sizeof(struct pixel)
2255                                              * (dst_w + 1));
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) {
2259                 vfree(row_buffer);
2260                 vfree(x_coeff);
2261                 vfree(y_coeff);
2262                 return -ENOMEM;
2263         }
2264         y_array_rows = y_coeff[0];
2265         rnd = (1 << (y_shift - 1));
2266         xup = (src_w <= dst_w) ? 1 : 0;
2267
2268         dst_p_line = dst;
2269
2270         for (j = 0; j < src_h;) {
2271                 curr_y_coeff = 1;
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;
2278                         }
2279                         src_p = src_p_line;
2280                         if (xup)
2281                                 scale_x_up(cf,  src_w, &src_p, x_coeff,
2282                                            x_shift, y_coeff[curr_y_coeff],
2283                                            row_buffer);
2284                         else
2285                                 scale_x_down(cf,  src_w, &src_p, x_coeff,
2286                                              x_shift, y_coeff[curr_y_coeff],
2287                                              row_buffer);
2288                         curr_y_coeff++;
2289                         for (s = 1; s < y_column_num; s++) {
2290                                 src_p = src_p_line = src_p_line + src_x_bytes;
2291                                 j++;
2292                                 if (xup)
2293                                         scale_x_up(cf,  src_w, &src_p,
2294                                                    x_coeff, x_shift,
2295                                                    y_coeff[curr_y_coeff],
2296                                                    row_buffer);
2297                                 else
2298                                         scale_x_down(cf,  src_w, &src_p,
2299                                                      x_coeff, x_shift,
2300                                                      y_coeff[curr_y_coeff],
2301                                                      row_buffer);
2302                                 curr_y_coeff++;
2303                         }
2304                         for (k = 0; k < dst_w; k++) {
2305                                 row_buffer[k].red = (row_buffer[k].red + rnd)
2306                                         >> y_shift;
2307                                 row_buffer[k].green = (row_buffer[k].green
2308                                                        + rnd)
2309                                         >> y_shift;
2310                                 row_buffer[k].blue = (row_buffer[k].blue + rnd)
2311                                         >> y_shift;
2312                                 put_pixel(row_buffer[k], dst, cf);
2313                         }
2314                         dst = dst_p_line = dst_p_line + dst_x_bytes;
2315                 }
2316                 src_p_line = src_p_line + src_x_bytes;
2317                 j++;
2318         }
2319         vfree(row_buffer);
2320         vfree(x_coeff);
2321         vfree(y_coeff);
2322         return 0;
2323 }
2324
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)
2328 {
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);
2332         int j;
2333         u32 x_shift, y_shift;
2334         u32 *x_coeff;
2335         u32 *y_coeff;
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;
2341         char *dst_p_line;
2342         int r, s;
2343         int y_array_rows;
2344         int y_column_num;
2345         int k;
2346         u32 rnd;
2347         int bi;
2348         int xup;
2349         int writes;
2350
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)
2354                                                   * (dst_w + 1));
2355         if (!row_buf_list[0] || !x_coeff || !y_coeff) {
2356                 vfree(row_buf_list[0]);
2357                 vfree(x_coeff);
2358                 vfree(y_coeff);
2359                 return -ENOMEM;
2360         }
2361         row_buf_list[1] = row_buf_list[0] + (dst_w + 1);
2362
2363         y_array_rows = y_coeff[0];
2364         rnd = (1 << (y_shift - 1));
2365         bi = 1;
2366         xup = (src_w <= dst_w) ? 1 : 0;
2367         writes = 0;
2368
2369         dst_p_line = dst;
2370         src_p = src_p_line;
2371
2372         row_buffer = row_buf_list[0];
2373
2374         for (j = 0; j < src_h;) {
2375                 memset(row_buf_list[0], 0, (2 * sizeof(struct pixel)
2376                                             * (dst_w + 1)));
2377                 curr_y_coeff = 1;
2378                 if (xup)
2379                         scale_x_up(cf,  src_w, &src_p, x_coeff,
2380                                    x_shift, 1, row_buffer);
2381                 else
2382                         scale_x_down(cf,  src_w, &src_p, x_coeff, x_shift, 1,
2383                                      row_buffer);
2384                 src_p = src_p_line = src_p_line + src_x_bytes;
2385                 j++;
2386                 for (r = 0; r < y_array_rows - 1; r++) {
2387                         struct pixel *old_row_buffer = row_buffer;
2388                         u32 prev_y_coeff_val;
2389
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;
2395                                 writes++;
2396                         }
2397                         curr_y_coeff++;
2398                         row_buffer = row_buf_list[(bi++) % 2];
2399                         prev_y_coeff_val = y_coeff[curr_y_coeff++];
2400                         if (xup)
2401                                 scale_x_up(cf,  src_w, &src_p, x_coeff,
2402                                            x_shift, 1, row_buffer);
2403                         else
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;
2407                         j++;
2408                         for (k = 0; k < dst_w; k++) {
2409                                 struct pixel pix;
2410                                 pix.red = ((old_row_buffer[k].red
2411                                             * prev_y_coeff_val)
2412                                            + (row_buffer[k].red
2413                                               * y_coeff[curr_y_coeff])
2414                                            + rnd) >> y_shift;
2415                                 pix.green = ((old_row_buffer[k].green
2416                                               * prev_y_coeff_val)
2417                                              + (row_buffer[k].green
2418                                                 * y_coeff[curr_y_coeff])
2419                                              + rnd) >> y_shift;
2420                                 pix.blue = ((old_row_buffer[k].blue
2421                                              * prev_y_coeff_val)
2422                                             + (row_buffer[k].blue
2423                                                * y_coeff[curr_y_coeff])
2424                                             + rnd) >> y_shift;
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);
2429                         }
2430                         dst = dst_p_line = dst_p_line + dst_x_bytes;
2431                         writes++;
2432                         curr_y_coeff++;
2433                 }
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);
2437
2438                         dst = dst_p_line = dst_p_line + dst_x_bytes;
2439                         writes++;
2440                 }
2441         }
2442         vfree(row_buf_list[0]);
2443         vfree(x_coeff);
2444         vfree(y_coeff);
2445
2446         return 0;
2447 }
2448
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)
2452 {
2453         int my_width, my_height;
2454         int err;
2455         int octpp = splash_octpp(cf);
2456
2457         jpeg_get_size(buf, &my_width, &my_height);
2458
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);
2463                 if (!mem)
2464                         return 17;
2465                 err = jpeg_decode(buf, mem, ((my_width + 15) & ~15),
2466                                   ((my_height + 15) & ~15), cf, decdata);
2467                 if (err) {
2468                         vfree(mem);
2469                         return err;
2470                 }
2471                 printk(KERN_INFO
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));
2478                 else
2479                         err = scale_y_down(mem, pic, cf, my_width, my_height,
2480                                            ((width + 15) & ~15),
2481                                            ((height + 15) & ~15));
2482                 vfree(mem);
2483                 if (err < 0)
2484                         return 17;
2485         } else {
2486                 err = jpeg_decode(buf, pic, ((width + 15) & ~15),
2487                                   ((height + 15) & ~15), cf, decdata);
2488                 if (err)
2489                         return err;
2490         }
2491         return 0;
2492 }