]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.suse/bootsplash
Fix oinkmaster patch.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / bootsplash
CommitLineData
2cb7cef9
BS
1From: mls@suse.de
2Subject: Bootsplash for current kernel
3Patch-mainline: no
4References: none
5
6Better support for other VTs. Don't change percent or silent status
7when installing a new jpeg. Provide splash_set_percent function.
8
9Signed-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 {
82094b55 860+ /* Switch bootsplash off */
2cb7cef9
BS
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+{
82094b55 1416+ datap = buf;
2cb7cef9
BS
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]] *
82094b55 1936+ IMULT(aaidct[i], aaidct[j]);
2cb7cef9
BS
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);