Hi there, I mentioned a while ago about a LPP boot. LPP is the Linux Progress Patch, and introduces a framebuffer progress page with progress bar. I got it working, but there were some drawbacks - 1) required compiling the image into the kernel 2) required adding CONSOLE=/dev/tty2 to the append line 3) if they didn't have vesa fb then they saw nothing 4) didn't work if it wasn't interactive, i.e if the startup required interaction, then you would not see it. conclusion : lpp is suitable for harddrive installs only. Then I came along the suse kernel patch, with "splash" program This is the framebuffer bootup that you see on suse machines. it overcomes _all_ the drawbacks of lpp : 1) the image is stored seperatly ( in miniroot.gz ) 2) the console stays on tty1, as it is just written ontop of the image ( in a set area) 3) if you don't have vesa fb compatible card, you just see normal knoppix bootup 4) Made in .de ;) one disadvantage - requires a statically compiled binary to be included in miniroot.gz It creates a framebuffer image and draws the console text over top of the image, which is in jpeg format. I have implemented this in a remaster and it works well. I have used isolinux, so size wasn't an issue. my image is 49KB, but could be smaller if more jpeg compression is used ( again not an issue with isolinux ) The statically compiled splash program is 384K. Recipe : ( makes 800x600 ;) Ingredients - 800x600 Jpg - example attached ( made with gimp - if anyone wants the .xcf email me ) - config file for the jpg - example attached - kernel patch - attached - "splash" program - sources attached all above programs and additinal documentation can be found at ftp://ftp.suse.com/pub/people/stepan/bootsplash What I did Instructions: ( no these wont make sence to everyone just to people who have remastered or Klaus ) statically compiled the splash.c program ( with gcc --static option ) and put it in /static of miniroot.gz made a directory "/splash" in miniroot.gz and put the .jpg and .cfg file there compiled a kernel with the patch ( after patching, make sure that the "CONFIG_FBCON_SPLASHSCREEN" is Y - in fb section.) then compile. replace the vmlinuz and kernel modules both in miniroot.gz, and in /lib/modules/ etc with the compiled ones. ( you will prolly want to edit the kernel Makefile and chage the version ) change linuxrc ( in miniroot.gz) to do the bootscreen. I have attached my linuxrc. basicly the change is adding splash -s -u 0 /splash/bootsplash-800x600.cfg 2>&1 > /dev/null where -u is the TTY. now, for those wanting to see this in action, you can download bootdemo.iso from my site. Burn this image onto CD as you would knoppix. It's only 1.9M, but must be burned onto CD as an ISO. It will start loading knoppix, but fail at the "accessing KNOPPIX on cdrom", as I have left out the KNOPPIX file. download from http://www.knoppix.net/mirror/bootdemo.iso As for syslinux vs isolinux as kernel sized increase ( read 2.6 ) there is need for a larger boot image. By not limiting the boot sequence to 1.44 M you can achive a lot more : - nice fb boot screens - memtest boot option - localboot option - multiple kernels ( e.g. non-SMP for dell machines that break when used with SMP kernel ) you can still include a 1.44M floppy image, without the above features for people that cannot boot off isolinux (who?), and provide instructions on how to do this ( easy with nero for example ) Hope this is of interest, and I hope this gets included with KNOPPIX, as the framebuffer boot is so sexy!! Best Regards Eaden McKee
Attachment:
bootsplash-800x600.jpg
Description: JPEG image
# This is the configuration file for the bootsplash pictures for SuSE-Linux 8.1. # This file is necessary to specify the coordinates of the text box on # the splash screen. # # Comments are welcome by stepan@suse.de # config file version version=2 # should the picture be displayed? state=1 # fgcolor is the text forground color. # bgcolor is the text background (i.e. transparent) color. fgcolor=FFFFFF bgcolor=000000 # (tx, ty) are the (x, y) coordinates of the text window in pixels. # tw/th is the width/height of the text window in pixels. tx=35 ty=201 tw=663 th=370 # (ax, ay) are the (x, y) coordinates for playing boot/shutdown animations #ax=112 #ay=30 # name of the picture file (full path recommended) jpeg=/splash/bootsplash-800x600.jpg
/* Splash control program. * * (c) 2001, 2002 by Stefan Reinauer <stepan@suse.de> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * */ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <libgen.h> #include <getopt.h> #define PROCSPLASH "/proc/splash" #define SPLASHDSC "/usr/share/splash/splash.dsc" #define BUFSIZE 4096 #ifndef FBMNGDEBUG #define DEBUG(x...) #else #define DEBUG(x...) printf(x) #endif int unit = 0; int version = 1; int state = -1; int fgcolor = -1; int bgcolor = -1; int tx = -1; int ty = -1; int tw = -1; int th = -1; int px = 0; int py = 0; int pw = 0; int ph = 0; int pr = 0; int pg = 0; int pb = 0; struct parstab { char *name; int *val; } parstab[] = { {"unit", &unit}, {"version", &version}, {"state", &state}, {"fgcolor", &fgcolor}, {"bgcolor", &bgcolor}, {"tx", &tx}, {"ty", &ty}, {"tw", &tw}, {"th", &th}, {"px", &px}, {"py", &py}, {"pw", &pw}, {"ph", &ph}, {"pr", &pr}, {"pg", &pg}, {"pb", &pb}, {"jpeg", (int *)0}, {(char *)0, (int *)0}, }; void setsplash(char *cfgfile, int filterflag) { struct stat stb; char buf[256]; char *jpgfile = 0; char *p; int l, size, fd; FILE *fp = 0; struct parstab *pt; unsigned char *pic; if (cfgfile) { if ((fp = fopen(cfgfile, "r")) == 0) { perror(cfgfile); exit(1); } while (fgets(buf, sizeof(buf), fp)) { l = strlen(buf); if (l == 0) continue; if (l == sizeof(buf) - 1) { fprintf(stderr, "line too long\n"); exit(1); } buf[--l] = 0; while(l && (buf[l - 1] == ' ' || (buf[l - 1] == '\t'))) buf[--l] = 0; for (p = buf; *p == ' ' || *p == '\t'; p++) ; if (*p == 0 || *p == '#') continue; for (pt = parstab; pt->name; pt++) { l = strlen(pt->name); if (!strncmp(p, pt->name, l) && (p[l] == ' ' || p[l] == '\t' || p[l] == '=')) break; } if (!pt->name) { fprintf(stderr, "syntax error: %s\n", p); exit(1); } while (p[l] == ' ' || p[l] == '\t') l++; if (p[l++] != '=') { fprintf(stderr, "syntax error: %s\n", p); exit(1); } while (p[l] == ' ' || p[l] == '\t') l++; if (pt->val) *pt->val = atoi(p + l); else jpgfile = strdup(p + l); } fclose(fp); if (!jpgfile) { l = strlen(cfgfile); if (l > 4 && !strcmp(cfgfile + l - 4, ".cfg")) { jpgfile = strdup(cfgfile); strcpy(jpgfile + l - 4, ".jpg"); } } if (jpgfile && (*jpgfile == 0 || tx < 0 || ty < 0 || tw <= 0 || th <= 0)) { free(jpgfile); jpgfile = 0; } } if (jpgfile) { if ((fp = fopen(jpgfile, "r")) == 0) { perror(jpgfile); exit(1); } if (fstat(fileno(fp), &stb) == -1) { perror("fstat"); exit(1); } l = stb.st_size; pic = calloc(35 + l, 1); if (pic == 0) { fprintf(stderr, "Out of memory.\n"); exit(1); } if (fread(pic + 35, l , 1, fp) != 1) { perror("fread"); exit(1); } fclose(fp); } else { l = 0; pic = calloc(35, 1); if (pic == 0) { fprintf(stderr, "Out of memory.\n"); exit(1); } } size = l; if (version != 1 && version != 2) { fprintf(stderr, "Illegal version: %d\n", version); exit(1); } if (version == 1 && unit != 0) { /* convert to version 2 */ tx *= 8; ty *= 16; tw *= 8; th *= 16; px = tx + 10; py = ty + 10; pw = tw - 20; ph = th - 20; pr = pg = pb = 240; state = 1; fgcolor = 0; bgcolor = 15; version = 2; } if (version == 1) { /* write version 1 file */ strcpy(pic, "BOOTSPL1"); pic[8] = tx; pic[9] = tx >> 8; pic[10] = ty; pic[11] = ty >> 8; pic[12] = tw; pic[13] = tw >> 8; pic[14] = th; pic[15] = th >> 8; pic[16] = size; pic[17] = size >> 8; pic[18] = size >> 16; pic[19] = size >> 24; if (l > 0) memmove(pic + 20, pic + 35, l); l += 20; } else { /* write version 2 file */ strcpy(pic, "BOOTSPL2"); pic[8] = unit; pic[9] = state; pic[10] = fgcolor; pic[11] = bgcolor; if (cfgfile && size == 0 && (state != -1 || fgcolor != -1 || bgcolor != -1)) size = -1; pic[12] = size; pic[13] = size >> 8; pic[14] = size >> 16; pic[15] = size >> 24; pic[16] = tx; pic[17] = tx >> 8; pic[18] = ty; pic[19] = ty >> 8; pic[20] = tw; pic[21] = tw >> 8; pic[22] = th; pic[23] = th >> 8; pic[24] = px; pic[25] = px >> 8; pic[26] = py; pic[27] = py >> 8; pic[28] = pw; pic[29] = pw >> 8; pic[30] = ph; pic[31] = ph >> 8; pic[32] = pr; pic[33] = pg; pic[34] = pb; l += 35; } if (filterflag) fd = 1; else if ((fd = open(PROCSPLASH, O_WRONLY)) == -1) { perror(PROCSPLASH); exit(1); } if (write(fd, pic, l) != l) { perror("write"); exit(1); } if (!filterflag) close(fd); free(pic); } void spawncommand(unsigned char *command) { DEBUG("splash: Spawning command %s.\n", command); system(command); } int main(int argc, char *argv[]) { int procsplash, splashdsc, c; int setflag = 0; int errflag = 0; int filterflag = 0; unsigned char *readbuffer; unsigned char *versiontext, *statustext; unsigned char *match,*command, *cmp; unsigned char *tokenize; while ((c = getopt(argc, argv, "fsu:")) != EOF) { switch (c) { case 's': setflag = 1; break; case 'f': filterflag = 1; break; case 'u': unit = atoi(optarg); break; case '?': errflag = 1; break; } } if (errflag || (argc != optind + 1 && (argc != optind || !setflag))) { printf("Usage: %s logstring\n",argv[0]); printf(" %s -s [-u unit] [cfgfile]\n",argv[0]); return 0; } readbuffer = malloc(BUFSIZE); if (!readbuffer) { DEBUG("splash: Not enough memory.\n"); return -ENOMEM; } if (!setflag || !filterflag) { procsplash = open(PROCSPLASH, O_RDONLY); if (procsplash < 0) { if (setflag) { perror(PROCSPLASH); exit(1); } DEBUG("splash: File %s not available.\n",PROCSPLASH); return 0; } if (read(procsplash, readbuffer, BUFSIZE)<0) { if (setflag) perror("read"); DEBUG("splash: Read error in file %s.\n",PROCSPLASH); return -EBUSY; } close(procsplash); } if (setflag) { if (!filterflag && !strncmp(readbuffer, "Splash screen v0", 16)) { fprintf(stderr, "Your kernel does not support new-style splash pictures.\n"); exit(1); } setsplash(argc > optind ? argv[optind] : 0, filterflag); exit(0); } versiontext=strtok(readbuffer,":"); statustext=strtok(NULL,":"); if (!statustext || strncmp(" on\n",statustext, 4)) { DEBUG("splash: Boot splash is off.\n"); return 0; } memset(readbuffer,0,BUFSIZE); splashdsc=open(SPLASHDSC,O_RDONLY); if (splashdsc<0) { DEBUG("splash: File %s not available.\n", SPLASHDSC); return -ENOENT; } if (read(splashdsc, readbuffer, BUFSIZE)<0) { DEBUG("splash: Read error in file %s.\n",SPLASHDSC); return -EBUSY; } DEBUG("splash: Looking for match with \"%s\"\n",basename(argv[1])); tokenize=readbuffer; do { match=strtok(tokenize,":"); tokenize=NULL; command=strtok(NULL,"\n"); DEBUG("splash: Match=\"%s\"\n",match); if (match && (cmp=strstr(basename(argv[1]),match)) && !strncmp(match,cmp,strlen(match)) ) { DEBUG("splash: Match found: \"%s\".\n",match); spawncommand(command); return 0; } } while (match && command); return 0; }
--- 2.4.19-vanilla/include/video/fbcon.h 2001-09-14 01:25:07.000000000 +0200 +++ 2.4.19-vanilla/include/video/fbcon.h 2002-11-03 22:27:20.000000000 +0100 @@ -43,4 +43,27 @@ }; +#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_penguin_xo; /* penguin area origin */ + int splash_penguin_yo; + int splash_penguin_wi; /* penguin area size */ + int splash_penguin_he; + int splash_penguin_r; /* penguin bg color */ + int splash_penguin_g; + int splash_penguin_b; + int splash_no_penguin; /* don't display him */ + char splash_jpeg[1]; /* jpeg */ +}; +#endif + extern struct display_switch fbcon_dummy; @@ -96,4 +119,9 @@ unsigned char fgshift, bgshift; unsigned short charmask; /* 0xff or 0x1ff */ + +#ifdef CONFIG_FBCON_SPLASHSCREEN + struct splash_data *splash_data; +#endif + }; --- 2.4.19-vanilla/drivers/video/fbcon.c 2002-08-03 02:39:45.000000000 +0200 +++ 2.4.19-vanilla/drivers/video/fbcon.c 2002-11-03 22:24:38.000000000 +0100 @@ -35,4 +35,7 @@ * - Brad Douglas <brad@neruo.com> * + * Alterations marked G.S. contributed by Gerard Sharp (gsharp@ihug.co.nz) + * Essentially a line of text above the Boot Logo stating kernel version. :) + * * The low level operations for the various display memory organizations are * now in separate source files. @@ -59,4 +62,5 @@ #undef FBCONDEBUG +#include <linux/version.h> #include <linux/config.h> #include <linux/module.h> @@ -105,4 +109,17 @@ #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; + #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) @@ -479,4 +496,7 @@ } +#if defined(CONFIG_FBCON_SPLASHSCREEN) +static int splash_registered=0; +#endif static void fbcon_init(struct vc_data *conp, int init) @@ -503,4 +523,24 @@ fb_display[unit].cmap.blue = 0; fb_display[unit].cmap.transp = 0; + +#ifdef CONFIG_FBCON_SPLASHSCREEN + if (!splash_registered && fb_display[unit].dispsw->setup == fbcon_cfb16.setup) { + 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].dispsw->setup != fbcon_cfb16.setup) { + 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 */ @@ -519,4 +559,13 @@ 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 + } @@ -659,5 +708,13 @@ 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 */ @@ -665,5 +722,6 @@ int step; - logo_lines = (LOGO_H + fontheight(p) - 1) / fontheight(p); + /* G.S. Make logo 1 (text) line taller - for version text */ + logo_lines = (LOGO_H + (fontheight(p)*2) - 1) / fontheight(p); q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows); step = logo_lines * old_cols; @@ -736,4 +794,9 @@ 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) @@ -1324,4 +1387,7 @@ 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: @@ -1384,4 +1450,7 @@ 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: @@ -1500,4 +1569,11 @@ 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,4 +1586,8 @@ 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; @@ -1554,4 +1634,13 @@ p->dispsw->clear_margins(conp, p, 0); if (logo_shown == -2) { + /* G.S.: Display a line above the Boot Logo to state what + * version of the kernel we are booting. + */ + char welcometext[] = "Linux " UTS_RELEASE; + unsigned short welcomestring[ sizeof(welcometext) ]; + int i; + for(i = 0; i < sizeof(welcometext); i++) + scr_writew(0x0700 | welcometext[i], &welcomestring[i]); + fbcon_putcs( conp, welcomestring, sizeof(welcometext), 0, 0 ); logo_shown = fg_console; fbcon_show_logo(); /* This is protected above by initmem_freed */ @@ -1600,4 +1689,7 @@ } else p->dispsw->clear(conp, p, real_y(p, 0), 0, height, conp->vc_cols); +#ifdef CONFIG_FBCON_SPLASHSCREEN + p->dispsw->clear_margins(conp, p, -1); +#endif conp->vc_video_erase_char = oldc; } @@ -1767,11 +1859,19 @@ 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; @@ -2151,4 +2251,6 @@ return 0; + /* G.S. : Move Penguin(s) down one line; for version line */ + fb += fontheight(p) * line; /* * Set colors if visual is PSEUDOCOLOR and we have enough colors, or for @@ -2194,4 +2296,8 @@ 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)) { @@ -2455,4 +2561,8 @@ #endif } + +#ifdef CONFIG_FBCON_SPLASHSCREEN + } +#endif if (p->fb_info->fbops->fb_rasterimg) --- 2.4.19-vanilla/drivers/video/fbcon-cfb16.c 2001-10-15 22:47:13.000000000 +0200 +++ 2.4.19-vanilla/drivers/video/fbcon-cfb16.c 2002-11-03 21:39:18.000000000 +0100 @@ -11,4 +11,5 @@ #include <linux/module.h> +#include <linux/config.h> #include <linux/tty.h> #include <linux/console.h> @@ -20,4 +21,7 @@ #include <video/fbcon-cfb16.h> +#ifdef CONFIG_FBCON_SPLASHSCREEN +#include "fbcon-splash.h" +#endif /* @@ -62,4 +66,10 @@ width *= fontwidth(p)*2; } +#ifdef CONFIG_FBCON_SPLASHSCREEN + if (splash_shown) { + 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; + } +#endif if (dy < sy || (dy == sy && dx < sx)) { src = p->screen_base + sy * linesize + sx; @@ -102,4 +112,29 @@ } +#ifdef CONFIG_FBCON_SPLASHSCREEN +static 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; + } +} +#endif + void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, int sx, int height, int width) @@ -108,4 +143,7 @@ int bytes = p->next_line, lines = height * fontheight(p); u32 bgx; +#ifdef CONFIG_FBCON_SPLASHSCREEN + int offset, transparent=0; +#endif dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2; @@ -114,4 +152,26 @@ width *= fontwidth(p)/4; + +#ifdef CONFIG_FBCON_SPLASHSCREEN + if (splash_shown) { + 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); + return; + } + } +#endif if (width * 8 == bytes) rectfill(dest, lines * width * 4, 1, bgx, bytes); @@ -120,4 +180,19 @@ } + +/* + * Helper function to read the background from the splashscreen + */ +#ifdef CONFIG_FBCON_SPLASHSCREEN +# define SPLASH_BGX(off) \ + if (transparent) { \ + bgx = *(u32*)(splashbgx + (off)); \ + eorx = fgx ^ bgx; \ + } +#else +# define SPLASH_BGX(off) +#endif + + void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) @@ -127,8 +202,34 @@ u32 eorx, fgx, bgx; +#ifdef CONFIG_FBCON_SPLASHSCREEN + int transparent = 0; + u8 *splashbgx = 0; +#endif + 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)]; + +#ifdef CONFIG_FBCON_SPLASHSCREEN + if (splash_shown) { + 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; + } + } +#endif + fgx |= (fgx << 16); bgx |= (bgx << 16); @@ -141,10 +242,17 @@ 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); } +#ifdef CONFIG_FBCON_SPLASHSCREEN + splashbgx += splash_bytes; +#endif } break; @@ -154,13 +262,21 @@ 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); } @@ -177,4 +293,8 @@ int rows, bytes = p->next_line; u32 eorx, fgx, bgx; +#ifdef CONFIG_FBCON_SPLASHSCREEN + int transparent = 0; + u8 *splashbgx0 = 0, *splashbgx; +#endif dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2; @@ -182,4 +302,24 @@ fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)]; bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)]; + +#ifdef CONFIG_FBCON_SPLASHSCREEN + if (splash_shown) { + 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; + } + } +#endif fgx |= (fgx << 16); bgx |= (bgx << 16); @@ -192,14 +332,27 @@ c = scr_readw(s++) & p->charmask; cdat = p->fontdata + c * fontheight(p); +#ifdef CONFIG_FBCON_SPLASHSCREEN + splashbgx = splashbgx0; +#endif 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); } +#ifdef CONFIG_FBCON_SPLASHSCREEN + splashbgx += splash_bytes; +#endif } dest0 += fontwidth(p)*2;; +#ifdef CONFIG_FBCON_SPLASHSCREEN + splashbgx0 += fontwidth(p) * 2; +#endif } break; @@ -209,19 +362,36 @@ c = scr_readw(s++) & p->charmask; cdat = p->fontdata + (c * fontheight(p) << 1); +#ifdef CONFIG_FBCON_SPLASHSCREEN + splashbgx = splashbgx0; +#endif 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); } +#ifdef CONFIG_FBCON_SPLASHSCREEN + splashbgx += splash_bytes; +#endif } dest0 += fontwidth(p)*2; +#ifdef CONFIG_FBCON_SPLASHSCREEN + splashbgx0 += fontwidth(p) * 2; +#endif } break; @@ -235,4 +405,9 @@ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2; +#ifdef CONFIG_FBCON_SPLASHSCREEN + if (splash_shown) { + dest += splash_data.splash_text_yo * bytes + splash_data.splash_text_xo * 2; + } +#endif for (rows = fontheight(p); rows--; dest += bytes) { switch (fontwidth(p)) { @@ -266,6 +441,55 @@ unsigned int right_width, bottom_width; +#ifdef CONFIG_FBCON_SPLASHSCREEN + 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; +#endif + bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]; +#ifdef CONFIG_FBCON_SPLASHSCREEN + if (bottom_only == -1) { + rectfill(p->screen_base, p->var.xres, p->var.yres, bgx, bytes); + return; + } + + if (splash_shown) { + 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; + } +#endif + if (!bottom_only && (right_width = p->var.xres-right_start)) rectfill(p->screen_base+right_start*2, right_width, --- 2.4.19-vanilla/drivers/video/Makefile 2002-08-03 02:39:45.000000000 +0200 +++ 2.4.19-vanilla/drivers/video/Makefile 2002-11-03 20:55:41.000000000 +0100 @@ -140,4 +140,7 @@ obj-$(CONFIG_FBCON_STI) += fbcon-sti.o +obj-$(CONFIG_FBCON_SPLASHSCREEN) += fbcon-splash.o +obj-$(CONFIG_FBCON_SPLASHSCREEN) += fbcon-jpegdec.o + include $(TOPDIR)/Rules.make --- 2.4.19-vanilla/drivers/video/fbcon-jpegdec.c Thu Sep 12 13:46:32 2002 +++ 2.4.19-vanilla/drivers/video/fbcon-jpegdec.c Thu Sep 12 14:38:32 2002 @@ -0,0 +1,935 @@ +/* + * 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> + +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) \ +) + +#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 \ +) + +#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; + } +} --- 2.4.19-vanilla/drivers/video/fbcon-jpegdec.h Thu Sep 12 13:46:33 2002 +++ 2.4.19-vanilla/drivers/video/fbcon-jpegdec.h Thu Sep 12 14:16:35 2002 @@ -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); --- 2.4.19-vanilla/drivers/video/fbcon-splash.c Thu Sep 12 13:46:33 2002 +++ 2.4.19-vanilla/drivers/video/fbcon-splash.c Thu Sep 12 14:35:27 2002 @@ -0,0 +1,481 @@ +/* + * linux/drivers/video/fbcon-splash.c - splash screen handling functions. + * + * (w) 2001 by Volker Poplawski, <volker@suse.de> + * Stefan Reinauer, <stepan@suse.de> + * Steffen Winterfeldt, <snwint@suse.de> + * + * 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 "2.0.3" + +#ifdef CONFIG_BLK_DEV_INITRD +unsigned char signature[] = "BOOTSPL1SPL2"; +#endif + +/* from drivers/char/console.c */ +extern void con_remap_def_color(int currcons, int new_color); + +/* 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_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); + +int __init splash_init(char *options) +{ + splash_default = simple_strtoul(options, NULL, 0); + return 0; +} + +__setup("splash=", splash_init); + + +void penguin_off(struct display *p, int update) +{ + unsigned int i, j, x, y, width, height; + unsigned short bg; + + if (fg_console != p->conp->vc_num) + return; + if (!linux_splash) + return; + if (!p->splash_data || p->splash_data->splash_penguin_wi <= 0 || p->splash_data->splash_penguin_he <= 0) + return; + if (p->var.bits_per_pixel != 16) + return; + bg = (p->splash_data->splash_penguin_r & 0xf8) << 8 | + (p->splash_data->splash_penguin_g & 0xfc) << 3 | + (p->splash_data->splash_penguin_b & 0xf8) >> 3; + x = p->splash_data->splash_penguin_xo; + y = p->splash_data->splash_penguin_yo; + width = p->splash_data->splash_penguin_wi; + height = p->splash_data->splash_penguin_he; + for (i = y; i < y + height; i++) + for (j = x; j < x + width; j++) + *(unsigned short *)(linux_splash + j * 2 + i * splash_bytes) = bg; + + if (update) { + 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 ); + if (p->dispsw->clear_margins) + p->dispsw->clear_margins(p->conp, p, 0); + } +} + +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; +} + +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; + struct display *p; + + printk(KERN_INFO "Looking for splash picture..."); + + p = &fb_display[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) + vfree(p->splash_data); + p->splash_data = vmalloc(sizeof(*p->splash_data) + splash_size); + if (!p->splash_data) + break; + 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_penguin_xo = p->splash_data->splash_text_xo + 10; + p->splash_data->splash_penguin_yo = p->splash_data->splash_text_yo + 10; + p->splash_data->splash_penguin_wi = p->splash_data->splash_text_wi - 20; + p->splash_data->splash_penguin_he = p->splash_data->splash_text_he - 20; + p->splash_data->splash_penguin_r = 0xf0; + p->splash_data->splash_penguin_g = 0xf0; + p->splash_data->splash_penguin_b = 0xf0; + p->splash_data->splash_no_penguin = 0; + 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) + vfree(p->splash_data); + p->splash_data = 0; + 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) + vfree(p->splash_data); + p->splash_data = vmalloc(sizeof(*p->splash_data) + splash_size); + if (!p->splash_data) + break; + 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_penguin_xo = ndata[24] + (ndata[25] << 8); + p->splash_data->splash_penguin_yo = ndata[26] + (ndata[27] << 8); + p->splash_data->splash_penguin_wi = ndata[28] + (ndata[29] << 8); + p->splash_data->splash_penguin_he = ndata[30] + (ndata[31] << 8); + p->splash_data->splash_penguin_r = ndata[32]; + p->splash_data->splash_penguin_g = ndata[33]; + p->splash_data->splash_penguin_b = ndata[34]; + p->splash_data->splash_no_penguin = 0; + splash_start = ndata + 35; + found = 1; + 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) { + vfree(p->splash_data); + p->splash_data = 0; + printk(" found, but has oversized text area!\n"); + return -1; + } + if (p->dispsw->setup != fbcon_cfb16.setup) { + vfree(p->splash_data); + p->splash_data = 0; + printk(" found, but framebuffer can't handle it!\n"); + return -1; + } + printk (" found (%dx%d, %d bytes).\n", width, height, splash_size); + /* copy data so that initrd memory can be freed. */ + memcpy(p->splash_data->splash_jpeg, splash_start, splash_size); + return unit; +} + +int splash_prepare(p) +struct display *p; +{ + int err; + int width, height, depth, size; + + if (!p->splash_data || !p->splash_data->splash_state) { + if (linux_splash) + vfree(linux_splash); + linux_splash = 0; + linux_splash_size = 0; + splash_shown = 0; + 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_shown = 0; + return -2; + } + + size = ((width + 15) & ~15) * ((height + 15) & ~15) * (depth>>3); + if (size != linux_splash_size) { + if (linux_splash) + vfree(linux_splash); + linux_splash_size = 0; + linux_splash = 0; + splash_shown = 0; + } + 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_shown = 0; + return -3; + } + + if (!decdata) + decdata = vmalloc(sizeof(*decdata)); + + 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_shown = 0; + return -4; + } + linux_splash_size = size; + splash_bytes = ((width + 15) & ~15) * (depth >> 3); + splash_data = *p->splash_data; + splash_shown = p->splash_data->splash_state; + if (p->splash_data->splash_no_penguin) + penguin_off(p, 0); + 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\n", + SPLASH_VERSION, color, p->var.xres, p->var.yres, 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); + if (p->dispsw->clear_margins) + p->dispsw->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 (!strcmp(buffer,"hide penguin\n") || !strcmp(buffer,"show penguin\n")) { + p = &fb_display[0]; + if (p->splash_data) { + if (*buffer == 'h') { + printk(KERN_INFO "Switching off penguin.\n"); + p->splash_data->splash_no_penguin = 1; + penguin_off(p, 1); + } else { + printk(KERN_INFO "Switching on penguin.\n"); + p->splash_data->splash_no_penguin = 0; + splash_status(p); + } + } + 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 --- 2.4.19-vanilla/drivers/video/fbcon-splash.h Thu Sep 12 13:46:33 2002 +++ 2.4.19-vanilla/drivers/video/fbcon-splash.h Thu Sep 12 13:51:25 2002 @@ -0,0 +1,18 @@ +/* + * linux/drivers/video/splash.h - splash screen definition. + * + * (w) 2001 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 */ --- 2.4.19-vanilla/drivers/video/Config.in 2002-08-03 02:39:45.000000000 +0200 +++ 2.4.19-vanilla/drivers/video/Config.in 2002-11-03 20:42:36.000000000 +0100 @@ -205,13 +205,19 @@ tristate ' Virtual Frame Buffer support (ONLY FOR TESTING!)' 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 @@ -314,7 +320,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" ]; 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 \ @@ -331,7 +339,9 @@ "$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \ "$CONFIG_FB_PVR2" = "m" -o "$CONFIG_FB_VOODOO1" = "m" -o \ "$CONFIG_FB_NEOMAGIC" = "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 \ --- 2.4.19-vanilla/drivers/char/console.c 2002-08-03 02:39:43.000000000 +0200 +++ 2.4.19-vanilla/drivers/char/console.c 2002-11-03 20:52:07.000000000 +0100 @@ -3004,4 +3004,29 @@ 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 /*
#!/static/sh # # KNOPPIX General Startup Script # (C) Klaus Knopper <knoppix@knopper.net> # # # This script needs some of the builtin ash commands (if, test, ...) # mount/umount, insmod/rmmod are also a builtin in ash-knoppix. # # hardcoded configurable options # Default maximum size of dynamic ramdisk in kilobytes RAMSIZE=1000000 # End of options # Don't allow interrupt signals trap "" 1 2 3 15 # "Safe" SCSI modules in the right order for autoprobe # Warning: The sym53c8xx.o and g_NCR* cause a kernel Oops if no such adapter # is present. # # NB: It looks like that ncr53c8xx.o is more stable than 53c7,8xx.o for # a ncr53c810 controller (at least on my installation box it's more # immune to SCSI timeouts) # Removed 53c7,8xx -> crashes if no device attached. # Removed AM53C974 -> crashes tmscsim if adapter found # Added initio.o on request (untested) SCSI_MODULES="aic7xxx.o aic7xxx_old.o BusLogic.o \ ncr53c8xx.o NCR53c406a.o \ initio.o \ advansys.o aha1740.o aha1542.o aha152x.o \ atp870u.o dtc.o eata.o fdomain.o gdth.o \ megaraid.o pas16.o pci2220i.o pci2000.o psi240i.o \ qlogicfas.o qlogicfc.o qlogicisp.o \ seagate.o t128.o tmscsim.o u14-34f.o ultrastor.o wd7000.o \ a100u2w.o 3w-xxxx.o" # Misc functions mountit(){ # Usage: mountit src dst "options" # Uses builtin mount of ash.knoppix # Builin filesystems BUILTIN_FS="iso9660 ext2 vfat" for fs in $BUILTIN_FS; do test -b $1 && mount -t $fs $3 $1 $2 >/dev/null 2>&1 && return 0 done return 1 } FOUND_SCSI="" FOUND_KNOPPIX="" INTERACTIVE="" # Clean input/output exec >/dev/console </dev/console 2>&1 # Reset fb color mode RESET="]R" # ANSI COLORS # Erase to end of line CRE=" [K" # Clear and reset Screen CLEAR="c" # Normal color NORMAL="[0;39m" # RED: Failure or error message RED="[1;31m" # GREEN: Success message GREEN="[1;32m" # YELLOW: Descriptions YELLOW="[1;33m" # BLUE: System mesages BLUE="[1;34m" # MAGENTA: Found devices or drivers MAGENTA="[1;35m" # CYAN: Questions CYAN="[1;36m" # BOLD WHITE: Hint WHITE="[1;37m" # Clear screen with colormode reset # echo "$CLEAR$RESET" # echo "$CLEAR" # We only need the builtin commands and /static at this point PATH=/static export PATH umask 022 # Mount /proc and /dev/pts mount -t proc none /proc mount -t devpts none /dev/pts # Bootsplash by Eadz at eadz.co.nz splash -s -u 0 /splash/bootsplash-800x600.cfg 2>&1 > /dev/null splash -s -u 1 /splash/bootsplash-800x600.cfg 2>&1 > /dev/null splash -s -u 2 /splash/bootsplash-800x600.cfg 2>&1 > /dev/null splash -s -u 3 /splash/bootsplash-800x600.cfg 2>&1 > /dev/null splash -s -u 4 /splash/bootsplash-800x600.cfg 2>&1 > /dev/null # Just go to the top of the screen echo -n "[H[J" echo "" # Be verbose #echo "${WHITE}Welcome to the ${CYAN}K${MAGENTA}N${YELLOW}O${WHITE}P${RED}P${GREEN}I${BLUE}X${WHITE} ${GREEN}KDE EDITION${NORMAL} live Linux-on-CD!${NORMAL}" echo "Welcome to ..." echo "${YELLOW}" echo "______ ______ ___________________________________ __" echo "___ //_/__ | / /_ __ \__ __ \__ __ \___ _/_ |/ /" echo "__ ,< __ |/ /_ / / /_ /_/ /_ /_/ /__ / __ / " echo "_ /| | _ /| / / /_/ /_ ____/_ ____/__/ / _ | " echo "/_/ |_| /_/ |_/ \____/ /_/ /_/ /___/ /_/|_| " echo "${WHITE}" echo " __ __ __ __ " echo "|_/| \|_ _) /| |_ _|.|_. _ _ " echo "| \|__/|__ __). | |__(_|||_|(_)| ) " echo "${NORMAL}" # Read boot command line with builtin cat command (shell read function fails in Kernel 2.4.19-rc1) CMDLINE="$(cat /proc/cmdline)" # Check if we are in interactive startup mode case "$CMDLINE" in *BOOT_IMAGE=expert\ *) INTERACTIVE="yes"; :>/interactive; ;; esac # Does the user want to skip scsi detection? NOSCSI="" case "$CMDLINE" in *noscsi*) NOSCSI="yes"; ;; esac # Disable kernel messages while probing modules in autodetect mode echo "0" > /proc/sys/kernel/printk # Mount module disk mountmodules(){ TYPE="$1"; shift echo -n "${CRE}${CYAN}Please insert ${TYPE} modules disk and hit Return. ${NORMAL}" read a echo -n "${CRE}${BLUE}Mounting ${TYPE} modules disk... ${NORMAL}" # We always mount over /modules/scsi (because it's there ;-) if mountit /dev/fd0 /modules/scsi "-o ro"; then echo "${GREEN}OK.${NORMAL}" return 0 fi echo "${RED}NOT FOUND.${NORMAL}" return 1 } # Unmount module disk umountmodules(){ TYPE="$1"; shift echo -n "${CRE}${BLUE}Unmounting ${TYPE} modules disk... ${NORMAL}" umount /modules/scsi 2>/dev/null echo "${GREEN}DONE.${NORMAL}" } # Ask user for modules askmodules(){ TYPE="$1"; shift echo "${BLUE}${TYPE} modules available:${WHITE}" c=""; for m in "$@"; do if test -f "/modules/scsi/$m"; then test -z "$c" && { echo -n " $m"; c="1"; } || { echo " $m"; c=""; } fi done [ -n "$c" ] && echo "" echo "${CYAN}Load ${TYPE} Modules?${NORMAL}" echo "${CYAN}[Enter full filename(s) (space-separated), Return for autoprobe, ${WHITE}n${CYAN} for none] ${NORMAL}" echo -n "${CYAN}insmod module(s)> ${NORMAL}" read MODULES case "$MODULES" in n|N) MODULES=""; ;; y|"") MODULES="$*"; ;; esac } # Try to load the given modules (full path or current directory) loadmodules(){ TYPE="$1"; shift test -n "$INTERACTIVE" && echo "6" > /proc/sys/kernel/printk for i in "$@"; do echo -n "${CRE}${BLUE}Probing ${TYPE}... ${MAGENTA}$i${NORMAL}" if test -f /modules/scsi/$i && insmod -f /modules/scsi/$i >/dev/null 2>&1 then echo "${CRE} ${GREEN}Found ${TYPE} device(s) handled by ${MAGENTA}$i${GREEN}.${NORMAL}" case "$TYPE" in scsi|SCSI) FOUND_SCSI="yes"; ;; esac fi done test -n "$INTERACTIVE" && echo "0" > /proc/sys/kernel/printk echo -n "${CRE}" } # Check for SCSI, use modules on bootfloppy first if test -n "$INTERACTIVE"; then # Let the user select interactively askmodules SCSI $(cd /modules/scsi; echo *.o) else # these are the autoprobe-safe modules MODULES="$SCSI_MODULES" fi test -z "$NOSCSI" && test -n "$MODULES" && loadmodules SCSI $MODULES # End of SCSI check # Check for misc modules in expert mode if test -n "$INTERACTIVE"; then another=""; answer="" while test "$answer" != "n" -a "$answer" != "N"; do echo -n "${CYAN}Do you want to load additional modules from$another floppy disk? [${WHITE}Y${CYAN}/n] ${NORMAL}" another=" another" read answer case "$answer" in n*|N*) break; ;; esac if mountmodules new; then askmodules new $(cd /modules/scsi; echo *.o) test -n "$MODULES" && loadmodules new $MODULES umountmodules current fi done fi # All interactively requested modules should be loaded now. # Check for ide-scsi supported CD-Roms et al. test -f /proc/scsi/scsi && FOUND_SCSI="yes" # Disable kernel messages again echo "0" > /proc/sys/kernel/printk # Now that the right SCSI driver is (hopefully) loaded, try to find CDROM DEVICES="/dev/hd?" test -n "$FOUND_SCSI" && DEVICES="/dev/scd? /dev/scd?? $DEVICES" # New: Also try parallel port CD-Roms [for Mike]. DEVICES="$DEVICES /dev/pcd?" # New: also check HD partitions for a KNOPPIX/KNOPPIX image test -n "$FOUND_SCSI" && DEVICES="$DEVICES /dev/sd?[1-9] /dev/sd?[1-9][0-9]" DEVICES="$DEVICES /dev/hd?[1-9] /dev/hd?[1-9][0-9]" for i in $DEVICES do echo -n "${CRE}${BLUE}Looking for CDROM in: ${MAGENTA}$i${NORMAL} " if mountit $i /cdrom "-o ro" >/dev/null 2>&1 then if test -d /cdrom/KNOPPIX then echo -n "${CRE} ${GREEN}Accessing KNOPPIX CDROM at ${MAGENTA}$i${GREEN}...${NORMAL}" FOUND_KNOPPIX="$i" break fi umount /cdrom fi done # Harddisk-installed script part version has been removed # (KNOPPIX can be booted directly from HD now). if test -n "$FOUND_KNOPPIX" -a -f /cdrom/KNOPPIX/KNOPPIX; then # DEBUG # echo "6" > /proc/sys/kernel/printk insmod -f /modules/cloop.o file=/cdrom/KNOPPIX/KNOPPIX mountit /dev/cloop /KNOPPIX "-o ro" || FOUND_KNOPPIX="" fi # Final test if everything succeeded. if test -n "$FOUND_KNOPPIX" then # copy library cache cat /KNOPPIX/etc/ld.so.cache > /etc/ld.so.cache echo "" # Enable kernel messages echo "6" > /proc/sys/kernel/printk # Set paths echo -n "${CRE}${BLUE}Setting paths...${NORMAL}" PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:." export PATH # Debian weirdness /bin/cp -a /KNOPPIX/etc/alternatives /etc/ 2>/dev/null # From here, we should have all essential commands available. hash -r # Clean up / rm -rf /modules /static # New in Kernel 2.4.x: tempfs with variable ramdisk size. # We check for available memory anyways and limit the ramdisks # to a reasonable size. FOUNDMEM="$(awk '/MemTotal/{print $2}' /proc/meminfo)" TOTALMEM="$(awk 'BEGIN{m=0};/MemFree|Cached/{m+=$2};END{print m}' /proc/meminfo)" # Be verbose echo "${CRE}${BLUE}Total memory found: ${YELLOW}${FOUNDMEM}${BLUE} kB${NORMAL}" # Now we need to use a little intuition for finding a ramdisk size # that keeps us from running out of space, but still doesn't crash the # machine due to lack of Ram # Minimum size of additional ram partitions MINSIZE=2000 # At least this much memory minus 30% should remain when home and var are full. MINLEFT=16000 # Maximum ramdisk size MAXSIZE="$(expr $TOTALMEM - $MINLEFT)" # Default ramdisk size for ramdisk RAMSIZE="$(expr $TOTALMEM / 5)" # Check for sufficient memory to mount extra ramdisk for /home + /var if test -n "$TOTALMEM" -a "$TOTALMEM" -gt "$MINLEFT"; then test -z "$RAMSIZE" && RAMSIZE=1000000 mkdir -p /ramdisk # tmpfs/varsize version, can use swap RAMSIZE=$(expr $RAMSIZE \* 4) echo -n "${CRE}${BLUE}Creating ${YELLOW}/ramdisk${BLUE} (dynamic size=${RAMSIZE}k) on ${MAGENTA}/dev/shm${BLUE}...${NORMAL}" # We need /bin/mount here for the -o size= option /bin/mount -t tmpfs -o "size=${RAMSIZE}k" /dev/shm /ramdisk && mkdir -p /ramdisk/home /ramdisk/var && ln -s /ramdisk/home /ramdisk/var / echo "${BLUE}Done.${NORMAL}" else mkdir -p /home /var fi echo -n "${CRE}${BLUE}Creating directories and symlinks on ramdisk...${NORMAL}" # Create common WRITABLE (empty) dirs mkdir -p /var/run /var/backups /var/cache/apache /var/local /var/lock/news \ /var/nis /var/preserve /var/state/misc /var/tmp /var/lib \ /var/spool/cups/tmp \ /mnt/cdrom /mnt/floppy /mnt/hd /mnt/test \ /home/knoppix /home/root /etc/sysconfig /etc/X11 /etc/cups chown knoppix.knoppix /home/knoppix # Create empty utmp and wtmp :> /var/run/utmp :> /var/run/wtmp # CUPS wants writable files. :-/ cp -a /KNOPPIX/etc/cups/*.conf /etc/cups/ 2>/dev/null # All files in here should be size zero after Knoppix.clean was run cp -a /KNOPPIX/var/local /KNOPPIX/var/games /KNOPPIX/var/log \ /KNOPPIX/var/spool /var/ 2>/dev/null cp -a /KNOPPIX/var/lib/games /KNOPPIX/var/lib/wine \ /KNOPPIX/var/lib/nfs /KNOPPIX/var/lib/xkb /KNOPPIX/var/lib/isdn \ /KNOPPIX/var/lib/kdm /KNOPPIX/var/lib/pcmcia \ /var/lib/ 2>/dev/null # Problematic directories in /var/lib (lots and lots of inodes) ln -s /KNOPPIX/var/lib/dpkg /KNOPPIX/var/lib/apt /KNOPPIX/var/lib/doc-base \ /KNOPPIX/var/lib/gnome /KNOPPIX/var/lib/kde \ /KNOPPIX/var/lib/scrollkeeper /KNOPPIX/var/lib/texmf \ /var/lib/ 2>/dev/null # Debian-apt ln -s /KNOPPIX/var/cache/apt /var/cache/ 2>/dev/null ln -s /KNOPPIX/etc/skel /KNOPPIX/etc/nessus /etc/dhcpc/resolv.conf \ /etc/ 2>/dev/null ln -s /KNOPPIX/dev/* /dev/ 2>/dev/null # Index files can be HUGE, so better replace cache/man tree by links later # cp -a /KNOPPIX/var/cache/man /var/cache/ 2>/dev/null # Create links from CDROM for UNWRITABLE (remaining) files cp -aus /KNOPPIX/var/* /var/ 2>/dev/null cp -aus /KNOPPIX/etc/* /etc/ 2>/dev/null # Make SURE that these are files, not links! rm -rf /etc/passwd /etc/shadow /etc/group \ /etc/ppp /etc/isdn /etc/ssh /etc/ioctl.save \ /etc/inittab /etc/network /etc/sudoers \ /etc/init /etc/localtime /etc/dhcpc /etc/pnm2ppa.conf 2>/dev/null cp -a /KNOPPIX/etc/passwd /KNOPPIX/etc/shadow /KNOPPIX/etc/group \ /KNOPPIX/etc/ppp /KNOPPIX/etc/isdn /KNOPPIX/etc/ssh \ /KNOPPIX/etc/inittab /KNOPPIX/etc/network /KNOPPIX/etc/sudoers \ /KNOPPIX/sbin/init /KNOPPIX/etc/dhcpc /etc/ 2>/dev/null # Extremely important, init crashes on shutdown if this is only a link :> /etc/ioctl.save :> /etc/pnm2ppa.conf # Diet libc bug workaround cp -f /KNOPPIX/etc/localtime /etc/localtime echo "${BLUE}Done.${NORMAL}" # Now tell kernel where the real modprobe lives echo "/sbin/modprobe" > /proc/sys/kernel/modprobe # Change root device from /dev/fd0 to /dev/ram0 echo "0x100" > /proc/sys/kernel/real-root-dev # Give control to the init process. echo "${CRE}${BLUE}Starting init process.${NORMAL}" rm -f /linuxrc exit 0 else echo "${CRE}${RED}Can't find KNOPPIX filesystem, sorry.${NORMAL}" echo "${RED}Dropping you to a (very limited) shell.${NORMAL}" echo "${RED}Press reset button to quit.${NORMAL}" echo "" echo "Additional builtin commands avaliable:" echo " cat mount umount" echo " insmod rmmod lsmod" echo "" PS1="knoppix# " export PS1 echo "6" > /proc/sys/kernel/printk # Allow signals trap 1 2 3 15 exec /static/ash fi