And here's my patch for 2.4.x:

        This kernel patch will allow you to have a full-screen
boot logo in any FBcon supported video mode, except for
VGA text mode. After applying the patch, you simply need to
answer `Y' to `Custom boot logo' under the Framebuffer Support
options. Then, place your custom boot_logo.ppm into
linux/Documentation/boot_logo.ppm

        When you recompile your kernel, the boot_logo.ppm
file will be reconstructed into a 214 color, 16 color, and
2 color B&W include file in linux/drivers/video/boot_logo.h

        When you boot into the logo-enabled kernel, the
logo will be automatically centered on your framebuffer,
and you will have 2 lines of kernel/init status at the bottom
of your screen. Like the std. ``penguin'' logo, your custom
logo will be repeated horizontally for however many processors
your have on your system, or however many logos will fit - whichever
is smaller. 

        To remove the logo from the screen, simply switch away
from, them back to, the original boot-up VT.

        Comments, suggestions, patches, etc. are welcome.


diff --new-file -u -r linux-2.4.x/Documentation/Configure.help 
linux-2.4.x-logo/Documentation/Configure.help
--- linux-2.4.x/Documentation/Configure.help    Wed Aug 30 12:57:37 2000
+++ linux-2.4.x-logo/Documentation/Configure.help       Sat Sep 23 20:12:50 2000
@@ -3052,6 +3052,21 @@
   running kernel whenever you want), say M here and read
   Documentation/modules.txt. The module will be called vga16fb.o.
 
+Customizable Boot Logo for graphics modes
+CONFIG_FBCON_LOGO_BOOT
+  This allows you to change the boot logo from the default
+  `penguin' bootup. If you enable this option, make sure that
+  the PNM utilities and development headers/libraries are installed.
+  (aka libgr and libgr-devel).
+
+  Place your custom logo as a PPM file in the Documentation directory:
+  
+       /usr/src/linux/Documentation/boot_logo.ppm
+
+  When you recompile your kernel and fbcon is enabled in a graphics
+  mode (ie anything but VGA text), your logo will be centered and
+  there will be 2 lines for boot messages.
+
 Select other compiled-in fonts
 CONFIG_FBCON_FONTS
   Say Y here if you would like to use fonts other than the default
diff --new-file -u -r linux-2.4.x/drivers/video/Config.in 
linux-2.4.x-logo/drivers/video/Config.in
--- linux-2.4.x/drivers/video/Config.in Mon Aug 14 09:04:25 2000
+++ linux-2.4.x-logo/drivers/video/Config.in    Sat Sep 23 19:44:52 2000
@@ -159,6 +159,7 @@
       tristate '  Virtual Frame Buffer support (ONLY FOR TESTING!)' CONFIG_FB_VIRTUAL
    fi
 
+   bool '  Custom boot splash screen (graphics mode only)?' CONFIG_FBCON_LOGO_BOOT
    bool '  Advanced low level driver options' CONFIG_FBCON_ADVANCED
    if [ "$CONFIG_FBCON_ADVANCED" = "y" ]; then
       tristate '    Monochrome support' CONFIG_FBCON_MFB
diff --new-file -u -r linux-2.4.x/drivers/video/Makefile 
linux-2.4.x-logo/drivers/video/Makefile
--- linux-2.4.x/drivers/video/Makefile  Mon Aug 14 09:04:25 2000
+++ linux-2.4.x-logo/drivers/video/Makefile     Sat Sep 23 20:14:48 2000
@@ -160,7 +160,7 @@
 include $(TOPDIR)/Rules.make
 
 clean:
-       rm -f core *.o *.a *.s
+       rm -f core *.o *.a *.s boot_logo.h
 
 ../conmakehash: ../conmakehash.c
        $(HOSTCC) $(HOSTCFLAGS) -o ../conmakehash ../conmakehash.c
@@ -171,3 +171,14 @@
            -e 's/dfont\(_uni.*\]\)/promfont\1 __initdata/' > promcon_tbl.c
 
 promcon_tbl.o: promcon_tbl.c $(TOPDIR)/include/linux/types.h
+
+ifeq ($(CONFIG_FBCON_LOGO_BOOT),y)
+fbcon.o: boot_logo.h
+
+boot_logo.h: $(TOPDIR)/Documentation/boot_logo.ppm
+       $(MAKE) -C $(TOPDIR)/scripts ppmtolinuxlogo
+       ppmquant 214 $(TOPDIR)/Documentation/boot_logo.ppm | 
+$(TOPDIR)/scripts/ppmtolinuxlogo >boot_logo.h
+       ppmquant 16 $(TOPDIR)/Documentation/boot_logo.ppm | 
+$(TOPDIR)/scripts/ppmtolinuxlogo -16 >>boot_logo.h
+       ppmquant 2 $(TOPDIR)/Documentation/boot_logo.ppm | 
+$(TOPDIR)/scripts/ppmtolinuxlogo -bw >>boot_logo.h
+endif
+
diff --new-file -u -r linux-2.4.x/drivers/video/fbcon.c 
linux-2.4.x-logo/drivers/video/fbcon.c
--- linux-2.4.x/drivers/video/fbcon.c   Mon Jul 24 21:24:26 2000
+++ linux-2.4.x-logo/drivers/video/fbcon.c      Sat Sep 23 20:03:04 2000
@@ -94,9 +94,12 @@
 #ifdef CONFIG_FBCON_VGA_PLANES
 #include <asm/io.h>
 #endif
+#ifndef CONFIG_FBCON_LOGO_BOOT
 #define INCLUDE_LINUX_LOGO_DATA
+#endif
 #include <asm/linux_logo.h>
 
+
 #include <video/fbcon.h>
 #include <video/fbcon-mac.h>   /* for 6x11 font on mac */
 #include <video/font.h>
@@ -107,8 +110,14 @@
 #  define DPRINTK(fmt, args...)
 #endif
 
-#define LOGO_H                 80
-#define LOGO_W                 80
+#ifndef CONFIG_FBCON_LOGO_BOOT
+#define LOGO_W 80
+#define LOGO_H 80
+#else
+#define INCLUDE_LINUX_LOGO16
+#define INCLUDE_LINUX_LOGOBW
+#include "boot_logo.h"
+#endif
 #define LOGO_LINE      (LOGO_W/8)
 
 struct display fb_display[MAX_NR_CONSOLES];
@@ -608,8 +617,12 @@
        /* Need to make room for the logo */
        int cnt;
        int step;
-    
+   
+#ifdef CONFIG_FBCON_LOGO_BOOT
+       logo_lines = nr_rows - 2;
+#else
        logo_lines = (LOGO_H + fontheight(p) - 1) / fontheight(p);
+#endif
        q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows);
        step = logo_lines * old_cols;
        for (r = q - logo_lines * old_cols; r < q; r++)
@@ -638,10 +651,15 @@
                conp->vc_pos += logo_lines * conp->vc_size_row;
            }
        }
+       if (conp->vc_y < logo_lines) {
+               conp->vc_y=logo_lines;
+               conp->vc_pos=logo_lines*conp->vc_size_row;
+       }
        scr_memsetw((unsigned short *)conp->vc_origin,
                    conp->vc_video_erase_char, 
                conp->vc_size_row * logo_lines);
     }
+
     
     /*
      *  ++guenther: console.c:vc_allocate() relies on initializing
@@ -2054,6 +2072,7 @@
     unsigned char *dst, *src;
     int i, j, n, x1, y1, x;
     int logo_depth, done = 0;
+    int num_logos,x_offset,y_offset;
 
     /* Return if the frame buffer is not mapped */
     if (!fb)
@@ -2114,8 +2133,17 @@
     if (p->fb_info->fbops->fb_rasterimg)
        p->fb_info->fbops->fb_rasterimg(p->fb_info, 1);
 
-    for (x = 0; x < smp_num_cpus * (LOGO_W + 8) &&
-        x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
+    num_logos=(p->var.xres/(LOGO_W+8));
+    num_logos=(num_logos < smp_num_cpus) ? num_logos : smp_num_cpus;
+#ifdef CONFIG_FBCON_LOGO_BOOT
+    y_offset=(p->var.yres-LOGO_H)/2;
+    x_offset=(p->var.xres-(LOGO_W+8)*num_logos)/2;
+#else
+    y_offset=0;
+    x_offset=0;
+#endif
+
+    for (x = x_offset; num_logos > 0; x += (LOGO_W + 8), num_logos--) {
         
 #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \
     defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)
@@ -2134,7 +2162,7 @@
                src = logo;
                bdepth = depth/8;
                for( y1 = 0; y1 < LOGO_H; y1++ ) {
-                   dst = fb + y1*line + x*bdepth;
+                   dst = fb + (y1+y_offset)*line + x*bdepth;
                    for( x1 = 0; x1 < LOGO_W; x1++, src++ ) {
                        val = (*src << redshift) |
                              (*src << greenshift) |
@@ -2160,7 +2188,7 @@
                src = linux_logo16;
                bdepth = (depth+7)/8;
                for( y1 = 0; y1 < LOGO_H; y1++ ) {
-                   dst = fb + y1*line + x*bdepth;
+                   dst = fb + (y1+y_offset)*line + x*bdepth;
                    for( x1 = 0; x1 < LOGO_W/2; x1++, src++ ) {
                        pix = (*src >> 4) | 0x10; /* upper nibble */
                        val = (pix << redshift) |
@@ -2208,7 +2236,7 @@
 
            src = logo;
            for( y1 = 0; y1 < LOGO_H; y1++ ) {
-               dst = fb + y1*line + x*bdepth;
+               dst = fb + (y1+y_offset)*line + x*bdepth;
                for( x1 = 0; x1 < LOGO_W; x1++, src++ ) {
                    val = safe_shift((linux_logo_red[*src-32]   & redmask), redshift) |
                          safe_shift((linux_logo_green[*src-32] & greenmask), 
greenshift) |
@@ -2234,7 +2262,7 @@
        if (depth == 4 && p->type == FB_TYPE_PACKED_PIXELS) {
                src = logo;
                for( y1 = 0; y1 < LOGO_H; y1++) {
-                       dst = fb + y1*line + x/2;
+                       dst = fb + (y1+y_offset)*line + x/2;
                        for( x1 = 0; x1 < LOGO_W/2; x1++) {
                                u8 q = *src++;
                                q = (q << 4) | (q >> 4);
@@ -2250,7 +2278,7 @@
                
            src = logo;
            for( y1 = 0; y1 < LOGO_H; y1++ ) {
-               dst = fb + y1*line + x;
+               dst = fb + (y1+y_offset)*line + x;
                for( x1 = 0; x1 < LOGO_W; x1++ )
                    fb_writeb (*src++, dst++);
            }
@@ -2283,7 +2311,7 @@
            src = logo;
            for( y1 = 0; y1 < LOGO_H; y1++ ) {
                for( x1 = 0; x1 < LOGO_LINE; x1++, src += logo_depth ) {
-                   dst = fb + y1*line + MAP_X(x/8+x1);
+                   dst = fb + (y1+y_offset)*line + MAP_X(x/8+x1);
                    for( bit = 0; bit < logo_depth; bit++ ) {
                        val = 0;
                        for( mask = 0x80, i = 0; i < 8; mask >>= 1, i++ ) {
@@ -2302,7 +2330,7 @@
            if (depth > logo_depth) {
                for( y1 = 0; y1 < LOGO_H; y1++ ) {
                    for( x1 = 0; x1 < LOGO_LINE; x1++ ) {
-                       dst = fb + y1*line + MAP_X(x/8+x1) + logo_depth*plane;
+                       dst = fb + (y1+y_offset)*line + MAP_X(x/8+x1) + 
+logo_depth*plane;
                        for( i = logo_depth; i < depth; i++, dst += plane )
                            *dst = (i == logo_depth && logo_depth == 4)
                                   ? 0xff : 0x00;
@@ -2329,9 +2357,9 @@
            for( y1 = 0; y1 < LOGO_H; y1++ ) {
                src = logo + y1*LOGO_LINE;
                if (is_hga)
-                   dst = fb + (y1%4)*8192 + (y1>>2)*line + x/8;
+                   dst = fb + ((y1+y_offset)%4)*8192 + ((y1+y_offset)>>2)*line + x/8;
                else
-                   dst = fb + y1*line + x/8;
+                   dst = fb + (y1+y_offset)*line + x/8;
                for( x1 = 0; x1 < LOGO_LINE; ++x1 )
                    fb_writeb(fb_readb(src++) ^ inverse, dst++);
            }
@@ -2347,7 +2375,7 @@
                src = logo;
                for (y1 = 0; y1 < LOGO_H; y1++) {
                        for (x1 = 0; x1 < LOGO_W / 2; x1++) {
-                               dst = fb + y1*line + x1/4 + x/8;
+                               dst = fb + (y1+y_offset)*line + x1/4 + x/8;
 
                                outb_p(0,0x3ce);
                                outb_p(*src >> 4,0x3cf);
diff --new-file -u -r linux-2.4.x/scripts/Makefile linux-2.4.x-logo/scripts/Makefile
--- linux-2.4.x/scripts/Makefile        Thu Mar 16 14:27:17 2000
+++ linux-2.4.x-logo/scripts/Makefile   Sat Sep 23 20:13:23 2000
@@ -39,7 +39,10 @@
 docproc: docproc.o
        ${HOSTCC} -o docproc docproc.o
 
+ppmtolinuxlogo: ppmtolinuxlogo.o
+       ${HOSTCC} -o ppmtolinuxlogo ppmtolinuxlogo.o -lpnm -lppm -lpgm -lpbm
+
 clean:
-       rm -f *~ kconfig.tk *.o tkparse mkdep split-include docproc
+       rm -f *~ kconfig.tk *.o tkparse mkdep split-include docproc ppmtolinuxlogo
 
 include $(TOPDIR)/Rules.make
diff --new-file -u -r linux-2.4.x/scripts/ppmtolinuxlogo.c 
linux-2.4.x-logo/scripts/ppmtolinuxlogo.c
--- linux-2.4.x/scripts/ppmtolinuxlogo.c        Wed Dec 31 19:00:00 1969
+++ linux-2.4.x-logo/scripts/ppmtolinuxlogo.c   Sat Sep 23 19:58:20 2000
@@ -0,0 +1,205 @@
+#include <stdio.h>
+
+#include <pnm.h>
+
+#define MAX_COLORS     214
+#define MAX_COLORS_16  16
+#define MAX_COLORS_BW  2
+
+int color_lookup(xel color,xel *colormap,int *used,int maxcolor)
+{
+       int i;
+
+       for (i=0;i<*used;i++) {
+               if (PPM_EQUAL(colormap[i],color))
+                       return i;
+       }
+
+       if (i >= maxcolor) {
+               fprintf(stderr,"Too many colors: %d\n",maxcolor);
+               exit(1);
+       }
+
+       (*used)++;
+       colormap[i]=color;
+       return i;
+}
+
+void print_data(int *data,int len,const char *prefix,const char *name)
+{
+       int i;
+
+       printf("unsigned char linux_logo%s%s[] __initdata = {",prefix,name);
+
+       for (i=0;i<len;i++) {
+               if ( (i%8) == 0) printf("\n ");
+               printf(" 0x%.2X,",data[i]);
+       }
+
+       printf("\n};\n\n");
+}
+
+void linux_encode_bw(xel **ppm,int rows,int cols,int colormax,const char *prefix)
+{
+       int *m;
+       int row,col,i,used=0,bytes;
+       xel black;
+
+       PPM_PUTR(black,0);
+       PPM_PUTG(black,0);
+       PPM_PUTB(black,0);
+
+       bytes=(cols+7)>>3;
+       m=malloc(sizeof(int)*rows*bytes);
+       for (row=i=0;row<rows;row++) {
+               for (col=0;col<cols;col++) {
+                       if ((col&7)==0) {
+                               m[++i] = 0;
+                       } else {
+                               m[i] <<= 1;
+                       }
+                       if (!PPM_EQUAL(ppm[row][col],black))
+                               m[i] |= 1;
+               }
+               /* End of row... */
+               for (;(col&7) != 0;col++) {
+                       m[i] <<= 1;
+               }
+       }
+
+       printf("#ifdef INCLUDE_LINUX_LOGOBW\n\n");
+
+       print_data(m,rows*bytes,prefix,"");
+
+       printf("\n#endif /* INCLUDE_LINUX_LOGOBW */\n\n");
+
+       free(m);
+}
+
+void linux_encode_16(xel **ppm,int rows,int cols,int colormax,const char *prefix)
+{
+       int *r,*g,*b,*m;
+       xel colormap[MAX_COLORS];
+       int row,col,i,used=0;
+
+       m=malloc(sizeof(int)*rows*((cols+1)>>1));
+       for (row=i=0;row<rows;row++) {
+               for (col=0;col<cols;col++) {
+                       if ((col&1)==0) {
+                               m[++i]=0;
+                       } else {
+                               m[i] <<= 4;
+                       }
+                       m[i] |= color_lookup(ppm[row][col],colormap,&used,colormax);
+               }
+       }
+
+       r=malloc(sizeof(int)*used);
+       g=malloc(sizeof(int)*used);
+       b=malloc(sizeof(int)*used);
+
+       for (i=0;i<used;i++) {
+               r[i]=PPM_GETR(colormap[i]);
+               g[i]=PPM_GETG(colormap[i]);
+               b[i]=PPM_GETB(colormap[i]);
+       }
+
+       printf("#ifdef INCLUDE_LINUX_LOGO%s\n\n",prefix);
+
+       print_data(r,used,prefix,"_red");
+       print_data(g,used,prefix,"_green");
+       print_data(b,used,prefix,"_blue");
+       print_data(m,rows*((cols+1)>>1),prefix,"");
+
+       printf("\n#endif /* INCLUDE_LINUX_LOGO%s */\n\n",prefix);
+
+       free(r);
+       free(g);
+       free(b);
+       free(m);
+}
+
+void linux_encode(xel **ppm,int rows,int cols,int colormax,const char *prefix)
+{
+       int *r,*g,*b,*m;
+       xel colormap[MAX_COLORS];
+       int row,col,i,used=0;
+
+       m=malloc(sizeof(int)*rows*cols);
+       for (row=i=0;row<rows;row++) {
+               for (col=0;col<cols;col++,i++) {
+                       m[i]=color_lookup(ppm[row][col],colormap,&used,colormax)+32;
+               }
+       }
+
+       r=malloc(sizeof(int)*used);
+       g=malloc(sizeof(int)*used);
+       b=malloc(sizeof(int)*used);
+
+       for (i=0;i<used;i++) {
+               r[i]=PPM_GETR(colormap[i]);
+               g[i]=PPM_GETG(colormap[i]);
+               b[i]=PPM_GETB(colormap[i]);
+       }
+
+       printf("#define LOGO_W %d\n",cols);
+       printf("#define LOGO_H %d\n\n",rows);
+
+       print_data(r,used,prefix,"_red");
+       print_data(g,used,prefix,"_green");
+       print_data(b,used,prefix,"_blue");
+       print_data(m,rows*cols,prefix,"");
+
+       free(r);
+       free(g);
+       free(b);
+       free(m);
+}
+
+int main(int argc,char **argv)
+{
+       xelval maxval;
+       xel **ppm;
+       FILE *inf;
+       int rows,cols,format,colors,colormax;
+       xel colormap[MAX_COLORS];
+       const char *prefix;
+       void (*encode)(xel **ppm,int rows,int cols,int colormax,const char *prefix);
+
+       if (argc>1 && strcmp(argv[1],"-16")==0) {
+               argc--;
+               memcpy(argv+1,argv+2,(argc-1)*sizeof(argv[0]));
+               prefix="16";
+               colormax=MAX_COLORS_16;
+               encode=linux_encode_16;
+       } else if (argc>1 && strcmp(argv[1],"-bw")==0) {
+               argc--;
+               memcpy(argv+1,argv+2,(argc-1)*sizeof(argv[0]));
+               prefix="_bw";
+               colormax=MAX_COLORS_BW;
+               encode=linux_encode_bw;
+       } else {
+               prefix="";
+               colormax=MAX_COLORS;
+               encode=linux_encode;
+       }
+
+       if (argc==1) {
+               inf=stdin;
+       } else {
+               inf=fopen(argv[1],"r");
+               if (inf==NULL)
+                       exit(1);
+       }
+
+       ppm=pnm_readpnm(inf,&cols,&rows,&maxval,&format);
+       if (format != RPPM_FORMAT &&
+           format != PPM_FORMAT) {
+               fprintf(stderr,"%s: Not a ppm file!\n",argv[1]);
+               exit(1);
+       }
+
+       encode(ppm,rows,cols,colormax,prefix);
+
+       return 0;
+}
-- 
Jason McMullan, Senior Linux Consultant, Linuxcare, Inc.
412.422.8077 tel, 412.656.3519 cell, 415.701.0792 fax
[EMAIL PROTECTED], http://www.linuxcare.com/
Linuxcare. Support for the revolution.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to