diff -urN linux-2.4.24.org/drivers/char/console.c linux-2.4.24/drivers/char/console.c --- linux-2.4.24.org/drivers/char/console.c 2004-01-19 21:00:14.495123806 +0100 +++ linux-2.4.24/drivers/char/console.c 2004-01-19 21:03:48.017721428 +0100 @@ -3025,6 +3025,31 @@ 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 -urN linux-2.4.24.org/drivers/char/keyboard.c linux-2.4.24/drivers/char/keyboard.c --- linux-2.4.24.org/drivers/char/keyboard.c 2004-01-19 21:00:14.168191795 +0100 +++ linux-2.4.24/drivers/char/keyboard.c 2004-01-19 21:03:48.066711241 +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; --- linux-2.4.29/drivers/char/n_tty.c.orig 2005-01-20 16:15:28.000000000 +0100 +++ linux-2.4.29/drivers/char/n_tty.c 2005-01-20 16:18:59.000000000 +0100 @@ -47,6 +47,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> @@ -1186,6 +1187,16 @@ 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 -urN linux-2.4.24.org/drivers/video/Config.in linux-2.4.24/drivers/video/Config.in --- linux-2.4.24.org/drivers/video/Config.in 2004-01-19 21:01:12.428076192 +0100 +++ linux-2.4.24/drivers/video/Config.in 2004-01-19 21:05:33.568745824 +0100 @@ -243,13 +243,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 @@ -361,7 +368,9 @@ "$CONFIG_FB_PVR2" = "y" -o "$CONFIG_FB_VOODOO1" = "y" -o \ "$CONFIG_FB_NEOMAGIC" = "y" -o "$CONFIG_FB_INTEL" = "y" -o \ "$CONFIG_FB_I810" = "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 \ @@ -380,7 +389,9 @@ "$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" -o \ "$CONFIG_FB_NEOMAGIC" = "m" -o "$CONFIG_FB_INTEL" = "m" -o \ "$CONFIG_FB_I810" = "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 -urN linux-2.4.24.org/drivers/video/fbcon.c linux-2.4.24/drivers/video/fbcon.c --- linux-2.4.24.org/drivers/video/fbcon.c 2004-01-19 21:01:12.383085548 +0100 +++ linux-2.4.24/drivers/video/fbcon.c 2004-01-19 21:03:48.196684214 +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 @@ -477,7 +495,9 @@ return display_desc; } - +#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 +521,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 +557,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 + } @@ -657,7 +706,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; @@ -734,6 +790,11 @@ 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); @@ -1323,6 +1384,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, @@ -1383,6 +1447,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, @@ -1499,6 +1566,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); } @@ -1509,6 +1583,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) @@ -1568,14 +1646,41 @@ { 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, @@ -1583,25 +1688,39 @@ 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 */ return 1; } + } (*info->blank)(blank, info); return 0; @@ -1762,13 +1881,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) @@ -2189,6 +2316,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)) { @@ -2450,7 +2580,10 @@ } #endif } - +#ifdef CONFIG_FBCON_SPLASHSCREEN + } +#endif + if (p->fb_info->fbops->fb_rasterimg) p->fb_info->fbops->fb_rasterimg(p->fb_info, 0); diff -urN linux-2.4.24.org/drivers/video/fbcon-jpegdec.c linux-2.4.24/drivers/video/fbcon-jpegdec.c --- linux-2.4.24.org/drivers/video/fbcon-jpegdec.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.24/drivers/video/fbcon-jpegdec.c 2004-01-19 21:03:48.203682758 +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 -urN linux-2.4.24.org/drivers/video/fbcon-jpegdec.h linux-2.4.24/drivers/video/fbcon-jpegdec.h --- linux-2.4.24.org/drivers/video/fbcon-jpegdec.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.24/drivers/video/fbcon-jpegdec.h 2004-01-19 21:03:48.205682343 +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 -urN linux-2.4.24.org/drivers/video/fbcon-splash16.c linux-2.4.24/drivers/video/fbcon-splash16.c --- linux-2.4.24.org/drivers/video/fbcon-splash16.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.24/drivers/video/fbcon-splash16.c 2004-01-19 21:03:48.209681511 +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 -urN linux-2.4.24.org/drivers/video/fbcon-splash.c linux-2.4.24/drivers/video/fbcon-splash.c --- linux-2.4.24.org/drivers/video/fbcon-splash.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.24/drivers/video/fbcon-splash.c 2004-01-19 21:03:48.216680056 +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 -urN linux-2.4.24.org/drivers/video/fbcon-splash.h linux-2.4.24/drivers/video/fbcon-splash.h --- linux-2.4.24.org/drivers/video/fbcon-splash.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.24/drivers/video/fbcon-splash.h 2004-01-19 21:03:48.218679640 +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 -urN linux-2.4.24.org/drivers/video/Makefile linux-2.4.24/drivers/video/Makefile --- linux-2.4.24.org/drivers/video/Makefile 2004-01-19 21:01:12.732012987 +0100 +++ linux-2.4.24/drivers/video/Makefile 2004-01-19 21:05:58.628528100 +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 macmodes.o # Each configuration option enables a list of files. @@ -159,6 +159,10 @@ 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 clean: diff -urN linux-2.4.24.org/include/video/fbcon.h linux-2.4.24/include/video/fbcon.h --- linux-2.4.24.org/include/video/fbcon.h 2004-01-19 20:59:23.213788389 +0100 +++ linux-2.4.24/include/video/fbcon.h 2004-01-19 21:03:48.295663632 +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,10 @@ 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 -urN linux-2.4.24.org/kernel/panic.c linux-2.4.24/kernel/panic.c --- linux-2.4.24.org/kernel/panic.c 2004-01-19 20:58:34.218977671 +0100 +++ linux-2.4.24/kernel/panic.c 2004-01-19 21:03:48.336655108 +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);