diff -urN linux.old/fs/partitions/check.c linux.dev/fs/partitions/check.c
--- linux.old/fs/partitions/check.c	2006-05-31 02:31:44.000000000 +0200
+++ linux.dev/fs/partitions/check.c	2006-06-15 01:27:17.000000000 +0200
@@ -29,6 +29,7 @@
 #include "ldm.h"
 #include "mac.h"
 #include "msdos.h"
+#include "openwrt.h"
 #include "osf.h"
 #include "sgi.h"
 #include "sun.h"
@@ -48,6 +49,9 @@
 	 * Probe partition formats with tables at disk address 0
 	 * that also have an ADFS boot block at 0xdc0.
 	 */
+#ifdef CONFIG_OPENWRT_PARTITION
+	openwrt_partition,
+#endif
 #ifdef CONFIG_ACORN_PARTITION_ICS
 	adfspart_check_ICS,
 #endif
diff -urN linux.old/fs/partitions/Kconfig linux.dev/fs/partitions/Kconfig
--- linux.old/fs/partitions/Kconfig	2006-05-31 02:31:44.000000000 +0200
+++ linux.dev/fs/partitions/Kconfig	2006-06-15 01:27:17.000000000 +0200
@@ -14,6 +14,12 @@
 
 	  If unsure, say N.
 
+config OPENWRT_PARTITION
+	bool "OpenWrt partition support" if PARTITION_ADVANCED
+	default y
+	help
+	  Support the custom OpenWrt partition map
+
 config ACORN_PARTITION
 	bool "Acorn partition support" if PARTITION_ADVANCED
 	default y if ARCH_ACORN
diff -urN linux.old/fs/partitions/Makefile linux.dev/fs/partitions/Makefile
--- linux.old/fs/partitions/Makefile	2006-05-31 02:31:44.000000000 +0200
+++ linux.dev/fs/partitions/Makefile	2006-06-15 01:27:17.000000000 +0200
@@ -11,6 +11,7 @@
 obj-$(CONFIG_MAC_PARTITION) += mac.o
 obj-$(CONFIG_LDM_PARTITION) += ldm.o
 obj-$(CONFIG_MSDOS_PARTITION) += msdos.o
+obj-$(CONFIG_OPENWRT_PARTITION) += openwrt.o
 obj-$(CONFIG_OSF_PARTITION) += osf.o
 obj-$(CONFIG_SGI_PARTITION) += sgi.o
 obj-$(CONFIG_SUN_PARTITION) += sun.o
diff -urN linux.old/fs/partitions/openwrt.c linux.dev/fs/partitions/openwrt.c
--- linux.old/fs/partitions/openwrt.c	1970-01-01 01:00:00.000000000 +0100
+++ linux.dev/fs/partitions/openwrt.c	2006-06-15 01:27:17.000000000 +0200
@@ -0,0 +1,249 @@
+/*
+ *  fs/partitions/openwrt.c
+ *
+ *  Code extracted from drivers/block/genhd.c
+ *  and fs/partitions/msdos.c
+ *
+ *  Copyright (C) 2006       Felix Fietkau <nbd@openwrt.org>
+ *  Copyright (C) 1991-1998  Linus Torvalds
+ *
+ *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
+ *  in the early extended-partition checks and added DM partitions
+ *
+ *  Support for DiskManager v6.0x added by Mark Lord,
+ *  with information provided by OnTrack.  This now works for linux fdisk
+ *  and LILO, as well as loadlin and bootln.  Note that disks other than
+ *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
+ *
+ *  More flexible handling of extended partitions - aeb, 950831
+ *
+ *  Check partition table on IDE disks for common CHS translations
+ *
+ *  Re-organised Feb 1998 Russell King
+ */
+
+#include <linux/config.h>
+
+#include "check.h"
+#include "openwrt.h"
+
+/*
+ * Many architectures don't like unaligned accesses, while
+ * the nr_sects and start_sect partition table entries are
+ * at a 2 (mod 4) address.
+ */
+#include <asm/unaligned.h>
+
+#define SYS_IND(p)	(get_unaligned(&p->sys_ind))
+#define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
+				get_unaligned(&p->nr_sects);	\
+				le32_to_cpu(__a); \
+			})
+
+#define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
+				get_unaligned(&p->start_sect);	\
+				le32_to_cpu(__a); \
+			})
+
+static inline int is_extended_partition(struct partition *p)
+{
+	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
+		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
+		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
+}
+
+#define MSDOS_LABEL_MAGIC1	0x55
+#define MSDOS_LABEL_MAGIC2	0xAA
+
+static inline int
+msdos_magic_present(unsigned char *p)
+{
+	return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
+}
+
+static inline int
+openwrt_magic_present(unsigned char *p)
+{
+	return (p[0] == 'O' && 
+			p[1] == 'W' &&
+			p[2] == 'R' &&
+			p[3] == 'T');
+}
+
+/*
+ * Create devices for each logical partition in an extended partition.
+ * The logical partitions form a linked list, with each entry being
+ * a partition table with two entries.  The first entry
+ * is the real data partition (with a start relative to the partition
+ * table start).  The second is a pointer to the next logical partition
+ * (with a start relative to the entire extended partition).
+ * We do not create a Linux partition for the partition tables, but
+ * only for the actual data partitions.
+ */
+
+static void
+parse_extended(struct parsed_partitions *state, struct block_device *bdev,
+			u32 first_sector, u32 first_size)
+{
+	struct partition *p;
+	Sector sect;
+	unsigned char *data;
+	u32 this_sector, this_size;
+	int sector_size = bdev_hardsect_size(bdev) / 512;
+	int loopct = 0;		/* number of links followed
+				   without finding a data partition */
+	int i;
+
+	this_sector = first_sector;
+	this_size = first_size;
+
+	while (1) {
+		if (++loopct > 100)
+			return;
+		if (state->next == state->limit)
+			return;
+		data = read_dev_sector(bdev, this_sector, &sect);
+		if (!data)
+			return;
+
+		if (!msdos_magic_present(data + 510))
+			goto done; 
+
+		p = (struct partition *) (data + 0x1be);
+
+		/*
+		 * Usually, the first entry is the real data partition,
+		 * the 2nd entry is the next extended partition, or empty,
+		 * and the 3rd and 4th entries are unused.
+		 * However, DRDOS sometimes has the extended partition as
+		 * the first entry (when the data partition is empty),
+		 * and OS/2 seems to use all four entries.
+		 */
+
+		/* 
+		 * First process the data partition(s)
+		 */
+		for (i=0; i<4; i++, p++) {
+			u32 offs, size, next;
+			if (!NR_SECTS(p) || is_extended_partition(p))
+				continue;
+
+			/* Check the 3rd and 4th entries -
+			   these sometimes contain random garbage */
+			offs = START_SECT(p)*sector_size;
+			size = NR_SECTS(p)*sector_size;
+			next = this_sector + offs;
+			if (i >= 2) {
+				if (offs + size > this_size)
+					continue;
+				if (next < first_sector)
+					continue;
+				if (next + size > first_sector + first_size)
+					continue;
+			}
+
+			put_partition(state, state->next, next, size);
+			if (SYS_IND(p) == LINUX_RAID_PARTITION)
+				state->parts[state->next].flags = 1;
+			loopct = 0;
+			if (++state->next == state->limit)
+				goto done;
+		}
+		/*
+		 * Next, process the (first) extended partition, if present.
+		 * (So far, there seems to be no reason to make
+		 *  parse_extended()  recursive and allow a tree
+		 *  of extended partitions.)
+		 * It should be a link to the next logical partition.
+		 */
+		p -= 4;
+		for (i=0; i<4; i++, p++)
+			if (NR_SECTS(p) && is_extended_partition(p))
+				break;
+		if (i == 4)
+			goto done;	 /* nothing left to do */
+
+		this_sector = first_sector + START_SECT(p) * sector_size;
+		this_size = NR_SECTS(p) * sector_size;
+		put_dev_sector(sect);
+	}
+done:
+	put_dev_sector(sect);
+}
+
+
+int openwrt_partition(struct parsed_partitions *state, struct block_device *bdev)
+{
+	int sector_size = bdev_hardsect_size(bdev) / 512;
+	Sector sect;
+	unsigned char *data;
+	struct partition *p;
+	int slot;
+	u32 last_block = 0;
+	u32 size = 0;
+	int firstfree = 5;
+
+	data = read_dev_sector(bdev, 0, &sect);
+	if (!data)
+		return -1;
+	if (!openwrt_magic_present(data)) {
+		printk("No OpenWrt partition table detected\n");	
+		put_dev_sector(sect);
+		return 0;
+	}
+
+	/*
+	 * Now that the 55aa signature is present, this is probably
+	 * either the boot sector of a FAT filesystem or a DOS-type
+	 * partition table. Reject this in case the boot indicator
+	 * is not 0 or 0x80.
+	 */
+	p = (struct partition *) (data + 0x1be);
+	for (slot = 1; slot <= 4; slot++, p++) {
+		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
+			put_dev_sector(sect);
+			return 0;
+		}
+	}
+
+	p = (struct partition *) (data + 0x1be);
+
+	/*
+	 * Look for partitions in two passes:
+	 * First find the primary and DOS-type extended partitions.
+	 */
+
+	state->next = 6;
+	for (slot = 1 ; slot <= 4 ; slot++, p++) {
+		u32 start = START_SECT(p)*sector_size;
+		size = NR_SECTS(p)*sector_size;
+		if (!size) {
+			if (firstfree > slot)
+				firstfree = slot;
+
+			continue;
+		}
+		if (is_extended_partition(p)) {
+			/* prevent someone doing mkfs or mkswap on an
+			   extended partition, but leave room for LILO */
+			last_block = start + size;
+			put_partition(state, slot, start, size == 1 ? 1 : 2);
+			printk(" <");
+			parse_extended(state, bdev, start, size);
+			printk(" >");
+			continue;
+		}
+		if ((start + size) > get_capacity(bdev->bd_disk))
+			size = get_capacity(bdev->bd_disk) - start;
+		last_block = start + size;
+		put_partition(state, slot, start, size);
+	}
+	if (last_block + 1024 < (size = get_capacity(bdev->bd_disk)))
+		put_partition(state, firstfree, last_block, size - last_block);
+
+	printk("\n");
+
+	put_dev_sector(sect);
+	return 1;
+}
+
diff -urN linux.old/fs/partitions/openwrt.h linux.dev/fs/partitions/openwrt.h
--- linux.old/fs/partitions/openwrt.h	1970-01-01 01:00:00.000000000 +0100
+++ linux.dev/fs/partitions/openwrt.h	2006-06-15 01:27:17.000000000 +0200
@@ -0,0 +1,6 @@
+/*
+ *  fs/partitions/openwrt.h
+ */
+
+int openwrt_partition(struct parsed_partitions *state, struct block_device *bdev);
+
