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 jmcmullan@linuxcare.com, 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 majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sat Oct 07 2000 - 21:00:13 EST