diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/boot/common/misc-common.c linuxppc_2_4_devel-local/arch/ppc/boot/common/misc-common.c
--- linuxppc_2_4_devel-prev/arch/ppc/boot/common/misc-common.c	Thu Sep 26 14:00:36 2002
+++ linuxppc_2_4_devel-local/arch/ppc/boot/common/misc-common.c	Tue Oct  1 19:38:58 2002
@@ -45,9 +45,6 @@
 extern char *vidmem;
 extern int lines, cols;
 extern int orig_x, orig_y;
-extern int keyb_present;
-extern int CRT_tstc(void);
-extern int CRT_getc(void);
 #else
 int cursor(int x, int y) {return 0;}
 void scroll(void) {}
@@ -56,6 +53,13 @@
 #define cols 0
 int orig_x = 0;
 int orig_y = 0;
+#endif
+
+#if defined(CONFIG_ALL_PPC) && (defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_FB_VESA))
+extern int keyb_present;
+extern int CRT_tstc(void);
+extern int CRT_getc(void);
+#else
 #define keyb_present 0
 int CRT_tstc(void) {return 0;}
 int CRT_getc(void) {return 0;}
@@ -119,6 +123,8 @@
 	}
 }
 
+extern void fb_putchar(unsigned char c);
+
 void 
 putc(const char c)
 {
@@ -133,6 +139,7 @@
 	x = orig_x;
 	y = orig_y;
 
+#if defined(CONFIG_VGA_CONSOLE)
 	if ( c == '\n' ) {
 		x = 0;
 		if ( ++y >= lines ) {
@@ -155,6 +162,9 @@
 			}
 		}
 	}
+#elif defined(CONFIG_FB_VESA)
+		fb_putchar(c);
+#endif
 
 	cursor(x, y);
 
@@ -164,44 +174,11 @@
 
 void puts(const char *s)
 {
-	int x,y;
 	char c;
 
-	x = orig_x;
-	y = orig_y;
-
 	while ( ( c = *s++ ) != '\0' ) {
-#if defined(CONFIG_SERIAL_CONSOLE)
-	        serial_putc(com_port, c);
-	        if ( c == '\n' ) serial_putc(com_port, '\r');
-#endif /* CONFIG_SERIAL_CONSOLE */
-
-		if ( c == '\n' ) {
-			x = 0;
-			if ( ++y >= lines ) {
-				scroll();
-				y--;
-			}
-		} else if (c == '\b') {
-		  if (x > 0) {
-		    x--;
-		  }
-		} else {
-			vidmem [ ( x + cols * y ) * 2 ] = c; 
-			if ( ++x >= cols ) {
-				x = 0;
-				if ( ++y >= lines ) {
-					scroll();
-					y--;
-				}
-			}
-		}
+		putc(c);
 	}
-
-	cursor(x, y);
-
-	orig_x = x;
-	orig_y = y;
 }
 
 void error(char *x)
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/boot/include/tty.h linuxppc_2_4_devel-local/arch/ppc/boot/include/tty.h
--- linuxppc_2_4_devel-prev/arch/ppc/boot/include/tty.h	Thu Jan  1 01:00:00 1970
+++ linuxppc_2_4_devel-local/arch/ppc/boot/include/tty.h	Tue Oct  1 19:38:58 2002
@@ -0,0 +1,80 @@
+/*
+ * arch/ppc/boot/include/tty.h
+ *
+ * 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.
+ */
+
+#ifndef _LINUX_TTY_H
+#define _LINUX_TTY_H
+
+/*
+ * This is a copy of include/linux/tty.h containing just the screen_info
+ * structure and related defines.  If a framebuffer is detected by the
+ * PReP boot loader, it will populate this structure and pass it to the
+ * kernel as a BI_SCREEN_INFO bi rec.
+ *
+ * Any changes to the screen_info structure in the kernel must be reflected
+ * in this file info.
+ */
+
+struct screen_info {
+	unsigned char  orig_x;			/* 0x00 */
+	unsigned char  orig_y;			/* 0x01 */
+	unsigned short dontuse1;		/* 0x02 -- EXT_MEM_K sits here */
+	unsigned short orig_video_page;		/* 0x04 */
+	unsigned char  orig_video_mode;		/* 0x06 */
+	unsigned char  orig_video_cols;		/* 0x07 */
+	unsigned short unused2;			/* 0x08 */
+	unsigned short orig_video_ega_bx;	/* 0x0a */
+	unsigned short unused3;			/* 0x0c */
+	unsigned char  orig_video_lines;	/* 0x0e */
+	unsigned char  orig_video_isVGA;	/* 0x0f */
+	unsigned short orig_video_points;	/* 0x10 */
+
+	/* VESA graphic mode -- linear frame buffer */
+	unsigned short lfb_width;		/* 0x12 */
+	unsigned short lfb_height;		/* 0x14 */
+	unsigned short lfb_depth;		/* 0x16 */
+	unsigned long  lfb_base;		/* 0x18 */
+	unsigned long  lfb_size;		/* 0x1c */
+	unsigned short dontuse2, dontuse3;	/* 0x20 -- CL_MAGIC and CL_OFFSET here */
+	unsigned short lfb_linelength;		/* 0x24 */
+	unsigned char  red_size;		/* 0x26 */
+	unsigned char  red_pos;			/* 0x27 */
+	unsigned char  green_size;		/* 0x28 */
+	unsigned char  green_pos;		/* 0x29 */
+	unsigned char  blue_size;		/* 0x2a */
+	unsigned char  blue_pos;		/* 0x2b */
+	unsigned char  rsvd_size;		/* 0x2c */
+	unsigned char  rsvd_pos;		/* 0x2d */
+	unsigned short vesapm_seg;		/* 0x2e */
+	unsigned short vesapm_off;		/* 0x30 */
+	unsigned short pages;			/* 0x32 */
+						/* 0x34 -- 0x3f reserved for future expansion */
+};
+
+extern struct screen_info screen_info;
+
+#define VIDEO_TYPE_MDA		0x10	/* Monochrome Text Display	*/
+#define VIDEO_TYPE_CGA		0x11	/* CGA Display 			*/
+#define VIDEO_TYPE_EGAM		0x20	/* EGA/VGA in Monochrome Mode	*/
+#define VIDEO_TYPE_EGAC		0x21	/* EGA in Color Mode		*/
+#define VIDEO_TYPE_VGAC		0x22	/* VGA+ in Color Mode		*/
+#define VIDEO_TYPE_VLFB		0x23	/* VESA VGA in graphic mode	*/
+
+#define VIDEO_TYPE_PICA_S3	0x30	/* ACER PICA-61 local S3 video	*/
+#define VIDEO_TYPE_MIPS_G364	0x31    /* MIPS Magnum 4000 G364 video  */
+#define VIDEO_TYPE_SNI_RM	0x32    /* SNI RM200 PCI video          */
+#define VIDEO_TYPE_SGI          0x33    /* Various SGI graphics hardware */
+
+#define VIDEO_TYPE_TGAC		0x40	/* DEC TGA */
+
+#define VIDEO_TYPE_SUN          0x50    /* Sun frame buffer. */
+#define VIDEO_TYPE_SUNPCI       0x51    /* Sun PCI based frame buffer. */
+
+#define VIDEO_TYPE_PMAC		0x60	/* PowerMacintosh frame buffer. */
+
+#endif
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/boot/prep/Makefile linuxppc_2_4_devel-local/arch/ppc/boot/prep/Makefile
--- linuxppc_2_4_devel-prev/arch/ppc/boot/prep/Makefile	Tue Oct  1 19:38:30 2002
+++ linuxppc_2_4_devel-local/arch/ppc/boot/prep/Makefile	Tue Oct  1 19:38:58 2002
@@ -31,7 +31,12 @@
 LIBS 				= ../lib/zlib.a ../of1275/of1275.a
 
 obj-$(CONFIG_SERIAL_CONSOLE)	+= ../common/ns16550.o
-obj-$(CONFIG_VGA_CONSOLE)	+= vreset.o kbd.o keymap.o
+obj-$(CONFIG_VGA_CONSOLE)	+= vreset.o
+obj-$(CONFIG_FB_VESA)		+= font.o fb.o simple-fb.o
+
+ifneq ($(CONFIG_VGA_CONSOLE)$(CONFIG_FB_VESA),)
+obj-y				+= kbd.o keymap.o
+endif
 
 # Tools
 MKPREP				:= ../utils/mkprep
@@ -40,6 +45,7 @@
 
 # Extra include search dirs
 CFLAGS_kbd.o			+= -I$(TOPDIR)/drivers/char
+CFLAGS_font.o			+= -I$(TOPDIR)/drivers/video
 
 all: zImage
 
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/boot/prep/fb.c linuxppc_2_4_devel-local/arch/ppc/boot/prep/fb.c
--- linuxppc_2_4_devel-prev/arch/ppc/boot/prep/fb.c	Thu Jan  1 01:00:00 1970
+++ linuxppc_2_4_devel-local/arch/ppc/boot/prep/fb.c	Tue Oct  1 19:53:38 2002
@@ -0,0 +1,258 @@
+/*
+ * arch/ppc/boot/prep/fb.c
+ *
+ * Copyright (C) Hollis Blanchard 2002.
+ * Copyright (C) David Monro 2002.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * residual code from David Monro
+ *
+ * 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 <asm/byteorder.h>
+#include <asm/residual.h>
+#include <asm/pnp.h>
+#include <video/font.h>
+#include "nonstdio.h"
+#include "of1275.h"
+#include "tty.h"
+
+extern void _printk(char const *fmt, ...);
+extern void fb_setup(struct screen_info *info);
+
+extern struct fbcon_font_desc font_vga_8x16;
+
+static RESIDUAL *res;
+struct screen_info screen_info = { 0, 25, 0, 0, 0, 80, 0, 0, 0, 25, 1, 16 };
+
+struct pci_address {
+	unsigned int a_hi;
+	unsigned int a_mid;
+	unsigned int a_lo;
+};
+struct pci_reg_property {
+	struct pci_address addr;
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+#define MAX_ADDRS	8
+#define REG_TYPE_MASK	(0x03000000)
+#define REG_TYPE_MEM	(0x02000000)
+
+static void
+set_default_colors(void)
+{
+	static unsigned char default_colors[] = {
+		0x00, 0x00, 0x00,
+		0x00, 0x00, 0xaa,
+		0x00, 0xaa, 0x00,
+		0x00, 0xaa, 0xaa,
+		0xaa, 0x00, 0x00,
+		0xaa, 0x00, 0xaa,
+		0xaa, 0x55, 0x00,
+		0xaa, 0xaa, 0xaa,
+		0x55, 0x55, 0x55,
+		0x55, 0x55, 0xff,
+		0x55, 0xff, 0x55,
+		0x55, 0xff, 0xff,
+		0xff, 0x55, 0x55,
+		0xff, 0x55, 0xff,
+		0xff, 0xff, 0x55,
+		0xff, 0xff, 0xff
+	};
+	ihandle instance;
+	int i, j;
+
+	instance = open("screen");
+	if (instance == OF_INVALID_HANDLE)
+		goto err;
+	for (j = -1, i = 0; i < 16; i++)
+		setcolor(instance, i, default_colors[++j],
+				      default_colors[++j],
+				      default_colors[++j]);
+	close(instance);
+err:
+}
+
+static int
+of_find_display(void)
+{
+	phandle ph;
+	ihandle ih;
+	int width, height, depth, bpl;
+	unsigned long addr, size;
+	unsigned long fbmem_minsz;
+	int addrslen;
+	int i;
+	struct pci_reg_property addrs[MAX_ADDRS];
+    
+	if ((ph = finddevice("/chosen")) == OF_INVALID_HANDLE)
+		goto notfound;
+	if (getprop(ph, "stdout", &ih, sizeof(ih)) != 4)
+		goto notfound;
+	if ((ph = instancetopackage(ih)) == OF_INVALID_HANDLE)
+		goto notfound;
+	if (getprop(ph, "depth", &depth, sizeof(depth)) != sizeof(depth))
+		goto notfound;
+	if (getprop(ph, "width", &width, sizeof(width)) != sizeof(width))
+		goto notfound;
+	if (getprop(ph, "height", &height, sizeof(height)) != sizeof(height))
+		goto notfound;
+	if (getprop(ph, "linebytes", &bpl, sizeof(bpl)) != sizeof(bpl))
+		bpl = width;	/* we allow linebytes not be set  */
+	if (bpl == 1)		/* required for GXT1000P at least */
+		bpl = 0x1000;
+
+	/* Guess the framebuffer address from the assigned addresses */
+	addrslen = getprop(ph, "assigned-address", &addrs, sizeof(addrs));
+	if (addrslen > sizeof(addrs))
+		addrslen = sizeof(addrs);
+
+	addr = 0; size = 0;
+	fbmem_minsz = bpl * height * depth / 8;
+
+	for (i = 0; i < addrslen / sizeof(addrs[0]); ++i) {
+		unsigned int cmpaddr = addrs[i].addr.a_lo;
+		unsigned int cmpsize = addrs[i].size_lo;
+		if (((addrs[i].addr.a_hi & REG_TYPE_MASK) == REG_TYPE_MEM) &&
+				(cmpaddr >= fbmem_minsz)) {
+			/* Fix address if not from the CPUs point of view */
+			if (cmpaddr < 0x40000000ul)
+				cmpaddr += 0xc0000000ul;
+
+			/* We select the largest "large enough" region */
+			if (cmpsize > size) {
+				addr = cmpaddr;
+				size = cmpsize;
+			}
+		}
+	}
+
+	if (!size)
+		goto notfound;
+	
+	/* Fill in screen_info structure */
+	screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
+	screen_info.lfb_depth        = depth;
+	screen_info.lfb_width        = width;
+	screen_info.lfb_height       = height;
+	screen_info.lfb_linelength   = bpl;
+	screen_info.lfb_base         = addr;
+	screen_info.lfb_size         = size / 65536;
+
+	/* Set the colour palette */
+	set_default_colors();
+
+	return 1;
+notfound:
+	return 0;
+}
+
+static int
+process_pnp_tag(int offset, int *found)
+{
+	PnP_TAG_PACKET *ptr;
+	int rawtag, tag, taglen;
+	int tagtype;
+
+	ptr = (PnP_TAG_PACKET *) & (res->DevicePnPHeap[offset]);
+	rawtag = res->DevicePnPHeap[offset];
+	if (rawtag & 0x80) {
+		taglen = 3 + ld_le16((unsigned short *)
+				&res->DevicePnPHeap[offset + 1]);
+		tag = rawtag & 0x7F;
+		if (tag == 0x04) {
+			tagtype = res->DevicePnPHeap[offset + 3];
+			if (tagtype == 0x04) {
+				unsigned char *ptr;
+				ptr = &(res->DevicePnPHeap[offset]);
+				screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
+				screen_info.lfb_depth = ptr[4] << 3;
+				screen_info.lfb_width = 
+					ld_le16((unsigned short *)&ptr[6]);
+				screen_info.lfb_height = 
+					ld_le16((unsigned short *)&ptr[8]);
+				screen_info.lfb_linelength = 
+					ld_le16((unsigned short *)(&ptr[10]));
+				screen_info.lfb_base = 
+					ld_le32((unsigned int *)(&ptr[12]));
+				if (screen_info.lfb_base < 0xC0000000ul)
+					screen_info.lfb_base += 0xC0000000ul;
+
+				screen_info.lfb_size = 
+				    ld_le32((unsigned int *)(&ptr[20])) / 65536;
+				*found = 1;
+				return -1;
+			}
+		}
+	} else {
+		tag = (rawtag >> 3) & 0xF;
+		taglen = (rawtag & 0x07) + 1;
+		if (tag == 0xF) {
+			taglen = -1;
+		}
+	}
+	return taglen;
+}
+
+static int
+process_pnp_desc(int offset)
+{
+	int incr;
+	int found = 0;
+
+	for (;;) {
+		incr = process_pnp_tag(offset, &found);
+		if (incr == -1)
+			break;
+
+		offset += incr;
+	}
+
+	return found;
+}
+
+static int
+residual_find_display(RESIDUAL *residual)
+{
+	int i;
+	int found = 0;
+
+	res = residual;
+
+	/* walk the tree looking for displays */
+	for (i = 0; i < res->ActualNumDevices; i++) {
+		if (res->Devices[i].DeviceId.BaseType == DisplayController) {
+			found = process_pnp_desc(res->Devices[i].AllocatedOffset);
+			break;
+		}
+	}
+
+	return found;
+}
+
+int
+fb_init(RESIDUAL *residual, void *promptr)
+{
+	int found = 0;
+
+	if (residual)
+		found = residual_find_display(residual);
+
+	if (!found && promptr)
+		found = of_find_display();
+
+	if (found) {
+		_printk("%dx%dx%d framebuffer found at 0x%08x (%d pages)\n",
+				screen_info.lfb_width,screen_info.lfb_height,
+				screen_info.lfb_depth, screen_info.lfb_base,
+				screen_info.lfb_size);
+		fb_setup(&screen_info);
+	}
+
+	return found;
+}
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/boot/prep/font.c linuxppc_2_4_devel-local/arch/ppc/boot/prep/font.c
--- linuxppc_2_4_devel-prev/arch/ppc/boot/prep/font.c	Thu Jan  1 01:00:00 1970
+++ linuxppc_2_4_devel-local/arch/ppc/boot/prep/font.c	Tue Oct  1 19:38:58 2002
@@ -0,0 +1 @@
+#include "font_8x16.c"
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/boot/prep/misc.c linuxppc_2_4_devel-local/arch/ppc/boot/prep/misc.c
--- linuxppc_2_4_devel-prev/arch/ppc/boot/prep/misc.c	Tue Oct  1 19:38:30 2002
+++ linuxppc_2_4_devel-local/arch/ppc/boot/prep/misc.c	Tue Oct  1 19:38:58 2002
@@ -24,6 +24,7 @@
 #include "mpc10x.h"
 #include "nonstdio.h"
 #include "of1275.h"
+#include "tty.h"
 #include "zlib.h"
 
 /*
@@ -59,15 +60,23 @@
 char *vidmem = (char *)0xC00B8000;
 int lines = 25, cols = 80;
 int orig_x, orig_y = 24;
+extern int vga_init(unsigned char *ISA_mem);
+#else
+int vga_init(unsigned char *ISA_mem) {return 0;}
 #endif /* CONFIG_VGA_CONSOLE */
 
 extern int CRT_tstc(void);
-extern int vga_init(unsigned char *ISA_mem);
 extern void gunzip(void *, int, unsigned char *, int *);
 extern unsigned long serial_init(int chan, void *ignored);
 extern void serial_fixups(void);
 extern unsigned long mpc10x_get_mem_size(int mem_map);
 
+#if defined(CONFIG_FB_VESA)
+extern int fb_init(RESIDUAL *residual, void *promptr);
+#else
+int fb_init(RESIDUAL *residual, void *promptr) {return 0;}
+#endif
+
 void
 writel(unsigned int val, unsigned int address)
 {
@@ -130,9 +139,13 @@
 #if defined(CONFIG_SERIAL_CONSOLE)
 	com_port = serial_init(0, NULL);
 #endif /* CONFIG_SERIAL_CONSOLE */
-#if defined(CONFIG_VGA_CONSOLE)
-	vga_init((unsigned char *)0xC0000000);
-#endif /* CONFIG_VGA_CONSOLE */
+
+	/*
+	 * If we can use the framebuffer, then do so, otherwise try to
+	 * drive the VGA hardware directly
+	 */
+	if (!fb_init(residual, promptr))
+		vga_init((unsigned char *)0xC0000000);
 
 	/*
 	 * Tell the user where we were loaded at and where we were relocated
@@ -352,6 +365,15 @@
 		rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
 		rec = (struct bi_record *)((unsigned long)rec + rec->size);
 
+#ifdef CONFIG_FB_VESA
+		if (screen_info.lfb_base) {
+		  rec->tag = BI_SCREEN_INFO;
+		  memcpy((char *)rec->data, &screen_info, sizeof(screen_info));
+		  rec->size = sizeof(struct bi_record) + sizeof(screen_info);
+		  rec = (struct bi_record *)((unsigned long)rec + rec->size);
+		}
+#endif
+
 		rec->tag = BI_CMD_LINE;
 		memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
 		rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/boot/prep/simple-fb.c linuxppc_2_4_devel-local/arch/ppc/boot/prep/simple-fb.c
--- linuxppc_2_4_devel-prev/arch/ppc/boot/prep/simple-fb.c	Thu Jan  1 01:00:00 1970
+++ linuxppc_2_4_devel-local/arch/ppc/boot/prep/simple-fb.c	Tue Oct  1 19:38:58 2002
@@ -0,0 +1,229 @@
+/*
+ * arch/ppc/boot/prep/simple-fb.c
+ *
+ * Copyright (C) Hollis Blanchard 2002.
+ * Copyright (C) Leigh Brown 2002.
+ *
+ * 26 Jun 2002
+ *
+ * only does width=8 fonts, but do we really need more?
+ * fb code adapted from fbcon-cfb8.c by Hollis Blanchard
+ *
+ * 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 <asm/byteorder.h>
+#include <video/font.h>
+#include "nonstdio.h"
+#include "tty.h"
+
+/*
+ * Explanation:
+ *
+ * cur_addr - the address of the first word of the character cell that the
+ * cursor is located at.
+ *
+ * line_factor - number of words (4 bytes) from the last word of the last
+ * character of a line to the first word of the first character cell of the 
+ * next line
+ *
+ */
+
+#define WORDS_PER_CELL_ROW 2
+
+static unsigned int *cur_addr;
+static unsigned int cur_x;
+static unsigned int cur_y;
+static unsigned int max_x;
+static unsigned int max_y;
+static unsigned int line_factor;
+static unsigned int curs_shown;
+static unsigned int initialized;
+
+extern struct fbcon_font_desc font_vga_8x16;
+
+/*
+ * used to expand each 4-bit font nibble into 4 bytes, giving us 1 fb byte per
+ * font bit. from fbcon-cfb8.c
+ */
+static unsigned int nibbletab[] = {
+    0x00000000,0x00000007,0x00000700,0x00000707,
+    0x00070000,0x00070007,0x00070700,0x00070707,
+    0x07000000,0x07000007,0x07000700,0x07000707,
+    0x07070000,0x07070007,0x07070700,0x07070707
+};
+
+static const struct fbcon_font_desc *font = &font_vga_8x16;
+
+extern void *memset(void *s, int c, size_t n);
+extern void *memcpy(void *dest, const void *src, int n);
+
+static void
+invert_cell(void)
+{
+	int y;
+	int lf = line_factor;
+	const unsigned int invert = 0xffffffff;
+	unsigned int *p = cur_addr;
+	for (y = font->height; y; --y) {
+		*(p)   ^= invert;
+		*(++p) ^= invert;
+		p      += lf;
+	}
+}
+
+static void
+hide_cursor(void)
+{
+	if (curs_shown) {
+		invert_cell();
+		curs_shown = 0;
+	}
+}
+
+static void
+show_cursor(void)
+{
+	if (!curs_shown) {
+		invert_cell();
+		curs_shown = 1;
+	}
+}
+
+static void
+home(void)
+{
+	cur_x = cur_y = 0;
+	cur_addr = (unsigned int *)screen_info.lfb_base;
+}
+
+static void
+clear(void)
+{
+	/* Black background */
+	memset((char *)screen_info.lfb_base, 0,
+		screen_info.lfb_linelength * screen_info.lfb_height);
+	home();
+}
+
+static void
+draw_char(unsigned char c)
+{
+	int y;
+	int offset = c * font->height;
+	int lf = line_factor;
+	unsigned int *addr = cur_addr;
+	unsigned char *fontdata = (unsigned char *)font->data;
+
+	for (y = font->height; y; --y) {
+		unsigned char chardata = fontdata[offset];
+
+		*(addr)   = nibbletab[chardata >> 4];  /* top 4 bytes/bits */
+		*(++addr) = nibbletab[chardata & 0xf]; /* bottom 4 bytes/bits */
+		addr     += lf;
+		offset++;
+	}
+}
+
+static void
+scroll(void)
+{
+	/* Scroll up one line - assumes lfb_height % font->height == 0 */
+	memcpy((void *)screen_info.lfb_base,
+	       (void *)screen_info.lfb_base + screen_info.lfb_width * font->height,
+	       screen_info.lfb_width * (screen_info.lfb_height - font->height));
+
+	/* Clear the bottom line - same assumption */
+	memset((void *)screen_info.lfb_base + screen_info.lfb_width * 
+			(screen_info.lfb_height - font->height),
+		0, screen_info.lfb_width * font->height);
+}
+
+static void
+cr(void)
+{
+	if (cur_x) {
+		cur_addr -= cur_x * WORDS_PER_CELL_ROW;
+		cur_x = 0;
+	}
+}
+
+static void
+lf(void)
+{
+	if (cur_y + 1 < max_y) {
+		cur_addr += max_x * WORDS_PER_CELL_ROW * font->height;
+		++cur_y;
+	}
+	else
+		scroll();
+}
+
+static inline void
+crlf(void)
+{
+	cr();
+	lf();
+}
+
+static void
+advance(void)
+{
+	++cur_x;
+	cur_addr += WORDS_PER_CELL_ROW;
+	if (cur_x >= max_x)
+		crlf();
+}
+
+static void
+bs(void)
+{
+	if (cur_x) {
+		cur_addr -= WORDS_PER_CELL_ROW;
+		--cur_x;
+	}
+	else if (cur_y) {
+		cur_addr -= (max_x * WORDS_PER_CELL_ROW) * 
+			    (font->height - 1) + WORDS_PER_CELL_ROW;
+		cur_x = max_x - 1;
+		--cur_y;
+	}
+}
+
+void
+fb_setup(void)
+{
+	max_x = screen_info.lfb_width >> 3; /* fixed 8 byte wide font */
+	max_y = screen_info.lfb_height / font->height;
+	line_factor = (max_x * WORDS_PER_CELL_ROW) - 1;
+
+	clear();
+	show_cursor();
+
+	initialized = 1;
+}
+
+void
+fb_putchar(unsigned char c)
+{
+	if (!initialized)
+		return;
+
+	hide_cursor();
+	switch (c) {
+		default:
+			draw_char(c);
+			advance();
+			break;
+		case '\n':
+			crlf();
+			break;
+		case '\b':
+			bs();
+			break;
+	}
+	show_cursor();
+}
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/kernel/setup.c linuxppc_2_4_devel-local/arch/ppc/kernel/setup.c
--- linuxppc_2_4_devel-prev/arch/ppc/kernel/setup.c	Thu Sep 26 13:58:59 2002
+++ linuxppc_2_4_devel-local/arch/ppc/kernel/setup.c	Tue Oct  1 19:38:58 2002
@@ -492,6 +492,18 @@
 		case BI_MEMSIZE:
 			boot_mem_size = data[0];
 			break;
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_FB_VGA16) || \
+    defined(CONFIG_FB_VGA16_MODULE) || defined(CONFIG_FB_VESA)
+		case BI_SCREEN_INFO:
+			if (rec->size == sizeof(struct screen_info) +
+					 sizeof(struct bi_record))
+				memcpy(&screen_info, &data[0],
+						sizeof(struct screen_info));
+			else
+				printk(KERN_WARNING
+				    "Ignoring invalid BI_SCREEN_INFO record\n");
+			break;
+#endif /* CONFIG_VGA_CONSOLE || CONFIG_FB_VGA16 || CONFIG_FB_VESA */
 		}
 		rec = (struct bi_record *)((ulong)rec + rec->size);
 	}
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/arch/ppc/platforms/prep_setup.c linuxppc_2_4_devel-local/arch/ppc/platforms/prep_setup.c
--- linuxppc_2_4_devel-prev/arch/ppc/platforms/prep_setup.c	Tue Oct  1 19:38:13 2002
+++ linuxppc_2_4_devel-local/arch/ppc/platforms/prep_setup.c	Tue Oct  1 19:38:58 2002
@@ -662,47 +662,6 @@
 #endif /* CONFIG_SOUND_CS4232 */
 
 /*
- * Fill out screen_info according to the residual data. This allows us to use
- * at least vesafb.
- */
-static void __init
-prep_init_vesa(void)
-{
-#if defined(CONFIG_PREP_RESIDUAL) && \
-	(defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \
-	 defined(CONFIG_FB_VESA))
-	PPC_DEVICE *vgadev;
-
-	vgadev = residual_find_device(~0, NULL, DisplayController, SVGAController,
-									-1, 0);
-	if (vgadev != NULL) {
-		PnP_TAG_PACKET *pkt;
-
-		pkt = PnP_find_large_vendor_packet(
-				(unsigned char *)&res->DevicePnPHeap[vgadev->AllocatedOffset],
-				0x04, 0); /* 0x04 = Display Tag */
-		if (pkt != NULL) {
-			unsigned char *ptr = (unsigned char *)pkt;
-
-			if (ptr[4]) {
-				/* graphics mode */
-				screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
-
-				screen_info.lfb_depth = ptr[4] * 8;
-
-				screen_info.lfb_width = swab16(*(short *)(ptr+6));
-				screen_info.lfb_height = swab16(*(short *)(ptr+8));
-				screen_info.lfb_linelength = swab16(*(short *)(ptr+10));
-
-				screen_info.lfb_base = swab32(*(long *)(ptr+12));
-				screen_info.lfb_size = swab32(*(long *)(ptr+20)) / 65536;
-			}
-		}
-	}
-#endif /* CONFIG_PREP_RESIDUAL */
-}
-
-/*
  * Set BAT 2 to access 0x80000000 so early progress messages will work
  */
 static __inline__ void
@@ -941,8 +900,6 @@
 	prep_init_sound();
 #endif /* CONFIG_SOUND_CS4232 */
 
-	prep_init_vesa();
-
 	switch (_prep_type) {
 	case _PREP_Motorola:
 		raven_init();
diff -urN -X /home/leigh/.diffex linuxppc_2_4_devel-prev/include/asm-ppc/bootinfo.h linuxppc_2_4_devel-local/include/asm-ppc/bootinfo.h
--- linuxppc_2_4_devel-prev/include/asm-ppc/bootinfo.h	Thu Sep 26 13:58:14 2002
+++ linuxppc_2_4_devel-local/include/asm-ppc/bootinfo.h	Tue Oct  1 19:38:58 2002
@@ -32,6 +32,7 @@
 #define BI_SYSMAP		0x1015
 #define BI_MACHTYPE		0x1016
 #define BI_MEMSIZE		0x1017
+#define BI_SCREEN_INFO		0x1018
 
 extern struct bi_record *find_bootinfo(void);
 extern void parse_bootinfo(struct bi_record *rec);
