]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.31/patches.suse/bootsplash
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / bootsplash
1 From: mls@suse.de
2 Subject: Bootsplash for current kernel
3 Patch-mainline: no
4 References: none
5
6 Better support for other VTs. Don't change percent or silent status
7 when installing a new jpeg. Provide splash_set_percent function.
8
9 Signed-off-by: mls@suse.de
10
11 ---
12 drivers/char/keyboard.c | 9
13 drivers/char/n_tty.c | 9
14 drivers/char/vt.c | 25
15 drivers/video/Kconfig | 4
16 drivers/video/Makefile | 1
17 drivers/video/bootsplash/Kconfig | 17
18 drivers/video/bootsplash/Makefile | 5
19 drivers/video/bootsplash/bootsplash.c | 1017 ++++++++++++++++++++++++++++++++++
20 drivers/video/bootsplash/bootsplash.h | 44 +
21 drivers/video/bootsplash/decode-jpg.c | 957 +++++++++++++++++++++++++++++++
22 drivers/video/bootsplash/decode-jpg.h | 35 +
23 drivers/video/bootsplash/render.c | 328 ++++++++++
24 drivers/video/console/bitblit.c | 39 +
25 drivers/video/console/fbcon.c | 53 +
26 drivers/video/console/fbcon.h | 28
27 drivers/video/vesafb.c | 8
28 include/linux/console_struct.h | 3
29 include/linux/fb.h | 8
30 kernel/panic.c | 12
31 19 files changed, 2601 insertions(+), 1 deletion(-)
32
33 --- a/drivers/char/keyboard.c
34 +++ b/drivers/char/keyboard.c
35 @@ -1180,6 +1180,15 @@ static void kbd_keycode(unsigned int key
36 if (keycode < BTN_MISC && printk_ratelimit())
37 printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode);
38
39 +#ifdef CONFIG_BOOTSPLASH
40 + /* This code has to be redone for some non-x86 platforms */
41 + if (down == 1 && (keycode == 0x3c || keycode == 0x01)) { /* F2 and ESC on PC keyboard */
42 + extern int splash_verbose(void);
43 + if (splash_verbose())
44 + return;
45 + }
46 +#endif
47 +
48 #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
49 if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
50 if (!sysrq_down) {
51 --- a/drivers/char/n_tty.c
52 +++ b/drivers/char/n_tty.c
53 @@ -1325,6 +1325,15 @@ do_it_again:
54 tty->minimum_to_wake = (minimum - (b - buf));
55
56 if (!input_available_p(tty, 0)) {
57 +#ifdef CONFIG_BOOTSPLASH
58 + if (file->f_dentry->d_inode->i_rdev == MKDEV(TTY_MAJOR,0) ||
59 + file->f_dentry->d_inode->i_rdev == MKDEV(TTY_MAJOR,1) ||
60 + file->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,0) ||
61 + file->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,1)) {
62 + extern int splash_verbose(void);
63 + (void)splash_verbose();
64 + }
65 +#endif
66 if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
67 retval = -EIO;
68 break;
69 --- a/drivers/char/vt.c
70 +++ b/drivers/char/vt.c
71 @@ -4092,6 +4092,31 @@ void vcs_scr_writew(struct vc_data *vc,
72 }
73 }
74
75 +#ifdef CONFIG_BOOTSPLASH
76 +void con_remap_def_color(struct vc_data *vc, int new_color)
77 +{
78 + unsigned short *sbuf = vc->vc_screenbuf;
79 + unsigned c, len = vc->vc_screenbuf_size >> 1;
80 + int old_color;
81 +
82 + if (sbuf) {
83 + old_color = vc->vc_def_color << 8;
84 + new_color <<= 8;
85 + while(len--) {
86 + c = *sbuf;
87 + if (((c ^ old_color) & 0xf000) == 0)
88 + *sbuf ^= (old_color ^ new_color) & 0xf000;
89 + if (((c ^ old_color) & 0x0f00) == 0)
90 + *sbuf ^= (old_color ^ new_color) & 0x0f00;
91 + sbuf++;
92 + }
93 + new_color >>= 8;
94 + }
95 + vc->vc_def_color = vc->vc_color = new_color;
96 + update_attr(vc);
97 +}
98 +#endif
99 +
100 /*
101 * Visible symbols for modules
102 */
103 --- /dev/null
104 +++ b/drivers/video/bootsplash/bootsplash.c
105 @@ -0,0 +1,1017 @@
106 +/*
107 + * linux/drivers/video/bootsplash/bootsplash.c -
108 + * splash screen handling functions.
109 + *
110 + * (w) 2001-2004 by Volker Poplawski, <volker@poplawski.de>,
111 + * Stefan Reinauer, <stepan@suse.de>,
112 + * Steffen Winterfeldt, <snwint@suse.de>,
113 + * Michael Schroeder <mls@suse.de>
114 + *
115 + * Ideas & SuSE screen work by Ken Wimer, <wimer@suse.de>
116 + *
117 + * For more information on this code check http://www.bootsplash.org/
118 + */
119 +
120 +#include <linux/module.h>
121 +#include <linux/types.h>
122 +#include <linux/fb.h>
123 +#include <linux/vt_kern.h>
124 +#include <linux/vmalloc.h>
125 +#include <linux/unistd.h>
126 +#include <linux/syscalls.h>
127 +
128 +#include <asm/irq.h>
129 +#include <asm/system.h>
130 +
131 +#include "../console/fbcon.h"
132 +#include "bootsplash.h"
133 +#include "decode-jpg.h"
134 +
135 +extern struct fb_ops vesafb_ops;
136 +extern signed char con2fb_map[MAX_NR_CONSOLES];
137 +
138 +#define SPLASH_VERSION "3.1.6-2004/03/31"
139 +
140 +/* These errors have to match fbcon-jpegdec.h */
141 +static unsigned char *jpg_errors[] = {
142 + "no SOI found",
143 + "not 8 bit",
144 + "height mismatch",
145 + "width mismatch",
146 + "bad width or height",
147 + "too many COMPPs",
148 + "illegal HV",
149 + "quant table selector",
150 + "picture is not YCBCR 221111",
151 + "unknow CID in scan",
152 + "dct not sequential",
153 + "wrong marker",
154 + "no EOI",
155 + "bad tables",
156 + "depth mismatch"
157 +};
158 +
159 +static struct jpeg_decdata *decdata = 0; /* private decoder data */
160 +
161 +static int splash_registered = 0;
162 +static int splash_usesilent = 0; /* shall we display the silentjpeg? */
163 +int splash_default = 0xf01;
164 +
165 +static int splash_check_jpeg(unsigned char *jpeg, int width, int height, int depth);
166 +
167 +static int __init splash_setup(char *options)
168 +{
169 + if(!strncmp("silent", options, 6)) {
170 + printk(KERN_INFO "bootsplash: silent mode.\n");
171 + splash_usesilent = 1;
172 + /* skip "silent," */
173 + if (strlen(options) == 6)
174 + return 0;
175 + options += 7;
176 + }
177 + if(!strncmp("verbose", options, 7)) {
178 + printk(KERN_INFO "bootsplash: verbose mode.\n");
179 + splash_usesilent = 0;
180 + return 0;
181 + }
182 + splash_default = simple_strtoul(options, NULL, 0);
183 + return 0;
184 +}
185 +
186 +__setup("splash=", splash_setup);
187 +
188 +
189 +static int splash_hasinter(unsigned char *buf, int num)
190 +{
191 + unsigned char *bufend = buf + num * 12;
192 + while(buf < bufend) {
193 + if (buf[1] > 127) /* inter? */
194 + return 1;
195 + buf += buf[3] > 127 ? 24 : 12; /* blend? */
196 + }
197 + return 0;
198 +}
199 +
200 +static int boxextract(unsigned char *buf, unsigned short *dp, unsigned char *cols, int *blendp)
201 +{
202 + dp[0] = buf[0] | buf[1] << 8;
203 + dp[1] = buf[2] | buf[3] << 8;
204 + dp[2] = buf[4] | buf[5] << 8;
205 + dp[3] = buf[6] | buf[7] << 8;
206 + *(unsigned int *)(cols + 0) =
207 + *(unsigned int *)(cols + 4) =
208 + *(unsigned int *)(cols + 8) =
209 + *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 8);
210 + if (dp[1] > 32767) {
211 + dp[1] = ~dp[1];
212 + *(unsigned int *)(cols + 4) = *(unsigned int *)(buf + 12);
213 + *(unsigned int *)(cols + 8) = *(unsigned int *)(buf + 16);
214 + *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 20);
215 + *blendp = 1;
216 + return 24;
217 + }
218 + return 12;
219 +}
220 +
221 +static void boxit(unsigned char *pic, int bytes, unsigned char *buf, int num, int percent, int overpaint)
222 +{
223 + int x, y, i, p, doblend, r, g, b, a, add;
224 + unsigned short data1[4];
225 + unsigned char cols1[16];
226 + unsigned short data2[4];
227 + unsigned char cols2[16];
228 + unsigned char *bufend;
229 + unsigned short *picp;
230 + unsigned int stipple[32], sti, stin, stinn, stixs, stixe, stiys, stiye;
231 + int xs, xe, ys, ye, xo, yo;
232 +
233 + if (num == 0)
234 + return;
235 + bufend = buf + num * 12;
236 + stipple[0] = 0xffffffff;
237 + stin = 1;
238 + stinn = 0;
239 + stixs = stixe = 0;
240 + stiys = stiye = 0;
241 + while(buf < bufend) {
242 + doblend = 0;
243 + buf += boxextract(buf, data1, cols1, &doblend);
244 + if (data1[0] == 32767 && data1[1] == 32767) {
245 + /* box stipple */
246 + if (stinn == 32)
247 + continue;
248 + if (stinn == 0) {
249 + stixs = data1[2];
250 + stixe = data1[3];
251 + stiys = stiye = 0;
252 + } else if (stinn == 4) {
253 + stiys = data1[2];
254 + stiye = data1[3];
255 + }
256 + stipple[stinn++] = (cols1[ 0] << 24) | (cols1[ 1] << 16) | (cols1[ 2] << 8) | cols1[ 3] ;
257 + stipple[stinn++] = (cols1[ 4] << 24) | (cols1[ 5] << 16) | (cols1[ 6] << 8) | cols1[ 7] ;
258 + stipple[stinn++] = (cols1[ 8] << 24) | (cols1[ 9] << 16) | (cols1[10] << 8) | cols1[11] ;
259 + stipple[stinn++] = (cols1[12] << 24) | (cols1[13] << 16) | (cols1[14] << 8) | cols1[15] ;
260 + stin = stinn;
261 + continue;
262 + }
263 + stinn = 0;
264 + if (data1[0] > 32767)
265 + buf += boxextract(buf, data2, cols2, &doblend);
266 + if (data1[0] == 32767 && data1[1] == 32766) {
267 + /* box copy */
268 + i = 12 * (short)data1[3];
269 + doblend = 0;
270 + i += boxextract(buf + i, data1, cols1, &doblend);
271 + if (data1[0] > 32767)
272 + boxextract(buf + i, data2, cols2, &doblend);
273 + }
274 + if (data1[0] == 32767)
275 + continue;
276 + if (data1[2] > 32767) {
277 + if (overpaint)
278 + continue;
279 + data1[2] = ~data1[2];
280 + }
281 + if (data1[3] > 32767) {
282 + if (percent == 65536)
283 + continue;
284 + data1[3] = ~data1[3];
285 + }
286 + if (data1[0] > 32767) {
287 + data1[0] = ~data1[0];
288 + for (i = 0; i < 4; i++)
289 + data1[i] = (data1[i] * (65536 - percent) + data2[i] * percent) >> 16;
290 + for (i = 0; i < 16; i++)
291 + cols1[i] = (cols1[i] * (65536 - percent) + cols2[i] * percent) >> 16;
292 + }
293 + *(unsigned int *)cols2 = *(unsigned int *)cols1;
294 + a = cols2[3];
295 + if (a == 0 && !doblend)
296 + continue;
297 +
298 + if (stixs >= 32768) {
299 + xo = xs = (stixs ^ 65535) + data1[0];
300 + xe = stixe ? stixe + data1[0] : data1[2];
301 + } else if (stixe >= 32768) {
302 + xs = stixs ? data1[2] - stixs : data1[0];
303 + xe = data1[2] - (stixe ^ 65535);
304 + xo = xe + 1;
305 + } else {
306 + xo = xs = stixs;
307 + xe = stixe ? stixe : data1[2];
308 + }
309 + if (stiys >= 32768) {
310 + yo = ys = (stiys ^ 65535) + data1[1];
311 + ye = stiye ? stiye + data1[1] : data1[3];
312 + } else if (stiye >= 32768) {
313 + ys = stiys ? data1[3] - stiys : data1[1];
314 + ye = data1[3] - (stiye ^ 65535);
315 + yo = ye + 1;
316 + } else {
317 + yo = ys = stiys;
318 + ye = stiye ? stiye : data1[3];
319 + }
320 + xo = 32 - (xo & 31);
321 + yo = stin - (yo % stin);
322 + if (xs < data1[0])
323 + xs = data1[0];
324 + if (xe > data1[2])
325 + xe = data1[2];
326 + if (ys < data1[1])
327 + ys = data1[1];
328 + if (ye > data1[3])
329 + ye = data1[3];
330 +
331 + for (y = ys; y <= ye; y++) {
332 + sti = stipple[(y + yo) % stin];
333 + x = (xs + xo) & 31;
334 + if (x)
335 + sti = (sti << x) | (sti >> (32 - x));
336 + if (doblend) {
337 + if ((p = data1[3] - data1[1]) != 0)
338 + p = ((y - data1[1]) << 16) / p;
339 + for (i = 0; i < 8; i++)
340 + cols2[i + 8] = (cols1[i] * (65536 - p) + cols1[i + 8] * p) >> 16;
341 + }
342 + add = (xs & 1);
343 + add ^= (add ^ y) & 1 ? 1 : 3; /* 2x2 ordered dithering */
344 + picp = (unsigned short *)(pic + xs * 2 + y * bytes);
345 + for (x = xs; x <= xe; x++) {
346 + if (!(sti & 0x80000000)) {
347 + sti <<= 1;
348 + picp++;
349 + add ^= 3;
350 + continue;
351 + }
352 + sti = (sti << 1) | 1;
353 + if (doblend) {
354 + if ((p = data1[2] - data1[0]) != 0)
355 + p = ((x - data1[0]) << 16) / p;
356 + for (i = 0; i < 4; i++)
357 + cols2[i] = (cols2[i + 8] * (65536 - p) + cols2[i + 12] * p) >> 16;
358 + a = cols2[3];
359 + }
360 + r = cols2[0];
361 + g = cols2[1];
362 + b = cols2[2];
363 + if (a != 255) {
364 + i = *picp;
365 + r = ((i >> 8 & 0xf8) * (255 - a) + r * a) / 255;
366 + g = ((i >> 3 & 0xfc) * (255 - a) + g * a) / 255;
367 + b = ((i << 3 & 0xf8) * (255 - a) + b * a) / 255;
368 + }
369 + #define CLAMP(x) ((x) >= 256 ? 255 : (x))
370 + i = ((CLAMP(r + add*2+1) & 0xf8) << 8) |
371 + ((CLAMP(g + add ) & 0xfc) << 3) |
372 + ((CLAMP(b + add*2+1) ) >> 3);
373 + *picp++ = i;
374 + add ^= 3;
375 + }
376 + }
377 + }
378 +}
379 +
380 +static int splash_check_jpeg(unsigned char *jpeg, int width, int height, int depth)
381 +{
382 + int size, err;
383 + unsigned char *mem;
384 +
385 + size = ((width + 15) & ~15) * ((height + 15) & ~15) * (depth >> 3);
386 + mem = vmalloc(size);
387 + if (!mem) {
388 + printk(KERN_INFO "bootsplash: no memory for decoded picture.\n");
389 + return -1;
390 + }
391 + if (!decdata)
392 + decdata = vmalloc(sizeof(*decdata));
393 + if ((err = jpeg_decode(jpeg, mem, ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata)))
394 + printk(KERN_INFO "bootsplash: error while decompressing picture: %s (%d)\n",jpg_errors[err - 1], err);
395 + vfree(mem);
396 + return err ? -1 : 0;
397 +}
398 +
399 +static void splash_free(struct vc_data *vc, struct fb_info *info)
400 +{
401 + if (!vc->vc_splash_data)
402 + return;
403 + if (info->silent_screen_base)
404 + info->screen_base = info->silent_screen_base;
405 + info->silent_screen_base = 0;
406 + if (vc->vc_splash_data->splash_silentjpeg)
407 + vfree(vc->vc_splash_data->splash_sboxes);
408 + vfree(vc->vc_splash_data);
409 + vc->vc_splash_data = 0;
410 + info->splash_data = 0;
411 +}
412 +
413 +static int splash_mkpenguin(struct splash_data *data, int pxo, int pyo, int pwi, int phe, int pr, int pg, int pb)
414 +{
415 + unsigned char *buf;
416 + int i;
417 +
418 + if (pwi ==0 || phe == 0)
419 + return 0;
420 + buf = (unsigned char *)data + sizeof(*data);
421 + pwi += pxo - 1;
422 + phe += pyo - 1;
423 + *buf++ = pxo;
424 + *buf++ = pxo >> 8;
425 + *buf++ = pyo;
426 + *buf++ = pyo >> 8;
427 + *buf++ = pwi;
428 + *buf++ = pwi >> 8;
429 + *buf++ = phe;
430 + *buf++ = phe >> 8;
431 + *buf++ = pr;
432 + *buf++ = pg;
433 + *buf++ = pb;
434 + *buf++ = 0;
435 + for (i = 0; i < 12; i++, buf++)
436 + *buf = buf[-12];
437 + buf[-24] ^= 0xff;
438 + buf[-23] ^= 0xff;
439 + buf[-1] = 0xff;
440 + return 2;
441 +}
442 +
443 +static const int splash_offsets[3][16] = {
444 + /* len, unit, size, state, fgcol, col, xo, yo, wi, he
445 + boxcnt, ssize, sboxcnt, percent, overok, palcnt */
446 + /* V1 */
447 + { 20, -1, 16, -1, -1, -1, 8, 10, 12, 14,
448 + -1, -1, -1, -1, -1, -1 },
449 + /* V2 */
450 + { 35, 8, 12, 9, 10, 11, 16, 18, 20, 22,
451 + -1, -1, -1, -1, -1, -1 },
452 + /* V3 */
453 + { 38, 8, 12, 9, 10, 11, 16, 18, 20, 22,
454 + 24, 28, 32, 34, 36, 37 },
455 +};
456 +
457 +#define SPLASH_OFF_LEN offsets[0]
458 +#define SPLASH_OFF_UNIT offsets[1]
459 +#define SPLASH_OFF_SIZE offsets[2]
460 +#define SPLASH_OFF_STATE offsets[3]
461 +#define SPLASH_OFF_FGCOL offsets[4]
462 +#define SPLASH_OFF_COL offsets[5]
463 +#define SPLASH_OFF_XO offsets[6]
464 +#define SPLASH_OFF_YO offsets[7]
465 +#define SPLASH_OFF_WI offsets[8]
466 +#define SPLASH_OFF_HE offsets[9]
467 +#define SPLASH_OFF_BOXCNT offsets[10]
468 +#define SPLASH_OFF_SSIZE offsets[11]
469 +#define SPLASH_OFF_SBOXCNT offsets[12]
470 +#define SPLASH_OFF_PERCENT offsets[13]
471 +#define SPLASH_OFF_OVEROK offsets[14]
472 +#define SPLASH_OFF_PALCNT offsets[15]
473 +
474 +static inline int splash_getb(unsigned char *pos, int off)
475 +{
476 + return off == -1 ? 0 : pos[off];
477 +}
478 +
479 +static inline int splash_gets(unsigned char *pos, int off)
480 +{
481 + return off == -1 ? 0 : pos[off] | pos[off + 1] << 8;
482 +}
483 +
484 +static inline int splash_geti(unsigned char *pos, int off)
485 +{
486 + return off == -1 ? 0 :
487 + pos[off] | pos[off + 1] << 8 | pos[off + 2] << 16 | pos[off + 3] << 24;
488 +}
489 +
490 +static int splash_getraw(unsigned char *start, unsigned char *end, int *update)
491 +{
492 + unsigned char *ndata;
493 + int version;
494 + int splash_size;
495 + int unit;
496 + int width, height;
497 + int silentsize;
498 + int boxcnt;
499 + int sboxcnt;
500 + int palcnt;
501 + int i, len;
502 + const int *offsets;
503 + struct vc_data *vc;
504 + struct fb_info *info;
505 + struct splash_data *sd;
506 + int oldpercent, oldsilent;
507 +
508 + if (update)
509 + *update = -1;
510 +
511 + if (!update || start[7] < '2' || start[7] > '3' || splash_geti(start, 12) != (int)0xffffffff)
512 + printk(KERN_INFO "bootsplash %s: looking for picture...\n", SPLASH_VERSION);
513 +
514 + for (ndata = start; ndata < end; ndata++) {
515 + if (ndata[0] != 'B' || ndata[1] != 'O' || ndata[2] != 'O' || ndata[3] != 'T')
516 + continue;
517 + if (ndata[4] != 'S' || ndata[5] != 'P' || ndata[6] != 'L' || ndata[7] < '1' || ndata[7] > '3')
518 + continue;
519 + version = ndata[7] - '0';
520 + offsets = splash_offsets[version - 1];
521 + len = SPLASH_OFF_LEN;
522 + unit = splash_getb(ndata, SPLASH_OFF_UNIT);
523 + if (unit >= MAX_NR_CONSOLES)
524 + continue;
525 + if (unit) {
526 + vc_allocate(unit);
527 + }
528 + vc = vc_cons[unit].d;
529 + info = registered_fb[(int)con2fb_map[unit]];
530 + width = info->var.xres;
531 + height = info->var.yres;
532 + splash_size = splash_geti(ndata, SPLASH_OFF_SIZE);
533 + if (splash_size == (int)0xffffffff && version > 1) {
534 + if ((sd = vc->vc_splash_data) != 0) {
535 + int up = 0;
536 + i = splash_getb(ndata, SPLASH_OFF_STATE);
537 + if (i != 255) {
538 + sd->splash_state = i;
539 + up = -1;
540 + }
541 + i = splash_getb(ndata, SPLASH_OFF_FGCOL);
542 + if (i != 255) {
543 + sd->splash_fg_color = i;
544 + up = -1;
545 + }
546 + i = splash_getb(ndata, SPLASH_OFF_COL);
547 + if (i != 255) {
548 + sd->splash_color = i;
549 + up = -1;
550 + }
551 + boxcnt = sboxcnt = 0;
552 + if (ndata + len <= end) {
553 + boxcnt = splash_gets(ndata, SPLASH_OFF_BOXCNT);
554 + sboxcnt = splash_gets(ndata, SPLASH_OFF_SBOXCNT);
555 + }
556 + if (boxcnt) {
557 + i = splash_gets(ndata, len);
558 + if (boxcnt + i <= sd->splash_boxcount && ndata + len + 2 + boxcnt * 12 <= end) {
559 +
560 + if (splash_geti(ndata, len + 2) != 0x7ffd7fff || !memcmp(ndata + len + 2, sd->splash_boxes + i * 12, 8)) {
561 +
562 + memcpy(sd->splash_boxes + i * 12, ndata + len + 2, boxcnt * 12);
563 + up |= 1;
564 + }
565 + }
566 + len += boxcnt * 12 + 2;
567 + }
568 + if (sboxcnt) {
569 + i = splash_gets(ndata, len);
570 + if (sboxcnt + i <= sd->splash_sboxcount && ndata + len + 2 + sboxcnt * 12 <= end) {
571 + if (splash_geti(ndata, len + 2) != 0x7ffd7fff || !memcmp(ndata + len + 2, sd->splash_sboxes + i * 12, 8)) {
572 + memcpy(sd->splash_sboxes + i * 12, ndata + len + 2, sboxcnt * 12);
573 + up |= 2;
574 + }
575 + }
576 + }
577 + if (update)
578 + *update = up;
579 + }
580 + return unit;
581 + }
582 + if (splash_size == 0) {
583 + printk(KERN_INFO "bootsplash: ...found, freeing memory.\n");
584 + if (vc->vc_splash_data)
585 + splash_free(vc, info);
586 + return unit;
587 + }
588 + boxcnt = splash_gets(ndata, SPLASH_OFF_BOXCNT);
589 + palcnt = 3 * splash_getb(ndata, SPLASH_OFF_PALCNT);
590 + if (ndata + len + splash_size > end) {
591 + printk(KERN_ERR "bootsplash: ...found, but truncated!\n");
592 + return -1;
593 + }
594 + if (!jpeg_check_size(ndata + len + boxcnt * 12 + palcnt, width, height)) {
595 + ndata += len + splash_size - 1;
596 + continue;
597 + }
598 + if (splash_check_jpeg(ndata + len + boxcnt * 12 + palcnt, width, height, info->var.bits_per_pixel))
599 + return -1;
600 + silentsize = splash_geti(ndata, SPLASH_OFF_SSIZE);
601 + if (silentsize)
602 + printk(KERN_INFO "bootsplash: silentjpeg size %d bytes\n", silentsize);
603 + if (silentsize >= splash_size) {
604 + printk(KERN_ERR "bootsplash: bigger than splashsize!\n");
605 + return -1;
606 + }
607 + splash_size -= silentsize;
608 + if (!splash_usesilent)
609 + silentsize = 0;
610 + else if (height * 2 * info->fix.line_length > info->fix.smem_len) {
611 + printk(KERN_WARNING "bootsplash: does not fit into framebuffer.\n");
612 + silentsize = 0;
613 + }
614 + sboxcnt = splash_gets(ndata, SPLASH_OFF_SBOXCNT);
615 + if (silentsize) {
616 + unsigned char *simage = ndata + len + splash_size + 12 * sboxcnt;
617 + if (!jpeg_check_size(simage, width, height) ||
618 + splash_check_jpeg(simage, width, height, info->var.bits_per_pixel)) {
619 + printk(KERN_WARNING "bootsplash: error in silent jpeg.\n");
620 + silentsize = 0;
621 + }
622 + }
623 + oldpercent = -1;
624 + oldsilent = -1;
625 + if (vc->vc_splash_data) {
626 + oldpercent = vc->vc_splash_data->splash_percent;
627 + oldsilent = vc->vc_splash_data->splash_dosilent;
628 + splash_free(vc, info);
629 + }
630 + vc->vc_splash_data = sd = vmalloc(sizeof(*sd) + splash_size + (version < 3 ? 2 * 12 : 0));
631 + if (!sd)
632 + break;
633 + sd->splash_silentjpeg = 0;
634 + sd->splash_sboxes = 0;
635 + sd->splash_sboxcount = 0;
636 + if (silentsize) {
637 + sd->splash_silentjpeg = vmalloc(silentsize);
638 + if (sd->splash_silentjpeg) {
639 + memcpy(sd->splash_silentjpeg, ndata + len + splash_size, silentsize);
640 + sd->splash_sboxes = vc->vc_splash_data->splash_silentjpeg;
641 + sd->splash_silentjpeg += 12 * sboxcnt;
642 + sd->splash_sboxcount = sboxcnt;
643 + }
644 + }
645 + sd->splash_state = splash_getb(ndata, SPLASH_OFF_STATE);
646 + sd->splash_fg_color = splash_getb(ndata, SPLASH_OFF_FGCOL);
647 + sd->splash_color = splash_getb(ndata, SPLASH_OFF_COL);
648 + sd->splash_overpaintok = splash_getb(ndata, SPLASH_OFF_OVEROK);
649 + sd->splash_text_xo = splash_gets(ndata, SPLASH_OFF_XO);
650 + sd->splash_text_yo = splash_gets(ndata, SPLASH_OFF_YO);
651 + sd->splash_text_wi = splash_gets(ndata, SPLASH_OFF_WI);
652 + sd->splash_text_he = splash_gets(ndata, SPLASH_OFF_HE);
653 + sd->splash_percent = oldpercent == -1 ? splash_gets(ndata, SPLASH_OFF_PERCENT) : oldpercent;
654 + if (version == 1) {
655 + sd->splash_text_xo *= 8;
656 + sd->splash_text_wi *= 8;
657 + sd->splash_text_yo *= 16;
658 + sd->splash_text_he *= 16;
659 + sd->splash_color = (splash_default >> 8) & 0x0f;
660 + sd->splash_fg_color = (splash_default >> 4) & 0x0f;
661 + sd->splash_state = splash_default & 1;
662 + }
663 + if (sd->splash_text_xo + sd->splash_text_wi > width || sd->splash_text_yo + sd->splash_text_he > height) {
664 + splash_free(vc, info);
665 + printk(KERN_ERR "bootsplash: found, but has oversized text area!\n");
666 + return -1;
667 + }
668 + if (!vc_cons[unit].d || info->fbops->fb_imageblit != cfb_imageblit) {
669 + splash_free(vc, info);
670 + printk(KERN_ERR "bootsplash: found, but framebuffer can't handle it!\n");
671 + return -1;
672 + }
673 + printk(KERN_INFO "bootsplash: ...found (%dx%d, %d bytes, v%d).\n", width, height, splash_size, version);
674 + if (version == 1) {
675 + printk(KERN_WARNING "bootsplash: Using deprecated v1 header. Updating your splash utility recommended.\n");
676 + printk(KERN_INFO "bootsplash: Find the latest version at http://www.bootsplash.org/\n");
677 + }
678 +
679 + /* fake penguin box for older formats */
680 + if (version == 1)
681 + boxcnt = splash_mkpenguin(sd, sd->splash_text_xo + 10, sd->splash_text_yo + 10, sd->splash_text_wi - 20, sd->splash_text_he - 20, 0xf0, 0xf0, 0xf0);
682 + else if (version == 2)
683 + boxcnt = splash_mkpenguin(sd, splash_gets(ndata, 24), splash_gets(ndata, 26), splash_gets(ndata, 28), splash_gets(ndata, 30), splash_getb(ndata, 32), splash_getb(ndata, 33), splash_getb(ndata, 34));
684 +
685 + memcpy((char *)sd + sizeof(*sd) + (version < 3 ? boxcnt * 12 : 0), ndata + len, splash_size);
686 + sd->splash_boxcount = boxcnt;
687 + sd->splash_boxes = (unsigned char *)sd + sizeof(*sd);
688 + sd->splash_palette = sd->splash_boxes + boxcnt * 12;
689 + sd->splash_jpeg = sd->splash_palette + palcnt;
690 + sd->splash_palcnt = palcnt / 3;
691 + sd->splash_dosilent = sd->splash_silentjpeg != 0 ? (oldsilent == -1 ? 1 : oldsilent) : 0;
692 + return unit;
693 + }
694 + printk(KERN_ERR "bootsplash: ...no good signature found.\n");
695 + return -1;
696 +}
697 +
698 +int splash_verbose(void)
699 +{
700 + struct vc_data *vc;
701 + struct fb_info *info;
702 +
703 + if (!splash_usesilent)
704 + return 0;
705 +
706 + vc = vc_cons[0].d;
707 +
708 + if (!vc || !vc->vc_splash_data || !vc->vc_splash_data->splash_state)
709 + return 0;
710 + if (fg_console != vc->vc_num)
711 + return 0;
712 + if (!vc->vc_splash_data->splash_silentjpeg || !vc->vc_splash_data->splash_dosilent)
713 + return 0;
714 + vc->vc_splash_data->splash_dosilent = 0;
715 + info = registered_fb[(int)con2fb_map[0]];
716 + if (!info->silent_screen_base)
717 + return 0;
718 + splashcopy(info->silent_screen_base, info->screen_base, info->var.yres, info->var.xres, info->fix.line_length, info->fix.line_length);
719 + info->screen_base = info->silent_screen_base;
720 + info->silent_screen_base = 0;
721 + return 1;
722 +}
723 +
724 +static void splash_off(struct fb_info *info)
725 +{
726 + if (info->silent_screen_base)
727 + info->screen_base = info->silent_screen_base;
728 + info->silent_screen_base = 0;
729 + info->splash_data = 0;
730 + if (info->splash_pic)
731 + vfree(info->splash_pic);
732 + info->splash_pic = 0;
733 + info->splash_pic_size = 0;
734 +}
735 +
736 +int splash_prepare(struct vc_data *vc, struct fb_info *info)
737 +{
738 + int err;
739 + int width, height, depth, size, sbytes;
740 +
741 + if (!vc->vc_splash_data || !vc->vc_splash_data->splash_state) {
742 + if (decdata)
743 + vfree(decdata);
744 + decdata = 0;
745 + splash_off(info);
746 + return -1;
747 + }
748 +
749 + width = info->var.xres;
750 + height = info->var.yres;
751 + depth = info->var.bits_per_pixel;
752 + if (depth != 16) { /* Other targets might need fixing */
753 + splash_off(info);
754 + return -2;
755 + }
756 +
757 + sbytes = ((width + 15) & ~15) * (depth >> 3);
758 + size = sbytes * ((height + 15) & ~15);
759 + if (size != info->splash_pic_size)
760 + splash_off(info);
761 + if (!info->splash_pic)
762 + info->splash_pic = vmalloc(size);
763 +
764 + if (!info->splash_pic) {
765 + printk(KERN_INFO "bootsplash: not enough memory.\n");
766 + splash_off(info);
767 + return -3;
768 + }
769 +
770 + if (!decdata)
771 + decdata = vmalloc(sizeof(*decdata));
772 +
773 + if (vc->vc_splash_data->splash_silentjpeg && vc->vc_splash_data->splash_dosilent) {
774 + /* fill area after framebuffer with other jpeg */
775 + if ((err = jpeg_decode(vc->vc_splash_data->splash_silentjpeg, info->splash_pic,
776 + ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) {
777 + printk(KERN_INFO "bootsplash: error while decompressing silent picture: %s (%d)\n", jpg_errors[err - 1], err);
778 + if (info->silent_screen_base)
779 + info->screen_base = info->silent_screen_base;
780 + vc->vc_splash_data->splash_dosilent = 0;
781 + } else {
782 + if (vc->vc_splash_data->splash_sboxcount)
783 + boxit(info->splash_pic, sbytes, vc->vc_splash_data->splash_sboxes,
784 + vc->vc_splash_data->splash_sboxcount, vc->vc_splash_data->splash_percent, 0);
785 +
786 + if (!info->silent_screen_base)
787 + info->silent_screen_base = info->screen_base;
788 + splashcopy(info->silent_screen_base, info->splash_pic, info->var.yres, info->var.xres, info->fix.line_length, sbytes);
789 + info->screen_base = info->silent_screen_base + info->fix.line_length * info->var.yres;
790 + }
791 + } else if (info->silent_screen_base)
792 + info->screen_base = info->silent_screen_base;
793 +
794 + if ((err = jpeg_decode(vc->vc_splash_data->splash_jpeg, info->splash_pic,
795 + ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) {
796 + printk(KERN_INFO "bootsplash: error while decompressing picture: %s (%d) .\n", jpg_errors[err - 1], err);
797 + splash_off(info);
798 + return -4;
799 + }
800 + info->splash_pic_size = size;
801 + info->splash_bytes = sbytes;
802 + if (vc->vc_splash_data->splash_boxcount)
803 + boxit(info->splash_pic, sbytes, vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount, vc->vc_splash_data->splash_percent, 0);
804 + if (vc->vc_splash_data->splash_state)
805 + info->splash_data = vc->vc_splash_data;
806 + else
807 + splash_off(info);
808 + return 0;
809 +}
810 +
811 +
812 +#ifdef CONFIG_PROC_FS
813 +
814 +#include <linux/proc_fs.h>
815 +
816 +static int splash_read_proc(char *buffer, char **start, off_t offset, int size,
817 + int *eof, void *data);
818 +static int splash_write_proc(struct file *file, const char *buffer,
819 + unsigned long count, void *data);
820 +static int splash_status(struct vc_data *vc);
821 +static int splash_recolor(struct vc_data *vc);
822 +static int splash_proc_register(void);
823 +
824 +static struct proc_dir_entry *proc_splash;
825 +
826 +static int splash_recolor(struct vc_data *vc)
827 +{
828 + if (!vc->vc_splash_data)
829 + return -1;
830 + if (!vc->vc_splash_data->splash_state)
831 + return 0;
832 + con_remap_def_color(vc, vc->vc_splash_data->splash_color << 4 | vc->vc_splash_data->splash_fg_color);
833 + if (fg_console == vc->vc_num) {
834 + update_region(vc,
835 + vc->vc_origin + vc->vc_size_row * vc->vc_top,
836 + vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
837 + }
838 + return 0;
839 +}
840 +
841 +static int splash_status(struct vc_data *vc)
842 +{
843 + struct fb_info *info;
844 + printk(KERN_INFO "bootsplash: status on console %d changed to %s\n", vc->vc_num, vc->vc_splash_data && vc->vc_splash_data->splash_state ? "on" : "off");
845 +
846 + info = registered_fb[(int) con2fb_map[vc->vc_num]];
847 + if (fg_console == vc->vc_num)
848 + splash_prepare(vc, info);
849 + if (vc->vc_splash_data && vc->vc_splash_data->splash_state) {
850 + con_remap_def_color(vc, vc->vc_splash_data->splash_color << 4 | vc->vc_splash_data->splash_fg_color);
851 + /* vc_resize also calls con_switch which resets yscroll */
852 + vc_resize(vc, vc->vc_splash_data->splash_text_wi / vc->vc_font.width, vc->vc_splash_data->splash_text_he / vc->vc_font.height);
853 + if (fg_console == vc->vc_num) {
854 + update_region(vc,
855 + vc->vc_origin + vc->vc_size_row * vc->vc_top,
856 + vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
857 + splash_clear_margins(vc->vc_splash_data, vc, info, 0);
858 + }
859 + } else {
860 + /* Switch bootsplash off */
861 + con_remap_def_color(vc, 0x07);
862 + vc_resize(vc, info->var.xres / vc->vc_font.width, info->var.yres / vc->vc_font.height);
863 + }
864 + return 0;
865 +}
866 +
867 +static int splash_read_proc(char *buffer, char **start, off_t offset, int size,
868 + int *eof, void *data)
869 +{
870 + int len = 0;
871 + off_t begin = 0;
872 + struct vc_data *vc = vc_cons[0].d;
873 + struct fb_info *info = registered_fb[(int)con2fb_map[0]];
874 + int color = vc->vc_splash_data ? vc->vc_splash_data->splash_color << 4 |
875 + vc->vc_splash_data->splash_fg_color : splash_default >> 4;
876 + int status = vc->vc_splash_data ? vc->vc_splash_data->splash_state & 1 : 0;
877 + len += sprintf(buffer + len, "Splash screen v%s (0x%02x, %dx%d%s): %s\n",
878 + SPLASH_VERSION, color, info->var.xres, info->var.yres,
879 + (vc->vc_splash_data ? vc->vc_splash_data->splash_dosilent : 0)? ", silent" : "",
880 + status ? "on" : "off");
881 + if (offset >= begin + len)
882 + return 0;
883 +
884 + *start = buffer + (begin - offset);
885 +
886 + return (size < begin + len - offset ? size : begin + len - offset);
887 +}
888 +
889 +void splash_set_percent(struct vc_data *vc, int pe)
890 +{
891 + struct fb_info *info;
892 + struct fbcon_ops *ops;
893 + int oldpe;
894 +
895 + if (pe < 0)
896 + pe = 0;
897 + if (pe > 65535)
898 + pe = 65535;
899 + pe += pe > 32767;;
900 +
901 + if (!vc->vc_splash_data || vc->vc_splash_data->splash_percent == pe)
902 + return;
903 +
904 + oldpe = vc->vc_splash_data->splash_percent;
905 + vc->vc_splash_data->splash_percent = pe;
906 + if (fg_console != vc->vc_num || !vc->vc_splash_data->splash_state) {
907 + return;
908 + }
909 + info = registered_fb[(int) con2fb_map[vc->vc_num]];
910 + ops = info->fbcon_par;
911 + if (ops->blank_state)
912 + return;
913 + if (!vc->vc_splash_data->splash_overpaintok || pe == 65536 || pe < oldpe) {
914 + if (splash_hasinter(vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount))
915 + splash_status(vc);
916 + else
917 + splash_prepare(vc, info);
918 + } else {
919 + if (vc->vc_splash_data->splash_silentjpeg && vc->vc_splash_data->splash_dosilent && info->silent_screen_base)
920 + boxit(info->silent_screen_base, info->fix.line_length, vc->vc_splash_data->splash_sboxes, vc->vc_splash_data->splash_sboxcount, vc->vc_splash_data->splash_percent, 1);
921 + boxit(info->screen_base, info->fix.line_length, vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount, vc->vc_splash_data->splash_percent, 1);
922 + }
923 +}
924 +
925 +static int splash_write_proc(struct file *file, const char *buffer,
926 + unsigned long count, void *data)
927 +{
928 + int new, unit;
929 + struct vc_data *vc;
930 +
931 + if (!buffer || !splash_default)
932 + return count;
933 +
934 + acquire_console_sem();
935 + unit = 0;
936 + if (buffer[0] == '@' && buffer[1] >= '0' && buffer[1] <= '9') {
937 + unit = buffer[1] - '0';
938 + buffer += 2;
939 + if (*buffer >= '0' && *buffer <= '9') {
940 + unit = unit * 10 + *buffer - '0';
941 + buffer++;
942 + }
943 + if (*buffer == ' ')
944 + buffer++;
945 + if (unit >= MAX_NR_CONSOLES || !vc_cons[unit].d) {
946 + release_console_sem();
947 + return count;
948 + }
949 + }
950 + vc = vc_cons[unit].d;
951 + if (!strncmp(buffer, "redraw", 6)) {
952 + splash_status(vc);
953 + release_console_sem();
954 + return count;
955 + }
956 + if (!strncmp(buffer, "show", 4) || !strncmp(buffer, "hide", 4)) {
957 + int pe;
958 +
959 + if (buffer[4] == ' ' && buffer[5] == 'p')
960 + pe = 0;
961 + else if (buffer[4] == '\n')
962 + pe = 65535;
963 + else
964 + pe = simple_strtoul(buffer + 5, NULL, 0);
965 + if (pe < 0)
966 + pe = 0;
967 + if (pe > 65535)
968 + pe = 65535;
969 + if (*buffer == 'h')
970 + pe = 65535 - pe;
971 + splash_set_percent(vc, pe);
972 + release_console_sem();
973 + return count;
974 + }
975 + if (!strncmp(buffer,"silent\n",7) || !strncmp(buffer,"verbose\n",8)) {
976 + if (vc->vc_splash_data && vc->vc_splash_data->splash_silentjpeg) {
977 + if (vc->vc_splash_data->splash_dosilent != (buffer[0] == 's')) {
978 + vc->vc_splash_data->splash_dosilent = buffer[0] == 's';
979 + splash_status(vc);
980 + }
981 + }
982 + release_console_sem();
983 + return count;
984 + }
985 + if (!strncmp(buffer,"freesilent\n",11)) {
986 + if (vc->vc_splash_data && vc->vc_splash_data->splash_silentjpeg) {
987 + printk(KERN_INFO "bootsplash: freeing silent jpeg\n");
988 + vc->vc_splash_data->splash_silentjpeg = 0;
989 + vfree(vc->vc_splash_data->splash_sboxes);
990 + vc->vc_splash_data->splash_sboxes = 0;
991 + vc->vc_splash_data->splash_sboxcount = 0;
992 + if (vc->vc_splash_data->splash_dosilent)
993 + splash_status(vc);
994 + vc->vc_splash_data->splash_dosilent = 0;
995 + }
996 + release_console_sem();
997 + return count;
998 + }
999 +
1000 + if (!strncmp(buffer, "BOOTSPL", 7)) {
1001 + int up = -1;
1002 + unit = splash_getraw((unsigned char *)buffer, (unsigned char *)buffer + count, &up);
1003 + if (unit >= 0) {
1004 + vc = vc_cons[unit].d;
1005 + if (up == -1)
1006 + splash_status(vc);
1007 + else {
1008 + struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
1009 + struct fbcon_ops *ops = info->fbcon_par;
1010 + if (ops->blank_state)
1011 + up = 0;
1012 + if ((up & 2) != 0 && vc->vc_splash_data->splash_silentjpeg && vc->vc_splash_data->splash_dosilent && info->silent_screen_base)
1013 + boxit(info->silent_screen_base, info->fix.line_length, vc->vc_splash_data->splash_sboxes, vc->vc_splash_data->splash_sboxcount, vc->vc_splash_data->splash_percent, 1);
1014 + if ((up & 1) != 0)
1015 + boxit(info->screen_base, info->fix.line_length, vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount, vc->vc_splash_data->splash_percent, 1);
1016 + }
1017 + }
1018 + release_console_sem();
1019 + return count;
1020 + }
1021 + if (!vc->vc_splash_data) {
1022 + release_console_sem();
1023 + return count;
1024 + }
1025 + if (buffer[0] == 't') {
1026 + vc->vc_splash_data->splash_state ^= 1;
1027 + splash_status(vc);
1028 + release_console_sem();
1029 + return count;
1030 + }
1031 + new = simple_strtoul(buffer, NULL, 0);
1032 + if (new > 1) {
1033 + /* expert user */
1034 + vc->vc_splash_data->splash_color = new >> 8 & 0xff;
1035 + vc->vc_splash_data->splash_fg_color = new >> 4 & 0x0f;
1036 + }
1037 + if ((new & 1) == vc->vc_splash_data->splash_state)
1038 + splash_recolor(vc);
1039 + else {
1040 + vc->vc_splash_data->splash_state = new & 1;
1041 + splash_status(vc);
1042 + }
1043 + release_console_sem();
1044 + return count;
1045 +}
1046 +
1047 +static int splash_proc_register(void)
1048 +{
1049 + if ((proc_splash = create_proc_entry("splash", 0, 0))) {
1050 + proc_splash->read_proc = splash_read_proc;
1051 + proc_splash->write_proc = splash_write_proc;
1052 + return 0;
1053 + }
1054 + return 1;
1055 +}
1056 +
1057 +# if 0
1058 +static int splash_proc_unregister(void)
1059 +{
1060 + if (proc_splash)
1061 + remove_proc_entry("splash", 0);
1062 + return 0;
1063 +}
1064 +# endif
1065 +#endif /* CONFIG_PROC_FS */
1066 +
1067 +void splash_init(void)
1068 +{
1069 + struct fb_info *info;
1070 + struct vc_data *vc;
1071 + int isramfs = 1;
1072 + int fd;
1073 + int len;
1074 + int max_len = 1024*1024*2;
1075 + char *mem;
1076 +
1077 + if (splash_registered)
1078 + return;
1079 + vc = vc_cons[0].d;
1080 + info = registered_fb[0];
1081 + if (!vc || !info || info->var.bits_per_pixel != 16)
1082 + return;
1083 +#ifdef CONFIG_PROC_FS
1084 + splash_proc_register();
1085 +#endif
1086 + splash_registered = 1;
1087 + if (vc->vc_splash_data)
1088 + return;
1089 + if ((fd = sys_open("/bootsplash", O_RDONLY, 0)) < 0) {
1090 + isramfs = 0;
1091 + fd = sys_open("/initrd.image", O_RDONLY, 0);
1092 + }
1093 + if (fd < 0)
1094 + return;
1095 + if ((len = (int)sys_lseek(fd, (off_t)0, 2)) <= 0) {
1096 + sys_close(fd);
1097 + return;
1098 + }
1099 + /* Don't look for more than the last 2MB */
1100 + if (len > max_len) {
1101 + printk( KERN_INFO "bootsplash: scanning last %dMB of initrd for signature\n",
1102 + max_len>>20);
1103 + sys_lseek(fd, (off_t)(len - max_len), 0);
1104 + len = max_len;
1105 + } else {
1106 + sys_lseek(fd, (off_t)0, 0);
1107 + }
1108 +
1109 + mem = vmalloc(len);
1110 + if (mem) {
1111 + acquire_console_sem();
1112 + if ((int)sys_read(fd, mem, len) == len && splash_getraw((unsigned char *)mem, (unsigned char *)mem + len, (int *)0) == 0 && vc->vc_splash_data)
1113 + vc->vc_splash_data->splash_state = splash_default & 1;
1114 + release_console_sem();
1115 + vfree(mem);
1116 + }
1117 + sys_close(fd);
1118 + if (isramfs)
1119 + sys_unlink("/bootsplash");
1120 + return;
1121 +}
1122 +
1123 --- /dev/null
1124 +++ b/drivers/video/bootsplash/bootsplash.h
1125 @@ -0,0 +1,44 @@
1126 +/*
1127 + * linux/drivers/video/bootsplash/bootsplash.h - splash screen definition.
1128 + *
1129 + * (w) 2001-2003 by Volker Poplawski, <volker@poplawski.de>
1130 + * Stefan Reinauer, <stepan@suse.de>
1131 + *
1132 + *
1133 + * idea and SuSE screen work by Ken Wimer, <wimer@suse.de>
1134 + */
1135 +
1136 +#ifndef __BOOTSPLASH_H
1137 +#define __BOOTSPLASH_H
1138 +
1139 +struct fb_info;
1140 +
1141 +/* splash.c */
1142 +extern int splash_prepare(struct vc_data *, struct fb_info *);
1143 +extern void splash_init(void);
1144 +
1145 +/* splash_render.c */
1146 +extern void splash_putcs(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
1147 + const unsigned short *s, int count, int ypos, int xpos);
1148 +extern void splash_putc(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
1149 + int c, int ypos, int xpos);
1150 +extern void splashcopy(u8 *dst, u8 *src, int height, int width, int dstbytes, int srcbytes);
1151 +extern void splash_clear(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy,
1152 + int sx, int height, int width);
1153 +extern void splash_bmove(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy,
1154 + int sx, int dy, int dx, int height, int width);
1155 +extern void splash_clear_margins(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
1156 + int bottom_only);
1157 +extern int splash_cursor(struct splash_data *sd, struct fb_info *info, struct fb_cursor *cursor);
1158 +extern void splash_bmove_redraw(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
1159 + int y, int sx, int dx, int width);
1160 +extern void splash_blank(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
1161 + int blank);
1162 +
1163 +/* vt.c */
1164 +extern void con_remap_def_color(struct vc_data *vc, int new_color);
1165 +
1166 +extern void acquire_console_sem(void);
1167 +extern void release_console_sem(void);
1168 +
1169 +#endif
1170 --- /dev/null
1171 +++ b/drivers/video/bootsplash/decode-jpg.c
1172 @@ -0,0 +1,957 @@
1173 +/*
1174 + * linux/drivers/video/bootsplash/decode-jpg.c - a tiny jpeg decoder.
1175 + *
1176 + * (w) August 2001 by Michael Schroeder, <mls@suse.de>
1177 + *
1178 + */
1179 +
1180 +#include <linux/string.h>
1181 +#include <asm/byteorder.h>
1182 +
1183 +#include "decode-jpg.h"
1184 +
1185 +#define ISHIFT 11
1186 +
1187 +#define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5))
1188 +#define IMULT(a, b) (((a) * (b)) >> ISHIFT)
1189 +#define ITOINT(a) ((a) >> ISHIFT)
1190 +
1191 +#ifndef __P
1192 +# define __P(x) x
1193 +#endif
1194 +
1195 +/* special markers */
1196 +#define M_BADHUFF -1
1197 +#define M_EOF 0x80
1198 +
1199 +struct in {
1200 + unsigned char *p;
1201 + unsigned int bits;
1202 + int left;
1203 + int marker;
1204 +
1205 + int (*func) __P((void *));
1206 + void *data;
1207 +};
1208 +
1209 +/*********************************/
1210 +struct dec_hufftbl;
1211 +struct enc_hufftbl;
1212 +
1213 +union hufftblp {
1214 + struct dec_hufftbl *dhuff;
1215 + struct enc_hufftbl *ehuff;
1216 +};
1217 +
1218 +struct scan {
1219 + int dc; /* old dc value */
1220 +
1221 + union hufftblp hudc;
1222 + union hufftblp huac;
1223 + int next; /* when to switch to next scan */
1224 +
1225 + int cid; /* component id */
1226 + int hv; /* horiz/vert, copied from comp */
1227 + int tq; /* quant tbl, copied from comp */
1228 +};
1229 +
1230 +/*********************************/
1231 +
1232 +#define DECBITS 10 /* seems to be the optimum */
1233 +
1234 +struct dec_hufftbl {
1235 + int maxcode[17];
1236 + int valptr[16];
1237 + unsigned char vals[256];
1238 + unsigned int llvals[1 << DECBITS];
1239 +};
1240 +
1241 +static void decode_mcus __P((struct in *, int *, int, struct scan *, int *));
1242 +static int dec_readmarker __P((struct in *));
1243 +static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *));
1244 +
1245 +static void setinput __P((struct in *, unsigned char *));
1246 +/*********************************/
1247 +
1248 +#undef PREC
1249 +#define PREC int
1250 +
1251 +static void idctqtab __P((unsigned char *, PREC *));
1252 +static void idct __P((int *, int *, PREC *, PREC, int));
1253 +static void scaleidctqtab __P((PREC *, PREC));
1254 +
1255 +/*********************************/
1256 +
1257 +static void initcol __P((PREC[][64]));
1258 +
1259 +static void col221111 __P((int *, unsigned char *, int));
1260 +static void col221111_16 __P((int *, unsigned char *, int));
1261 +
1262 +/*********************************/
1263 +
1264 +#define M_SOI 0xd8
1265 +#define M_APP0 0xe0
1266 +#define M_DQT 0xdb
1267 +#define M_SOF0 0xc0
1268 +#define M_DHT 0xc4
1269 +#define M_DRI 0xdd
1270 +#define M_SOS 0xda
1271 +#define M_RST0 0xd0
1272 +#define M_EOI 0xd9
1273 +#define M_COM 0xfe
1274 +
1275 +static unsigned char *datap;
1276 +
1277 +static int getbyte(void)
1278 +{
1279 + return *datap++;
1280 +}
1281 +
1282 +static int getword(void)
1283 +{
1284 + int c1, c2;
1285 + c1 = *datap++;
1286 + c2 = *datap++;
1287 + return c1 << 8 | c2;
1288 +}
1289 +
1290 +struct comp {
1291 + int cid;
1292 + int hv;
1293 + int tq;
1294 +};
1295 +
1296 +#define MAXCOMP 4
1297 +struct jpginfo {
1298 + int nc; /* number of components */
1299 + int ns; /* number of scans */
1300 + int dri; /* restart interval */
1301 + int nm; /* mcus til next marker */
1302 + int rm; /* next restart marker */
1303 +};
1304 +
1305 +static struct jpginfo info;
1306 +static struct comp comps[MAXCOMP];
1307 +
1308 +static struct scan dscans[MAXCOMP];
1309 +
1310 +static unsigned char quant[4][64];
1311 +
1312 +static struct dec_hufftbl dhuff[4];
1313 +
1314 +#define dec_huffdc (dhuff + 0)
1315 +#define dec_huffac (dhuff + 2)
1316 +
1317 +static struct in in;
1318 +
1319 +static int readtables(int till)
1320 +{
1321 + int m, l, i, j, lq, pq, tq;
1322 + int tc, th, tt;
1323 +
1324 + for (;;) {
1325 + if (getbyte() != 0xff)
1326 + return -1;
1327 + if ((m = getbyte()) == till)
1328 + break;
1329 +
1330 + switch (m) {
1331 + case 0xc2:
1332 + return 0;
1333 +
1334 + case M_DQT:
1335 + lq = getword();
1336 + while (lq > 2) {
1337 + pq = getbyte();
1338 + tq = pq & 15;
1339 + if (tq > 3)
1340 + return -1;
1341 + pq >>= 4;
1342 + if (pq != 0)
1343 + return -1;
1344 + for (i = 0; i < 64; i++)
1345 + quant[tq][i] = getbyte();
1346 + lq -= 64 + 1;
1347 + }
1348 + break;
1349 +
1350 + case M_DHT:
1351 + l = getword();
1352 + while (l > 2) {
1353 + int hufflen[16], k;
1354 + unsigned char huffvals[256];
1355 +
1356 + tc = getbyte();
1357 + th = tc & 15;
1358 + tc >>= 4;
1359 + tt = tc * 2 + th;
1360 + if (tc > 1 || th > 1)
1361 + return -1;
1362 + for (i = 0; i < 16; i++)
1363 + hufflen[i] = getbyte();
1364 + l -= 1 + 16;
1365 + k = 0;
1366 + for (i = 0; i < 16; i++) {
1367 + for (j = 0; j < hufflen[i]; j++)
1368 + huffvals[k++] = getbyte();
1369 + l -= hufflen[i];
1370 + }
1371 + dec_makehuff(dhuff + tt, hufflen,
1372 + huffvals);
1373 + }
1374 + break;
1375 +
1376 + case M_DRI:
1377 + l = getword();
1378 + info.dri = getword();
1379 + break;
1380 +
1381 + default:
1382 + l = getword();
1383 + while (l-- > 2)
1384 + getbyte();
1385 + break;
1386 + }
1387 + }
1388 + return 0;
1389 +}
1390 +
1391 +static void dec_initscans(void)
1392 +{
1393 + int i;
1394 +
1395 + info.nm = info.dri + 1;
1396 + info.rm = M_RST0;
1397 + for (i = 0; i < info.ns; i++)
1398 + dscans[i].dc = 0;
1399 +}
1400 +
1401 +static int dec_checkmarker(void)
1402 +{
1403 + int i;
1404 +
1405 + if (dec_readmarker(&in) != info.rm)
1406 + return -1;
1407 + info.nm = info.dri;
1408 + info.rm = (info.rm + 1) & ~0x08;
1409 + for (i = 0; i < info.ns; i++)
1410 + dscans[i].dc = 0;
1411 + return 0;
1412 +}
1413 +
1414 +int jpeg_check_size(unsigned char *buf, int width, int height)
1415 +{
1416 + datap = buf;
1417 + getbyte();
1418 + getbyte();
1419 + readtables(M_SOF0);
1420 + getword();
1421 + getbyte();
1422 + if (height != getword() || width != getword())
1423 + return 0;
1424 + return 1;
1425 +}
1426 +
1427 +int jpeg_decode(buf, pic, width, height, depth, decdata)
1428 +unsigned char *buf, *pic;
1429 +int width, height, depth;
1430 +struct jpeg_decdata *decdata;
1431 +{
1432 + int i, j, m, tac, tdc;
1433 + int mcusx, mcusy, mx, my;
1434 + int max[6];
1435 +
1436 + if (!decdata || !buf || !pic)
1437 + return -1;
1438 + datap = buf;
1439 + if (getbyte() != 0xff)
1440 + return ERR_NO_SOI;
1441 + if (getbyte() != M_SOI)
1442 + return ERR_NO_SOI;
1443 + if (readtables(M_SOF0))
1444 + return ERR_BAD_TABLES;
1445 + getword();
1446 + i = getbyte();
1447 + if (i != 8)
1448 + return ERR_NOT_8BIT;
1449 + if (((getword() + 15) & ~15) != height)
1450 + return ERR_HEIGHT_MISMATCH;
1451 + if (((getword() + 15) & ~15) != width)
1452 + return ERR_WIDTH_MISMATCH;
1453 + if ((height & 15) || (width & 15))
1454 + return ERR_BAD_WIDTH_OR_HEIGHT;
1455 + info.nc = getbyte();
1456 + if (info.nc > MAXCOMP)
1457 + return ERR_TOO_MANY_COMPPS;
1458 + for (i = 0; i < info.nc; i++) {
1459 + int h, v;
1460 + comps[i].cid = getbyte();
1461 + comps[i].hv = getbyte();
1462 + v = comps[i].hv & 15;
1463 + h = comps[i].hv >> 4;
1464 + comps[i].tq = getbyte();
1465 + if (h > 3 || v > 3)
1466 + return ERR_ILLEGAL_HV;
1467 + if (comps[i].tq > 3)
1468 + return ERR_QUANT_TABLE_SELECTOR;
1469 + }
1470 + if (readtables(M_SOS))
1471 + return ERR_BAD_TABLES;
1472 + getword();
1473 + info.ns = getbyte();
1474 + if (info.ns != 3)
1475 + return ERR_NOT_YCBCR_221111;
1476 + for (i = 0; i < 3; i++) {
1477 + dscans[i].cid = getbyte();
1478 + tdc = getbyte();
1479 + tac = tdc & 15;
1480 + tdc >>= 4;
1481 + if (tdc > 1 || tac > 1)
1482 + return ERR_QUANT_TABLE_SELECTOR;
1483 + for (j = 0; j < info.nc; j++)
1484 + if (comps[j].cid == dscans[i].cid)
1485 + break;
1486 + if (j == info.nc)
1487 + return ERR_UNKNOWN_CID_IN_SCAN;
1488 + dscans[i].hv = comps[j].hv;
1489 + dscans[i].tq = comps[j].tq;
1490 + dscans[i].hudc.dhuff = dec_huffdc + tdc;
1491 + dscans[i].huac.dhuff = dec_huffac + tac;
1492 + }
1493 +
1494 + i = getbyte();
1495 + j = getbyte();
1496 + m = getbyte();
1497 +
1498 + if (i != 0 || j != 63 || m != 0)
1499 + return ERR_NOT_SEQUENTIAL_DCT;
1500 +
1501 + if (dscans[0].cid != 1 || dscans[1].cid != 2 || dscans[2].cid != 3)
1502 + return ERR_NOT_YCBCR_221111;
1503 +
1504 + if (dscans[0].hv != 0x22 || dscans[1].hv != 0x11 || dscans[2].hv != 0x11)
1505 + return ERR_NOT_YCBCR_221111;
1506 +
1507 + mcusx = width >> 4;
1508 + mcusy = height >> 4;
1509 +
1510 +
1511 + idctqtab(quant[dscans[0].tq], decdata->dquant[0]);
1512 + idctqtab(quant[dscans[1].tq], decdata->dquant[1]);
1513 + idctqtab(quant[dscans[2].tq], decdata->dquant[2]);
1514 + initcol(decdata->dquant);
1515 + setinput(&in, datap);
1516 +
1517 +#if 0
1518 + /* landing zone */
1519 + img[len] = 0;
1520 + img[len + 1] = 0xff;
1521 + img[len + 2] = M_EOF;
1522 +#endif
1523 +
1524 + dec_initscans();
1525 +
1526 + dscans[0].next = 6 - 4;
1527 + dscans[1].next = 6 - 4 - 1;
1528 + dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */
1529 + for (my = 0; my < mcusy; my++) {
1530 + for (mx = 0; mx < mcusx; mx++) {
1531 + if (info.dri && !--info.nm)
1532 + if (dec_checkmarker())
1533 + return ERR_WRONG_MARKER;
1534 +
1535 + decode_mcus(&in, decdata->dcts, 6, dscans, max);
1536 + idct(decdata->dcts, decdata->out, decdata->dquant[0], IFIX(128.5), max[0]);
1537 + idct(decdata->dcts + 64, decdata->out + 64, decdata->dquant[0], IFIX(128.5), max[1]);
1538 + idct(decdata->dcts + 128, decdata->out + 128, decdata->dquant[0], IFIX(128.5), max[2]);
1539 + idct(decdata->dcts + 192, decdata->out + 192, decdata->dquant[0], IFIX(128.5), max[3]);
1540 + idct(decdata->dcts + 256, decdata->out + 256, decdata->dquant[1], IFIX(0.5), max[4]);
1541 + idct(decdata->dcts + 320, decdata->out + 320, decdata->dquant[2], IFIX(0.5), max[5]);
1542 +
1543 + switch (depth) {
1544 + case 24:
1545 + col221111(decdata->out, pic + (my * 16 * mcusx + mx) * 16 * 3, mcusx * 16 * 3);
1546 + break;
1547 + case 16:
1548 + col221111_16(decdata->out, pic + (my * 16 * mcusx + mx) * (16 * 2), mcusx * (16 * 2));
1549 + break;
1550 + default:
1551 + return ERR_DEPTH_MISMATCH;
1552 + break;
1553 + }
1554 + }
1555 + }
1556 +
1557 + m = dec_readmarker(&in);
1558 + if (m != M_EOI)
1559 + return ERR_NO_EOI;
1560 +
1561 + return 0;
1562 +}
1563 +
1564 +/****************************************************************/
1565 +/************** huffman decoder ***************/
1566 +/****************************************************************/
1567 +
1568 +static int fillbits __P((struct in *, int, unsigned int));
1569 +static int dec_rec2
1570 +__P((struct in *, struct dec_hufftbl *, int *, int, int));
1571 +
1572 +static void setinput(in, p)
1573 +struct in *in;
1574 +unsigned char *p;
1575 +{
1576 + in->p = p;
1577 + in->left = 0;
1578 + in->bits = 0;
1579 + in->marker = 0;
1580 +}
1581 +
1582 +static int fillbits(in, le, bi)
1583 +struct in *in;
1584 +int le;
1585 +unsigned int bi;
1586 +{
1587 + int b, m;
1588 +
1589 + if (in->marker) {
1590 + if (le <= 16)
1591 + in->bits = bi << 16, le += 16;
1592 + return le;
1593 + }
1594 + while (le <= 24) {
1595 + b = *in->p++;
1596 + if (b == 0xff && (m = *in->p++) != 0) {
1597 + if (m == M_EOF) {
1598 + if (in->func && (m = in->func(in->data)) == 0)
1599 + continue;
1600 + }
1601 + in->marker = m;
1602 + if (le <= 16)
1603 + bi = bi << 16, le += 16;
1604 + break;
1605 + }
1606 + bi = bi << 8 | b;
1607 + le += 8;
1608 + }
1609 + in->bits = bi; /* tmp... 2 return values needed */
1610 + return le;
1611 +}
1612 +
1613 +static int dec_readmarker(in)
1614 +struct in *in;
1615 +{
1616 + int m;
1617 +
1618 + in->left = fillbits(in, in->left, in->bits);
1619 + if ((m = in->marker) == 0)
1620 + return 0;
1621 + in->left = 0;
1622 + in->marker = 0;
1623 + return m;
1624 +}
1625 +
1626 +#define LEBI_DCL int le, bi
1627 +#define LEBI_GET(in) (le = in->left, bi = in->bits)
1628 +#define LEBI_PUT(in) (in->left = le, in->bits = bi)
1629 +
1630 +#define GETBITS(in, n) ( \
1631 + (le < (n) ? le = fillbits(in, le, bi), bi = in->bits : 0), \
1632 + (le -= (n)), \
1633 + bi >> le & ((1 << (n)) - 1) \
1634 +)
1635 +
1636 +#define UNGETBITS(in, n) ( \
1637 + le += (n) \
1638 +)
1639 +
1640 +
1641 +static int dec_rec2(in, hu, runp, c, i)
1642 +struct in *in;
1643 +struct dec_hufftbl *hu;
1644 +int *runp;
1645 +int c, i;
1646 +{
1647 + LEBI_DCL;
1648 +
1649 + LEBI_GET(in);
1650 + if (i) {
1651 + UNGETBITS(in, i & 127);
1652 + *runp = i >> 8 & 15;
1653 + i >>= 16;
1654 + } else {
1655 + for (i = DECBITS; (c = ((c << 1) | GETBITS(in, 1))) >= (hu->maxcode[i]); i++);
1656 + if (i >= 16) {
1657 + in->marker = M_BADHUFF;
1658 + return 0;
1659 + }
1660 + i = hu->vals[hu->valptr[i] + c - hu->maxcode[i - 1] * 2];
1661 + *runp = i >> 4;
1662 + i &= 15;
1663 + }
1664 + if (i == 0) { /* sigh, 0xf0 is 11 bit */
1665 + LEBI_PUT(in);
1666 + return 0;
1667 + }
1668 + /* receive part */
1669 + c = GETBITS(in, i);
1670 + if (c < (1 << (i - 1)))
1671 + c += (-1 << i) + 1;
1672 + LEBI_PUT(in);
1673 + return c;
1674 +}
1675 +
1676 +#define DEC_REC(in, hu, r, i) ( \
1677 + r = GETBITS(in, DECBITS), \
1678 + i = hu->llvals[r], \
1679 + i & 128 ? \
1680 + ( \
1681 + UNGETBITS(in, i & 127), \
1682 + r = i >> 8 & 15, \
1683 + i >> 16 \
1684 + ) \
1685 + : \
1686 + ( \
1687 + LEBI_PUT(in), \
1688 + i = dec_rec2(in, hu, &r, r, i), \
1689 + LEBI_GET(in), \
1690 + i \
1691 + ) \
1692 +)
1693 +
1694 +static void decode_mcus(in, dct, n, sc, maxp)
1695 +struct in *in;
1696 +int *dct;
1697 +int n;
1698 +struct scan *sc;
1699 +int *maxp;
1700 +{
1701 + struct dec_hufftbl *hu;
1702 + int i, r, t;
1703 + LEBI_DCL;
1704 +
1705 + memset(dct, 0, n * 64 * sizeof(*dct));
1706 + LEBI_GET(in);
1707 + while (n-- > 0) {
1708 + hu = sc->hudc.dhuff;
1709 + *dct++ = (sc->dc += DEC_REC(in, hu, r, t));
1710 +
1711 + hu = sc->huac.dhuff;
1712 + i = 63;
1713 + while (i > 0) {
1714 + t = DEC_REC(in, hu, r, t);
1715 + if (t == 0 && r == 0) {
1716 + dct += i;
1717 + break;
1718 + }
1719 + dct += r;
1720 + *dct++ = t;
1721 + i -= r + 1;
1722 + }
1723 + *maxp++ = 64 - i;
1724 + if (n == sc->next)
1725 + sc++;
1726 + }
1727 + LEBI_PUT(in);
1728 +}
1729 +
1730 +static void dec_makehuff(hu, hufflen, huffvals)
1731 +struct dec_hufftbl *hu;
1732 +int *hufflen;
1733 +unsigned char *huffvals;
1734 +{
1735 + int code, k, i, j, d, x, c, v;
1736 + for (i = 0; i < (1 << DECBITS); i++)
1737 + hu->llvals[i] = 0;
1738 +
1739 +/*
1740 + * llvals layout:
1741 + *
1742 + * value v already known, run r, backup u bits:
1743 + * vvvvvvvvvvvvvvvv 0000 rrrr 1 uuuuuuu
1744 + * value unknown, size b bits, run r, backup u bits:
1745 + * 000000000000bbbb 0000 rrrr 0 uuuuuuu
1746 + * value and size unknown:
1747 + * 0000000000000000 0000 0000 0 0000000
1748 + */
1749 + code = 0;
1750 + k = 0;
1751 + for (i = 0; i < 16; i++, code <<= 1) { /* sizes */
1752 + hu->valptr[i] = k;
1753 + for (j = 0; j < hufflen[i]; j++) {
1754 + hu->vals[k] = *huffvals++;
1755 + if (i < DECBITS) {
1756 + c = code << (DECBITS - 1 - i);
1757 + v = hu->vals[k] & 0x0f; /* size */
1758 + for (d = 1 << (DECBITS - 1 - i); --d >= 0;) {
1759 + if (v + i < DECBITS) { /* both fit in table */
1760 + x = d >> (DECBITS - 1 - v -
1761 + i);
1762 + if (v && x < (1 << (v - 1)))
1763 + x += (-1 << v) + 1;
1764 + x = x << 16 | (hu-> vals[k] & 0xf0) << 4 |
1765 + (DECBITS - (i + 1 + v)) | 128;
1766 + } else
1767 + x = v << 16 | (hu-> vals[k] & 0xf0) << 4 |
1768 + (DECBITS - (i + 1));
1769 + hu->llvals[c | d] = x;
1770 + }
1771 + }
1772 + code++;
1773 + k++;
1774 + }
1775 + hu->maxcode[i] = code;
1776 + }
1777 + hu->maxcode[16] = 0x20000; /* always terminate decode */
1778 +}
1779 +
1780 +/****************************************************************/
1781 +/************** idct ***************/
1782 +/****************************************************************/
1783 +
1784 +#define ONE ((PREC)IFIX(1.))
1785 +#define S2 ((PREC)IFIX(0.382683432))
1786 +#define C2 ((PREC)IFIX(0.923879532))
1787 +#define C4 ((PREC)IFIX(0.707106781))
1788 +
1789 +#define S22 ((PREC)IFIX(2 * 0.382683432))
1790 +#define C22 ((PREC)IFIX(2 * 0.923879532))
1791 +#define IC4 ((PREC)IFIX(1 / 0.707106781))
1792 +
1793 +#define C3IC1 ((PREC)IFIX(0.847759065)) /* c3/c1 */
1794 +#define C5IC1 ((PREC)IFIX(0.566454497)) /* c5/c1 */
1795 +#define C7IC1 ((PREC)IFIX(0.198912367)) /* c7/c1 */
1796 +
1797 +#define XPP(a,b) (t = a + b, b = a - b, a = t)
1798 +#define XMP(a,b) (t = a - b, b = a + b, a = t)
1799 +#define XPM(a,b) (t = a + b, b = b - a, a = t)
1800 +
1801 +#define ROT(a,b,s,c) ( t = IMULT(a + b, s), \
1802 + a = IMULT(a, c - s) + t, \
1803 + b = IMULT(b, c + s) - t)
1804 +
1805 +#define IDCT \
1806 +( \
1807 + XPP(t0, t1), \
1808 + XMP(t2, t3), \
1809 + t2 = IMULT(t2, IC4) - t3, \
1810 + XPP(t0, t3), \
1811 + XPP(t1, t2), \
1812 + XMP(t4, t7), \
1813 + XPP(t5, t6), \
1814 + XMP(t5, t7), \
1815 + t5 = IMULT(t5, IC4), \
1816 + ROT(t4, t6, S22, C22),\
1817 + t6 -= t7, \
1818 + t5 -= t6, \
1819 + t4 -= t5, \
1820 + XPP(t0, t7), \
1821 + XPP(t1, t6), \
1822 + XPP(t2, t5), \
1823 + XPP(t3, t4) \
1824 +)
1825 +
1826 +static unsigned char zig2[64] = {
1827 + 0, 2, 3, 9, 10, 20, 21, 35,
1828 + 14, 16, 25, 31, 39, 46, 50, 57,
1829 + 5, 7, 12, 18, 23, 33, 37, 48,
1830 + 27, 29, 41, 44, 52, 55, 59, 62,
1831 + 15, 26, 30, 40, 45, 51, 56, 58,
1832 + 1, 4, 8, 11, 19, 22, 34, 36,
1833 + 28, 42, 43, 53, 54, 60, 61, 63,
1834 + 6, 13, 17, 24, 32, 38, 47, 49
1835 +};
1836 +
1837 +void idct(in, out, quant, off, max)
1838 +int *in;
1839 +int *out;
1840 +PREC *quant;
1841 +PREC off;
1842 +int max;
1843 +{
1844 + PREC t0, t1, t2, t3, t4, t5, t6, t7, t;
1845 + PREC tmp[64], *tmpp;
1846 + int i, j;
1847 + unsigned char *zig2p;
1848 +
1849 + t0 = off;
1850 + if (max == 1) {
1851 + t0 += in[0] * quant[0];
1852 + for (i = 0; i < 64; i++)
1853 + out[i] = ITOINT(t0);
1854 + return;
1855 + }
1856 + zig2p = zig2;
1857 + tmpp = tmp;
1858 + for (i = 0; i < 8; i++) {
1859 + j = *zig2p++;
1860 + t0 += in[j] * quant[j];
1861 + j = *zig2p++;
1862 + t5 = in[j] * quant[j];
1863 + j = *zig2p++;
1864 + t2 = in[j] * quant[j];
1865 + j = *zig2p++;
1866 + t7 = in[j] * quant[j];
1867 + j = *zig2p++;
1868 + t1 = in[j] * quant[j];
1869 + j = *zig2p++;
1870 + t4 = in[j] * quant[j];
1871 + j = *zig2p++;
1872 + t3 = in[j] * quant[j];
1873 + j = *zig2p++;
1874 + t6 = in[j] * quant[j];
1875 + IDCT;
1876 + tmpp[0 * 8] = t0;
1877 + tmpp[1 * 8] = t1;
1878 + tmpp[2 * 8] = t2;
1879 + tmpp[3 * 8] = t3;
1880 + tmpp[4 * 8] = t4;
1881 + tmpp[5 * 8] = t5;
1882 + tmpp[6 * 8] = t6;
1883 + tmpp[7 * 8] = t7;
1884 + tmpp++;
1885 + t0 = 0;
1886 + }
1887 + for (i = 0; i < 8; i++) {
1888 + t0 = tmp[8 * i + 0];
1889 + t1 = tmp[8 * i + 1];
1890 + t2 = tmp[8 * i + 2];
1891 + t3 = tmp[8 * i + 3];
1892 + t4 = tmp[8 * i + 4];
1893 + t5 = tmp[8 * i + 5];
1894 + t6 = tmp[8 * i + 6];
1895 + t7 = tmp[8 * i + 7];
1896 + IDCT;
1897 + out[8 * i + 0] = ITOINT(t0);
1898 + out[8 * i + 1] = ITOINT(t1);
1899 + out[8 * i + 2] = ITOINT(t2);
1900 + out[8 * i + 3] = ITOINT(t3);
1901 + out[8 * i + 4] = ITOINT(t4);
1902 + out[8 * i + 5] = ITOINT(t5);
1903 + out[8 * i + 6] = ITOINT(t6);
1904 + out[8 * i + 7] = ITOINT(t7);
1905 + }
1906 +}
1907 +
1908 +static unsigned char zig[64] = {
1909 + 0, 1, 5, 6, 14, 15, 27, 28,
1910 + 2, 4, 7, 13, 16, 26, 29, 42,
1911 + 3, 8, 12, 17, 25, 30, 41, 43,
1912 + 9, 11, 18, 24, 31, 40, 44, 53,
1913 + 10, 19, 23, 32, 39, 45, 52, 54,
1914 + 20, 22, 33, 38, 46, 51, 55, 60,
1915 + 21, 34, 37, 47, 50, 56, 59, 61,
1916 + 35, 36, 48, 49, 57, 58, 62, 63
1917 +};
1918 +
1919 +static PREC aaidct[8] = {
1920 + IFIX(0.3535533906), IFIX(0.4903926402),
1921 + IFIX(0.4619397663), IFIX(0.4157348062),
1922 + IFIX(0.3535533906), IFIX(0.2777851165),
1923 + IFIX(0.1913417162), IFIX(0.0975451610)
1924 +};
1925 +
1926 +
1927 +static void idctqtab(qin, qout)
1928 +unsigned char *qin;
1929 +PREC *qout;
1930 +{
1931 + int i, j;
1932 +
1933 + for (i = 0; i < 8; i++)
1934 + for (j = 0; j < 8; j++)
1935 + qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] *
1936 + IMULT(aaidct[i], aaidct[j]);
1937 +}
1938 +
1939 +static void scaleidctqtab(q, sc)
1940 +PREC *q;
1941 +PREC sc;
1942 +{
1943 + int i;
1944 +
1945 + for (i = 0; i < 64; i++)
1946 + q[i] = IMULT(q[i], sc);
1947 +}
1948 +
1949 +/****************************************************************/
1950 +/************** color decoder ***************/
1951 +/****************************************************************/
1952 +
1953 +#define ROUND
1954 +
1955 +/*
1956 + * YCbCr Color transformation:
1957 + *
1958 + * y:0..255 Cb:-128..127 Cr:-128..127
1959 + *
1960 + * R = Y + 1.40200 * Cr
1961 + * G = Y - 0.34414 * Cb - 0.71414 * Cr
1962 + * B = Y + 1.77200 * Cb
1963 + *
1964 + * =>
1965 + * Cr *= 1.40200;
1966 + * Cb *= 1.77200;
1967 + * Cg = 0.19421 * Cb + .50937 * Cr;
1968 + * R = Y + Cr;
1969 + * G = Y - Cg;
1970 + * B = Y + Cb;
1971 + *
1972 + * =>
1973 + * Cg = (50 * Cb + 130 * Cr + 128) >> 8;
1974 + */
1975 +
1976 +static void initcol(q)
1977 +PREC q[][64];
1978 +{
1979 + scaleidctqtab(q[1], IFIX(1.77200));
1980 + scaleidctqtab(q[2], IFIX(1.40200));
1981 +}
1982 +
1983 +/* This is optimized for the stupid sun SUNWspro compiler. */
1984 +#define STORECLAMP(a,x) \
1985 +( \
1986 + (a) = (x), \
1987 + (unsigned int)(x) >= 256 ? \
1988 + ((a) = (x) < 0 ? 0 : 255) \
1989 + : \
1990 + 0 \
1991 +)
1992 +
1993 +#define CLAMP(x) ((unsigned int)(x) >= 256 ? ((x) < 0 ? 0 : 255) : (x))
1994 +
1995 +#ifdef ROUND
1996 +
1997 +#define CBCRCG(yin, xin) \
1998 +( \
1999 + cb = outc[0 +yin*8+xin], \
2000 + cr = outc[64+yin*8+xin], \
2001 + cg = (50 * cb + 130 * cr + 128) >> 8 \
2002 +)
2003 +
2004 +#else
2005 +
2006 +#define CBCRCG(yin, xin) \
2007 +( \
2008 + cb = outc[0 +yin*8+xin], \
2009 + cr = outc[64+yin*8+xin], \
2010 + cg = (3 * cb + 8 * cr) >> 4 \
2011 +)
2012 +
2013 +#endif
2014 +
2015 +#define PIC(yin, xin, p, xout) \
2016 +( \
2017 + y = outy[(yin) * 8 + xin], \
2018 + STORECLAMP(p[(xout) * 3 + 0], y + cr), \
2019 + STORECLAMP(p[(xout) * 3 + 1], y - cg), \
2020 + STORECLAMP(p[(xout) * 3 + 2], y + cb) \
2021 +)
2022 +
2023 +#ifdef __LITTLE_ENDIAN
2024 +#define PIC_16(yin, xin, p, xout, add) \
2025 +( \
2026 + y = outy[(yin) * 8 + xin], \
2027 + y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
2028 + ((CLAMP(y - cg + add ) & 0xfc) << 3) | \
2029 + ((CLAMP(y + cb + add*2+1) ) >> 3), \
2030 + p[(xout) * 2 + 0] = y & 0xff, \
2031 + p[(xout) * 2 + 1] = y >> 8 \
2032 +)
2033 +#else
2034 +#ifdef CONFIG_PPC
2035 +#define PIC_16(yin, xin, p, xout, add) \
2036 +( \
2037 + y = outy[(yin) * 8 + xin], \
2038 + y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 7) | \
2039 + ((CLAMP(y - cg + add*2+1) & 0xf8) << 2) | \
2040 + ((CLAMP(y + cb + add*2+1) ) >> 3), \
2041 + p[(xout) * 2 + 0] = y >> 8, \
2042 + p[(xout) * 2 + 1] = y & 0xff \
2043 +)
2044 +#else
2045 +#define PIC_16(yin, xin, p, xout, add) \
2046 +( \
2047 + y = outy[(yin) * 8 + xin], \
2048 + y = ((CLAMP(y + cr + add*2+1) & 0xf8) << 8) | \
2049 + ((CLAMP(y - cg + add ) & 0xfc) << 3) | \
2050 + ((CLAMP(y + cb + add*2+1) ) >> 3), \
2051 + p[(xout) * 2 + 0] = y >> 8, \
2052 + p[(xout) * 2 + 1] = y & 0xff \
2053 +)
2054 +#endif
2055 +#endif
2056 +
2057 +#define PIC221111(xin) \
2058 +( \
2059 + CBCRCG(0, xin), \
2060 + PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
2061 + PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
2062 + PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
2063 + PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1) \
2064 +)
2065 +
2066 +#define PIC221111_16(xin) \
2067 +( \
2068 + CBCRCG(0, xin), \
2069 + PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0, 3), \
2070 + PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1, 0), \
2071 + PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0, 1), \
2072 + PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1, 2) \
2073 +)
2074 +
2075 +static void col221111(out, pic, width)
2076 +int *out;
2077 +unsigned char *pic;
2078 +int width;
2079 +{
2080 + int i, j, k;
2081 + unsigned char *pic0, *pic1;
2082 + int *outy, *outc;
2083 + int cr, cg, cb, y;
2084 +
2085 + pic0 = pic;
2086 + pic1 = pic + width;
2087 + outy = out;
2088 + outc = out + 64 * 4;
2089 + for (i = 2; i > 0; i--) {
2090 + for (j = 4; j > 0; j--) {
2091 + for (k = 0; k < 8; k++) {
2092 + PIC221111(k);
2093 + }
2094 + outc += 8;
2095 + outy += 16;
2096 + pic0 += 2 * width;
2097 + pic1 += 2 * width;
2098 + }
2099 + outy += 64 * 2 - 16 * 4;
2100 + }
2101 +}
2102 +
2103 +static void col221111_16(out, pic, width)
2104 +int *out;
2105 +unsigned char *pic;
2106 +int width;
2107 +{
2108 + int i, j, k;
2109 + unsigned char *pic0, *pic1;
2110 + int *outy, *outc;
2111 + int cr, cg, cb, y;
2112 +
2113 + pic0 = pic;
2114 + pic1 = pic + width;
2115 + outy = out;
2116 + outc = out + 64 * 4;
2117 + for (i = 2; i > 0; i--) {
2118 + for (j = 4; j > 0; j--) {
2119 + for (k = 0; k < 8; k++) {
2120 + PIC221111_16(k);
2121 + }
2122 + outc += 8;
2123 + outy += 16;
2124 + pic0 += 2 * width;
2125 + pic1 += 2 * width;
2126 + }
2127 + outy += 64 * 2 - 16 * 4;
2128 + }
2129 +}
2130 --- /dev/null
2131 +++ b/drivers/video/bootsplash/decode-jpg.h
2132 @@ -0,0 +1,35 @@
2133 +/*
2134 + * linux/drivers/video/bootsplash/decode-jpg.h - a tiny jpeg decoder.
2135 + *
2136 + * (w) August 2001 by Michael Schroeder, <mls@suse.de>
2137 + */
2138 +
2139 +#ifndef __DECODE_JPG_H
2140 +#define __DECODE_JPG_H
2141 +
2142 +#define ERR_NO_SOI 1
2143 +#define ERR_NOT_8BIT 2
2144 +#define ERR_HEIGHT_MISMATCH 3
2145 +#define ERR_WIDTH_MISMATCH 4
2146 +#define ERR_BAD_WIDTH_OR_HEIGHT 5
2147 +#define ERR_TOO_MANY_COMPPS 6
2148 +#define ERR_ILLEGAL_HV 7
2149 +#define ERR_QUANT_TABLE_SELECTOR 8
2150 +#define ERR_NOT_YCBCR_221111 9
2151 +#define ERR_UNKNOWN_CID_IN_SCAN 10
2152 +#define ERR_NOT_SEQUENTIAL_DCT 11
2153 +#define ERR_WRONG_MARKER 12
2154 +#define ERR_NO_EOI 13
2155 +#define ERR_BAD_TABLES 14
2156 +#define ERR_DEPTH_MISMATCH 15
2157 +
2158 +struct jpeg_decdata {
2159 + int dcts[6 * 64 + 16];
2160 + int out[64 * 6];
2161 + int dquant[3][64];
2162 +};
2163 +
2164 +extern int jpeg_decode(unsigned char *, unsigned char *, int, int, int, struct jpeg_decdata *);
2165 +extern int jpeg_check_size(unsigned char *, int, int);
2166 +
2167 +#endif
2168 --- /dev/null
2169 +++ b/drivers/video/bootsplash/Kconfig
2170 @@ -0,0 +1,17 @@
2171 +#
2172 +# Bootsplash configuration
2173 +#
2174 +
2175 +menu "Bootsplash configuration"
2176 +
2177 +config BOOTSPLASH
2178 + bool "Bootup splash screen"
2179 + depends on FRAMEBUFFER_CONSOLE && FB_VESA
2180 + default n
2181 + ---help---
2182 + This option enables the Linux bootsplash screen. For more
2183 + information on the bootsplash screen have a look at
2184 + http://www.bootsplash.org/.
2185 + If you are unsure, say N
2186 +endmenu
2187 +
2188 --- /dev/null
2189 +++ b/drivers/video/bootsplash/Makefile
2190 @@ -0,0 +1,5 @@
2191 +# Makefile for the Linux bootsplash
2192 +
2193 +obj-$(CONFIG_BOOTSPLASH) += bootsplash.o
2194 +obj-$(CONFIG_BOOTSPLASH) += decode-jpg.o
2195 +obj-$(CONFIG_BOOTSPLASH) += render.o
2196 --- /dev/null
2197 +++ b/drivers/video/bootsplash/render.c
2198 @@ -0,0 +1,328 @@
2199 +/*
2200 + * linux/drivers/video/bootsplash/render.c - splash screen render functions.
2201 + */
2202 +
2203 +#include <linux/module.h>
2204 +#include <linux/types.h>
2205 +#include <linux/fb.h>
2206 +#include <linux/vt_kern.h>
2207 +#include <linux/selection.h>
2208 +#include <asm/irq.h>
2209 +#include <asm/system.h>
2210 +
2211 +#include "../console/fbcon.h"
2212 +#include "bootsplash.h"
2213 +
2214 +void splash_putcs(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
2215 + const unsigned short *s, int count, int ypos, int xpos)
2216 +{
2217 + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
2218 + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
2219 + int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
2220 + u8 *src;
2221 + u8 *dst, *splashsrc;
2222 + unsigned int d, x, y;
2223 + u32 dd, fgx, bgx;
2224 + u16 c = scr_readw(s);
2225 +
2226 + int fg_color, bg_color, transparent;
2227 + if (console_blanked)
2228 + return;
2229 + fg_color = attr_fgcol(fgshift, c);
2230 + bg_color = attr_bgcol(bgshift, c);
2231 + transparent = sd->splash_color == bg_color;
2232 + xpos = xpos * vc->vc_font.width + sd->splash_text_xo;
2233 + ypos = ypos * vc->vc_font.height + sd->splash_text_yo;
2234 + splashsrc = (u8 *)(info->splash_pic + ypos * info->splash_bytes + xpos * 2);
2235 + dst = (u8 *)(info->screen_base + ypos * info->fix.line_length + xpos * 2);
2236 +
2237 + fgx = ((u32 *)info->pseudo_palette)[fg_color];
2238 + if (transparent && sd->splash_color == 15) {
2239 + if (fgx == 0xffea)
2240 + fgx = 0xfe4a;
2241 + else if (fgx == 0x57ea)
2242 + fgx = 0x0540;
2243 + else if (fgx == 0xffff)
2244 + fgx = 0x52aa;
2245 + }
2246 + bgx = ((u32 *)info->pseudo_palette)[bg_color];
2247 + d = 0;
2248 +
2249 + while (count--) {
2250 + c = scr_readw(s++);
2251 + src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * ((vc->vc_font.width + 7) >> 3);
2252 +
2253 + for (y = 0; y < vc->vc_font.height; y++) {
2254 + for (x = 0; x < vc->vc_font.width; x += 2) {
2255 + if ((x & 7) == 0)
2256 + d = *src++;
2257 + if (d & 0x80)
2258 + dd = fgx;
2259 + else
2260 + dd = transparent ? *(u16 *)splashsrc : bgx;
2261 + splashsrc += 2;
2262 + if (d & 0x40)
2263 + dd |= fgx << 16;
2264 + else
2265 + dd |= (transparent ? *(u16 *)splashsrc : bgx) << 16;
2266 + splashsrc += 2;
2267 + d <<= 2;
2268 + fb_writel(dd, dst);
2269 + dst += 4;
2270 + }
2271 + dst += info->fix.line_length - vc->vc_font.width * 2;
2272 + splashsrc += info->splash_bytes - vc->vc_font.width * 2;
2273 + }
2274 + dst -= info->fix.line_length * vc->vc_font.height - vc->vc_font.width * 2;
2275 + splashsrc -= info->splash_bytes * vc->vc_font.height - vc->vc_font.width * 2;
2276 + }
2277 +}
2278 +
2279 +static void splash_renderc(struct splash_data *sd, struct fb_info *info, int fg_color, int bg_color, u8 *src, int ypos, int xpos, int height, int width)
2280 +{
2281 + int transparent = sd->splash_color == bg_color;
2282 + u32 dd, fgx, bgx;
2283 + u8 *dst, *splashsrc;
2284 + unsigned int d, x, y;
2285 +
2286 + if (console_blanked)
2287 + return;
2288 + splashsrc = (u8 *)(info->splash_pic + ypos * info->splash_bytes + xpos * 2);
2289 + dst = (u8 *)(info->screen_base + ypos * info->fix.line_length + xpos * 2);
2290 + fgx = ((u32 *)info->pseudo_palette)[fg_color];
2291 + if (transparent && sd->splash_color == 15) {
2292 + if (fgx == 0xffea)
2293 + fgx = 0xfe4a;
2294 + else if (fgx == 0x57ea)
2295 + fgx = 0x0540;
2296 + else if (fgx == 0xffff)
2297 + fgx = 0x52aa;
2298 + }
2299 + bgx = ((u32 *)info->pseudo_palette)[bg_color];
2300 + d = 0;
2301 + for (y = 0; y < height; y++) {
2302 + for (x = 0; x < width; x += 2) {
2303 + if ((x & 7) == 0)
2304 + d = *src++;
2305 + if (d & 0x80)
2306 + dd = fgx;
2307 + else
2308 + dd = transparent ? *(u16 *)splashsrc : bgx;
2309 + splashsrc += 2;
2310 + if (d & 0x40)
2311 + dd |= fgx << 16;
2312 + else
2313 + dd |= (transparent ? *(u16 *)splashsrc : bgx) << 16;
2314 + splashsrc += 2;
2315 + d <<= 2;
2316 + fb_writel(dd, dst);
2317 + dst += 4;
2318 + }
2319 + dst += info->fix.line_length - width * 2;
2320 + splashsrc += info->splash_bytes - width * 2;
2321 + }
2322 +}
2323 +
2324 +void splash_putc(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
2325 + int c, int ypos, int xpos)
2326 +{
2327 + unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
2328 + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
2329 + int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
2330 + u8 *src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * ((vc->vc_font.width + 7) >> 3);
2331 + xpos = xpos * vc->vc_font.width + sd->splash_text_xo;
2332 + ypos = ypos * vc->vc_font.height + sd->splash_text_yo;
2333 + splash_renderc(sd, info, attr_fgcol(fgshift, c), attr_bgcol(bgshift, c), src, ypos, xpos, vc->vc_font.height, vc->vc_font.width);
2334 +}
2335 +
2336 +void splashcopy(u8 *dst, u8 *src, int height, int width, int dstbytes, int srcbytes)
2337 +{
2338 + int i;
2339 +
2340 + while (height-- > 0) {
2341 + u32 *p = (u32 *)dst;
2342 + u32 *q = (u32 *)src;
2343 + for (i=0; i < width/4; i++) {
2344 + fb_writel(*q++,p++);
2345 + fb_writel(*q++,p++);
2346 + }
2347 + if (width & 2)
2348 + fb_writel(*q++,p++);
2349 + if (width & 1)
2350 + fb_writew(*(u16*)q,(u16*)p);
2351 + dst += dstbytes;
2352 + src += srcbytes;
2353 + }
2354 +}
2355 +
2356 +static void splashset(u8 *dst, int height, int width, int dstbytes, u32 bgx) {
2357 + int i;
2358 +
2359 + bgx |= bgx << 16;
2360 + while (height-- > 0) {
2361 + u32 *p = (u32 *)dst;
2362 + for (i=0; i < width/4; i++) {
2363 + fb_writel(bgx,p++);
2364 + fb_writel(bgx,p++);
2365 + }
2366 + if (width & 2)
2367 + fb_writel(bgx,p++);
2368 + if (width & 1)
2369 + fb_writew(bgx,(u16*)p);
2370 + dst += dstbytes;
2371 + }
2372 +}
2373 +
2374 +static void splashfill(struct fb_info *info, int sy, int sx, int height, int width) {
2375 + splashcopy((u8 *)(info->screen_base + sy * info->fix.line_length + sx * 2), (u8 *)(info->splash_pic + sy * info->splash_bytes + sx * 2), height, width, info->fix.line_length, info->splash_bytes);
2376 +}
2377 +
2378 +void splash_clear(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy,
2379 + int sx, int height, int width)
2380 +{
2381 + int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
2382 + int bg_color = attr_bgcol_ec(bgshift, vc, info);
2383 + int transparent = sd->splash_color == bg_color;
2384 + u32 bgx;
2385 + u8 *dst;
2386 +
2387 + if (console_blanked)
2388 + return;
2389 + sy = sy * vc->vc_font.height + sd->splash_text_yo;
2390 + sx = sx * vc->vc_font.width + sd->splash_text_xo;
2391 + height *= vc->vc_font.height;
2392 + width *= vc->vc_font.width;
2393 + if (transparent) {
2394 + splashfill(info, sy, sx, height, width);
2395 + return;
2396 + }
2397 + dst = (u8 *)(info->screen_base + sy * info->fix.line_length + sx * 2);
2398 + bgx = ((u32 *)info->pseudo_palette)[bg_color];
2399 + splashset(dst, height, width, info->fix.line_length, bgx);
2400 +}
2401 +
2402 +void splash_bmove(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy,
2403 + int sx, int dy, int dx, int height, int width)
2404 +{
2405 + struct fb_copyarea area;
2406 +
2407 + if (console_blanked)
2408 + return;
2409 + area.sx = sx * vc->vc_font.width;
2410 + area.sy = sy * vc->vc_font.height;
2411 + area.dx = dx * vc->vc_font.width;
2412 + area.dy = dy * vc->vc_font.height;
2413 + area.sx += sd->splash_text_xo;
2414 + area.sy += sd->splash_text_yo;
2415 + area.dx += sd->splash_text_xo;
2416 + area.dy += sd->splash_text_yo;
2417 + area.height = height * vc->vc_font.height;
2418 + area.width = width * vc->vc_font.width;
2419 +
2420 + info->fbops->fb_copyarea(info, &area);
2421 +}
2422 +
2423 +void splash_clear_margins(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
2424 + int bottom_only)
2425 +{
2426 + unsigned int tw = vc->vc_cols*vc->vc_font.width;
2427 + unsigned int th = vc->vc_rows*vc->vc_font.height;
2428 +
2429 + if (console_blanked)
2430 + return;
2431 + if (!bottom_only) {
2432 + /* top margin */
2433 + splashfill(info, 0, 0, sd->splash_text_yo, info->var.xres);
2434 + /* left margin */
2435 + splashfill(info, sd->splash_text_yo, 0, th, sd->splash_text_xo);
2436 + /* right margin */
2437 + splashfill(info, sd->splash_text_yo, sd->splash_text_xo + tw, th, info->var.xres - sd->splash_text_xo - tw);
2438 +
2439 + }
2440 + splashfill(info, sd->splash_text_yo + th, 0, info->var.yres - sd->splash_text_yo - th, info->var.xres);
2441 +}
2442 +
2443 +int splash_cursor(struct splash_data *sd, struct fb_info *info, struct fb_cursor *cursor)
2444 +{
2445 + int i;
2446 + unsigned int dsize, s_pitch;
2447 +
2448 + if (info->state != FBINFO_STATE_RUNNING)
2449 + return 0;
2450 +
2451 + s_pitch = (cursor->image.width + 7) >> 3;
2452 + dsize = s_pitch * cursor->image.height;
2453 + if (cursor->enable) {
2454 + switch (cursor->rop) {
2455 + case ROP_XOR:
2456 + for (i = 0; i < dsize; i++)
2457 + info->fb_cursordata[i] = cursor->image.data[i] ^ cursor->mask[i];
2458 + break;
2459 + case ROP_COPY:
2460 + default:
2461 + for (i = 0; i < dsize; i++)
2462 + info->fb_cursordata[i] = cursor->image.data[i] & cursor->mask[i];
2463 + break;
2464 + }
2465 + } else if (info->fb_cursordata != cursor->image.data)
2466 + memcpy(info->fb_cursordata, cursor->image.data, dsize);
2467 + cursor->image.data = info->fb_cursordata;
2468 + splash_renderc(sd, info, cursor->image.fg_color, cursor->image.bg_color, (u8 *)info->fb_cursordata, cursor->image.dy + sd->splash_text_yo, cursor->image.dx + sd->splash_text_xo, cursor->image.height, cursor->image.width);
2469 + return 0;
2470 +}
2471 +
2472 +void splash_bmove_redraw(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width)
2473 +{
2474 + unsigned short *d = (unsigned short *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
2475 + unsigned short *s = d + (dx - sx);
2476 + unsigned short *start = d;
2477 + unsigned short *ls = d;
2478 + unsigned short *le = d + width;
2479 + unsigned short c;
2480 + int x = dx;
2481 + unsigned short attr = 1;
2482 +
2483 + if (console_blanked)
2484 + return;
2485 + do {
2486 + c = scr_readw(d);
2487 + if (attr != (c & 0xff00)) {
2488 + attr = c & 0xff00;
2489 + if (d > start) {
2490 + splash_putcs(sd, vc, info, start, d - start, y, x);
2491 + x += d - start;
2492 + start = d;
2493 + }
2494 + }
2495 + if (s >= ls && s < le && c == scr_readw(s)) {
2496 + if (d > start) {
2497 + splash_putcs(sd, vc, info, start, d - start, y, x);
2498 + x += d - start + 1;
2499 + start = d + 1;
2500 + } else {
2501 + x++;
2502 + start++;
2503 + }
2504 + }
2505 + s++;
2506 + d++;
2507 + } while (d < le);
2508 + if (d > start)
2509 + splash_putcs(sd, vc, info, start, d - start, y, x);
2510 +}
2511 +
2512 +void splash_blank(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int blank)
2513 +{
2514 + if (blank) {
2515 + if (info->silent_screen_base)
2516 + splashset((u8 *)info->silent_screen_base, info->var.yres, info->var.xres, info->fix.line_length, 0);
2517 + splashset((u8 *)info->screen_base, info->var.yres, info->var.xres, info->fix.line_length, 0);
2518 + } else {
2519 + if (info->silent_screen_base)
2520 + splash_prepare(vc, info);
2521 + splash_clear_margins(vc->vc_splash_data, vc, info, 0);
2522 + /* no longer needed, done in fbcon_blank */
2523 + /* update_screen(vc->vc_num); */
2524 + }
2525 +}
2526 +
2527 --- a/drivers/video/console/bitblit.c
2528 +++ b/drivers/video/console/bitblit.c
2529 @@ -17,6 +17,9 @@
2530 #include <linux/console.h>
2531 #include <asm/types.h>
2532 #include "fbcon.h"
2533 +#ifdef CONFIG_BOOTSPLASH
2534 +#include "../bootsplash/bootsplash.h"
2535 +#endif
2536
2537 /*
2538 * Accelerated handlers.
2539 @@ -47,6 +50,13 @@ static void bit_bmove(struct vc_data *vc
2540 {
2541 struct fb_copyarea area;
2542
2543 +#ifdef CONFIG_BOOTSPLASH
2544 + if (info->splash_data) {
2545 + splash_bmove(info->splash_data, vc, info,
2546 + sy, sx, dy, dx, height, width);
2547 + return;
2548 + }
2549 +#endif
2550 area.sx = sx * vc->vc_font.width;
2551 area.sy = sy * vc->vc_font.height;
2552 area.dx = dx * vc->vc_font.width;
2553 @@ -63,6 +73,13 @@ static void bit_clear(struct vc_data *vc
2554 int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
2555 struct fb_fillrect region;
2556
2557 +#ifdef CONFIG_BOOTSPLASH
2558 + if (info->splash_data) {
2559 + splash_clear(info->splash_data, vc, info,
2560 + sy, sx, height, width);
2561 + return;
2562 + }
2563 +#endif
2564 region.color = attr_bgcol_ec(bgshift, vc, info);
2565 region.dx = sx * vc->vc_font.width;
2566 region.dy = sy * vc->vc_font.height;
2567 @@ -160,6 +177,13 @@ static void bit_putcs(struct vc_data *vc
2568 image.height = vc->vc_font.height;
2569 image.depth = 1;
2570
2571 +#ifdef CONFIG_BOOTSPLASH
2572 + if (info->splash_data) {
2573 + splash_putcs(info->splash_data, vc, info, s, count, yy, xx);
2574 + return;
2575 + }
2576 +#endif
2577 +
2578 if (attribute) {
2579 buf = kmalloc(cellsize, GFP_KERNEL);
2580 if (!buf)
2581 @@ -213,6 +237,13 @@ static void bit_clear_margins(struct vc_
2582 unsigned int bs = info->var.yres - bh;
2583 struct fb_fillrect region;
2584
2585 +#ifdef CONFIG_BOOTSPLASH
2586 + if (info->splash_data) {
2587 + splash_clear_margins(info->splash_data, vc, info, bottom_only);
2588 + return;
2589 + }
2590 +#endif
2591 +
2592 region.color = attr_bgcol_ec(bgshift, vc, info);
2593 region.rop = ROP_COPY;
2594
2595 @@ -379,6 +410,14 @@ static void bit_cursor(struct vc_data *v
2596 cursor.image.depth = 1;
2597 cursor.rop = ROP_XOR;
2598
2599 +#ifdef CONFIG_BOOTSPLASH
2600 + if (info->splash_data) {
2601 + splash_cursor(info->splash_data, info, &cursor);
2602 + ops->cursor_reset = 0;
2603 + return;
2604 + }
2605 +#endif
2606 +
2607 if (info->fbops->fb_cursor)
2608 err = info->fbops->fb_cursor(info, &cursor);
2609
2610 --- a/drivers/video/console/fbcon.c
2611 +++ b/drivers/video/console/fbcon.c
2612 @@ -90,6 +90,9 @@
2613 #endif
2614
2615 #include "fbcon.h"
2616 +#ifdef CONFIG_BOOTSPLASH
2617 +#include "../bootsplash/bootsplash.h"
2618 +#endif
2619
2620 #ifdef FBCONDEBUG
2621 # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
2622 @@ -105,7 +108,11 @@ enum {
2623
2624 static struct display fb_display[MAX_NR_CONSOLES];
2625
2626 +#ifdef CONFIG_BOOTSPLASH
2627 +signed char con2fb_map[MAX_NR_CONSOLES];
2628 +#else
2629 static signed char con2fb_map[MAX_NR_CONSOLES];
2630 +#endif
2631 static signed char con2fb_map_boot[MAX_NR_CONSOLES];
2632
2633 static int logo_lines;
2634 @@ -578,6 +585,10 @@ static int fbcon_takeover(int show_logo)
2635 for (i = first_fb_vc; i <= last_fb_vc; i++)
2636 con2fb_map[i] = info_idx;
2637
2638 +#ifdef CONFIG_BOOTSPLASH
2639 + splash_init();
2640 +#endif
2641 +
2642 err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,
2643 fbcon_is_default);
2644
2645 @@ -1180,6 +1191,16 @@ static void fbcon_init(struct vc_data *v
2646 new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
2647 new_cols /= vc->vc_font.width;
2648 new_rows /= vc->vc_font.height;
2649 +
2650 +#ifdef CONFIG_BOOTSPLASH
2651 + if (vc->vc_splash_data && vc->vc_splash_data->splash_state) {
2652 + new_cols = vc->vc_splash_data->splash_text_wi / vc->vc_font.width;
2653 + new_rows = vc->vc_splash_data->splash_text_he / vc->vc_font.height;
2654 + logo = 0;
2655 + con_remap_def_color(vc, vc->vc_splash_data->splash_color << 4 | vc->vc_splash_data->splash_fg_color);
2656 + }
2657 +#endif
2658 +
2659 vc_resize(vc, new_cols, new_rows);
2660
2661 /*
2662 @@ -1875,6 +1896,10 @@ static int fbcon_scroll(struct vc_data *
2663 fbcon_softback_note(vc, t, count);
2664 if (logo_shown >= 0)
2665 goto redraw_up;
2666 +#ifdef CONFIG_BOOTSPLASH
2667 + if (info->splash_data)
2668 + goto redraw_up;
2669 +#endif
2670 switch (p->scrollmode) {
2671 case SCROLL_MOVE:
2672 fbcon_redraw_blit(vc, info, p, t, b - t - count,
2673 @@ -1966,6 +1991,10 @@ static int fbcon_scroll(struct vc_data *
2674 count = vc->vc_rows;
2675 if (logo_shown >= 0)
2676 goto redraw_down;
2677 +#ifdef CONFIG_BOOTSPLASH
2678 + if (info->splash_data)
2679 + goto redraw_down;
2680 +#endif
2681 switch (p->scrollmode) {
2682 case SCROLL_MOVE:
2683 fbcon_redraw_blit(vc, info, p, b - 1, b - t - count,
2684 @@ -2114,6 +2143,14 @@ static void fbcon_bmove_rec(struct vc_da
2685 }
2686 return;
2687 }
2688 +
2689 +#ifdef CONFIG_BOOTSPLASH
2690 + if (info->splash_data && sy == dy && height == 1) {
2691 + /* must use slower redraw bmove to keep background pic intact */
2692 + splash_bmove_redraw(info->splash_data, vc, info, sy, sx, dx, width);
2693 + return;
2694 + }
2695 +#endif
2696 ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
2697 height, width);
2698 }
2699 @@ -2222,6 +2259,10 @@ static int fbcon_switch(struct vc_data *
2700 info = registered_fb[con2fb_map[vc->vc_num]];
2701 ops = info->fbcon_par;
2702
2703 +#ifdef CONFIG_BOOTSPLASH
2704 + splash_prepare(vc, info);
2705 +#endif
2706 +
2707 if (softback_top) {
2708 if (softback_lines)
2709 fbcon_set_origin(vc);
2710 @@ -2349,6 +2390,12 @@ static void fbcon_generic_blank(struct v
2711 {
2712 struct fb_event event;
2713
2714 +#ifdef CONFIG_BOOTSPLASH
2715 + if (info->splash_data) {
2716 + splash_blank(info->splash_data, vc, info, blank);
2717 + return;
2718 + }
2719 +#endif
2720 if (blank) {
2721 unsigned short charmask = vc->vc_hi_font_mask ?
2722 0x1ff : 0xff;
2723 @@ -2553,6 +2600,12 @@ static int fbcon_do_set_font(struct vc_d
2724
2725 cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
2726 rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
2727 +#ifdef CONFIG_BOOTSPLASH
2728 + if (info->splash_data) {
2729 + cols = info->splash_data->splash_text_wi;
2730 + rows = info->splash_data->splash_text_he;
2731 + }
2732 +#endif
2733 cols /= w;
2734 rows /= h;
2735 vc_resize(vc, cols, rows);
2736 --- a/drivers/video/console/fbcon.h
2737 +++ b/drivers/video/console/fbcon.h
2738 @@ -25,6 +25,34 @@
2739 * low-level frame buffer device
2740 */
2741
2742 +#ifdef CONFIG_BOOTSPLASH
2743 +struct splash_data {
2744 + int splash_state; /* show splash? */
2745 + int splash_color; /* transparent color */
2746 + int splash_fg_color; /* foreground color */
2747 + int splash_width; /* width of image */
2748 + int splash_height; /* height of image */
2749 + int splash_text_xo; /* text area origin */
2750 + int splash_text_yo;
2751 + int splash_text_wi; /* text area size */
2752 + int splash_text_he;
2753 + int splash_showtext; /* silent/verbose mode */
2754 + int splash_boxcount;
2755 + int splash_percent;
2756 + int splash_overpaintok; /* is it ok to overpaint boxes */
2757 + int splash_palcnt;
2758 + char *oldscreen_base; /* pointer to top of virtual screen */
2759 + unsigned char *splash_boxes;
2760 + unsigned char *splash_jpeg; /* jpeg */
2761 + unsigned char *splash_palette; /* palette for 8-bit */
2762 +
2763 + int splash_dosilent; /* show silent jpeg */
2764 + unsigned char *splash_silentjpeg;
2765 + unsigned char *splash_sboxes;
2766 + int splash_sboxcount;
2767 +};
2768 +#endif
2769 +
2770 struct display {
2771 /* Filled in by the low-level console driver */
2772 const u_char *fontdata;
2773 --- a/drivers/video/Kconfig
2774 +++ b/drivers/video/Kconfig
2775 @@ -2054,4 +2054,8 @@ if FB || SGI_NEWPORT_CONSOLE
2776 source "drivers/video/logo/Kconfig"
2777 endif
2778
2779 +if FB
2780 + source "drivers/video/bootsplash/Kconfig"
2781 +endif
2782 +
2783 endmenu
2784 --- a/drivers/video/Makefile
2785 +++ b/drivers/video/Makefile
2786 @@ -14,6 +14,7 @@ fb-objs := $(f
2787 obj-$(CONFIG_VT) += console/
2788 obj-$(CONFIG_LOGO) += logo/
2789 obj-y += backlight/ display/
2790 +obj-$(CONFIG_BOOTSPLASH) += bootsplash/
2791
2792 obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
2793 obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
2794 --- a/drivers/video/vesafb.c
2795 +++ b/drivers/video/vesafb.c
2796 @@ -174,7 +174,10 @@ static int vesafb_setcolreg(unsigned reg
2797 return err;
2798 }
2799
2800 -static struct fb_ops vesafb_ops = {
2801 +#ifndef CONFIG_BOOTSPLASH
2802 +static
2803 +#endif
2804 +struct fb_ops vesafb_ops = {
2805 .owner = THIS_MODULE,
2806 .fb_setcolreg = vesafb_setcolreg,
2807 .fb_pan_display = vesafb_pan_display,
2808 @@ -258,6 +261,9 @@ static int __init vesafb_probe(struct pl
2809 * option to simply use size_total as that
2810 * wastes plenty of kernel address space. */
2811 size_remap = size_vmode * 2;
2812 +#ifdef CONFIG_BOOTSPLASH
2813 + size_remap *= 2; /* some more for the images */
2814 +#endif
2815 if (vram_remap)
2816 size_remap = vram_remap * 1024 * 1024;
2817 if (size_remap < size_vmode)
2818 --- a/include/linux/console_struct.h
2819 +++ b/include/linux/console_struct.h
2820 @@ -107,6 +107,9 @@ struct vc_data {
2821 struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */
2822 unsigned long vc_uni_pagedir;
2823 unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
2824 +#ifdef CONFIG_BOOTSPLASH
2825 + struct splash_data *vc_splash_data;
2826 +#endif
2827 /* additional information is in vt_kern.h */
2828 };
2829
2830 --- a/include/linux/fb.h
2831 +++ b/include/linux/fb.h
2832 @@ -849,6 +849,14 @@ struct fb_info {
2833 void *fbcon_par; /* fbcon use-only private area */
2834 /* From here on everything is device dependent */
2835 void *par;
2836 +#ifdef CONFIG_BOOTSPLASH
2837 + struct splash_data *splash_data;
2838 + unsigned char *splash_pic;
2839 + int splash_pic_size;
2840 + int splash_bytes;
2841 + char *silent_screen_base; /* real screen base */
2842 + char fb_cursordata[64];
2843 +#endif
2844 };
2845
2846 #ifdef MODULE
2847 --- a/kernel/panic.c
2848 +++ b/kernel/panic.c
2849 @@ -109,6 +109,12 @@ NORET_TYPE void panic(const char * fmt,
2850 * We can't use the "normal" timers since we just panicked..
2851 */
2852 printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
2853 +#ifdef CONFIG_BOOTSPLASH
2854 + {
2855 + extern int splash_verbose(void);
2856 + (void)splash_verbose();
2857 + }
2858 +#endif
2859 for (i = 0; i < panic_timeout*1000; ) {
2860 touch_nmi_watchdog();
2861 i += panic_blink(i);
2862 @@ -133,6 +139,12 @@ NORET_TYPE void panic(const char * fmt,
2863 disabled_wait(caller);
2864 #endif
2865 local_irq_enable();
2866 +#ifdef CONFIG_BOOTSPLASH
2867 + {
2868 + extern int splash_verbose(void);
2869 + (void)splash_verbose();
2870 + }
2871 +#endif
2872 for (i = 0;;) {
2873 touch_softlockup_watchdog();
2874 i += panic_blink(i);