diff -ruN ixp4xx.orig/harddisk/base-files/sbin/updating ixp4xx/harddisk/base-files/sbin/updating
--- ixp4xx.orig/harddisk/base-files/sbin/updating	1970-01-01 03:00:00.000000000 +0300
+++ ixp4xx/harddisk/base-files/sbin/updating	2009-03-14 08:05:12.000000000 +0200
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# new kernel into flash
+SIZE=$(ls -l /update/zImage)
+set a$SIZE
+erase /dev/mtd1 0 12 1 >/dev/null 2>&1
+dd if=/update/zImage of=/dev/mtd1 bs=$5 count=1
+rm -rf /update/zImage
+
+exit 0
diff -ruN ixp4xx.orig/image/encode_crc/encode_crc.c ixp4xx/image/encode_crc/encode_crc.c
--- ixp4xx.orig/image/encode_crc/encode_crc.c	1970-01-01 03:00:00.000000000 +0300
+++ ixp4xx/image/encode_crc/encode_crc.c	2009-03-14 07:24:15.000000000 +0200
@@ -0,0 +1,151 @@
+/* **************************************************************************
+
+   This program creates a CRC checksum and encodes the file that is named
+   in the command line.
+   
+   Compile with:  gcc encode_crc.c -Wall -o encode_crc
+
+   Author:     Michael Margraf  (michael.margraf@freecom.com)
+   Copyright:  Freecom Technology GmbH, Berlin, 2004
+               www.freecom.com
+
+  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.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ ************************************************************************* */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+// *******************************************************************
+// CCITT polynom G(x)=x^16+x^12+x^5+1
+#define POLYNOM  0x1021
+#define DEVICE_IS_FSG
+
+// CRC algorithm with MSB first
+int make_crc16(int crc, char new)
+{
+  int i;
+  crc = crc ^ (((int)new) << 8);
+  
+  for(i=0; i<8; i++) {  // work on 8 bits in "new"
+    crc <<= 1;          // MSBs first
+    if(crc & 0x10000)  crc ^= POLYNOM;
+  }
+  return crc & 0xFFFF;
+}
+
+// *******************************************************************
+// Reads the file "filename" into memory and returns pointer to the buffer.
+static char *readfile(char *filename, int *size)
+{
+	FILE		*fp;
+	char		*buffer;
+	struct stat	info;
+	
+	if (stat(filename,&info)!=0)
+		return NULL;
+
+	if ((fp=fopen(filename,"r"))==NULL)
+		return NULL;
+
+	buffer=NULL;
+	for (;;)
+	{
+		if ((buffer=(char *)malloc(info.st_size+1))==NULL)
+			break;
+
+		if (fread(buffer,1,info.st_size,fp)!=info.st_size)
+		{
+			free(buffer);
+			buffer=NULL;
+			break;
+		}
+
+		buffer[info.st_size]='\0';
+		if(size) *size = info.st_size;
+
+		break;
+	}
+
+	(void)fclose(fp);
+
+	return buffer;
+}
+
+
+// *******************************************************************
+int main(int argc, char** argv)
+{
+  if(argc < 2) {
+    printf("ERROR: Argument missing!\n\n");
+    return 1;
+  }
+
+  int count;  // size of file in bytes
+  char *p, *master = readfile(argv[1], &count);
+  if(!master) {
+    printf("ERROR: File not found!\n");
+    return 1;
+  }
+
+  int crc = 0xFFFF, z;
+
+  p = master;
+  for(z=0; z<count; z++)
+    crc = make_crc16(crc, *(p++));  // calculate CRC
+  short crc16 = (short)crc;
+
+	/*
+  if(argc > 2) {   // with flag for device recognition ?
+    p = argv[2];
+    for(z=strlen(p); z>0; z--) {
+      crc ^= (int)(*p);
+      *(p++) = (char)crc;  // encode device flag
+    }
+  }
+	*/
+
+  p = master;
+  for(z=0; z<count; z++) {
+    crc ^= (int)(*p);
+    *(p++) = (char)crc;  // encode file
+  }
+
+
+  // write encoded file...
+  FILE *fp = fopen(argv[1], "w");
+  if(!fp) {
+    printf("ERROR: File not writeable!\n");
+    return 1;
+  }
+
+  if(argc > 2)   // add flag for device recognition ?
+    fwrite(argv[2], strlen(argv[2]), sizeof(char), fp);
+
+  #ifdef DEVICE_IS_FSG
+  // byte swap (IXP4xx is big endian)
+  crc16 = ((crc16 >> 8) & 0xFF) | ((crc16 << 8) & 0xFF00);
+  #endif
+  fwrite(&crc16, 1, sizeof(short), fp);     // first write CRC
+
+  fwrite(master, count, sizeof(char), fp);  // write content
+  fclose(fp);
+
+  free(master);
+  return 0;
+}
diff -ruN ixp4xx.orig/image/encode_crc/Makefile ixp4xx/image/encode_crc/Makefile
--- ixp4xx.orig/image/encode_crc/Makefile	1970-01-01 03:00:00.000000000 +0300
+++ ixp4xx/image/encode_crc/Makefile	2009-03-14 07:24:27.000000000 +0200
@@ -0,0 +1,7 @@
+all: encode_crc
+
+encode_crc: encode_crc.o
+	@gcc encode_crc.c -o encode_crc 
+
+clean:
+	-rm -f *.elf *.gdb *.o *.s encode_crc
diff -ruN ixp4xx.orig/image/Makefile ixp4xx/image/Makefile
--- ixp4xx.orig/image/Makefile	2009-02-19 14:12:38.000000000 +0200
+++ ixp4xx/image/Makefile	2009-03-14 11:59:59.000000000 +0200
@@ -20,6 +20,15 @@
 		-p -o $(BIN_DIR)/openwrt-nslu2-$(1)-16mb.bin
 endef
 
+define Image/Build/fsg3
+	$(CP) $(BIN_DIR)/openwrt-fsg3-zImage $(TARGET_DIR)/zImage
+	rm -rf $(TARGET_DIR)/{var,jffs,rom}
+	$(INSTALL_DIR) $(TARGET_DIR)/var
+	$(TAR) cfz $(BIN_DIR)/openwrt-$(BOARD)-$(2).bin --owner=root --group=root -C $(TARGET_DIR)/ .
+	$(MAKE) -C encode_crc
+	./encode_crc/encode_crc $(BIN_DIR)/openwrt-$(BOARD)-$(2).bin
+endef
+
 define Build/Compile
 	mkdir -p $(BIN_DIR)
 	$(MAKE) -C apex \
@@ -58,6 +67,7 @@
     $(call prepare_generic_squashfs,$(KDIR)/root.squashfs)
 	dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/openwrt-$(BOARD)-$(1).img bs=131072 conv=sync
 	$(call Image/Build/slug,$(1))
+	$(call Image/Build/fsg3,$(1),fsg3-webupgrade,$(1))
 endef
 
 $(eval $(call BuildImage))
diff -ruN ixp4xx.orig/patches-2.6.28/fsg3-fixup.patch ixp4xx/patches-2.6.28/fsg3-fixup.patch
--- ixp4xx.orig/patches-2.6.28/fsg3-fixup.patch	1970-01-01 03:00:00.000000000 +0300
+++ ixp4xx/patches-2.6.28/fsg3-fixup.patch	2009-03-14 11:54:03.000000000 +0200
@@ -0,0 +1,88 @@
+diff -ruN linux-2.6.28.5.orig/arch/arm/mach-ixp4xx/fsg-setup.c linux-2.6.28.5/arch/arm/mach-ixp4xx/fsg-setup.c
+--- linux-2.6.28.5.orig/arch/arm/mach-ixp4xx/fsg-setup.c	2009-02-12 19:51:15.000000000 +0200
++++ linux-2.6.28.5/arch/arm/mach-ixp4xx/fsg-setup.c	2009-03-14 11:51:56.000000000 +0200
+@@ -29,6 +29,7 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/flash.h>
+ #include <asm/gpio.h>
++#include <asm/setup.h>
+ 
+ static struct flash_platform_data fsg_flash_data = {
+ 	.map_name		= "cfi_probe",
+@@ -263,6 +264,69 @@
+ 
+ }
+ 
++void __init openwrt_fixup(struct machine_desc *mdesc, struct tag *t,
++			    char **from, struct meminfo *meminfo)
++{
++	static char openwrt_init_tag[] __initdata = " init=/etc/preinit";
++	static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
++
++	for (; t->hdr.size; t = tag_next(t)){
++		/* Locate the Freecom cmdline */
++		if (t->hdr.tag == ATAG_CMDLINE) {
++			char *p = t->u.cmdline.cmdline;
++			u32 size = t->hdr.size;
++
++			/* Swap command line because redboot is big endian. */
++			if (--size > 0) {
++				const u32 *from = (const u32*)p;
++				u32 *to = (u32*)default_command_line;
++
++				if (size > COMMAND_LINE_SIZE/4)
++					size = COMMAND_LINE_SIZE/4;
++
++				while (size-- > 0)
++				#ifdef CONFIG_CPU_BIG_ENDIAN
++					to[size] = from[size];
++				#else
++					to[size] = swab32(from[size]);
++				#endif
++
++				default_command_line[COMMAND_LINE_SIZE-1] = 0;
++
++				/* Boot always from sda. */
++				char *pp = strstr(default_command_line, "root=/dev/");
++				if(pp) {
++					*(pp+10) = 's';
++					*(pp+14) = 0; /* drop "mem=64M@0x00000000" */
++				}
++			}
++		}
++	}
++
++	printk("%s(%d): End of table at 0x%0lx\n", __FUNCTION__, __LINE__, t);
++
++	/* Overwrite the end of the table with a new cmdline tag. */ 
++	t->hdr.tag = ATAG_CMDLINE;
++	t->hdr.size =
++		(sizeof (struct tag_header) +
++		 strlen(p) + strlen(openwrt_init_tag) + 1 + 4) >> 2;
++
++	strlcpy(t->u.cmdline.cmdline, default_command_line, COMMAND_LINE_SIZE);
++	strlcpy(t->u.cmdline.cmdline + strlen(default_command_line), openwrt_init_tag,
++		COMMAND_LINE_SIZE - strlen(default_command_line));
++
++	printk("%s(%d): New cmdline '%s' at 0x%0lx\n",
++	       __FUNCTION__, __LINE__,
++	       t->u.cmdline.cmdline, (unsigned long)t->u.cmdline.cmdline);
++
++	t = tag_next(t);
++
++	printk("%s(%d): New end of table at 0x%0lx\n", __FUNCTION__, __LINE__, t);
++
++	t->hdr.tag = ATAG_NONE;
++	t->hdr.size = 0;
++}
++
+ MACHINE_START(FSG, "Freecom FSG-3")
+ 	/* Maintainer: www.nslu2-linux.org */
+ 	.phys_io	= IXP4XX_PERIPHERAL_BASE_PHYS,
+@@ -272,5 +336,6 @@
+ 	.timer		= &ixp4xx_timer,
+ 	.boot_params	= 0x0100,
+ 	.init_machine	= fsg_init,
++	.fixup		= openwrt_fixup,
+ MACHINE_END
+ 
