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