]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/commitdiff
Fehlende Datei für Bootsplash nachgereicht.
authorcasemaster <casemaster@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Sat, 1 Jul 2006 19:50:22 +0000 (19:50 +0000)
committercasemaster <casemaster@ea5c0bd1-69bd-2848-81d8-4f18e57aeed8>
Sat, 1 Jul 2006 19:50:22 +0000 (19:50 +0000)
git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@189 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8

src/patches/bootsplash-3.0.7-2.4.31-vanilla.diff [new file with mode: 0644]

diff --git a/src/patches/bootsplash-3.0.7-2.4.31-vanilla.diff b/src/patches/bootsplash-3.0.7-2.4.31-vanilla.diff
new file mode 100644 (file)
index 0000000..84d7ed3
--- /dev/null
@@ -0,0 +1,2890 @@
+diff -ruN linux-2.4.31/Makefile linux-2.4.31-bs/Makefile
+--- linux-2.4.31/Makefile      2005-04-04 02:42:20.000000000 +0100
++++ linux-2.4.31-bs/Makefile   2005-05-18 12:16:16.000000000 +0100
+@@ -1,7 +1,7 @@
+ VERSION = 2
+ PATCHLEVEL = 4
+ SUBLEVEL = 31
+-EXTRAVERSION =
++EXTRAVERSION =
+ KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+diff -ruN linux-2.4.31/drivers/char/console.c linux-2.4.31-bs/drivers/char/console.c
+--- linux-2.4.31/drivers/char/console.c        2005-01-19 14:09:44.000000000 +0000
++++ linux-2.4.31-bs/drivers/char/console.c     2005-05-05 22:20:15.000000000 +0100
+@@ -3031,6 +3031,32 @@
+       return 0;
+ }
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++void con_remap_def_color(int currcons, int new_color)
++{
++        unsigned short *sbuf = screenbuf;
++        unsigned c, len = screenbuf_size >> 1;
++        int old_color;
++
++        if (sbuf) {
++                old_color = def_color << 8;
++                new_color <<= 8;
++                while(len--) {
++                        c = *sbuf;
++                        if (((c ^ old_color) & 0xf000) == 0)
++                                *sbuf ^= (old_color ^ new_color) & 0xf000;
++                        if (((c ^ old_color) & 0x0f00) == 0)
++                                *sbuf ^= (old_color ^ new_color) & 0x0f00;
++                        sbuf++;
++                }
++                new_color >>= 8;
++        }
++        def_color = color = new_color;
++        update_attr(currcons);
++}
++#endif
++
++
+ /*
+  *    Visible symbols for modules
+  */
+diff -ruN linux-2.4.31/drivers/char/keyboard.c linux-2.4.31-bs/drivers/char/keyboard.c
+--- linux-2.4.31/drivers/char/keyboard.c       2003-11-28 18:26:20.000000000 +0000
++++ linux-2.4.31-bs/drivers/char/keyboard.c    2005-05-05 22:27:48.000000000 +0100
+@@ -263,6 +263,15 @@
+       } else
+               rep = test_and_set_bit(keycode, key_down);
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++        /* This code has to be redone for some non-x86 platforms */
++        if (keycode == 0x3c || keycode == 0x01) {       /* F2 and ESC on a PC keyboard */
++                extern int splash_verbose(void);
++                if (splash_verbose())
++                    goto out;
++        }
++#endif
++
+ #ifdef CONFIG_MAGIC_SYSRQ             /* Handle the SysRq Hack */
+       if (keycode == SYSRQ_KEY) {
+               sysrq_pressed = !up_flag;
+diff -ruN linux-2.4.31/drivers/char/n_tty.c linux-2.4.31-bs/drivers/char/n_tty.c
+--- linux-2.4.31/drivers/char/n_tty.c  2005-01-19 14:09:47.000000000 +0000
++++ linux-2.4.31-bs/drivers/char/n_tty.c       2005-05-05 22:14:50.000000000 +0100
+@@ -45,6 +45,7 @@
+ #include <linux/string.h>
+ #include <linux/slab.h>
+ #include <linux/poll.h>
++#include <linux/config.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+@@ -1184,6 +1185,17 @@
+               return -EIO;
+       }
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++       if (file->f_dentry->d_inode->i_rdev == CONSOLE_DEV ||
++           file->f_dentry->d_inode->i_rdev == SYSCONS_DEV ||
++           file->f_dentry->d_inode->i_rdev == MKDEV(TTYAUX_MAJOR,0) ||
++           file->f_dentry->d_inode->i_rdev == MKDEV(TTY_MAJOR,1)) {
++               extern int splash_verbose(void);
++               (void)splash_verbose();
++       }
++#endif
++
++
+       c = job_control(tty, file);
+       if(c < 0)
+               return c;
+diff -ruN linux-2.4.31/drivers/video/Config.in linux-2.4.31-bs/drivers/video/Config.in
+--- linux-2.4.31/drivers/video/Config.in       2004-02-18 13:36:31.000000000 +0000
++++ linux-2.4.31-bs/drivers/video/Config.in    2005-05-05 22:24:55.000000000 +0100
+@@ -239,13 +239,20 @@
+       tristate '  Virtual Frame Buffer support (ONLY FOR TESTING!) (EXPERIMENTAL)' CONFIG_FB_VIRTUAL
+    fi
++   dep_bool '  Use splash screen instead of boot logo' CONFIG_FBCON_SPLASHSCREEN $CONFIG_BLK_DEV_INITRD
++   if [ "$CONFIG_FBCON_SPLASHSCREEN" = "y" ]; then
++      define_bool CONFIG_FBCON_CFB16 y
++   fi
++
+    bool '  Advanced low level driver options' CONFIG_FBCON_ADVANCED
+    if [ "$CONFIG_FBCON_ADVANCED" = "y" ]; then
+       tristate '    Monochrome support' CONFIG_FBCON_MFB
+       tristate '    2 bpp packed pixels support' CONFIG_FBCON_CFB2
+       tristate '    4 bpp packed pixels support' CONFIG_FBCON_CFB4
+       tristate '    8 bpp packed pixels support' CONFIG_FBCON_CFB8
+-      tristate '    16 bpp packed pixels support' CONFIG_FBCON_CFB16
++      if [ "$CONFIG_FBCON_SPLASHSCREEN" != "y" ]; then
++         tristate '    16 bpp packed pixels support' CONFIG_FBCON_CFB16
++      fi
+       tristate '    24 bpp packed pixels support' CONFIG_FBCON_CFB24
+       tristate '    32 bpp packed pixels support' CONFIG_FBCON_CFB32
+       tristate '    Amiga bitplanes support' CONFIG_FBCON_AFB
+@@ -355,7 +362,9 @@
+          "$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
+          "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \
+          "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" ]; then
+-       define_tristate CONFIG_FBCON_CFB16 y
++        if [ "$CONFIG_FBCON_CFB16" != "m" ]; then
++           define_tristate CONFIG_FBCON_CFB16 y
++        fi
+       else
+        if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
+             "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
+@@ -373,7 +382,9 @@
+             "$CONFIG_FB_INTEL" = "m" -o \
+             "$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" -o \
+             "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_INTEL" = "m" ]; then
+-          define_tristate CONFIG_FBCON_CFB16 m
++            if [ "$CONFIG_FBCON_CFB16" != "y" ]; then
++              define_tristate CONFIG_FBCON_CFB16 m
++           fi
+        fi
+       fi
+       if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
+diff -ruN linux-2.4.31/drivers/video/Makefile linux-2.4.31-bs/drivers/video/Makefile
+--- linux-2.4.31/drivers/video/Makefile        2004-02-18 13:36:31.000000000 +0000
++++ linux-2.4.31-bs/drivers/video/Makefile     2005-05-06 11:28:28.000000000 +0100
+@@ -14,7 +14,7 @@
+                 fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \
+                 fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \
+                 fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \
+-                fbcon-cfb8.o fbcon-mac.o fbcon-mfb.o \
++                fbcon-cfb8.o fbcon-splash16.o fbcon-mac.o fbcon-mfb.o \
+                 cyber2000fb.o sa1100fb.o fbcon-hga.o fbgen.o
+ # Each configuration option enables a list of files.
+@@ -154,6 +154,9 @@
+ obj-$(CONFIG_FBCON_VGA)           += fbcon-vga.o
+ obj-$(CONFIG_FBCON_HGA)           += fbcon-hga.o
+ obj-$(CONFIG_FBCON_STI)           += fbcon-sti.o
++obj-$(CONFIG_FBCON_SPLASHSCREEN)  += fbcon-splash.o
++obj-$(CONFIG_FBCON_SPLASHSCREEN)  += fbcon-splash16.o
++obj-$(CONFIG_FBCON_SPLASHSCREEN)  += fbcon-jpegdec.o
+ include $(TOPDIR)/Rules.make
+diff -ruN linux-2.4.31/drivers/video/fbcon-jpegdec.c linux-2.4.31-bs/drivers/video/fbcon-jpegdec.c
+--- linux-2.4.31/drivers/video/fbcon-jpegdec.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.31-bs/drivers/video/fbcon-jpegdec.c      2005-05-06 11:22:05.000000000 +0100
+@@ -0,0 +1,960 @@
++/* 
++ *    linux/drivers/video/fbcon-jpegdec.c - a tiny jpeg decoder.
++ *      
++ *      (w) August 2001 by Michael Schroeder, <mls@suse.de>
++ *                  
++ */
++
++#include <linux/config.h>
++#include <linux/string.h>
++#include <asm/byteorder.h>
++
++struct display;
++#include "fbcon-splash.h"
++#include "fbcon-jpegdec.h"
++
++#define ISHIFT 11
++
++#define IFIX(a) ((int)((a) * (1 << ISHIFT) + .5))
++#define IMULT(a, b) (((a) * (b)) >> ISHIFT)
++#define ITOINT(a) ((a) >> ISHIFT)
++
++#ifndef __P
++# define __P(x) x
++#endif
++
++/* special markers */
++#define M_BADHUFF     -1
++#define M_EOF         0x80
++
++struct in {
++      unsigned char *p;
++      unsigned int bits;
++      int left;
++      int marker;
++
++      int (*func) __P((void *));
++      void *data;
++};
++
++/*********************************/
++struct dec_hufftbl;
++struct enc_hufftbl;
++
++union hufftblp {
++      struct dec_hufftbl *dhuff;
++      struct enc_hufftbl *ehuff;
++};
++
++struct scan {
++      int dc;                 /* old dc value */
++
++      union hufftblp hudc;
++      union hufftblp huac;
++      int next;               /* when to switch to next scan */
++
++      int cid;                /* component id */
++      int hv;                 /* horiz/vert, copied from comp */
++      int tq;                 /* quant tbl, copied from comp */
++};
++
++/*********************************/
++
++#define DECBITS 10            /* seems to be the optimum */
++
++struct dec_hufftbl {
++      int maxcode[17];
++      int valptr[16];
++      unsigned char vals[256];
++      unsigned int llvals[1 << DECBITS];
++};
++
++static void decode_mcus __P((struct in *, int *, int, struct scan *, int *));
++static int dec_readmarker __P((struct in *));
++static void dec_makehuff __P((struct dec_hufftbl *, int *, unsigned char *));
++
++static void setinput __P((struct in *, unsigned char *));
++/*********************************/
++
++#undef PREC
++#define PREC int
++
++static void idctqtab __P((unsigned char *, PREC *));
++static void idct __P((int *, int *, PREC *, PREC, int));
++static void scaleidctqtab __P((PREC *, PREC));
++
++/*********************************/
++
++static void initcol __P((PREC[][64]));
++
++static void col221111 __P((int *, unsigned char *, int));
++static void col221111_16 __P((int *, unsigned char *, int));
++
++/*********************************/
++
++#define M_SOI 0xd8
++#define M_APP0        0xe0
++#define M_DQT 0xdb
++#define M_SOF0        0xc0
++#define M_DHT   0xc4
++#define M_DRI 0xdd
++#define M_SOS 0xda
++#define M_RST0        0xd0
++#define M_EOI 0xd9
++#define M_COM 0xfe
++
++static unsigned char *datap;
++
++static int getbyte(void)
++{
++      return *datap++;
++}
++
++static int getword(void)
++{
++      int c1, c2;
++      c1 = *datap++;
++      c2 = *datap++;
++      return c1 << 8 | c2;
++}
++
++struct comp {
++      int cid;
++      int hv;
++      int tq;
++};
++
++#define MAXCOMP 4
++struct jpginfo {
++      int nc;                 /* number of components */
++      int ns;                 /* number of scans */
++      int dri;                /* restart interval */
++      int nm;                 /* mcus til next marker */
++      int rm;                 /* next restart marker */
++};
++
++static struct jpginfo info;
++static struct comp comps[MAXCOMP];
++
++static struct scan dscans[MAXCOMP];
++
++static unsigned char quant[4][64];
++
++static struct dec_hufftbl dhuff[4];
++
++#define dec_huffdc (dhuff + 0)
++#define dec_huffac (dhuff + 2)
++
++static struct in in;
++
++static int readtables(int till)
++{
++      int m, l, i, j, lq, pq, tq;
++      int tc, th, tt;
++
++      for (;;) {
++              if (getbyte() != 0xff)
++                      return -1;
++              if ((m = getbyte()) == till)
++                      break;
++
++              switch (m) {
++              case 0xc2:
++                      return 0;
++
++              case M_DQT:
++                      lq = getword();
++                      while (lq > 2) {
++                              pq = getbyte();
++                              tq = pq & 15;
++                              if (tq > 3)
++                                      return -1;
++                              pq >>= 4;
++                              if (pq != 0)
++                                      return -1;
++                              for (i = 0; i < 64; i++)
++                                      quant[tq][i] = getbyte();
++                              lq -= 64 + 1;
++                      }
++                      break;
++
++              case M_DHT:
++                      l = getword();
++                      while (l > 2) {
++                              int hufflen[16], k;
++                              unsigned char huffvals[256];
++
++                              tc = getbyte();
++                              th = tc & 15;
++                              tc >>= 4;
++                              tt = tc * 2 + th;
++                              if (tc > 1 || th > 1)
++                                      return -1;
++                              for (i = 0; i < 16; i++)
++                                      hufflen[i] = getbyte();
++                              l -= 1 + 16;
++                              k = 0;
++                              for (i = 0; i < 16; i++) {
++                                      for (j = 0; j < hufflen[i]; j++)
++                                              huffvals[k++] = getbyte();
++                                      l -= hufflen[i];
++                              }
++                              dec_makehuff(dhuff + tt, hufflen,
++                                           huffvals);
++                      }
++                      break;
++
++              case M_DRI:
++                      l = getword();
++                      info.dri = getword();
++                      break;
++
++              default:
++                      l = getword();
++                      while (l-- > 2)
++                              getbyte();
++                      break;
++              }
++      }
++      return 0;
++}
++
++static void dec_initscans(void)
++{
++      int i;
++
++      info.nm = info.dri + 1;
++      info.rm = M_RST0;
++      for (i = 0; i < info.ns; i++)
++              dscans[i].dc = 0;
++}
++
++static int dec_checkmarker(void)
++{
++      int i;
++
++      if (dec_readmarker(&in) != info.rm)
++              return -1;
++      info.nm = info.dri;
++      info.rm = (info.rm + 1) & ~0x08;
++      for (i = 0; i < info.ns; i++)
++              dscans[i].dc = 0;
++      return 0;
++}
++
++int jpeg_check_size(unsigned char *buf, int width, int height)
++{
++      datap = buf;
++      getbyte(); 
++      getbyte(); 
++      readtables(M_SOF0);
++      getword();
++      getbyte();
++        if (height != getword() || width != getword())
++              return 0;
++        return 1;
++}
++
++int jpeg_decode(buf, pic, width, height, depth, decdata)
++unsigned char *buf, *pic;
++int width, height, depth;
++struct jpeg_decdata *decdata;
++{
++      int i, j, m, tac, tdc;
++      int mcusx, mcusy, mx, my;
++      int max[6];
++
++      if (!decdata)
++              return -1;
++      datap = buf;
++      if (getbyte() != 0xff)
++              return ERR_NO_SOI;
++      if (getbyte() != M_SOI)
++              return ERR_NO_SOI;
++      if (readtables(M_SOF0))
++              return ERR_BAD_TABLES;
++      getword();
++      i = getbyte();
++      if (i != 8)
++              return ERR_NOT_8BIT;
++      if (((getword() + 15) & ~15) != height)
++              return ERR_HEIGHT_MISMATCH;
++      if (((getword() + 15) & ~15) != width)
++              return ERR_WIDTH_MISMATCH;
++      if ((height & 15) || (width & 15))
++              return ERR_BAD_WIDTH_OR_HEIGHT;
++      info.nc = getbyte();
++      if (info.nc > MAXCOMP)
++              return ERR_TOO_MANY_COMPPS;
++      for (i = 0; i < info.nc; i++) {
++              int h, v;
++              comps[i].cid = getbyte();
++              comps[i].hv = getbyte();
++              v = comps[i].hv & 15;
++              h = comps[i].hv >> 4;
++              comps[i].tq = getbyte();
++              if (h > 3 || v > 3)
++                      return ERR_ILLEGAL_HV;
++              if (comps[i].tq > 3)
++                      return ERR_QUANT_TABLE_SELECTOR;
++      }
++      if (readtables(M_SOS))
++              return ERR_BAD_TABLES;
++      getword();
++      info.ns = getbyte();
++      if (info.ns != 3)
++              return ERR_NOT_YCBCR_221111;
++      for (i = 0; i < 3; i++) {
++              dscans[i].cid = getbyte();
++              tdc = getbyte();
++              tac = tdc & 15;
++              tdc >>= 4;
++              if (tdc > 1 || tac > 1)
++                      return ERR_QUANT_TABLE_SELECTOR;
++              for (j = 0; j < info.nc; j++)
++                      if (comps[j].cid == dscans[i].cid)
++                              break;
++              if (j == info.nc)
++                      return ERR_UNKNOWN_CID_IN_SCAN;
++              dscans[i].hv = comps[j].hv;
++              dscans[i].tq = comps[j].tq;
++              dscans[i].hudc.dhuff = dec_huffdc + tdc;
++              dscans[i].huac.dhuff = dec_huffac + tac;
++      }
++      
++      i = getbyte();
++      j = getbyte();
++      m = getbyte();
++      
++      if (i != 0 || j != 63 || m != 0)
++              return ERR_NOT_SEQUENTIAL_DCT;
++      
++      if (dscans[0].cid != 1 || dscans[1].cid != 2 || dscans[2].cid != 3)
++              return ERR_NOT_YCBCR_221111;
++
++      if (dscans[0].hv != 0x22 || dscans[1].hv != 0x11 || dscans[2].hv != 0x11)
++              return ERR_NOT_YCBCR_221111;
++
++      mcusx = width >> 4;
++      mcusy = height >> 4;
++
++
++      idctqtab(quant[dscans[0].tq], decdata->dquant[0]);
++      idctqtab(quant[dscans[1].tq], decdata->dquant[1]);
++      idctqtab(quant[dscans[2].tq], decdata->dquant[2]);
++      initcol(decdata->dquant);
++      setinput(&in, datap);
++
++#if 0
++      /* landing zone */
++      img[len] = 0;
++      img[len + 1] = 0xff;
++      img[len + 2] = M_EOF;
++#endif
++
++      dec_initscans();
++
++      dscans[0].next = 6 - 4;
++      dscans[1].next = 6 - 4 - 1;
++      dscans[2].next = 6 - 4 - 1 - 1; /* 411 encoding */
++      for (my = 0; my < mcusy; my++) {
++              for (mx = 0; mx < mcusx; mx++) {
++                      if (info.dri && !--info.nm)
++                              if (dec_checkmarker())
++                                      return ERR_WRONG_MARKER;
++                      
++                      decode_mcus(&in, decdata->dcts, 6, dscans, max);
++                      idct(decdata->dcts, decdata->out, decdata->dquant[0], IFIX(128.5), max[0]);
++                      idct(decdata->dcts + 64, decdata->out + 64, decdata->dquant[0], IFIX(128.5), max[1]);
++                      idct(decdata->dcts + 128, decdata->out + 128, decdata->dquant[0], IFIX(128.5), max[2]);
++                      idct(decdata->dcts + 192, decdata->out + 192, decdata->dquant[0], IFIX(128.5), max[3]);
++                      idct(decdata->dcts + 256, decdata->out + 256, decdata->dquant[1], IFIX(0.5), max[4]);
++                      idct(decdata->dcts + 320, decdata->out + 320, decdata->dquant[2], IFIX(0.5), max[5]);
++
++                      switch (depth) {
++                      case 24:
++                              col221111(decdata->out, pic + (my * 16 * mcusx + mx) * 16 * 3, mcusx * 16 * 3);
++                              break;
++                      case 16:
++                              col221111_16(decdata->out, pic + (my * 16 * mcusx + mx) * (16 * 2), mcusx * (16 * 2));
++                              break;
++                      default:
++                              return ERR_DEPTH_MISMATCH;
++                              break;
++                      }
++              }
++      }
++      
++      m = dec_readmarker(&in);
++      if (m != M_EOI)
++              return ERR_NO_EOI;
++
++      return 0;
++}
++
++/****************************************************************/
++/**************       huffman decoder             ***************/
++/****************************************************************/
++
++static int fillbits __P((struct in *, int, unsigned int));
++static int dec_rec2
++__P((struct in *, struct dec_hufftbl *, int *, int, int));
++
++static void setinput(in, p)
++struct in *in;
++unsigned char *p;
++{
++      in->p = p;
++      in->left = 0;
++      in->bits = 0;
++      in->marker = 0;
++}
++
++static int fillbits(in, le, bi)
++struct in *in;
++int le;
++unsigned int bi;
++{
++      int b, m;
++
++      if (in->marker) {
++              if (le <= 16)
++                      in->bits = bi << 16, le += 16;
++              return le;
++      }
++      while (le <= 24) {
++              b = *in->p++;
++              if (b == 0xff && (m = *in->p++) != 0) {
++                      if (m == M_EOF) {
++                              if (in->func && (m = in->func(in->data)) == 0)
++                                      continue;
++                      }
++                      in->marker = m;
++                      if (le <= 16)
++                              bi = bi << 16, le += 16;
++                      break;
++              }
++              bi = bi << 8 | b;
++              le += 8;
++      }
++      in->bits = bi;          /* tmp... 2 return values needed */
++      return le;
++}
++
++static int dec_readmarker(in)
++struct in *in;
++{
++      int m;
++
++      in->left = fillbits(in, in->left, in->bits);
++      if ((m = in->marker) == 0)
++              return 0;
++      in->left = 0;
++      in->marker = 0;
++      return m;
++}
++
++#define LEBI_DCL      int le, bi
++#define LEBI_GET(in)  (le = in->left, bi = in->bits)
++#define LEBI_PUT(in)  (in->left = le, in->bits = bi)
++
++#define GETBITS(in, n) (                                      \
++  (le < (n) ? le = fillbits(in, le, bi), bi = in->bits : 0),  \
++  (le -= (n)),                                                        \
++  bi >> le & ((1 << (n)) - 1)                                 \
++)
++
++#define UNGETBITS(in, n) (    \
++  le += (n)                   \
++)
++
++
++static int dec_rec2(in, hu, runp, c, i)
++struct in *in;
++struct dec_hufftbl *hu;
++int *runp;
++int c, i;
++{
++      LEBI_DCL;
++
++      LEBI_GET(in);
++      if (i) {
++              UNGETBITS(in, i & 127);
++              *runp = i >> 8 & 15;
++              i >>= 16;
++      } else {
++              for (i = DECBITS; (c = ((c << 1) | GETBITS(in, 1))) >= (hu->maxcode[i]); i++);
++              if (i >= 16) {
++                      in->marker = M_BADHUFF;
++                      return 0;
++              }
++              i = hu->vals[hu->valptr[i] + c - hu->maxcode[i - 1] * 2];
++              *runp = i >> 4;
++              i &= 15;
++      }
++      if (i == 0) {           /* sigh, 0xf0 is 11 bit */
++              LEBI_PUT(in);
++              return 0;
++      }
++      /* receive part */
++      c = GETBITS(in, i);
++      if (c < (1 << (i - 1)))
++              c += (-1 << i) + 1;
++      LEBI_PUT(in);
++      return c;
++}
++
++#define DEC_REC(in, hu, r, i)  (      \
++  r = GETBITS(in, DECBITS),           \
++  i = hu->llvals[r],                  \
++  i & 128 ?                           \
++    (                                 \
++      UNGETBITS(in, i & 127),         \
++      r = i >> 8 & 15,                        \
++      i >> 16                         \
++    )                                 \
++  :                                   \
++    (                                 \
++      LEBI_PUT(in),                   \
++      i = dec_rec2(in, hu, &r, r, i), \
++      LEBI_GET(in),                   \
++      i                                       \
++    )                                 \
++)
++
++static void decode_mcus(in, dct, n, sc, maxp)
++struct in *in;
++int *dct;
++int n;
++struct scan *sc;
++int *maxp;
++{
++      struct dec_hufftbl *hu;
++      int i, r, t;
++      LEBI_DCL;
++
++      memset(dct, 0, n * 64 * sizeof(*dct));
++      LEBI_GET(in);
++      while (n-- > 0) {
++              hu = sc->hudc.dhuff;
++              *dct++ = (sc->dc += DEC_REC(in, hu, r, t));
++
++              hu = sc->huac.dhuff;
++              i = 63;
++              while (i > 0) {
++                      t = DEC_REC(in, hu, r, t);
++                      if (t == 0 && r == 0) {
++                              dct += i;
++                              break;
++                      }
++                      dct += r;
++                      *dct++ = t;
++                      i -= r + 1;
++              }
++              *maxp++ = 64 - i;
++              if (n == sc->next)
++                      sc++;
++      }
++      LEBI_PUT(in);
++}
++
++static void dec_makehuff(hu, hufflen, huffvals)
++struct dec_hufftbl *hu;
++int *hufflen;
++unsigned char *huffvals;
++{
++      int code, k, i, j, d, x, c, v;
++      for (i = 0; i < (1 << DECBITS); i++)
++              hu->llvals[i] = 0;
++
++/*
++ * llvals layout:
++ *
++ * value v already known, run r, backup u bits:
++ *  vvvvvvvvvvvvvvvv 0000 rrrr 1 uuuuuuu
++ * value unknown, size b bits, run r, backup u bits:
++ *  000000000000bbbb 0000 rrrr 0 uuuuuuu
++ * value and size unknown:
++ *  0000000000000000 0000 0000 0 0000000
++ */
++      code = 0;
++      k = 0;
++      for (i = 0; i < 16; i++, code <<= 1) {  /* sizes */
++              hu->valptr[i] = k;
++              for (j = 0; j < hufflen[i]; j++) {
++                      hu->vals[k] = *huffvals++;
++                      if (i < DECBITS) {
++                              c = code << (DECBITS - 1 - i);
++                              v = hu->vals[k] & 0x0f; /* size */
++                              for (d = 1 << (DECBITS - 1 - i); --d >= 0;) {
++                                      if (v + i < DECBITS) {  /* both fit in table */
++                                              x = d >> (DECBITS - 1 - v -
++                                                        i);
++                                              if (v && x < (1 << (v - 1)))
++                                                      x += (-1 << v) + 1;
++                                              x = x << 16 | (hu-> vals[k] & 0xf0) << 4 |
++                                                      (DECBITS - (i + 1 + v)) | 128;
++                                      } else
++                                              x = v << 16 | (hu-> vals[k] & 0xf0) << 4 |
++                                                      (DECBITS - (i + 1));
++                                      hu->llvals[c | d] = x;
++                              }
++                      }
++                      code++;
++                      k++;
++              }
++              hu->maxcode[i] = code;
++      }
++      hu->maxcode[16] = 0x20000;      /* always terminate decode */
++}
++
++/****************************************************************/
++/**************             idct                  ***************/
++/****************************************************************/
++
++#define ONE ((PREC)IFIX(1.))
++#define S2  ((PREC)IFIX(0.382683432))
++#define C2  ((PREC)IFIX(0.923879532))
++#define C4  ((PREC)IFIX(0.707106781))
++
++#define S22 ((PREC)IFIX(2 * 0.382683432))
++#define C22 ((PREC)IFIX(2 * 0.923879532))
++#define IC4 ((PREC)IFIX(1 / 0.707106781))
++
++#define C3IC1 ((PREC)IFIX(0.847759065))       /* c3/c1 */
++#define C5IC1 ((PREC)IFIX(0.566454497))       /* c5/c1 */
++#define C7IC1 ((PREC)IFIX(0.198912367))       /* c7/c1 */
++
++#define XPP(a,b) (t = a + b, b = a - b, a = t)
++#define XMP(a,b) (t = a - b, b = a + b, a = t)
++#define XPM(a,b) (t = a + b, b = b - a, a = t)
++
++#define ROT(a,b,s,c) (        t = IMULT(a + b, s),    \
++                      a = IMULT(a, c - s) + t,        \
++                      b = IMULT(b, c + s) - t)
++
++#define IDCT          \
++(                     \
++  XPP(t0, t1),                \
++  XMP(t2, t3),                \
++  t2 = IMULT(t2, IC4) - t3,   \
++  XPP(t0, t3),                \
++  XPP(t1, t2),                \
++  XMP(t4, t7),                \
++  XPP(t5, t6),                \
++  XMP(t5, t7),                \
++  t5 = IMULT(t5, IC4),        \
++  ROT(t4, t6, S22, C22),\
++  t6 -= t7,           \
++  t5 -= t6,           \
++  t4 -= t5,           \
++  XPP(t0, t7),                \
++  XPP(t1, t6),                \
++  XPP(t2, t5),                \
++  XPP(t3, t4)         \
++)
++
++static unsigned char zig2[64] = {
++      0, 2, 3, 9, 10, 20, 21, 35,
++      14, 16, 25, 31, 39, 46, 50, 57,
++      5, 7, 12, 18, 23, 33, 37, 48,
++      27, 29, 41, 44, 52, 55, 59, 62,
++      15, 26, 30, 40, 45, 51, 56, 58,
++      1, 4, 8, 11, 19, 22, 34, 36,
++      28, 42, 43, 53, 54, 60, 61, 63,
++      6, 13, 17, 24, 32, 38, 47, 49
++};
++
++void idct(in, out, quant, off, max)
++int *in;
++int *out;
++PREC *quant;
++PREC off;
++int max;
++{
++      PREC t0, t1, t2, t3, t4, t5, t6, t7, t;
++      PREC tmp[64], *tmpp;
++      int i, j;
++      unsigned char *zig2p;
++
++      t0 = off;
++      if (max == 1) {
++              t0 += in[0] * quant[0];
++              for (i = 0; i < 64; i++)
++                      out[i] = ITOINT(t0);
++              return;
++      }
++      zig2p = zig2;
++      tmpp = tmp;
++      for (i = 0; i < 8; i++) {
++              j = *zig2p++;
++              t0 += in[j] * quant[j];
++              j = *zig2p++;
++              t5 = in[j] * quant[j];
++              j = *zig2p++;
++              t2 = in[j] * quant[j];
++              j = *zig2p++;
++              t7 = in[j] * quant[j];
++              j = *zig2p++;
++              t1 = in[j] * quant[j];
++              j = *zig2p++;
++              t4 = in[j] * quant[j];
++              j = *zig2p++;
++              t3 = in[j] * quant[j];
++              j = *zig2p++;
++              t6 = in[j] * quant[j];
++              IDCT;
++              tmpp[0 * 8] = t0;
++              tmpp[1 * 8] = t1;
++              tmpp[2 * 8] = t2;
++              tmpp[3 * 8] = t3;
++              tmpp[4 * 8] = t4;
++              tmpp[5 * 8] = t5;
++              tmpp[6 * 8] = t6;
++              tmpp[7 * 8] = t7;
++              tmpp++;
++              t0 = 0;
++      }
++      for (i = 0; i < 8; i++) {
++              t0 = tmp[8 * i + 0];
++              t1 = tmp[8 * i + 1];
++              t2 = tmp[8 * i + 2];
++              t3 = tmp[8 * i + 3];
++              t4 = tmp[8 * i + 4];
++              t5 = tmp[8 * i + 5];
++              t6 = tmp[8 * i + 6];
++              t7 = tmp[8 * i + 7];
++              IDCT;
++              out[8 * i + 0] = ITOINT(t0);
++              out[8 * i + 1] = ITOINT(t1);
++              out[8 * i + 2] = ITOINT(t2);
++              out[8 * i + 3] = ITOINT(t3);
++              out[8 * i + 4] = ITOINT(t4);
++              out[8 * i + 5] = ITOINT(t5);
++              out[8 * i + 6] = ITOINT(t6);
++              out[8 * i + 7] = ITOINT(t7);
++      }
++}
++
++static unsigned char zig[64] = {
++      0, 1, 5, 6, 14, 15, 27, 28,
++      2, 4, 7, 13, 16, 26, 29, 42,
++      3, 8, 12, 17, 25, 30, 41, 43,
++      9, 11, 18, 24, 31, 40, 44, 53,
++      10, 19, 23, 32, 39, 45, 52, 54,
++      20, 22, 33, 38, 46, 51, 55, 60,
++      21, 34, 37, 47, 50, 56, 59, 61,
++      35, 36, 48, 49, 57, 58, 62, 63
++};
++
++static PREC aaidct[8] = {
++      IFIX(0.3535533906), IFIX(0.4903926402),
++      IFIX(0.4619397663), IFIX(0.4157348062),
++      IFIX(0.3535533906), IFIX(0.2777851165),
++      IFIX(0.1913417162), IFIX(0.0975451610)
++};
++
++
++static void idctqtab(qin, qout)
++unsigned char *qin;
++PREC *qout;
++{
++      int i, j;
++
++      for (i = 0; i < 8; i++)
++              for (j = 0; j < 8; j++)
++                      qout[zig[i * 8 + j]] = qin[zig[i * 8 + j]] * 
++                                              IMULT(aaidct[i], aaidct[j]);
++}
++
++static void scaleidctqtab(q, sc)
++PREC *q;
++PREC sc;
++{
++      int i;
++
++      for (i = 0; i < 64; i++)
++              q[i] = IMULT(q[i], sc);
++}
++
++/****************************************************************/
++/**************          color decoder            ***************/
++/****************************************************************/
++
++#define ROUND
++
++/*
++ * YCbCr Color transformation:
++ *
++ * y:0..255   Cb:-128..127   Cr:-128..127
++ *
++ *      R = Y                + 1.40200 * Cr
++ *      G = Y - 0.34414 * Cb - 0.71414 * Cr
++ *      B = Y + 1.77200 * Cb
++ *
++ * =>
++ *      Cr *= 1.40200;
++ *      Cb *= 1.77200;
++ *      Cg = 0.19421 * Cb + .50937 * Cr;
++ *      R = Y + Cr;
++ *      G = Y - Cg;
++ *      B = Y + Cb;
++ *
++ * =>
++ *      Cg = (50 * Cb + 130 * Cr + 128) >> 8;
++ */
++
++static void initcol(q)
++PREC q[][64];
++{
++      scaleidctqtab(q[1], IFIX(1.77200));
++      scaleidctqtab(q[2], IFIX(1.40200));
++}
++
++/* This is optimized for the stupid sun SUNWspro compiler. */
++#define STORECLAMP(a,x)                               \
++(                                             \
++  (a) = (x),                                  \
++  (unsigned int)(x) >= 256 ?                  \
++    ((a) = (x) < 0 ? 0 : 255)                 \
++  :                                           \
++    0                                         \
++)
++
++#define CLAMP(x) ((unsigned int)(x) >= 256 ? ((x) < 0 ? 0 : 255) : (x))
++
++#ifdef ROUND
++
++#define CBCRCG(yin, xin)                      \
++(                                             \
++  cb = outc[0 +yin*8+xin],                    \
++  cr = outc[64+yin*8+xin],                    \
++  cg = (50 * cb + 130 * cr + 128) >> 8                \
++)
++
++#else
++
++#define CBCRCG(yin, xin)                      \
++(                                             \
++  cb = outc[0 +yin*8+xin],                    \
++  cr = outc[64+yin*8+xin],                    \
++  cg = (3 * cb + 8 * cr) >> 4                 \
++)
++
++#endif
++
++#define PIC(yin, xin, p, xout)                        \
++(                                             \
++  y = outy[(yin) * 8 + xin],                  \
++  STORECLAMP(p[(xout) * 3 + 0], y + cr),      \
++  STORECLAMP(p[(xout) * 3 + 1], y - cg),      \
++  STORECLAMP(p[(xout) * 3 + 2], y + cb)               \
++)
++
++#ifdef __LITTLE_ENDIAN
++#define PIC_16(yin, xin, p, xout, add)                 \
++(                                                \
++  y = outy[(yin) * 8 + xin],                     \
++  y = ((CLAMP(y + cr + add*2+1) & 0xf8) <<  8) | \
++      ((CLAMP(y - cg + add    ) & 0xfc) <<  3) | \
++      ((CLAMP(y + cb + add*2+1)       ) >>  3),  \
++  p[(xout) * 2 + 0] = y & 0xff,                  \
++  p[(xout) * 2 + 1] = y >> 8                     \
++)
++#else
++#ifdef CONFIG_PPC
++#define PIC_16(yin, xin, p, xout, add)                 \
++(                                                \
++  y = outy[(yin) * 8 + xin],                     \
++  y = ((CLAMP(y + cr + add*2+1) & 0xf8) <<  7) | \
++      ((CLAMP(y - cg + add*2+1) & 0xf8) <<  2) | \
++      ((CLAMP(y + cb + add*2+1)       ) >>  3),  \
++  p[(xout) * 2 + 0] = y >> 8,                    \
++  p[(xout) * 2 + 1] = y & 0xff                   \
++)
++#else
++#define PIC_16(yin, xin, p, xout, add)                 \
++(                                                \
++  y = outy[(yin) * 8 + xin],                     \
++  y = ((CLAMP(y + cr + add*2+1) & 0xf8) <<  8) | \
++      ((CLAMP(y - cg + add    ) & 0xfc) <<  3) | \
++      ((CLAMP(y + cb + add*2+1)       ) >>  3),  \
++  p[(xout) * 2 + 0] = y >> 8,                    \
++  p[(xout) * 2 + 1] = y & 0xff                   \
++)
++#endif
++#endif
++
++#define PIC221111(xin)                                                \
++(                                                             \
++  CBCRCG(0, xin),                                             \
++  PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0), \
++  PIC(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1), \
++  PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0), \
++  PIC(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1)  \
++)
++
++#define PIC221111_16(xin)                                               \
++(                                                                     \
++  CBCRCG(0, xin),                                                     \
++  PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0, 3),     \
++  PIC_16(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1, 0),     \
++  PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0, 1),     \
++  PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1, 2)      \
++)
++
++static void col221111(out, pic, width)
++int *out;
++unsigned char *pic;
++int width;
++{
++      int i, j, k;
++      unsigned char *pic0, *pic1;
++      int *outy, *outc;
++      int cr, cg, cb, y;
++
++      pic0 = pic;
++      pic1 = pic + width;
++      outy = out;
++      outc = out + 64 * 4;
++      for (i = 2; i > 0; i--) {
++              for (j = 4; j > 0; j--) {
++                      for (k = 0; k < 8; k++) {
++                              PIC221111(k);
++                      }
++                      outc += 8;
++                      outy += 16;
++                      pic0 += 2 * width;
++                      pic1 += 2 * width;
++              }
++              outy += 64 * 2 - 16 * 4;
++      }
++}
++
++static void col221111_16(out, pic, width)
++int *out;
++unsigned char *pic;
++int width;
++{
++      int i, j, k;
++      unsigned char *pic0, *pic1;
++      int *outy, *outc;
++      int cr, cg, cb, y;
++
++      pic0 = pic;
++      pic1 = pic + width;
++      outy = out;
++      outc = out + 64 * 4;
++      for (i = 2; i > 0; i--) {
++              for (j = 4; j > 0; j--) {
++                      for (k = 0; k < 8; k++) {
++                          PIC221111_16(k);
++                      }
++                      outc += 8;
++                      outy += 16;
++                      pic0 += 2 * width;
++                      pic1 += 2 * width;
++              }
++              outy += 64 * 2 - 16 * 4;
++      }
++}
+diff -ruN linux-2.4.31/drivers/video/fbcon-jpegdec.h linux-2.4.31-bs/drivers/video/fbcon-jpegdec.h
+--- linux-2.4.31/drivers/video/fbcon-jpegdec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.31-bs/drivers/video/fbcon-jpegdec.h      2005-05-06 11:23:55.000000000 +0100
+@@ -0,0 +1,24 @@
++#define ERR_NO_SOI 1
++#define ERR_NOT_8BIT 2
++#define ERR_HEIGHT_MISMATCH 3
++#define ERR_WIDTH_MISMATCH 4
++#define ERR_BAD_WIDTH_OR_HEIGHT 5
++#define ERR_TOO_MANY_COMPPS 6
++#define ERR_ILLEGAL_HV 7
++#define ERR_QUANT_TABLE_SELECTOR 8
++#define ERR_NOT_YCBCR_221111 9
++#define ERR_UNKNOWN_CID_IN_SCAN 10
++#define ERR_NOT_SEQUENTIAL_DCT 11
++#define ERR_WRONG_MARKER 12
++#define ERR_NO_EOI 13
++#define ERR_BAD_TABLES 14
++#define ERR_DEPTH_MISMATCH 15
++
++struct jpeg_decdata {
++      int dcts[6 * 64 + 16];
++      int out[64 * 6];
++      int dquant[3][64];
++};
++
++extern int jpeg_decode(unsigned char *, unsigned char *, int, int, int, struct jpeg_decdata *);
++extern int jpeg_check_size(unsigned char *, int, int);
+diff -ruN linux-2.4.31/drivers/video/fbcon-splash.c linux-2.4.31-bs/drivers/video/fbcon-splash.c
+--- linux-2.4.31/drivers/video/fbcon-splash.c  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.31-bs/drivers/video/fbcon-splash.c       2005-05-06 11:24:52.000000000 +0100
+@@ -0,0 +1,848 @@
++/* 
++ *    linux/drivers/video/fbcon-splash.c - splash screen handling functions.
++ *    
++ *    (w) 2001-2003 by Volker Poplawski, <volker@suse.de>
++ *                Stefan Reinauer, <stepan@suse.de>
++ *                Steffen Winterfeldt, <snwint@suse.de>
++ *                
++ *           Ideas & SuSE screen work by Ken Wimer, <wimer@suse.de>
++ */
++
++#include <linux/version.h>
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/fb.h>
++#include <linux/vt_kern.h>
++#include <linux/vmalloc.h>
++
++#include <asm/irq.h>
++#include <asm/system.h>
++
++#include <video/fbcon.h>
++#include <video/font.h>
++#include <video/fbcon-cfb16.h>  /* for fbcon_cfb16 */
++
++#include "fbcon-splash.h"
++#include "fbcon-jpegdec.h"
++
++#define SPLASH_VERSION "3.0.7-2003/03/10"
++
++#ifdef CONFIG_BLK_DEV_INITRD
++unsigned char signature[] = "BOOTSPL1SPL2SPL3";
++#endif
++
++/* from drivers/char/console.c */
++extern void con_remap_def_color(int currcons, int new_color);
++
++/* from drivers/video/fbcon-splash16.c */
++extern void splashfill(u8 *dest, u8 *src, int width, int height, 
++                      int dest_linesize, int src_linesize);
++
++/* internal control states and data pointers */
++struct splash_data splash_data;
++
++unsigned char *linux_splash;  /* decoded picture */
++int linux_splash_size = 0;
++
++static struct jpeg_decdata *decdata = 0; /* private decoder data */
++
++int splash_bytes;             /* bytes per line in linux_splash */
++int splash_shown = 0;         /* is the splash onscreen? */
++int splash_usesilent = 0;     /* shall we display the silentjpeg */
++int splash_default = 0xf01;
++
++static int splash_status(struct display *p);
++static int splash_recolor(struct display *p);
++static int splash_check_jpeg(unsigned char *jpeg, int width, int height, int depth);
++
++extern struct display_switch fbcon_splash16;
++
++int __init splash_init(char *options)
++{
++      if(!strncmp("silent",options,6)) {
++              printk(KERN_INFO "bootsplash: silent mode.\n");
++              splash_usesilent = 1;
++              /* skip "silent," */
++              if (strlen(options)==6)
++                      return 0;
++              options+=7;
++      }
++      if(!strncmp("verbose",options,7)) {
++              printk(KERN_INFO "bootsplash: verbose mode.\n");
++              splash_usesilent = 0;
++              return 0;
++      }
++              
++      splash_default = simple_strtoul(options, NULL, 0);
++
++      return 0;
++}
++
++__setup("splash=", splash_init);
++
++
++static int splash_hasinter(unsigned char *buf, int num)
++{
++    unsigned char *bufend = buf + num * 12;
++    while(buf < bufend) {
++      if (buf[1] > 127)               /* inter? */
++          return 1;
++      buf += buf[3] > 127 ? 24 : 12;  /* blend? */
++    }
++    return 0;
++}
++
++static int boxextract(unsigned char *buf, unsigned short *dp, unsigned char *cols, int *blendp)
++{
++    dp[0] = buf[0] | buf[1] << 8;
++    dp[1] = buf[2] | buf[3] << 8;
++    dp[2] = buf[4] | buf[5] << 8;
++    dp[3] = buf[6] | buf[7] << 8;
++    *(unsigned int *)(cols + 0) =
++      *(unsigned int *)(cols + 4) =
++      *(unsigned int *)(cols + 8) =
++      *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 8);
++    if (dp[1] > 32767) {
++      dp[1] = ~dp[1];
++      *(unsigned int *)(cols + 4) = *(unsigned int *)(buf + 12);
++      *(unsigned int *)(cols + 8) = *(unsigned int *)(buf + 16);
++      *(unsigned int *)(cols + 12) = *(unsigned int *)(buf + 20);
++      *blendp = 1;
++      return 24;
++    }
++    return 12;
++}
++
++static void boxit(unsigned char *pic, int bytes, unsigned char *buf, int num, int percent, int overpaint)
++{
++    int x, y, i, p, doblend, r, g, b, a, add;
++    unsigned short data1[4];
++    unsigned char cols1[16];
++    unsigned short data2[4];
++    unsigned char cols2[16];
++    unsigned char *bufend;
++    unsigned short *picp;
++
++    if (num == 0)
++      return;
++    bufend = buf + num * 12;
++    while(buf < bufend) {
++      doblend = 0;
++      buf += boxextract(buf, data1, cols1, &doblend);
++      if (data1[0] > 32767)
++          buf += boxextract(buf, data2, cols2, &doblend);
++      if (data1[2] > 32767) {
++          if (overpaint)
++              continue;
++          data1[2] = ~data1[2];
++      }
++      if (data1[3] > 32767) {
++          if (percent == 65536)
++              continue;
++          data1[3] = ~data1[3];
++      }
++      if (data1[0] > 32767) {
++          data1[0] = ~data1[0];
++          for (i = 0; i < 4; i++)
++              data1[i] = (data1[i] * (65536 - percent) + data2[i] * percent) >> 16;
++          for (i = 0; i < 16; i++)
++              cols1[i] = (cols1[i] * (65536 - percent) + cols2[i] * percent) >> 16;
++      }
++      *(unsigned int *)cols2 = *(unsigned int *)cols1;
++      a = cols2[3];
++      if (a == 0 && !doblend)
++          continue;
++      for (y = data1[1]; y <= data1[3]; y++) {
++          if (doblend) {
++              if ((p = data1[3] - data1[1]) != 0)
++                  p = ((y - data1[1]) << 16) / p;
++              for (i = 0; i < 8; i++)
++                  cols2[i + 8] = (cols1[i] * (65536 - p) + cols1[i + 8] * p) >> 16;
++          }
++          add = (data1[0] & 1);
++          add ^= (add ^ y) & 1 ? 1 : 3;               /* 2x2 ordered dithering */
++          picp = (unsigned short *)(pic + data1[0] * 2 + y * bytes);
++          for (x = data1[0]; x <= data1[2]; x++) {
++              if (doblend) {
++                  if ((p = data1[2] - data1[0]) != 0)
++                      p = ((x - data1[0]) << 16) / p;
++                  for (i = 0; i < 4; i++)
++                      cols2[i] = (cols2[i + 8] * (65536 - p) + cols2[i + 12] * p) >> 16;
++                  a = cols2[3];
++              }
++              r = cols2[0];
++              g = cols2[1];
++              b = cols2[2];
++              if (a != 255) {
++                  i = *picp;
++                  r = ((i >> 8 & 0xf8) * (255 - a) + r * a) / 255;
++                  g = ((i >> 3 & 0xfc) * (255 - a) + g * a) / 255;
++                  b = ((i << 3 & 0xf8) * (255 - a) + b * a) / 255;
++              }
++  #define CLAMP(x) ((x) >= 256 ? 255 : (x))
++              i = ((CLAMP(r + add*2+1) & 0xf8) <<  8) |
++                  ((CLAMP(g + add    ) & 0xfc) <<  3) |
++                  ((CLAMP(b + add*2+1)       ) >>  3);
++              *picp++ = i;
++              add ^= 3;
++          }
++      }
++    }
++}
++
++static int splash_check_jpeg(unsigned char *jpeg, int width, int height, int depth)
++{
++    int size, err;
++    unsigned char *mem;
++
++    size = ((width + 15) & ~15) * ((height + 15) & ~15) * (depth >> 3);
++    mem = vmalloc(size);
++    if (!mem) {
++      printk(KERN_INFO "No memory for decoded picture!\n");
++      return -1;
++    }
++    if (!decdata)
++      decdata = vmalloc(sizeof(*decdata));
++    if ((err = jpeg_decode(jpeg, mem, ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata)))
++        printk(KERN_INFO "error %d while decompressing picture.\n",err);
++    vfree(mem);
++    return err ? -1 : 0;
++}
++
++static void splash_free(struct display * p)
++{
++    if (!p->splash_data)
++      return;
++    if (p->splash_data->oldscreen_base)
++          p->screen_base = p->splash_data->oldscreen_base;
++    if (p->splash_data->olddispsw)
++          p->dispsw = p->splash_data->olddispsw;
++    if (p->splash_data->splash_silentjpeg)
++          vfree(p->splash_data->splash_sboxes);
++    vfree(p->splash_data);
++    p->splash_data = 0;
++}
++
++static int splash_mkpenguin(struct splash_data *data, int pxo, int pyo, int pwi, int phe, int pr, int pg, int pb)
++{
++    unsigned char *buf;
++    int i;
++
++    if (pwi ==0 || phe == 0)
++      return 0;
++    buf = (unsigned char *)data + sizeof(*data);
++    pwi += pxo - 1;
++    phe += pyo - 1;
++    *buf++ = pxo;
++    *buf++ = pxo >> 8;
++    *buf++ = pyo;
++    *buf++ = pyo >> 8;
++    *buf++ = pwi;
++    *buf++ = pwi >> 8;
++    *buf++ = phe;
++    *buf++ = phe >> 8;
++    *buf++ = pr;
++    *buf++ = pg;
++    *buf++ = pb;
++    *buf++ = 0;
++    for (i = 0; i < 12; i++, buf++)
++      *buf = buf[-12];
++    buf[-24] ^= 0xff;
++    buf[-23] ^= 0xff;
++    buf[-1] = 0xff;
++    return 2;
++}
++
++int splash_getraw(unsigned char *start, unsigned char *end)
++{
++      unsigned char *ndata;
++      int found = 0;
++      int splash_size = 0;
++      void *splash_start = 0;
++        int unit = 0;
++        int width = 0, height = 0;
++      int silentsize;
++      int boxcount = 0;
++      int sboxcount = 0;
++      int palcnt = 0;
++      struct display *p;
++
++      printk(KERN_INFO "Looking for splash picture...");
++
++      p = &fb_display[0];
++        silentsize = 0;
++
++      for (ndata = start; ndata < end; ndata++) {
++              if (*((unsigned int *)ndata) != *((unsigned int *)signature))
++                      continue;
++              if (*((unsigned int *)(ndata+4))==*((unsigned int *)(signature+4))) {
++                      printk(".");
++                      unit = 0;
++                      p = &fb_display[0];
++                      width = p->var.xres;
++                      height = p->var.yres;
++
++                      splash_size = ndata[16] + (ndata[17] << 8) + (ndata[18] << 16) + (ndata[19] << 24);
++                      if (ndata + 20 + splash_size > end) {
++                              printk(" found, but truncated!\n");
++                              return -1;
++                      }
++                      if (!jpeg_check_size(ndata + 20, width, height)) { 
++                              ndata += 20 - 1 + splash_size;
++                              continue;
++                      }
++                      if (splash_check_jpeg(ndata + 20, width, height, p->var.bits_per_pixel))
++                              return -1;
++                      if (p->splash_data)
++                              splash_free(p);
++                      p->splash_data = vmalloc(sizeof(*p->splash_data) + splash_size + 24);
++                      if (!p->splash_data)
++                              break;
++
++                      p->splash_data->oldscreen_base = 0;
++                      p->splash_data->olddispsw = 0;
++                      p->splash_data->splash_silentjpeg = 0;
++
++                      p->splash_data->splash_text_xo = ndata[ 8] + (ndata[ 9] << 8);
++                      p->splash_data->splash_text_yo = ndata[10] + (ndata[11] << 8);
++                      p->splash_data->splash_text_wi = ndata[12] + (ndata[13] << 8);
++                      p->splash_data->splash_text_he = ndata[14] + (ndata[15] << 8);
++                      /* use 8x16 font... */
++                      p->splash_data->splash_text_xo *= 8;
++                      p->splash_data->splash_text_wi *= 8;
++                      p->splash_data->splash_text_yo *= 16;
++                      p->splash_data->splash_text_he *= 16;
++                      p->splash_data->splash_color = (splash_default >> 8) & 0x0f;
++                      p->splash_data->splash_fg_color = (splash_default >> 4) & 0x0f;
++                      p->splash_data->splash_state = splash_default & 1;
++                      p->splash_data->splash_percent = 0;
++                      p->splash_data->splash_overpaintok = 0;
++                      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);
++                      splash_start = ndata + 20;
++                      found = 1;
++                      break;
++              }
++              if (*((unsigned int *)(ndata + 4)) == *((unsigned int *)(signature+8))) {
++                      printk(".");
++                      unit = ndata[8];
++                      if (unit >= MAX_NR_CONSOLES)
++                          continue;
++                      if (unit)
++                          vc_allocate(unit);
++                      p = &fb_display[unit];
++                      width = fb_display[unit].var.xres;
++                      height = fb_display[unit].var.yres;
++                      splash_size = ndata[12] + (ndata[13] << 8) + (ndata[14] << 16) + (ndata[15] << 24);
++                      if (splash_size == -1) {
++                          printk(" found, updating values.\n");
++                          if (p->splash_data) {
++                              if (ndata[9] != 255)
++                                  p->splash_data->splash_state = ndata[9];
++                              if (ndata[10] != 255)
++                                  p->splash_data->splash_fg_color = ndata[10];
++                              if (ndata[11] != 255)
++                                  p->splash_data->splash_color = ndata[11];
++                          }
++                          return unit;
++                      }
++                      if (splash_size == 0) {
++                              printk(" found, freeing memory.\n");
++                              if (p->splash_data)
++                                      splash_free(p);
++                              return unit;
++                      }
++                      if (ndata + 35 + splash_size > end) {
++                              printk(" found, but truncated!\n");
++                              return -1;
++                      }
++                      if (!jpeg_check_size(ndata + 35, width, height)) {
++                              ndata += 35 - 1 + splash_size;
++                              continue;
++                      }
++                      if (splash_check_jpeg(ndata + 35, width, height, p->var.bits_per_pixel))
++                              return -1;
++                      if (p->splash_data)
++                              splash_free(p);
++                      p->splash_data = vmalloc(sizeof(*p->splash_data) + splash_size + 24);
++                      if (!p->splash_data)
++                              break;
++
++                      p->splash_data->oldscreen_base = 0;
++                      p->splash_data->olddispsw = 0;
++                      p->splash_data->splash_silentjpeg = 0;
++
++                      p->splash_data->splash_state = ndata[9];
++                      p->splash_data->splash_fg_color = ndata[10];
++                      p->splash_data->splash_color = ndata[11];
++                      p->splash_data->splash_text_xo = ndata[16] + (ndata[17] << 8);
++                      p->splash_data->splash_text_yo = ndata[18] + (ndata[19] << 8);
++                      p->splash_data->splash_text_wi = ndata[20] + (ndata[21] << 8);
++                      p->splash_data->splash_text_he = ndata[22] + (ndata[23] << 8);
++                      p->splash_data->splash_percent = 0;
++                      p->splash_data->splash_overpaintok = 0;
++                      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]);
++                      splash_start = ndata + 35;
++                      found = 2;
++                      break;
++              }
++              if (*((unsigned int *)(ndata + 4)) == *((unsigned int *)(signature+12))) {
++                      printk(".");
++                      unit = ndata[8];
++                      if (unit >= MAX_NR_CONSOLES)
++                          continue;
++                      if (unit)
++                          vc_allocate(unit);
++                      p = &fb_display[unit];
++                      width = p->var.xres;
++                      height = p->var.yres;
++                      splash_size = ndata[12] + (ndata[13] << 8) + (ndata[14] << 16) + (ndata[15] << 24);
++                      if (splash_size == -1) {
++                          printk(" found, updating values.\n");
++                          if (p->splash_data) {
++                              if (ndata[9] != 255)
++                                  p->splash_data->splash_state = ndata[9];
++                              if (ndata[10] != 255)
++                                  p->splash_data->splash_fg_color = ndata[10];
++                              if (ndata[11] != 255)
++                                  p->splash_data->splash_color = ndata[11];
++                          }
++                          return unit;
++                      }
++                      if (splash_size == 0) {
++                              printk(" found, freeing memory.\n");
++                              if (p->splash_data)
++                                      splash_free(p);
++                              return unit;
++                      }
++                      boxcount = ndata[24] + (ndata[25] << 8);
++                      palcnt = ndata[37] * 3;
++                      if (ndata + 38 + splash_size > end) {
++                              printk(" found, but truncated!\n");
++                              return -1;
++                      }
++                      if (!jpeg_check_size(ndata + 38 + boxcount * 12 + palcnt, width, height)) {
++                              ndata += 38 - 1 + splash_size;
++                              continue;
++                      }
++                      if (splash_check_jpeg(ndata + 38 + boxcount * 12 + palcnt, width, height, p->var.bits_per_pixel))
++                              return -1;
++                      silentsize = ndata[28] + (ndata[29] << 8) + (ndata[30] << 16) + (ndata[31] << 24);
++                      if (silentsize)
++                          printk(" silenjpeg size %d bytes,", silentsize);
++                      if (silentsize >= splash_size) {
++                              printk(" bigger than splashsize!\n");
++                              return -1;
++                      }
++                      splash_size -= silentsize;
++                      if (!splash_usesilent || !p->fb_info->fbops->fb_get_fix ) {
++                              silentsize = 0;
++                      } else {
++                              struct fb_fix_screeninfo fix;
++                              p->fb_info->fbops->fb_get_fix(&fix, unit, 0);
++                              if (height * 2 * p->next_line > fix.smem_len) {
++                                      printk(" does not fit into framebuffer.\n");
++                                      silentsize = 0;
++                              }
++                      }
++
++                      sboxcount = ndata[32] + (ndata[33] << 8);
++                      if (silentsize) {
++                              char *simage=ndata + 38 + splash_size + 12 * sboxcount;
++                              if (!jpeg_check_size(simage, width, height) ||
++                                  splash_check_jpeg(simage, width, height, p->var.bits_per_pixel)) {
++                                      printk(" error in silent jpeg.\n");
++                                      silentsize = 0;
++                              }
++                      }
++                      if (p->splash_data)
++                              splash_free(p);
++                      p->splash_data = vmalloc(sizeof(*p->splash_data) + splash_size);
++                      if (!p->splash_data)
++                              break;
++                      p->splash_data->oldscreen_base = 0;
++                      p->splash_data->olddispsw = 0;
++                      p->splash_data->splash_silentjpeg = 0;
++                      if (silentsize) {
++                              p->splash_data->splash_silentjpeg = vmalloc(silentsize);
++                              if (p->splash_data->splash_silentjpeg) {
++                                      memcpy(p->splash_data->splash_silentjpeg, ndata + 38 + splash_size, silentsize);
++                                      p->splash_data->splash_sboxes = p->splash_data->splash_silentjpeg;
++                                      p->splash_data->splash_silentjpeg += 12 * sboxcount;
++                                      p->splash_data->splash_sboxcount = sboxcount;
++                              }
++                      }
++                      p->splash_data->splash_state = ndata[9];
++                      p->splash_data->splash_fg_color = ndata[10];
++                      p->splash_data->splash_color = ndata[11];
++                      p->splash_data->splash_overpaintok = ndata[36];
++                      p->splash_data->splash_text_xo = ndata[16] + (ndata[17] << 8);
++                      p->splash_data->splash_text_yo = ndata[18] + (ndata[19] << 8);
++                      p->splash_data->splash_text_wi = ndata[20] + (ndata[21] << 8);
++                      p->splash_data->splash_text_he = ndata[22] + (ndata[23] << 8);
++                      p->splash_data->splash_percent = ndata[34] + (ndata[35] << 8);
++                      p->splash_data->splash_percent += p->splash_data->splash_percent > 32767;
++                      splash_start = ndata + 38;
++                      found = 3;
++                      break;
++              }
++      }
++      
++      if (!found) {
++              printk(" no good signature found.\n");
++              return -1;
++      }
++      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) {
++              splash_free(p);
++              p->splash_data = 0;
++              printk(" found, but has oversized text area!\n");
++              return -1;
++      }
++      if (p->dispsw->setup != fbcon_cfb16.setup) {
++              splash_free(p);
++              p->splash_data = 0;
++              printk(" found, but framebuffer can't handle it!\n");
++              return -1;
++      }
++      printk(" found (%dx%d, %d bytes, v%d).\n", width, height, splash_size, found);
++
++      if (found==1) {
++              printk(KERN_WARNING "bootsplash: Using deprecated v1 header. Updating your splash utility recommended.\n");
++              printk(KERN_INFO    "bootsplash: Find the latest version at ftp.suse.com/pub/people/stepan/bootsplash/\n");
++      }
++
++      /* copy data so that initrd memory can be freed. */
++      memcpy((char *)p->splash_data + sizeof(*p->splash_data) + (found < 3 ? boxcount * 12 : 0), splash_start, splash_size);
++      p->splash_data->splash_boxcount = boxcount;
++      p->splash_data->splash_boxes = (unsigned char *)p->splash_data + sizeof(*p->splash_data);
++      p->splash_data->splash_jpeg = (unsigned char *)p->splash_data + sizeof(*p->splash_data) + boxcount * 12 + palcnt;
++      p->splash_data->splash_palette = (unsigned char *)p->splash_data + sizeof(*p->splash_data) + boxcount * 12;
++      p->splash_data->splash_palcnt = palcnt / 3;
++      p->splash_data->splash_dosilent = p->splash_data->splash_silentjpeg != 0;
++      return unit;
++}
++
++int splash_verbose(void) 
++{
++    struct display *p;
++
++    p = &fb_display[0];
++    if (!p || !p->splash_data || !p->splash_data->splash_state || !p->conp)
++      return 0;
++    if (fg_console != p->conp->vc_num)
++      return 0;
++    if (!p->splash_data->splash_silentjpeg || !p->splash_data->splash_dosilent)
++      return 0;
++    if (!p->splash_data->oldscreen_base)
++      return 0;
++
++    p->splash_data->splash_dosilent = 0;
++
++    splashfill(p->splash_data->oldscreen_base, p->screen_base, p->var.xres, p->var.yres, p->next_line, p->next_line);
++    p->screen_base = p->splash_data->oldscreen_base;
++
++    return 1;
++}
++
++static void splash_off(struct display *p)
++{
++    if (p->splash_data && p->splash_data->oldscreen_base)
++      p->screen_base = p->splash_data->oldscreen_base;
++    if (p->splash_data && p->splash_data->olddispsw)
++      p->dispsw = p->splash_data->olddispsw;
++    splash_shown = 0;
++}
++
++int splash_prepare(struct display *p)
++{
++      int err;
++        int width, height, depth, size, sbytes;
++
++      if (!p->splash_data || !p->splash_data->splash_state) {
++              if (linux_splash)
++                      vfree(linux_splash);
++              if (decdata)
++                      vfree(decdata);
++              linux_splash = 0;
++              decdata = 0;
++              linux_splash_size = 0;
++              splash_off(p);
++              return -1;
++      }
++
++        width = p->var.xres;
++        height = p->var.yres;
++        depth = p->var.bits_per_pixel;
++      if (depth != 16) {      /* Other targets might need fixing */
++              splash_off(p);
++              return -2;
++      }
++
++      sbytes = ((width + 15) & ~15) * (depth >> 3);
++      size = sbytes * ((height + 15) & ~15);
++      if (size != linux_splash_size) {
++              if (linux_splash)
++                      vfree(linux_splash);
++              linux_splash_size = 0;
++              linux_splash = 0;
++              splash_off(p);
++      }
++      if (!linux_splash)
++              linux_splash = vmalloc(size);
++
++      if (!linux_splash) {
++              linux_splash_size = 0;
++              printk(KERN_INFO "Not enough memory for splash screen.\n");
++              splash_off(p);
++              return -3;
++      }
++
++      if (!decdata)
++          decdata = vmalloc(sizeof(*decdata));
++
++      if (!p->splash_data->oldscreen_base)
++              p->splash_data->oldscreen_base = p->screen_base;
++
++      if (p->splash_data->splash_silentjpeg && p->splash_data->splash_dosilent) {
++              printk(KERN_INFO "Got silent jpeg.\n");
++              /* fill area after framebuffer with other jpeg */
++              if ((err = jpeg_decode(p->splash_data->splash_silentjpeg, linux_splash, 
++                       ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) {
++                      printk(KERN_INFO "Error %d while decompressing silent jpeg.\n", err);
++                      p->screen_base = p->splash_data->oldscreen_base;
++                      p->splash_data->splash_dosilent = 0;
++              } else {
++                      if (p->splash_data->splash_sboxcount)
++                              boxit(linux_splash, sbytes, p->splash_data->splash_sboxes, 
++                                      p->splash_data->splash_sboxcount, p->splash_data->splash_percent, 0);
++
++                      splashfill(p->screen_base, linux_splash, p->var.xres, p->var.yres, p->next_line, sbytes);
++                      p->screen_base = p->splash_data->oldscreen_base + p->next_line * p->var.yres;
++              }
++      } else
++              p->screen_base = p->splash_data->oldscreen_base;
++
++      if ((err = jpeg_decode(p->splash_data->splash_jpeg, linux_splash, 
++               ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) {
++              printk(KERN_INFO "Error %d while decompressing splash screen.\n", err);
++              vfree(linux_splash);
++              linux_splash = 0;
++              linux_splash_size = 0;
++              splash_off(p);
++              return -4;
++      }
++      linux_splash_size = size;
++      splash_bytes = sbytes;
++      if (p->splash_data->splash_boxcount)
++              boxit(linux_splash, sbytes, p->splash_data->splash_boxes, p->splash_data->splash_boxcount, p->splash_data->splash_percent, 0);
++      splash_data = *p->splash_data;
++      splash_shown = p->splash_data->splash_state;
++      if (splash_shown) {
++          if (p->dispsw != &fbcon_splash16)
++              p->splash_data->olddispsw = p->dispsw;
++          p->dispsw = &fbcon_splash16;
++      } else
++              splash_off(p);
++      return 0;
++}
++
++
++#ifdef CONFIG_PROC_FS
++#include <linux/proc_fs.h>
++
++struct proc_dir_entry *proc_splash;
++int splash_read_proc(char *buffer, char **start, off_t offset, int size,
++                      int *eof, void *data);
++int splash_write_proc(struct file *file, const char *buffer,
++                      unsigned long count, void *data);
++
++int splash_read_proc(char *buffer, char **start, off_t offset, int size,
++                      int *eof, void *data)
++{
++      int len = 0;
++      
++      off_t begin = 0;
++      struct display *p = &fb_display[0];
++
++      int color = p->splash_data ? p->splash_data->splash_color << 4 |
++                      p->splash_data->splash_fg_color : splash_default >> 4;
++      int status = p->splash_data ? p->splash_data->splash_state & 1 : 0;
++      len += sprintf(buffer + len, "Splash screen v%s (0x%02x, %dx%d%s): %s\n",
++                      SPLASH_VERSION, color, p->var.xres, p->var.yres,
++                      (p->splash_data ?  p->splash_data->splash_dosilent : 0)? ", silent" : "",
++                                      status ? "on" : "off");
++      if (offset >= begin + len)
++              return 0;
++
++      *start = buffer + (begin - offset);
++
++      return (size < begin + len - offset ? size : begin + len - offset);
++}
++
++static int splash_recolor(struct display *p)
++{
++      if (!p->splash_data)
++          return -1;
++      if (!p->splash_data->splash_state)
++          return 0;
++      con_remap_def_color(p->conp->vc_num, p->splash_data->splash_color << 4 | p->splash_data->splash_fg_color);
++      if (fg_console == p->conp->vc_num) {
++              splash_data = *p->splash_data;
++              update_region(fg_console,
++                            p->conp->vc_origin +
++                            p->conp->vc_size_row *
++                            p->conp->vc_top,
++                            p->conp->vc_size_row *
++                            (p->conp->vc_bottom -
++                             p->conp->vc_top) / 2);
++      }
++      return 0;
++}
++
++static int splash_status(struct display *p)
++{
++      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");
++
++      if (fg_console == p->conp->vc_num)
++              splash_prepare(p);
++      if (p->splash_data && p->splash_data->splash_state) {
++              con_remap_def_color(p->conp->vc_num, p->splash_data->splash_color << 4 | p->splash_data->splash_fg_color);
++              /* resize_con also calls con_switch which resets yscroll */
++              vc_resize_con(p->splash_data->splash_text_he / fontheight(p),
++                              p->splash_data->splash_text_wi / fontwidth(p),
++                              p->conp->vc_num);
++              if (fg_console == p->conp->vc_num) {
++                      update_region(fg_console,
++                                    p->conp->vc_origin +
++                                    p->conp->vc_size_row *
++                                    p->conp->vc_top,
++                                    p->conp->vc_size_row *
++                                    (p->conp->vc_bottom -
++                                     p->conp->vc_top) / 2);
++                          fbcon_splash16.clear_margins(p->conp, p, 0);
++              }
++      } else {
++              /* Switch bootsplash off */
++              con_remap_def_color(p->conp->vc_num, 0x07);
++              vc_resize_con(p->var.yres / fontheight(p),
++                            p->var.xres / fontwidth(p),
++                            p->conp->vc_num);
++      }
++      return 0;
++}
++
++int splash_write_proc(struct file *file, const char *buffer,
++                    unsigned long count, void *data)
++{
++        int new, unit;
++      struct display *p;
++      
++      if (!buffer || !splash_default)
++              return count;
++
++      if (!strncmp(buffer, "show", 4) || !strncmp(buffer, "hide", 4)) {
++              int pe;
++
++              p = &fb_display[0];
++              if (buffer[4] == ' ' && buffer[5] == 'p')
++                      pe = 0;
++              else if (buffer[4] == '\n')
++                      pe = 65535;
++              else
++                      pe = simple_strtoul(buffer + 5, NULL, 0);
++              if (pe < 0)
++                      pe = 0;
++              if (pe > 65535)
++                      pe = 65535;
++              if (*buffer == 'h')
++                      pe = 65535 - pe;
++              pe += pe > 32767;
++              if (p->splash_data && p->splash_data->splash_percent != pe) {
++                      p->splash_data->splash_percent = pe;
++                      if (fg_console != p->conp->vc_num || !p->splash_data->splash_state)
++                          return count;
++                      if (!p->splash_data->splash_overpaintok || p->splash_data->splash_percent == 65536) {
++                              if (splash_hasinter(p->splash_data->splash_boxes, p->splash_data->splash_boxcount))
++                                      splash_status(p);
++                              else
++                                      splash_prepare(p);
++                      } else {
++                              if (p->splash_data->splash_silentjpeg && p->splash_data->splash_dosilent && p->splash_data->oldscreen_base)
++                                      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);
++                              boxit(p->screen_base, p->next_line, p->splash_data->splash_boxes, p->splash_data->splash_boxcount, p->splash_data->splash_percent, 1);
++                      }
++              }
++              return count;
++      }
++      if (!strncmp(buffer,"silent\n",7) || !strncmp(buffer,"verbose\n",8)) {
++              p = &fb_display[0];
++              if (p->splash_data && p->splash_data->splash_silentjpeg) {
++                  if (p->splash_data->splash_dosilent != (buffer[0] == 's')) {
++                      p->splash_data->splash_dosilent = buffer[0] == 's';
++                      splash_status(p);
++                  }
++              }
++              return count;
++      }
++      if (!strncmp(buffer,"freesilent\n",11)) {
++              p = &fb_display[0];
++              if (p->splash_data && p->splash_data->splash_silentjpeg) {
++                  printk(KERN_INFO "bootsplash: freeing silent jpeg\n");
++                  p->splash_data->splash_silentjpeg = 0;
++                  vfree(p->splash_data->splash_sboxes);
++                  p->splash_data->splash_sboxes = 0;
++                  p->splash_data->splash_sboxcount = 0;
++                  if (p->splash_data->splash_dosilent)
++                      splash_status(p);
++                  p->splash_data->splash_dosilent = 0;
++              }
++              return count;
++      }
++
++      if (!strncmp(buffer, signature, 7)) {
++          unit = splash_getraw((unsigned char *)buffer, (unsigned char *)buffer + count);
++          if (unit >= 0) {
++              p = &fb_display[unit];
++              splash_status(p);
++          }
++          return count;
++      }
++      p = &fb_display[0];
++      if (!p->splash_data)
++              return count;
++      if (buffer[0] == 't') {
++              p->splash_data->splash_state ^= 1;
++              splash_status(p);
++              return count;
++      }
++      new = simple_strtoul(buffer, NULL, 0);
++      if (new > 1) {
++              /* expert user */
++              p->splash_data->splash_color    = new >> 8 & 0xff;
++              p->splash_data->splash_fg_color = new >> 4 & 0x0f;
++      }
++      if ((new & 1) == p->splash_data->splash_state)
++              splash_recolor(p);
++      else {
++              p->splash_data->splash_state = new & 1;
++              splash_status(p);
++      }
++      return count;
++}
++
++int splash_proc_register(void)
++{
++      if ((proc_splash = create_proc_entry("splash", 0, 0))) {
++              proc_splash->read_proc = splash_read_proc;
++              proc_splash->write_proc = splash_write_proc;
++              return 0;
++      }
++      return 1;
++}
++
++int splash_proc_unregister(void)
++{
++      if (proc_splash)
++              remove_proc_entry("splash", 0);
++      return 0;
++}
++#endif
+diff -ruN linux-2.4.31/drivers/video/fbcon-splash.h linux-2.4.31-bs/drivers/video/fbcon-splash.h
+--- linux-2.4.31/drivers/video/fbcon-splash.h  1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.31-bs/drivers/video/fbcon-splash.h       2005-05-06 11:25:18.000000000 +0100
+@@ -0,0 +1,18 @@
++/* 
++ *    linux/drivers/video/splash.h - splash screen definition.
++ *    
++ *    (w) 2001-2003 by Volker Poplawski, <volker@suse.de>
++ *                Stefan Reinauer, <stepan@suse.de>
++ *                
++ *                
++ *    idea and SuSE screen work by Ken Wimer, <wimer@suse.de>
++ */
++
++extern int splash_getraw(unsigned char *, unsigned char *);
++extern int splash_prepare(struct display *);
++
++extern int splash_shown;              /* is splash shown? */
++extern struct splash_data splash_data;        /* image data, copied over
++                                         from display */
++extern unsigned char *linux_splash;   /* decoded pic data */
++extern int splash_bytes;              /* bytes per line */
+diff -ruN linux-2.4.31/drivers/video/fbcon-splash16.c linux-2.4.31-bs/drivers/video/fbcon-splash16.c
+--- linux-2.4.31/drivers/video/fbcon-splash16.c        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.31-bs/drivers/video/fbcon-splash16.c     2005-05-06 11:24:19.000000000 +0100
+@@ -0,0 +1,488 @@
++/*
++ *  linux/drivers/video/fbcon-splash16.c -- Low level frame buffer operations for 16 bpp
++ *                                          framebuffer operation. Modified to present
++ *                                        boot splash screen. 2002/11/7 stepan@suse.de
++ * 
++ * Based on linux/drivers/video/fbcon-cfb16.c, which is
++ *
++ *    Created 5 Apr 1997 by Geert Uytterhoeven
++ *
++ *  This file is subject to the terms and conditions of the GNU General Public
++ *  License.  See the file COPYING in the main directory of this archive for
++ *  more details.
++ */
++
++#include <linux/module.h>
++#include <linux/config.h>
++#include <linux/tty.h>
++#include <linux/console.h>
++#include <linux/string.h>
++#include <linux/fb.h>
++#include <asm/io.h>
++
++#include <video/fbcon.h>
++#include <video/fbcon-cfb16.h>
++
++#include "fbcon-splash.h"
++
++    /*
++     *  16 bpp packed pixels
++     */
++
++static u32 tab_cfb16[] = {
++#if defined(__BIG_ENDIAN)
++    0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
++#elif defined(__LITTLE_ENDIAN)
++    0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
++#else
++#error FIXME: No endianness??
++#endif
++};
++
++void fbcon_splash16_bmove(struct display *p, int sy, int sx, int dy, int dx,
++                     int height, int width)
++{
++    int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
++    u8 *src, *dst;
++
++    if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) {
++      fb_memmove(p->screen_base + dy * linesize,
++                p->screen_base + sy * linesize,
++                height * linesize);
++      return;
++    }
++    if (fontwidthlog(p)) {
++      sx <<= fontwidthlog(p)+1;
++      dx <<= fontwidthlog(p)+1;
++      width <<= fontwidthlog(p)+1;
++    } else {
++      sx *= fontwidth(p)*2;
++      dx *= fontwidth(p)*2;
++      width *= fontwidth(p)*2;
++    }
++    sx += splash_data.splash_text_xo*2 + splash_data.splash_text_yo * bytes;
++    dx += splash_data.splash_text_xo*2 + splash_data.splash_text_yo * bytes;
++    if (dy < sy || (dy == sy && dx < sx)) {
++      src = p->screen_base + sy * linesize + sx;
++      dst = p->screen_base + dy * linesize + dx;
++      for (rows = height * fontheight(p); rows--;) {
++          fb_memmove(dst, src, width);
++          src += bytes;
++          dst += bytes;
++      }
++    } else {
++      src = p->screen_base + (sy+height) * linesize + sx - bytes;
++      dst = p->screen_base + (dy+height) * linesize + dx - bytes;
++      for (rows = height * fontheight(p); rows--;) {
++          fb_memmove(dst, src, width);
++          src -= bytes;
++          dst -= bytes;
++      }
++    }
++}
++
++static inline void rectfill(u8 *dest, int width, int height, u32 data,
++                          int linesize)
++{
++    int i;
++
++    data |= data<<16;
++
++    while (height-- > 0) {
++      u32 *p = (u32 *)dest;
++      for (i = 0; i < width/4; i++) {
++          fb_writel(data, p++);
++          fb_writel(data, p++);
++      }
++      if (width & 2)
++          fb_writel(data, p++);
++      if (width & 1)
++          fb_writew(data, (u16*)p);
++      dest += linesize;
++    }
++}
++
++void splashfill(u8 *dest, u8 *src, int width, int height,
++                       int dest_linesize, int src_linesize)
++{
++
++    int i;
++
++    while (height-- > 0) {
++      u32 *p = (u32 *)dest;
++      u32 *q = (u32 *)src;
++
++      for (i=0; i < width/4; i++) {
++          fb_writel(*q++,p++);
++          fb_writel(*q++,p++);
++      }
++      if (width & 2)
++          fb_writel(*q++,p++);
++      if (width & 1)
++          fb_writew(*(u16*)q,(u16*)p);
++      dest += dest_linesize;
++      src  += src_linesize;
++    }
++}
++
++void fbcon_splash16_clear(struct vc_data *conp, struct display *p, int sy, int sx,
++                     int height, int width)
++{
++    u8 *dest;
++    int bytes = p->next_line, lines = height * fontheight(p);
++    u32 bgx;
++    int offset, transparent=0;
++
++    dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2;
++
++    bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
++
++    width *= fontwidth(p)/4;
++
++    dest   += splash_data.splash_text_yo * bytes  +
++                splash_data.splash_text_xo * 2;
++
++    transparent = (splash_data.splash_color == attr_bgcol_ec(p, conp));
++    
++    if (transparent) {
++      offset = (sy * fontheight(p) + splash_data.splash_text_yo) * splash_bytes +
++               (sx * fontwidth(p) + splash_data.splash_text_xo) *  2;
++      
++      if ((width * 8 == bytes && splash_bytes == bytes))
++          splashfill(dest,linux_splash + offset, lines * width * 4, 
++                          1, bytes, splash_bytes);
++      else
++          splashfill(dest,linux_splash + offset, width*4, lines,
++                          bytes, splash_bytes);
++    } else {
++       if (width * 8 == bytes)
++          rectfill(dest, lines * width * 4, 1, bgx, bytes);
++       else
++          rectfill(dest, width * 4, lines, bgx, bytes);
++    }
++}
++
++
++/*
++ *  Helper function to read the background from the splashscreen
++ */
++# define SPLASH_BGX(off)                      \
++      if (transparent) {                      \
++          bgx = *(u32*)(splashbgx + (off));   \
++          eorx = fgx ^ bgx;                   \
++      }
++
++
++void fbcon_splash16_putc(struct vc_data *conp, struct display *p, int c, int yy,
++                    int xx)
++{
++    u8 *dest, *cdat, bits;
++    int bytes = p->next_line, rows;
++    u32 eorx, fgx, bgx;
++    int transparent = 0;
++    u8 *splashbgx = 0;
++ 
++    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
++
++    fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
++    bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
++
++    transparent = (splash_data.splash_color == attr_bgcol(p, c));
++    
++    dest += splash_data.splash_text_xo * 2 + splash_data.splash_text_yo * bytes;
++    splashbgx = linux_splash +
++          (yy * fontheight(p) + splash_data.splash_text_yo) * splash_bytes + 
++          (xx * fontwidth(p) + splash_data.splash_text_xo) * 2;
++
++    if (transparent && splash_data.splash_color == 0xf) {
++      if (fgx == 0xffea)
++          fgx = 0xfe4a;
++      else if (fgx == 0x57ea)
++          fgx = 0x0540;
++      else if (fgx == 0xffff)
++          fgx = 0x52aa;
++    }
++
++    fgx |= (fgx << 16);
++    bgx |= (bgx << 16);
++    eorx = fgx ^ bgx;
++
++    switch (fontwidth(p)) {
++    case 4:
++    case 8:
++      cdat = p->fontdata + (c & p->charmask) * fontheight(p);
++      for (rows = fontheight(p); rows--; dest += bytes) {
++          bits = *cdat++;
++          SPLASH_BGX(0);
++          fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest);
++          SPLASH_BGX(4);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4);
++          if (fontwidth(p) == 8) {
++              SPLASH_BGX(8);
++              fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8);
++              SPLASH_BGX(12);
++              fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12);
++          }
++
++          splashbgx += splash_bytes;
++
++      }
++      break;
++    case 12:
++    case 16:
++      cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
++      for (rows = fontheight(p); rows--; dest += bytes) {
++          bits = *cdat++;
++          SPLASH_BGX(0);
++          fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest);
++          SPLASH_BGX(4);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4);
++          SPLASH_BGX(8);
++          fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8);
++          SPLASH_BGX(12);
++          fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12);
++          bits = *cdat++;
++          SPLASH_BGX(16);
++          fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest+16);
++          SPLASH_BGX(20);
++          fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+20);
++          if (fontwidth(p) == 16) {
++              SPLASH_BGX(24);
++              fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+24);
++              SPLASH_BGX(28);
++              fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+28);
++          }
++      }
++      break;
++    }
++}
++
++void fbcon_splash16_putcs(struct vc_data *conp, struct display *p,
++                     const unsigned short *s, int count, int yy, int xx)
++{
++    u8 *cdat, *dest, *dest0;
++    u16 c;
++    int rows, bytes = p->next_line;
++    u32 eorx, fgx, bgx;
++    int transparent = 0;
++    u8 *splashbgx0 = 0, *splashbgx;
++
++    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
++    c = scr_readw(s);
++    fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
++    bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
++
++    transparent = (splash_data.splash_color == attr_bgcol(p, c));
++    
++    dest0 += splash_data.splash_text_xo * 2 + splash_data.splash_text_yo * bytes;
++    splashbgx0 = linux_splash +
++            (yy * fontheight(p) + splash_data.splash_text_yo) * splash_bytes +
++            (xx * fontwidth(p) + splash_data.splash_text_xo) * 2;
++
++    if (transparent && splash_data.splash_color == 0xf) {
++      if (fgx == 0xffea)
++          fgx = 0xfe4a;
++      else if (fgx == 0x57ea)
++          fgx = 0x0540;
++      else if (fgx == 0xffff)
++          fgx = 0x52aa;
++    }
++
++    fgx |= (fgx << 16);
++    bgx |= (bgx << 16);
++    eorx = fgx ^ bgx;
++
++    switch (fontwidth(p)) {
++    case 4:
++    case 8:
++      while (count--) {
++          c = scr_readw(s++) & p->charmask;
++          cdat = p->fontdata + c * fontheight(p);
++
++          splashbgx = splashbgx0;
++
++          for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
++              u8 bits = *cdat++;
++              SPLASH_BGX(0);
++              fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest);
++              SPLASH_BGX(4);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4);
++              if (fontwidth(p) == 8) {
++                  SPLASH_BGX(8);
++                  fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8);
++                  SPLASH_BGX(12);
++                  fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12);
++              }
++              splashbgx += splash_bytes;
++          }
++
++          dest0 += fontwidth(p)*2;
++          splashbgx0 += fontwidth(p) * 2;
++      }
++
++      break;
++    case 12:
++    case 16:
++      while (count--) {
++          c = scr_readw(s++) & p->charmask;
++          cdat = p->fontdata + (c * fontheight(p) << 1);
++
++          splashbgx = splashbgx0;
++
++          for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
++              u8 bits = *cdat++;
++              SPLASH_BGX(0);
++              fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest);
++              SPLASH_BGX(4);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+4);
++              SPLASH_BGX(8);
++              fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+8);
++              SPLASH_BGX(12);
++              fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+12);
++              bits = *cdat++;
++              SPLASH_BGX(16);
++              fb_writel((tab_cfb16[bits >> 6] & eorx) ^ bgx, dest+16);
++              SPLASH_BGX(20);
++              fb_writel((tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx, dest+20);
++              if (fontwidth(p) == 16) {
++                  SPLASH_BGX(24);
++                  fb_writel((tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx, dest+24);
++                  SPLASH_BGX(28);
++                  fb_writel((tab_cfb16[bits & 3] & eorx) ^ bgx, dest+28);
++              }
++              splashbgx += splash_bytes;
++          }
++
++          dest0 += fontwidth(p)*2;
++          splashbgx0 += fontwidth(p) * 2;
++      }
++
++      break;
++    }
++}
++
++void fbcon_splash16_revc(struct display *p, int xx, int yy)
++{
++    u8 *dest;
++    int bytes = p->next_line, rows;
++
++    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
++    dest += splash_data.splash_text_yo * bytes + splash_data.splash_text_xo * 2;
++
++    for (rows = fontheight(p); rows--; dest += bytes) {
++      switch (fontwidth(p)) {
++      case 16:
++          fb_writel(fb_readl(dest+24) ^ 0xffffffff, dest+24);
++          fb_writel(fb_readl(dest+28) ^ 0xffffffff, dest+28);
++          /* FALL THROUGH */
++      case 12:
++          fb_writel(fb_readl(dest+16) ^ 0xffffffff, dest+16);
++          fb_writel(fb_readl(dest+20) ^ 0xffffffff, dest+20);
++          /* FALL THROUGH */
++      case 8:
++          fb_writel(fb_readl(dest+8) ^ 0xffffffff, dest+8);
++          fb_writel(fb_readl(dest+12) ^ 0xffffffff, dest+12);
++          /* FALL THROUGH */
++      case 4:
++          fb_writel(fb_readl(dest+0) ^ 0xffffffff, dest+0);
++          fb_writel(fb_readl(dest+4) ^ 0xffffffff, dest+4);
++      }
++    }
++}
++
++void fbcon_splash16_clear_margins(struct vc_data *conp, struct display *p,
++                             int bottom_only)
++{
++    int bytes = p->next_line;
++    u32 bgx;
++
++    unsigned int right_start = conp->vc_cols*fontwidth(p);
++    unsigned int bottom_start = conp->vc_rows*fontheight(p);
++    unsigned int right_width, bottom_width;
++
++    int left_margin_width = splash_data.splash_text_xo;
++    int text_width = conp->vc_cols * fontwidth(p);
++    int right_margin_width = p->var.xres - text_width - left_margin_width;
++    int top_margin_height = splash_data.splash_text_yo;
++    int text_height = conp->vc_rows * fontheight(p);
++    int bottom_margin_height = p->var.yres - text_height - top_margin_height;
++ 
++    bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
++
++    if (bottom_only == -1) {
++      printk(KERN_DEBUG "Called with bottom-only\n");
++      splashfill(p->screen_base, linux_splash, p->var.xres, p->var.yres, bytes, splash_bytes); 
++      return;
++    }
++
++    if (!bottom_only && (right_width = p->var.xres-right_start)) {
++      /* left margin */
++      splashfill(p->screen_base + top_margin_height * bytes,
++                 linux_splash + top_margin_height * 
++                 splash_bytes, left_margin_width,
++                 text_height, bytes, splash_bytes);
++
++      /* right margin */
++      splashfill(p->screen_base + left_margin_width*2 + text_width*2 +
++                  top_margin_height * bytes, linux_splash +
++                  left_margin_width*2 + text_width*2 + top_margin_height *
++                  splash_bytes, right_margin_width, text_height,
++                  bytes, splash_bytes);
++    }
++
++    if ((bottom_width = p->var.yres-bottom_start))
++      /* bottom margin */
++      splashfill(p->screen_base + (top_margin_height + text_height) *
++                  bytes, linux_splash + (top_margin_height +
++                  text_height) * splash_bytes, p->var.xres, 
++                  bottom_margin_height, bytes, splash_bytes);
++
++    /* top margin */
++    splashfill(p->screen_base, linux_splash,
++          p->var.xres, top_margin_height,
++          bytes, splash_bytes);
++
++    /* leave function if work is done */
++    return;
++}
++
++
++    /*
++     *  `switch' for the low level operations
++     */
++
++struct display_switch fbcon_splash16 = {
++    bmove:            fbcon_splash16_bmove,
++    clear:            fbcon_splash16_clear,
++    putc:             fbcon_splash16_putc,
++    putcs:            fbcon_splash16_putcs,
++    revc:             fbcon_splash16_revc,
++    clear_margins:    fbcon_splash16_clear_margins,
++    fontwidthmask:    FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
++};
++
++
++#ifdef MODULE
++MODULE_LICENSE("GPL");
++
++int init_module(void)
++{
++    return 0;
++}
++
++void cleanup_module(void)
++{}
++#endif /* MODULE */
++
++
++    /*
++     *  Visible symbols for modules
++     */
++
++EXPORT_SYMBOL(fbcon_splash16);
++EXPORT_SYMBOL(fbcon_splash16_bmove);
++EXPORT_SYMBOL(fbcon_splash16_clear);
++EXPORT_SYMBOL(fbcon_splash16_putc);
++EXPORT_SYMBOL(fbcon_splash16_putcs);
++EXPORT_SYMBOL(fbcon_splash16_revc);
++EXPORT_SYMBOL(fbcon_splash16_clear_margins);
+diff -ruN linux-2.4.31/drivers/video/fbcon.c linux-2.4.31-bs/drivers/video/fbcon.c
+--- linux-2.4.31/drivers/video/fbcon.c 2004-11-17 11:54:21.000000000 +0000
++++ linux-2.4.31-bs/drivers/video/fbcon.c      2005-05-06 11:21:29.000000000 +0100
+@@ -76,6 +76,7 @@
+ #include <linux/smp.h>
+ #include <linux/init.h>
+ #include <linux/pm.h>
++#include <linux/vmalloc.h>
+ #include <asm/irq.h>
+ #include <asm/system.h>
+@@ -104,6 +105,23 @@
+ #include <video/fbcon-mac.h>  /* for 6x11 font on mac */
+ #include <video/font.h>
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++#include <video/fbcon-cfb16.h> /* for fbcon_cfb16 */
++#include "fbcon-splash.h"
++
++extern void con_remap_def_color(int currcons, int new_color);
++
++extern int splash_default;
++extern int splash_shown;
++
++extern struct display_switch fbcon_splash16;
++
++#ifdef CONFIG_PROC_FS
++int splash_proc_register(void);
++int splash_proc_unregister(void);
++#endif
++#endif
++
+ #ifdef FBCONDEBUG
+ #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+ #else
+@@ -478,6 +496,10 @@
+ }
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++static int splash_registered=0;
++#endif
++
+ static void fbcon_init(struct vc_data *conp, int init)
+ {
+     int unit = conp->vc_num;
+@@ -501,6 +523,26 @@
+     fb_display[unit].cmap.green = 0;
+     fb_display[unit].cmap.blue = 0;
+     fb_display[unit].cmap.transp = 0;
++
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    if (!splash_registered && fb_display[unit].var.bits_per_pixel == 16 ) {
++       if (unit == 0 && !fb_display[unit].splash_data) {
++           extern unsigned long initrd_start, initrd_end;
++
++           if (initrd_start && !splash_getraw((unsigned char *)initrd_start, (unsigned char *)initrd_end) && fb_display[unit].splash_data)
++               fb_display[unit].splash_data->splash_state = splash_default & 1;
++       }
++       splash_registered = 1;
++#ifdef CONFIG_PROC_FS
++       splash_proc_register();
++#endif
++    }
++    if (fb_display[unit].splash_data && fb_display[unit].var.bits_per_pixel != 16 ) {
++       vfree(fb_display[unit].splash_data);
++       fb_display[unit].splash_data = 0;
++    }
++#endif
++
+     fbcon_setup(unit, init, !init);
+     /* Must be done after fbcon_setup to prevent excess updates */
+     conp->vc_display_fg = &info->display_fg;
+@@ -517,6 +559,15 @@
+     fbcon_free_font(p);
+     p->dispsw = &fbcon_dummy;
+     p->conp = 0;
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    if (splash_registered) {
++#ifdef CONFIG_PROC_FS
++        splash_proc_unregister();
++#endif
++       splash_registered = 0;
++    }
++#endif
++
+ }
+@@ -658,6 +709,14 @@
+     nr_cols = p->var.xres/fontwidth(p);
+     nr_rows = p->var.yres/fontheight(p);
+     
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    if (p->splash_data && p->splash_data->splash_state) {
++       nr_cols = p->splash_data->splash_text_wi / fontwidth(p);
++       nr_rows = p->splash_data->splash_text_he / fontheight(p);
++       logo = 0;
++    }
++#endif
++
+     if (logo) {
+       /* Need to make room for the logo */
+       int cnt, step, erase_char;
+@@ -735,6 +794,12 @@
+     p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1;
+     p->bgcol = 0;
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    if(p->splash_data && p->splash_data->splash_state)
++       con_remap_def_color(con, p->splash_data->splash_color << 4 | p->splash_data->splash_fg_color);
++#endif
++
++
+     if (!init) {
+       if (conp->vc_cols != nr_cols || conp->vc_rows != nr_rows)
+           vc_resize_con(nr_rows, nr_cols, con);
+@@ -1324,6 +1389,9 @@
+           if (softback_top)
+               fbcon_softback_note(conp, t, count);
+           if (logo_shown >= 0) goto redraw_up;
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++           if (splash_shown) goto redraw_up;
++#endif
+           switch (p->scrollmode & __SCROLL_YMASK) {
+           case __SCROLL_YMOVE:
+               p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
+@@ -1384,6 +1452,9 @@
+       case SM_DOWN:
+           if (count > conp->vc_rows)  /* Maximum realistic size */
+               count = conp->vc_rows;
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++           if (splash_shown) goto redraw_down;
++#endif
+           switch (p->scrollmode & __SCROLL_YMASK) {
+           case __SCROLL_YMOVE:
+               p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count,
+@@ -1500,6 +1571,13 @@
+       }
+       return;
+     }
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    if (splash_shown && sy == dy) {
++       /* must use slower redraw bmove to keep background pic intact */
++       fbcon_redraw_bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width);
++       return;
++    }
++#endif
+     p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width);
+ }
+@@ -1510,6 +1588,10 @@
+     struct display *p = &fb_display[unit];
+     struct fb_info *info = p->fb_info;
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    splash_prepare(p);
++#endif
++
+     if (softback_top) {
+       int l = fbcon_softback_size / conp->vc_size_row;
+       if (softback_lines)
+@@ -1570,13 +1652,40 @@
+     struct display *p = &fb_display[conp->vc_num];
+     struct fb_info *info = p->fb_info;
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    struct display_switch *olddispsw=NULL;
++    char    *oldscreen_base=NULL;
++#endif
++
+     if (blank < 0)    /* Entering graphics mode */
+       return 0;
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++
++    if (p->splash_data && p->splash_data->oldscreen_base) {
++       oldscreen_base = p->screen_base;
++        p->screen_base = p->splash_data->oldscreen_base;
++    }
++    if (p->splash_data && p->splash_data->olddispsw) {
++        olddispsw = p->dispsw;
++        p->dispsw = p->splash_data->olddispsw;
++    }
++#endif
++
+     fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW);
+     if (!p->can_soft_blank) {
+       if (blank) {
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++           if (p->splash_data && p->splash_data->oldscreen_base) {
++               oldscreen_base = p->screen_base;
++               p->screen_base = p->splash_data->oldscreen_base;
++           }
++           if (p->splash_data && p->splash_data->olddispsw) {
++               olddispsw = p->dispsw;
++               p->dispsw = p->splash_data->olddispsw;
++           }
++#endif
+           if (p->visual == FB_VISUAL_MONO01) {
+               if (p->screen_base)
+                   fb_memset255(p->screen_base,
+@@ -1584,20 +1693,33 @@
+                                p->var.bits_per_pixel>>3);
+           } else {
+               unsigned short oldc;
+-              u_int height;
++              u_int height, width;
+               u_int y_break;
+               oldc = conp->vc_video_erase_char;
+               conp->vc_video_erase_char &= p->charmask;
+               height = conp->vc_rows;
++                width  = conp->vc_cols;
+               y_break = p->vrows-p->yscroll;
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++               if (splash_shown) {
++                       width=p->var.xres/fontwidth(p);
++                       height=p->var.yres/fontheight(p);
++               }
++#endif
+               if (height > y_break) {
+-                      p->dispsw->clear(conp, p, real_y(p, 0), 0, y_break, conp->vc_cols);
+-                      p->dispsw->clear(conp, p, real_y(p, y_break), 0, height-y_break, conp->vc_cols);
++                       p->dispsw->clear(conp, p, real_y(p, 0), 0, y_break, width);
++                       p->dispsw->clear(conp, p, real_y(p, y_break), 0, height-y_break, width);
+               } else
+-                      p->dispsw->clear(conp, p, real_y(p, 0), 0, height, conp->vc_cols);
++                      p->dispsw->clear(conp, p, real_y(p, 0), 0, height, width);
+               conp->vc_video_erase_char = oldc;
+           }
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++           if(oldscreen_base)
++               p->screen_base=oldscreen_base;
++           if(olddispsw)
++               p->dispsw=olddispsw;
++#endif
+           return 0;
+       } else {
+           /* Tell console.c that it has to restore the screen itself */
+@@ -1763,13 +1885,21 @@
+     if (resize) {
+       struct vc_data *conp = p->conp;
++        __u32 xres = p->var.xres, yres = p->var.yres;
++
+       /* reset wrap/pan */
+       p->var.xoffset = p->var.yoffset = p->yscroll = 0;
+       p->vrows = p->var.yres_virtual/h;
+-      if ((p->var.yres % h) && (p->var.yres_virtual % h < p->var.yres % h))
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++       if (p->splash_data && p->splash_data->splash_state) {
++           xres = p->splash_data->splash_text_wi;
++           yres = p->splash_data->splash_text_he;
++        }
++#endif
++       if ((yres % h) && (p->var.yres_virtual % h < p->var.yres % h))
+           p->vrows--;
+       updatescrollmode(p);
+-      vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
++      vc_resize_con( yres/h, xres/w, unit );
+         if (CON_IS_VISIBLE(conp) && softback_buf) {
+           int l = fbcon_softback_size / conp->vc_size_row;
+           if (l > 5)
+@@ -2193,6 +2323,9 @@
+     if (p->fb_info->fbops->fb_rasterimg)
+       p->fb_info->fbops->fb_rasterimg(p->fb_info, 1);
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    if (!splash_shown) {
++#endif
+     for (x = 0; x < smp_num_cpus * (LOGO_W + 8) &&
+        x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
+        
+@@ -2454,7 +2587,9 @@
+       }
+ #endif                        
+     }
+-    
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    }
++#endif
+     if (p->fb_info->fbops->fb_rasterimg)
+       p->fb_info->fbops->fb_rasterimg(p->fb_info, 0);
+diff -ruN linux-2.4.31/include/video/fbcon.h linux-2.4.31-bs/include/video/fbcon.h
+--- linux-2.4.31/include/video/fbcon.h 2003-08-25 12:44:44.000000000 +0100
++++ linux-2.4.31-bs/include/video/fbcon.h      2005-05-18 11:02:36.000000000 +0100
+@@ -42,6 +42,35 @@
+     unsigned int fontwidthmask;      /* 1 at (1 << (width - 1)) if width is supported */
+ }; 
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++struct splash_data {
++       int     splash_state;                   /* show splash? */
++       int     splash_color;                   /* transparent color */
++       int     splash_fg_color;                /* foreground color */
++       int     splash_width;                   /* width of image */
++       int     splash_height;                  /* height of image */
++       int     splash_text_xo;                 /* text area origin */
++       int     splash_text_yo;
++       int     splash_text_wi;                 /* text area size */
++       int     splash_text_he;
++       int     splash_showtext;                /* silent/verbose mode */
++       int     splash_boxcount;
++       int     splash_percent;
++       int     splash_overpaintok;             /* is it ok to overpaint boxes */
++       int     splash_palcnt;
++       struct display_switch *olddispsw;       /* old dispsw, normally &fbcon_cfb16*/
++       char    *oldscreen_base;                /* pointer to top of virtual screen */
++       unsigned char *splash_boxes;
++       unsigned char *splash_jpeg;             /* jpeg */
++       unsigned char *splash_palette;          /* palette for 8-bit */
++
++       int     splash_dosilent;                /* show silent jpeg */
++       unsigned char *splash_silentjpeg;
++       unsigned char *splash_sboxes;
++       int     splash_sboxcount;
++};
++#endif
++
+ extern struct display_switch fbcon_dummy;
+    /*
+@@ -95,6 +124,11 @@
+     short yscroll;                  /* Hardware scrolling */
+     unsigned char fgshift, bgshift;
+     unsigned short charmask;        /* 0xff or 0x1ff */
++
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++    struct splash_data *splash_data;
++#endif
++
+ };
+ /* drivers/video/fbcon.c */
+diff -ruN linux-2.4.31/kernel/panic.c linux-2.4.31-bs/kernel/panic.c
+--- linux-2.4.31/kernel/panic.c        2004-11-17 11:54:22.000000000 +0000
++++ linux-2.4.31-bs/kernel/panic.c     2005-05-18 11:08:01.000000000 +0100
+@@ -83,6 +83,13 @@
+                * We can't use the "normal" timers since we just panicked..
+                */
+               printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);
++
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++               {
++                       extern int splash_verbose(void);
++                       (void)splash_verbose();
++               }
++#endif
+               mdelay(panic_timeout*1000);
+               /*
+                *      Should we run the reboot notifier. For the moment Im
+@@ -103,6 +110,12 @@
+         disabled_wait(caller);
+ #endif
+       sti();
++#ifdef CONFIG_FBCON_SPLASHSCREEN
++       {
++               extern int splash_verbose(void);
++               (void)splash_verbose();
++       }
++#endif
+       for(;;) {
+ #if defined(CONFIG_X86) && defined(CONFIG_VT) 
+               extern void panic_blink(void);