Index: target/linux/ar71xx/files/drivers/mtd/wrt160nl_part.c
===================================================================
--- target/linux/ar71xx/files/drivers/mtd/wrt160nl_part.c	(revision 20230)
+++ target/linux/ar71xx/files/drivers/mtd/wrt160nl_part.c	(working copy)
@@ -123,13 +123,8 @@
 		goto free_hdr;
 	}
 
-	kernel_len = uheader->ih_size / master->erasesize;
-	if (uheader->ih_size % master->erasesize)
-		kernel_len++;
-
-	kernel_len++;
-	kernel_len *= master->erasesize;
-
+	kernel_len = le32_to_cpu(theader->offsets[1]) + sizeof(struct cybertan_header);
+	
 	trx_parts[0].name = "u-boot";
 	trx_parts[0].offset = 0;
 	trx_parts[0].size = 4 * master->erasesize;
Index: target/linux/ar71xx/image/Makefile
===================================================================
--- target/linux/ar71xx/image/Makefile	(revision 20230)
+++ target/linux/ar71xx/image/Makefile	(working copy)
@@ -297,16 +297,12 @@
 define Image/Build/CyberTAN
 	$(call PatchKernelGzip,$(2),$(3))
 	$(call MkImageGzip,$(KDIR)/vmlinux-$(2).bin.gz,$(KDIR)/vmlinux-$(2).uImage)
-	( \
-		dd if=$(KDIR)/vmlinux-$(2).uImage bs=64k conv=sync; \
-		dd if=/dev/zero bs=1 count=65476; \
-		dd if=$(KDIR)/root.$(1) bs=64k; \
-	) > $(KDIR)/vmlinux-$(2).image
-	$(STAGING_DIR_HOST)/bin/trx -o $(KDIR)/vmlinux-$(2).trx \
-		-f $(KDIR)/vmlinux-$(2).image
-	-$(STAGING_DIR_HOST)/bin/addpattern -B $(2) -v v$(4) -g \
-		-i $(KDIR)/vmlinux-$(2).trx \
+	$(STAGING_DIR_HOST)/bin/trx -o $(KDIR)/image.tmp -f $(KDIR)/vmlinux-$(2).uImage \
+		-x 32 -a 0x10000 -x -32 -f $(KDIR)/root.$(1)
+	-$(STAGING_DIR_HOST)/bin/addpattern -B $(2) -v v$(4) \
+		-i $(KDIR)/image.tmp \
 		-o $(call imgname,$(1),$(2)).bin
+	rm $(KDIR)/image.tmp
 endef
 
 wndr3700_mtdlayout=mtdparts=spi0.0:320k(u-boot)ro,128k(u-boot-env)ro,1024k(kernel),6656k(rootfs),64k(art)ro,7680k@0x70000(firmware)
Index: package/mtd/src/crc32.h
===================================================================
--- package/mtd/src/crc32.h	(revision 20230)
+++ package/mtd/src/crc32.h	(working copy)
@@ -7,7 +7,7 @@
 
 /* Return a 32-bit CRC of the contents of the buffer. */
 
-	static inline uint32_t
+static inline uint32_t
 crc32(uint32_t val, const void *ss, int len)
 {
 	const unsigned char *s = ss;
@@ -16,4 +16,11 @@
 	return val;
 }
 
+static inline unsigned int crc32buf(char *buf, size_t len)
+{
+	return crc32(0xFFFFFFFF, buf, len);
+}
+
+
+
 #endif
Index: package/mtd/src/mtd.c
===================================================================
--- package/mtd/src/mtd.c	(revision 20230)
+++ package/mtd/src/mtd.c	(working copy)
@@ -44,10 +44,23 @@
 #include "mtd-api.h"
 #include "fis.h"
 #include "mtd.h"
+#include "crc32.h"
 
 #define MAX_ARGS 8
 #define JFFS2_DEFAULT_DIR	"" /* directory name without /, empty means root dir */
 
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define STORE32_LE(X)           ((((X) & 0x000000FF) << 24) | (((X) & 0x0000FF00) << 8) | (((X) & 0x00FF0000) >> 8) | (((X) & 0xFF000000) >> 24))
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define STORE32_LE(X)           (X)
+#else
+#error unkown endianness!
+#endif
+
+ssize_t pread(int fd, void *buf, size_t count, off_t offset);
+ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);
+
+#define TRX_MAGIC       0x30524448      /* "HDR0" */
 struct trx_header {
 	uint32_t magic;		/* "HDR0" */
 	uint32_t len;		/* Length of file including header */
@@ -252,6 +265,82 @@
 }
 
 static int
+mtd_fixtrx(const char *mtd, size_t offset)
+{
+	int fd;
+	struct trx_header *trx;
+	char *buf;
+	ssize_t res;
+	size_t block_offset;
+
+	if (quiet < 2)
+		fprintf(stderr, "Trying to fix trx header in %s at 0x%x...\n", mtd, offset);
+	
+	block_offset = offset & ~(erasesize - 1);
+	offset -= block_offset;
+	
+	fd = mtd_check_open(mtd);
+	if(fd < 0) {
+		fprintf(stderr, "Could not open mtd device: %s\n", mtd);
+		exit(1);
+	}
+
+	if (block_offset + erasesize > mtdsize) {
+		fprintf(stderr, "Offset too large, device size 0x%x\n", mtdsize);
+		exit(1);
+	}
+	
+	buf = malloc(erasesize);
+	if (!buf) {
+		perror("malloc");
+		exit(1);
+	}
+	
+	res = pread(fd, buf, erasesize, block_offset);
+	if (res != erasesize) {
+		perror("pread");
+		exit(1);
+	}
+	
+	trx = (struct trx_header *) (buf + offset);
+	if (trx->magic != STORE32_LE(0x30524448)) {
+		fprintf(stderr, "No trx magic found\n");
+		exit(1);
+	}
+	
+	if (trx->len == STORE32_LE(erasesize - offset)) {
+		if (quiet < 2)
+			fprintf(stderr, "Header already fixed, exiting\n");
+		close(fd);
+		return 0;
+	}
+
+	trx->len = STORE32_LE(erasesize - offset);
+	
+	trx->crc32 = STORE32_LE(crc32buf((char*) &trx->flag_version, erasesize - offset - 3*4));
+	if (mtd_erase_block(fd, block_offset)) {
+		fprintf(stderr, "Can't erease block at 0x%x (%s)\n", block_offset, strerror(errno));
+		exit(1);
+	}
+	
+	if (quiet < 2)
+		fprintf(stderr, "New crc32: 0x%x, rewriting block\n", trx->crc32);
+	
+	if (pwrite(fd, buf, erasesize, block_offset) != erasesize) {
+		fprintf(stderr, "Error writing block (%s)\n", strerror(errno));
+		exit(1);
+	}
+	
+	if (quiet < 2)
+		fprintf(stderr, "Done.\n");
+	
+	close (fd);
+	sync();
+	return 0;
+
+}
+
+static int
 mtd_refresh(const char *mtd)
 {
 	int fd;
@@ -480,6 +569,7 @@
 	"        erase                   erase all data on device\n"
 	"        write <imagefile>|-     write <imagefile> (use - for stdin) to device\n"
 	"        jffs2write <file>       append <file> to the jffs2 partition on the device\n"
+	"        fixtrx                  fix the checksum in a trx header on first boot\n"
 	"Following options are available:\n"
 	"        -q                      quiet mode (once: no [w] on writing,\n"
 	"                                           twice: no status messages)\n"
@@ -488,6 +578,7 @@
 	"        -e <device>             erase <device> before executing the command\n"
 	"        -d <name>               directory for jffs2write, defaults to \"tmp\"\n"
 	"        -j <name>               integrate <file> into jffs2 data when writing an image\n"
+	"        -o offset               offset of the trx header in the partition (for fixtrx)\n"
 #ifdef FIS_SUPPORT
 	"        -F <part>[:<size>[:<entrypoint>]][,<part>...]\n"
 	"                                alter the fis partition table to create new partitions replacing\n"
@@ -518,12 +609,14 @@
 	int ch, i, boot, imagefd = 0, force, unlocked;
 	char *erase[MAX_ARGS], *device = NULL;
 	char *fis_layout = NULL;
+	size_t offset = 0;
 	enum {
 		CMD_ERASE,
 		CMD_WRITE,
 		CMD_UNLOCK,
 		CMD_REFRESH,
-		CMD_JFFS2WRITE
+		CMD_JFFS2WRITE,
+		CMD_FIXTRX
 	} cmd = -1;
 
 	erase[0] = NULL;
@@ -536,7 +629,7 @@
 #ifdef FIS_SUPPORT
 			"F:"
 #endif
-			"frqe:d:j:")) != -1)
+			"frqe:d:j:o:")) != -1)
 		switch (ch) {
 			case 'f':
 				force = 1;
@@ -561,6 +654,14 @@
 			case 'd':
 				jffs2dir = optarg;
 				break;
+			case 'o':
+				errno = 0;
+				offset = strtoul(optarg, 0, 0);
+				if (errno) {
+					fprintf(stderr, "-o: illegal numeric string\n");
+					usage();
+				}
+				break;
 #ifdef FIS_SUPPORT
 			case 'F':
 				fis_layout = optarg;
@@ -585,6 +686,9 @@
 	} else if ((strcmp(argv[0], "erase") == 0) && (argc == 2)) {
 		cmd = CMD_ERASE;
 		device = argv[1];
+	} else if ((strcmp(argv[0], "fixtrx") == 0) && (argc == 2)) {
+		cmd = CMD_FIXTRX;
+		device = argv[1];
 	} else if ((strcmp(argv[0], "write") == 0) && (argc == 3)) {
 		cmd = CMD_WRITE;
 		device = argv[2];
@@ -657,6 +761,9 @@
 		case CMD_REFRESH:
 			mtd_refresh(device);
 			break;
+		case CMD_FIXTRX:
+			mtd_fixtrx(device, offset);
+			break;
 	}
 
 	sync();
Index: package/mtd/src/trx.c
===================================================================
--- package/mtd/src/trx.c	(revision 20230)
+++ package/mtd/src/trx.c	(working copy)
@@ -31,6 +31,7 @@
 #include <sys/ioctl.h>
 #include "mtd-api.h"
 #include "mtd.h"
+#include "crc32.h"
 
 #define TRX_MAGIC       0x30524448      /* "HDR0" */
 struct trx_header {
@@ -41,39 +42,6 @@
 	unsigned offsets[3];	/* Offsets of partitions from start of header */
 };
 
-static unsigned long *crc32 = NULL;
-
-static void init_crc32()
-{
-	unsigned long crc;
-	unsigned long poly = 0xEDB88320L;
-	int n, bit;
-
-	if (crc32)
-		return;
-
-	crc32 = (unsigned long *) malloc(256 * sizeof(unsigned long));
-	if (!crc32) {
-		perror("malloc");
-		exit(1);
-	}
-
-	for (n = 0; n < 256; n++) {
-		crc = (unsigned long) n;
-		for (bit = 0; bit < 8; bit++)
-			crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
-		crc32[n] = crc;
-	}
-}
-
-static unsigned int crc32buf(char *buf, size_t len)
-{
-	unsigned int crc = 0xFFFFFFFF;
-	for (; len; len--, buf++)
-		crc = crc32[(crc ^ *buf) & 0xff] ^ (crc >> 8);
-	return crc;
-}
-
 int
 trx_fixup(int fd, const char *name)
 {
Index: tools/firmware-utils/src/trx.c
===================================================================
--- tools/firmware-utils/src/trx.c	(revision 20230)
+++ tools/firmware-utils/src/trx.c	(working copy)
@@ -77,7 +77,7 @@
 
 void usage(void)
 {
-	fprintf(stderr, "Usage: trx [-o outfile] [-m maxlen] [-a align] [-b offset] [-f file] [-f file [-f file]]\n");
+	fprintf(stderr, "Usage: trx [-o outfile] [-m maxlen] [-a align] [-b absolute offset] [-x relative offset] [-f file] [-f file [-f file]]\n");
 	exit(EXIT_FAILURE);
 }
 
@@ -90,6 +90,7 @@
 	char *e;
 	int c, i, append = 0;
 	size_t n;
+	ssize_t n2;
 	uint32_t cur_len;
 	unsigned long maxlen = TRX_MAX_LEN;
 	struct trx_header *p;
@@ -110,7 +111,7 @@
 	in = NULL;
 	i = 0;
 
-	while ((c = getopt(argc, argv, "-:o:m:a:b:f:A:")) != -1) {
+	while ((c = getopt(argc, argv, "-:o:m:a:x:b:f:A:")) != -1) {
 		switch (c) {
 			case 'A':
 				append = 1;
@@ -201,6 +202,25 @@
 					cur_len = n;
 				}
 				break;
+			case 'x':
+				errno = 0;
+				n2 = strtol(optarg, &e, 0);
+				if (errno || (e == optarg) || *e) {
+					fprintf(stderr, "illegal numeric string\n");
+					usage();
+				}
+				if (n2 < 0) {
+					if (-n2 > cur_len) {
+						fprintf(stderr, "WARNING: current length smaller then -x %d offset\n",n2);
+						cur_len = 0;
+					} else
+						cur_len += n2;
+				} else {
+					memset(buf + cur_len, 0, n2);
+					cur_len += n2;
+				}
+				
+				break;
 			default:
 				usage();
 		}
