From: Roman.Hodek@informatik.uni-erlangen.de (Roman Hodek)
Date: Thu, 9 Oct 1997 22:51:38 +0200 (CEST)
To: linux-m68k@lists.linux-m68k.org
Subject: L68K: Non-native partition format support
Sender: owner-linux-m68k@phil.uni-sb.de


Ok, here it is: the promised general support for foreign partition
formats.

Changes:

 - Moved parser functions from genhd.c to their own partbl_*.c files.

 - Corrected some minor things in the parsers (e.g. ntohl converted to
   be32_to_cpu and the like). Made appearance more consistent (e.g.,
   each one now prints the format name).

 - Partition parsers can be modules.

 - Configuration: The native format is always statically included into
   the kernel. If you additionally select CONFIG_FOREIGN_PARTITIONS,
   you can build the other formats either directly into the kernel or
   as modules. (Hope I got it all right... :-)

 - There's a file /proc/partition-formats, which lists the currently
   available partition formats.

 - Kerneld support: If none of the available parsers want to grok a
   device, the kernel tries to load other parsers with kerneld. For
   that, there is a table of magics (type, offset, value) that is
   consulted to find out potential candidates. The more complicated
   cases (Amiga, Atari) are handeled by calling a probe function
   instead of magic checking. All formats that maybe apply to the
   device are loaded and tried in a second run.

 - The Atari format parser now really checks whether a sector could be
   an Atari rootsector. Since there's no magic, some heuristics have
   to be applied: If there's at least one primary partition entry that
   is 1) marked valid, 2) has a partition ID that is 3 alphanumeric
   chars, and 3) both start and end sectors are before end-of-disk,
   then the sector is assumed to be an Atari root sector. Sorry,
   that's the best possible...

 - <asm-m68k/atari_rootsec.h> has been moved to <linux/atari_rootsec.h>,
   so that it also can be used if compiling for other architectures.
   Don't forget the -E option to patch so that the old file is removed :-)

Unfortunately, there are some new #ifdef's in genhd.c ... don't know
what the big master penguin thinks about that :-) But I couldn't think
of any clever way to avoid them, and at least there are now less
#ifdef's in genhd.c then before :-)

Ah, Jes, can you forward this to DaveM, too, for checking? I don't
have his e-mail at hand here (@home).

Roman

------------------------------------------------------------------------------
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/Documentation/Configure.help linux-2.1.57/Documentation/Configure.help
--- linux-2.1.57.orig/Documentation/Configure.help	Sat Sep 20 14:24:50 1997
+++ linux-2.1.57/Documentation/Configure.help	Wed Oct  8 23:43:35 1997
@@ -4441,6 +4441,70 @@
   Documentation/modules.txt. The module will be called ufs.o. If you
   haven't heard about all of this before, it's safe to say N.
 
+Support for foreign partition tables
+CONFIG_FOREIGN_PARTITIONS
+  Say Y here if you want to include other partitioning schemes than
+  the native one of your machine. The native partition format is
+  selected automatically for you, but all other formats must be
+  requested explicitly below.
+
+MS-DOS partition support
+CONFIG_MSDOS_PARTITION
+  This option enables support for using hard disks that were
+  partitioned on an MS-DOS system. This may be useful if you are
+  sharing a hard disk between i386 and m68k Linux boxes, for example.
+  Say Y if you need this feature; users who are only using their
+  system-native partitioning scheme can say N here. You also have the
+  option to build the MS-DOS partition parser as a module, so that it
+  can be loaded at runtime.
+
+OSF partition support
+CONFIG_OSF_PARTITION
+  This option enables support for using hard disks that were
+  partitioned with the OSF partitioning scheme. Say Y if you need this
+  feature; users who are only using their system-native partitioning
+  scheme can say N here. You also have the option to build the OSF
+  partition parser as a module, so that it can be loaded at runtime.
+
+Sun partition support
+CONFIG_SUN_PARTITION
+  Like most systems, SunOS uses its own partition table format,
+  incompatible with all others. Saying Y here allows you to read these
+  partition tables and further mount SunOS disks on your Linux box if
+  you also have configured BSD ufs filesystem support. This is mainly
+  used to carry data from a Sparc under SunOS to your Linux box via a
+  removable medium like magneto-optical or ZIP drives. If you don't
+  know what all this is about, say N. You also have the option to
+  build the Sun partition parser as a module, so that it can be loaded
+  at runtime.
+
+Amiga RDB partition support
+CONFIG_AMIGA_PARTITION
+  This option enables support for using hard disks that were
+  partitioned with the Amiga rigid disk block format. Say Y if you
+  need this feature; users who are only using their system-native
+  partitioning scheme can say N here. You also have the option to
+  build the Amiga partition parser as a module, so that it can be
+  loaded at runtime.
+
+Atari partition support
+CONFIG_ATARI_PARTITION
+  This option enables support for using hard disks that were
+  partitioned with the Atari partition format. Supported are AHDI 3.0
+  format and the ICD extension to the original definition. Say Y if
+  you need this feature; users who are only using their system-native
+  partitioning scheme can say N here. You also have the option to
+  build the Atari partition parser as a module, so that it can be
+  loaded at runtime.
+
+Mac partition support
+CONFIG_MAC_PARTITION
+  This option enables support for using hard disks that were
+  partitioned with the Mac partitioning scheme. Say Y if you need this
+  feature; users who are only using their system-native partitioning
+  scheme can say N here. You also have the option to build the Mac
+  partition parser as a module, so that it can be loaded at runtime.
+
 BSD disklabel (FreeBSD partition tables) support
 CONFIG_BSD_DISKLABEL
   FreeBSD uses its own partition scheme on your PC. It requires only
@@ -4451,16 +4515,6 @@
   Linux box if you also have configured BSD ufs filesystem support. If
   you don't know what all this is about, say N.
 
-SMD disklabel (Sun partition tables) support
-CONFIG_SMD_DISKLABEL
-  Like most systems, SunOS uses its own partition table format,
-  incompatible with all others. Saying Y here allows you to read these
-  partition tables and further mount SunOS disks on your Linux box if
-  you also have configured BSD ufs filesystem support. This is mainly
-  used to carry data from a Sparc under SunOS to your Linux box via a
-  removable medium like magneto-optical or ZIP drives. If you don't
-  know what all this is about, say N.
-
 SMB filesystem support (to mount WfW shares etc..)
 CONFIG_SMB_FS
   SMB (Server Message Buffer) is the protocol Windows for Workgroups
@@ -6001,14 +6055,6 @@
   kernel and a gdb on another machine. After this link is working, you
   can analyse and modify kernel behaviour in gdb almost as you would
   do for a normal program.
-
-MSDOS partition support
-CONFIG_MSDOS_PARTITION
-  This option enables support for using hard disks that were
-  partitioned on an MS-DOS system.  This may be useful if you are
-  sharing a hard disk between i386 and m68k Linux boxes, for example.
-  Say Y if you need this feature; users who are only using their
-  system-native partitioning scheme can say N here.
 
 Build PowerMac Kernel (not PReP)
 CONFIG_PMAC
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/Makefile linux-2.1.57/drivers/block/Makefile
--- linux-2.1.57.orig/drivers/block/Makefile	Mon Sep 29 18:38:04 1997
+++ linux-2.1.57/drivers/block/Makefile	Wed Oct  8 22:43:23 1997
@@ -16,11 +16,59 @@
 
 
 L_TARGET := block.a
-L_OBJS   := ll_rw_blk.o genhd.o
+L_OBJS   := ll_rw_blk.o
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
-LX_OBJS :=
+LX_OBJS := genhd.o
 MX_OBJS :=
+
+ifeq ($(CONFIG_MSDOS_PARTITION),y)
+  L_OBJS += partbl_msdos.o
+else
+  ifeq ($(CONFIG_MSDOS_PARTITION),m)
+    M_OBJS += partbl_msdos.o
+  endif
+endif
+
+ifeq ($(CONFIG_OSF_PARTITION),y)
+  L_OBJS += partbl_osf.o
+else
+  ifeq ($(CONFIG_OSF_PARTITION),m)
+    M_OBJS += partbl_osf.o
+  endif
+endif
+
+ifeq ($(CONFIG_SUN_PARTITION),y)
+  L_OBJS += partbl_sun.o
+else
+  ifeq ($(CONFIG_SUN_PARTITION),m)
+    M_OBJS += partbl_sun.o
+  endif
+endif
+
+ifeq ($(CONFIG_AMIGA_PARTITION),y)
+  L_OBJS += partbl_amiga.o
+else
+  ifeq ($(CONFIG_AMIGA_PARTITION),m)
+    M_OBJS += partbl_amiga.o
+  endif
+endif
+
+ifeq ($(CONFIG_ATARI_PARTITION),y)
+  L_OBJS += partbl_atari.o
+else
+  ifeq ($(CONFIG_ATARI_PARTITION),m)
+    M_OBJS += partbl_atari.o
+  endif
+endif
+
+ifeq ($(CONFIG_MAC_PARTITION),y)
+  L_OBJS += partbl_mac.o
+else
+  ifeq ($(CONFIG_MAC_PARTITION),m)
+    M_OBJS += partbl_mac.o
+  endif
+endif
 
 ifeq ($(CONFIG_MAC_FLOPPY),y)
 L_OBJS += swim3.o
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/acsi.c linux-2.1.57/drivers/block/acsi.c
--- linux-2.1.57.orig/drivers/block/acsi.c	Fri Sep  5 18:23:04 1997
+++ linux-2.1.57/drivers/block/acsi.c	Wed Oct  8 20:50:10 1997
@@ -73,7 +73,6 @@
 #include <asm/atariints.h>
 #include <asm/atari_acsi.h>
 #include <asm/atari_stdma.h>
-#include <asm/atari_rootsec.h>
 
 
 #define DEBUG
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/genhd.c linux-2.1.57/drivers/block/genhd.c
--- linux-2.1.57.orig/drivers/block/genhd.c	Wed Sep 10 21:16:18 1997
+++ linux-2.1.57/drivers/block/genhd.c	Thu Oct  9 22:27:21 1997
@@ -16,9 +16,13 @@
  *  More flexible handling of extended partitions - aeb, 950831
  *
  *  Check partition table on IDE disks for common CHS translations
+ *
+ *  Moved partition table parsers into separate files and modularized them
+ *  (10/08/97 Roman Hodek)
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/genhd.h>
 #include <linux/kernel.h>
@@ -26,30 +30,15 @@
 #include <linux/string.h>
 #include <linux/blk.h>
 #include <linux/init.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif
 
 #include <asm/system.h>
 
-/*
- * Many architectures don't like unaligned accesses, which is
- * frequently the case with the nr_sects and start_sect partition
- * table entries.
- */
-#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); \
-			})
-
 struct gendisk *gendisk_head = NULL;
 
-static int current_minor = 0;
+int current_minor = 0;
 extern int *blk_size[];
 extern void rd_load(void);
 extern void initrd_load(void);
@@ -59,6 +48,8 @@
 extern int scsi_dev_init(void);
 extern int net_dev_init(void);
 
+struct partition_parser *partition_parsers = NULL;
+
 /*
  * disk_name() is used by genhd.c and md.c.
  * It formats the devicename of the indicated disk
@@ -94,7 +85,7 @@
 	return buf;
 }
 
-static void add_partition (struct gendisk *hd, int minor, int start, int size)
+void add_partition (struct gendisk *hd, int minor, int start, int size)
 {
 	char buf[8];
 	hd->part[minor].start_sect = start;
@@ -102,13 +93,7 @@
 	printk(" %s", disk_name(hd, minor, buf));
 }
 
-static inline int is_extended_partition(struct partition *p)
-{
-	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
-		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
-}
-
-static unsigned int get_ptable_blocksize(kdev_t dev)
+unsigned int get_ptable_blocksize(kdev_t dev)
 {
   int ret = 1024;
 
@@ -154,795 +139,161 @@
 
 }
 
-#ifdef CONFIG_MSDOS_PARTITION
-/*
- * 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.
- */
 
-#define MSDOS_LABEL_MAGIC		0xAA55
+#if CONFIG_KERNELD && CONFIG_FOREIGN_PARTITIONS
 
-static void extended_partition(struct gendisk *hd, kdev_t dev)
+#include <linux/kerneld.h>
+
+#ifdef CONFIG_AMIGA_PARTITION_MODULE
+#include <linux/affs_hardblocks.h>
+static int probe_amiga_partition(struct gendisk *hd, kdev_t dev,
+				 struct buffer_head *bh_0)
 {
 	struct buffer_head *bh;
-	struct partition *p;
-	unsigned long first_sector, first_size, this_sector, this_size;
-	int mask = (1 << hd->minor_shift) - 1;
-	int i;
+	int blk, res;
 
-	first_sector = hd->part[MINOR(dev)].start_sect;
-	first_size = hd->part[MINOR(dev)].nr_sects;
-	this_sector = first_sector;
+	if (*(u32 *)bh_0->b_data == cpu_to_be32(IDNAME_RIGIDDISK))
+		return 1;
 
-	while (1) {
-		if ((current_minor & mask) == 0)
-			return;
-		if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
-			return;
-	  /*
-	   * This block is from a device that we're about to stomp on.
-	   * So make sure nobody thinks this block is usable.
-	   */
-		bh->b_state = 0;
-
-		if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
-			goto done;
-
-		p = (struct partition *) (0x1BE + bh->b_data);
-
-		this_size = hd->part[MINOR(dev)].nr_sects;
-
-		/*
-		 * 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++) {
-		    if (!NR_SECTS(p) || is_extended_partition(p))
-		      continue;
-
-		    /* Check the 3rd and 4th entries -
-		       these sometimes contain random garbage */
-		    if (i >= 2
-			&& START_SECT(p) + NR_SECTS(p) > this_size
-			&& (this_sector + START_SECT(p) < first_sector ||
-			    this_sector + START_SECT(p) + NR_SECTS(p) >
-			     first_sector + first_size))
-		      continue;
-
-		    add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
-		    current_minor++;
-		    if ((current_minor & mask) == 0)
-		      goto done;
-		}
-		/*
-		 * Next, process the (first) extended partition, if present.
-		 * (So far, there seems to be no reason to make
-		 *  extended_partition()  recursive and allow a tree
-		 *  of extended partitions.)
-		 * It should be a link to the next logical partition.
-		 * Create a minor for this just long enough to get the next
-		 * partition table.  The minor will be reused for the next
-		 * data 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 */
-
-		hd->part[current_minor].nr_sects = NR_SECTS(p);
-		hd->part[current_minor].start_sect = first_sector + START_SECT(p);
-		this_sector = first_sector + START_SECT(p);
-		dev = MKDEV(hd->major, current_minor);
+	/* also need to check other possible RDB blocks */
+	for (blk = 1; blk < RDB_ALLOCATION_LIMIT; blk++) {
+		if (!(bh = bread(dev,blk,512)))
+			return -1;
+		res = *(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK);
 		brelse(bh);
+		if (res)
+			return 1;
 	}
-done:
-	brelse(bh);
+	return 0;
 }
+#endif
 
-#ifdef CONFIG_BSD_DISKLABEL
-/* 
- * Create devices for BSD partitions listed in a disklabel, under a
- * dos-like partition. See extended_partition() for more information.
- */
-static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev)
-{
-	struct buffer_head *bh;
-	struct bsd_disklabel *l;
-	struct bsd_partition *p;
-	int mask = (1 << hd->minor_shift) - 1;
-
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
-		return;
-	bh->b_state = 0;
-	l = (struct bsd_disklabel *) (bh->b_data+512);
-	if (l->d_magic != BSD_DISKMAGIC) {
-		brelse(bh);
-		return;
-	}
-
-	p = &l->d_partitions[0];
-	while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) {
-		if ((current_minor & mask) >= (4 + hd->max_p))
-			break;
-
-		if (p->p_fstype != BSD_FS_UNUSED) {
-			add_partition(hd, current_minor, p->p_offset, p->p_size);
-			current_minor++;
-		}
-		p++;
-	}
-	brelse(bh);
-
+#ifdef CONFIG_ATARI_PARTITION_MODULE
+#include <linux/atari_rootsec.h>
+#include <linux/ctype.h>
+#define	VALID_PARTITION(pi,hdsiz)					     \
+    (((pi)->flg & 1) &&							     \
+     isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \
+     be32_to_cpu((pi)->st) <= (hdsiz) &&				     \
+     be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
+static int probe_atari_partition(struct gendisk *hd, kdev_t dev,
+				 struct buffer_head *bh_0)
+{
+	struct rootsector *rs;
+	u32 hd_size;
+	int res;
+
+	rs = (struct rootsector *)bh_0->b_data;
+	hd_size = hd->part[0].nr_sects;
+	res = VALID_PARTITION( &rs->part[0], hd_size ) ||
+	      VALID_PARTITION( &rs->part[1], hd_size ) ||
+	      VALID_PARTITION( &rs->part[2], hd_size ) ||
+	      VALID_PARTITION( &rs->part[3], hd_size );
+	return res;
 }
 #endif
 
-static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	int i, minor = current_minor;
-	struct buffer_head *bh;
-	struct partition *p;
-	unsigned char *data;
-	int mask = (1 << hd->minor_shift) - 1;
-#ifdef CONFIG_BLK_DEV_IDE
-	int tested_for_xlate = 0;
+/*
+ * This table lists the magics to recognize the partition formats that are
+ * availble as modules. The magics can be stored as 16 or 32 bit little-endian
+ * or big-endian numbers. For the more complicated cases (Amiga and Atari), a
+ * function doing the real work is called.
+ */
+
+enum partbl_probe_type { BE16, BE32, LE16, LE32, FUNC };
 
-read_mbr:
+static struct partbl_probe {
+	char *name;
+	enum partbl_probe_type type;
+	u32 offset;
+	u32 magic;
+	int (*func)(struct gendisk *hd, kdev_t dev, struct buffer_head *bh_0);
+} partbl_modules[] = {
+#ifdef CONFIG_MSDOS_PARTITION_MODULE
+	{ "msdos", LE16, 510, 0xAA55, NULL },
+#endif
+#ifdef CONFIG_OSF_PARTITION_MODULE
+	{ "osf",   LE32,  64, 0x82564557, NULL },
+#endif
+#ifdef CONFIG_SUN_PARTITION_MODULE
+	{ "sun",   BE16, 508, 0xDABE, NULL },
 #endif
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-		printk(" unable to read partition table\n");
-		return -1;
-	}
-	data = bh->b_data;
-	/* In some cases we modify the geometry    */
-	/*  of the drive (below), so ensure that   */
-	/*  nobody else tries to re-use this data. */
-	bh->b_state = 0;
-#ifdef CONFIG_BLK_DEV_IDE
-check_table:
+#ifdef CONFIG_AMIGA_PARTITION_MODULE
+	{ "amiga", FUNC,   0,      0, probe_amiga_partition },
 #endif
-	if (*(unsigned short *)  (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
-		brelse(bh);
-		return 0;
-	}
-	p = (struct partition *) (0x1be + data);
-
-#ifdef CONFIG_BLK_DEV_IDE
-	if (!tested_for_xlate++) {	/* Do this only once per disk */
-		/*
-		 * Look for various forms of IDE disk geometry translation
-		 */
-		extern int ide_xlate_1024(kdev_t, int, const char *);
-		unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
-		if (SYS_IND(p) == EZD_PARTITION) {
-			/*
-			 * The remainder of the disk must be accessed using
-			 * a translated geometry that reduces the number of 
-			 * apparent cylinders to less than 1024 if possible.
-			 *
-			 * ide_xlate_1024() will take care of the necessary
-			 * adjustments to fool fdisk/LILO and partition check.
-			 */
-			if (ide_xlate_1024(dev, -1, " [EZD]")) {
-				data += 512;
-				goto check_table;
-			}
-		} else if (SYS_IND(p) == DM6_PARTITION) {
-
-			/*
-			 * Everything on the disk is offset by 63 sectors,
-			 * including a "new" MBR with its own partition table,
-			 * and the remainder of the disk must be accessed using
-			 * a translated geometry that reduces the number of 
-			 * apparent cylinders to less than 1024 if possible.
-			 *
-			 * ide_xlate_1024() will take care of the necessary
-			 * adjustments to fool fdisk/LILO and partition check.
-			 */
-			if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
-				brelse(bh);
-				goto read_mbr;	/* start over with new MBR */
-			}
-		} else if (sig <= 0x1ae &&
-			   *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) &&
-			   (1 & *(unsigned char *)(data + sig + 2))) {
-			/* DM6 signature in MBR, courtesy of OnTrack */
-			(void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
-		} else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
-			/*
-			 * DM6 on other than the first (boot) drive
-			 */
-			(void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
-		} else {
-			/*
-			 * Examine the partition table for common translations.
-			 * This is necessary for drives for situations where
-			 * the translated geometry is unavailable from the BIOS.
-			 */
-			for (i = 0; i < 4 ; i++) {
-				struct partition *q = &p[i];
-				if (NR_SECTS(q)
-				   && (q->sector & 63) == 1
-				   && (q->end_sector & 63) == 63) {
-					unsigned int heads = q->end_head + 1;
-					if (heads == 32 || heads == 64 || heads == 128 || heads == 255) {
-
-						(void) ide_xlate_1024(dev, heads, " [PTBL]");
-						break;
-					}
-				}
-			}
-		}
-	}
-#endif	/* CONFIG_BLK_DEV_IDE */
-
-	printk(" DOS");	/* show partition type */
-	current_minor += 4;  /* first "extra" minor (for extended partitions) */
-	for (i=1 ; i<=4 ; minor++,i++,p++) {
-		if (!NR_SECTS(p))
-			continue;
-		add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
-		if (is_extended_partition(p)) {
-			printk(" <");
-			/*
-			 * If we are rereading the partition table, we need
-			 * to set the size of the partition so that we will
-			 * be able to bread the block containing the extended
-			 * partition info.
-			 */
-			hd->sizes[minor] = hd->part[minor].nr_sects 
-			  	>> (BLOCK_SIZE_BITS - 9);
-			extended_partition(hd, MKDEV(hd->major, minor));
-			printk(" >");
-			/* prevent someone doing mkfs or mkswap on an
-			   extended partition, but leave room for LILO */
-			if (hd->part[minor].nr_sects > 2)
-				hd->part[minor].nr_sects = 2;
-		}
-#ifdef CONFIG_BSD_DISKLABEL
-		if (SYS_IND(p) == BSD_PARTITION) {
-			printk(" BSD<");
-			bsd_disklabel_partition(hd, MKDEV(hd->major, minor));
-			printk(" >");
-		}
+#ifdef CONFIG_ATARI_PARTITION_MODULE
+	{ "atari", FUNC,   0,      0, probe_atari_partition },
 #endif
-	}
-	/*
-	 *  Check for old-style Disk Manager partition table
-	 */
-	if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
-		p = (struct partition *) (0x1be + data);
-		for (i = 4 ; i < 16 ; i++, current_minor++) {
-			p--;
-			if ((current_minor & mask) == 0)
-				break;
-			if (!(START_SECT(p) && NR_SECTS(p)))
-				continue;
-			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
-		}
-	}
-	printk("\n");
-	brelse(bh);
-	return 1;
-}
-
-#endif /* CONFIG_MSDOS_PARTITION */
+#ifdef CONFIG_MAC_PARTITION_MODULE
+	{ "mac",   BE16,   0, 0x4552, NULL },
+#endif
+};
 
-#ifdef CONFIG_OSF_PARTITION
+#define N_PARTBL_MODULES sizeof(partbl_modules)/sizeof(*partbl_modules)
 
-static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
+/*
+ * Try to load all partition parsers that could apply to this device
+ */
+static int try_to_load_parser(struct gendisk *hd, kdev_t dev)
 {
-	int i;
-	int mask = (1 << hd->minor_shift) - 1;
+	int i, hit = 0, loaded = 0;
+	char modname[24];
+	struct partbl_probe *mod;
+	struct partition_parser *p;
 	struct buffer_head *bh;
-	struct disklabel {
-		u32 d_magic;
-		u16 d_type,d_subtype;
-		u8 d_typename[16];
-		u8 d_packname[16];
-		u32 d_secsize;
-		u32 d_nsectors;
-		u32 d_ntracks;
-		u32 d_ncylinders;
-		u32 d_secpercyl;
-		u32 d_secprtunit;
-		u16 d_sparespertrack;
-		u16 d_sparespercyl;
-		u32 d_acylinders;
-		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
-		u32 d_headswitch, d_trkseek, d_flags;
-		u32 d_drivedata[5];
-		u32 d_spare[5];
-		u32 d_magic2;
-		u16 d_checksum;
-		u16 d_npartitions;
-		u32 d_bbsize, d_sbsize;
-		struct d_partition {
-			u32 p_size;
-			u32 p_offset;
-			u32 p_fsize;
-			u8  p_fstype;
-			u8  p_frag;
-			u16 p_cpg;
-		} d_partitions[8];
-	} * label;
-	struct d_partition * partition;
-#define DISKLABELMAGIC (0x82564557UL)
 
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
-		printk("unable to read partition table\n");
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
 		return -1;
-	}
-	label = (struct disklabel *) (bh->b_data+64);
-	partition = label->d_partitions;
-	if (label->d_magic != DISKLABELMAGIC) {
-		printk("magic: %08x\n", label->d_magic);
-		brelse(bh);
-		return 0;
-	}
-	if (label->d_magic2 != DISKLABELMAGIC) {
-		printk("magic2: %08x\n", label->d_magic2);
-		brelse(bh);
-		return 0;
-	}
-	printk(" OSF");
-	for (i = 0 ; i < label->d_npartitions; i++, partition++) {
-		if ((current_minor & mask) == 0)
-		        break;
-		if (partition->p_size)
-			add_partition(hd, current_minor,
-				first_sector+partition->p_offset,
-				partition->p_size);
-		current_minor++;
-	}
-	printk("\n");
-	brelse(bh);
-	return 1;
-}
-
-#endif /* CONFIG_OSF_PARTITION */
 
-#ifdef CONFIG_SUN_PARTITION
-
-static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	int i, csum;
-	unsigned short *ush;
-	struct buffer_head *bh;
-	struct sun_disklabel {
-		unsigned char info[128];   /* Informative text string */
-		unsigned char spare[292];  /* Boot information etc. */
-		unsigned short rspeed;     /* Disk rotational speed */
-		unsigned short pcylcount;  /* Physical cylinder count */
-		unsigned short sparecyl;   /* extra sects per cylinder */
-		unsigned char spare2[4];   /* More magic... */
-		unsigned short ilfact;     /* Interleave factor */
-		unsigned short ncyl;       /* Data cylinder count */
-		unsigned short nacyl;      /* Alt. cylinder count */
-		unsigned short ntrks;      /* Tracks per cylinder */
-		unsigned short nsect;      /* Sectors per track */
-		unsigned char spare3[4];   /* Even more magic... */
-		struct sun_partition {
-			__u32 start_cylinder;
-			__u32 num_sectors;
-		} partitions[8];
-		unsigned short magic;      /* Magic number */
-		unsigned short csum;       /* Label xor'd checksum */
-	} * label;		
-	struct sun_partition *p;
-	unsigned long spc;
-#define SUN_LABEL_MAGIC          0xDABE
-
-	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
-		printk("Dev %s: unable to read partition table\n",
-		       kdevname(dev));
-		return -1;
-	}
-	label = (struct sun_disklabel *) bh->b_data;
-	p = label->partitions;
-	if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
-#if 0
-		printk("Dev %s Sun disklabel: bad magic %04x\n",
-		       kdevname(dev), be16_to_cpu(label->magic));
-#endif
-		brelse(bh);
-		return 0;
-	}
-	/* Look at the checksum */
-	ush = ((unsigned short *) (label+1)) - 1;
-	for(csum = 0; ush >= ((unsigned short *) label);)
-		csum ^= *ush--;
-	if(csum) {
-		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
-		       kdevname(dev));
-		brelse(bh);
-		return 0;
-	}
-	printk(" UFS");
-	/* All Sun disks have 8 partition entries */
-	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
-	for(i=0; i < 8; i++, p++) {
-		unsigned long st_sector;
-		int num_sectors;
-
-		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
-		num_sectors = be32_to_cpu(p->num_sectors);
-		if (num_sectors)
-			add_partition(hd, current_minor, st_sector, num_sectors);
-		current_minor++;
-	}
-	printk("\n");
-	brelse(bh);
-	return 1;
-}
-
-#endif /* CONFIG_SUN_PARTITION */
-
-#ifdef CONFIG_AMIGA_PARTITION
-#include <asm/byteorder.h>
-#include <linux/affs_hardblocks.h>
-
-static __inline__ u32
-checksum_block(u32 *m, int size)
-{
-	u32 sum = 0;
-
-	while (size--)
-		sum += htonl(*m++);
-	return sum;
-}
-
-static int
-amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
-{
-	struct buffer_head	*bh;
-	struct RigidDiskBlock	*rdb;
-	struct PartitionBlock	*pb;
-	int			 start_sect;
-	int			 nr_sects;
-	int			 blk;
-	int			 part, res;
-
-	set_blocksize(dev,512);
-	res = 0;
-
-	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
-		if(!(bh = bread(dev,blk,512))) {
-			printk("Dev %s: unable to read RDB block %d\n",
-			       kdevname(dev),blk);
-			goto rdb_done;
-		}
-		if (*(u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) {
-			rdb = (struct RigidDiskBlock *)bh->b_data;
-			if (checksum_block((u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) {
-				printk("Dev %s: RDB in block %d has bad checksum\n",
-				       kdevname(dev),blk);
-				brelse(bh);
-				continue;
-			}
-			printk(" RDSK");
-			blk = htonl(rdb->rdb_PartitionList);
-			brelse(bh);
-			for (part = 1; blk > 0 && part <= 16; part++) {
-				if (!(bh = bread(dev,blk,512))) {
-					printk("Dev %s: unable to read partition block %d\n",
-						       kdevname(dev),blk);
-					goto rdb_done;
-				}
-				pb  = (struct PartitionBlock *)bh->b_data;
-				blk = htonl(pb->pb_Next);
-				if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block(
-				    (u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) {
-					
-					/* Tell Kernel about it */
-
-					if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 -
-							  htonl(pb->pb_Environment[9])) *
-							 htonl(pb->pb_Environment[3]) *
-							 htonl(pb->pb_Environment[5]))) {
-						continue;
-					}
-					start_sect = htonl(pb->pb_Environment[9]) *
-						     htonl(pb->pb_Environment[3]) *
-						     htonl(pb->pb_Environment[5]);
-					add_partition(hd,current_minor,start_sect,nr_sects);
-					current_minor++;
-					res = 1;
-				}
-				brelse(bh);
-			}
-			printk("\n");
+	for( i = 0, mod = partbl_modules; i < N_PARTBL_MODULES; ++i, ++mod ) {
+		/* don't probe already loaded formats again */
+		for( p = partition_parsers; p; p = p->next )
+			if (!strcmp( mod->name, p->name))
+				goto skip;
+		
+		switch( mod->type ) {
+		    case LE16:
+			hit = le16_to_cpu(*(u16 *)(bh->b_data+mod->offset)) ==
+			      mod->magic;
 			break;
-		}
-	}
-
-rdb_done:
-	set_blocksize(dev,BLOCK_SIZE);
-	return res;
-}
-#endif /* CONFIG_AMIGA_PARTITION */
-
-#ifdef CONFIG_MAC_PARTITION
-#include <linux/ctype.h>
-
-/*
- * Code to understand MacOS partition tables.
- */
-
-#define MAC_PARTITION_MAGIC	0x504d
-
-/* type field value for A/UX or other Unix partitions */
-#define APPLE_AUX_TYPE	"Apple_UNIX_SVR2"
-
-struct mac_partition {
-	__u16	signature;	/* expected to be MAC_PARTITION_MAGIC */
-	__u16	res1;
-	__u32	map_count;	/* # blocks in partition map */
-	__u32	start_block;	/* absolute starting block # of partition */
-	__u32	block_count;	/* number of blocks in partition */
-	char	name[32];	/* partition name */
-	char	type[32];	/* string type description */
-	__u32	data_start;	/* rel block # of first data block */
-	__u32	data_count;	/* number of data blocks */
-	__u32	status;		/* partition status bits */
-	__u32	boot_start;
-	__u32	boot_size;
-	__u32	boot_load;
-	__u32	boot_load2;
-	__u32	boot_entry;
-	__u32	boot_entry2;
-	__u32	boot_cksum;
-	char	processor[16];	/* identifies ISA of boot */
-	/* there is more stuff after this that we don't need */
-};
-
-#define MAC_STATUS_BOOTABLE	8	/* partition is bootable */
-
-#define MAC_DRIVER_MAGIC	0x4552
-
-/* Driver descriptor structure, in block 0 */
-struct mac_driver_desc {
-	__u16	signature;	/* expected to be MAC_DRIVER_MAGIC */
-	__u16	block_size;
-	__u32	block_count;
-    /* ... more stuff */
-};
-
-static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
-{
-	struct buffer_head *bh;
-	int blk, blocks_in_map;
-	int dev_bsize, dev_pos, pos;
-	unsigned secsize;
-	int first_bootable = 1;
-	struct mac_partition *part;
-	struct mac_driver_desc *md;
-
-	dev_bsize = get_ptable_blocksize(dev);
-	dev_pos = 0;
-	/* Get 0th block and look at the first partition map entry. */
-	if ((bh = bread(dev, 0, dev_bsize)) == 0) {
-	    printk("%s: error reading partition table\n",
-		   kdevname(dev));
-	    return -1;
-	}
-	md = (struct mac_driver_desc *) bh->b_data;
-	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
-		brelse(bh);
-		return 0;
-	}
-	secsize = be16_to_cpu(md->block_size);
-	if (secsize >= dev_bsize) {
-		brelse(bh);
-		dev_pos = secsize;
-		if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
-			printk("%s: error reading partition table\n",
-			       kdevname(dev));
-			return -1;
-		}
-	}
-	part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
-	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
-		brelse(bh);
-		return 0;		/* not a MacOS disk */
-	}
-	blocks_in_map = be32_to_cpu(part->map_count);
-	for (blk = 1; blk <= blocks_in_map; ++blk) {
-		pos = blk * secsize;
-		if (pos >= dev_pos + dev_bsize) {
-			brelse(bh);
-			dev_pos = pos;
-			if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
-				printk("%s: error reading partition table\n",
-				       kdevname(dev));
-				return -1;
-			}
-		}
-		part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
-		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
+		    case LE32:
+			hit = le32_to_cpu(*(u32 *)(bh->b_data+mod->offset)) ==
+			      mod->magic;
+			break;
+		    case BE16:
+			hit = be16_to_cpu(*(u16 *)(bh->b_data+mod->offset)) ==
+			      mod->magic;
+			break;
+		    case BE32:
+			hit = be32_to_cpu(*(u32 *)(bh->b_data+mod->offset)) ==
+			      mod->magic;
+			break;
+		    case FUNC:
+			hit = mod->func(hd, dev, bh) > 0;
 			break;
-		blocks_in_map = be32_to_cpu(part->map_count);
-		add_partition(hd, current_minor,
-			fsec + be32_to_cpu(part->start_block) * (secsize/512),
-			be32_to_cpu(part->block_count) * (secsize/512));
-
-#ifdef CONFIG_PMAC
-		/*
-		 * If this is the first bootable partition, tell the
-		 * setup code, in case it wants to make this the root.
-		 */
-		if (first_bootable
-		    && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
-		    && strcasecmp(part->processor, "powerpc") == 0) {
-			note_bootable_part(dev, blk);
-			first_bootable = 0;
 		}
-#endif /* CONFIG_PMAC */
-
-		++current_minor;
+		if (hit) {
+			strcpy(modname, "part-format-");
+			strcat(modname, mod->name);
+			request_module(modname);
+			++loaded;
+		}
+	    skip:
 	}
 	brelse(bh);
-	printk("\n");
-	return 1;
+	return loaded;
 }
 
-#endif /* CONFIG_MAC_PARTITION */
-
-#ifdef CONFIG_ATARI_PARTITION
-#include <asm/atari_rootsec.h>
-
-/* ++guenther: this should be settable by the user ("make config")?.
- */
-#define ICD_PARTS
-
-static int atari_partition (struct gendisk *hd, kdev_t dev,
-			    unsigned long first_sector)
-{
-  int minor = current_minor, m_lim = current_minor + hd->max_p;
-  struct buffer_head *bh;
-  struct rootsector *rs;
-  struct partition_info *pi;
-  ulong extensect;
-#ifdef ICD_PARTS
-  int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
-#endif
-
-  bh = bread (dev, 0, get_ptable_blocksize(dev));
-  if (!bh)
-    {
-      printk (" unable to read block 0\n");
-      return -1;
-    }
-
-  rs = (struct rootsector *) bh->b_data;
-  pi = &rs->part[0];
-  printk (" AHDI");
-  for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
-    {
-      if (pi->flg & 1)
-	/* active partition */
-	{
-	  if (memcmp (pi->id, "XGM", 3) == 0)
-	    /* extension partition */
-	    {
-	      struct rootsector *xrs;
-	      struct buffer_head *xbh;
-	      ulong partsect;
+#endif /* CONFIG_KERNELD && CONFIG_FOREIGN_PARTITIONS */
 
-#ifdef ICD_PARTS
-	      part_fmt = 1;
-#endif
-	      printk(" XGM<");
-	      partsect = extensect = pi->st;
-	      while (1)
-		{
-		  xbh = bread (dev, partsect / 2, 1024);
-		  if (!xbh)
-		    {
-		      printk (" block %ld read failed\n", partsect);
-		      brelse(bh);
-		      return 0;
-		    }
-		  if (partsect & 1)
-		    xrs = (struct rootsector *) &xbh->b_data[512];
-		  else
-		    xrs = (struct rootsector *) &xbh->b_data[0];
-
-		  /* ++roman: sanity check: bit 0 of flg field must be set */
-		  if (!(xrs->part[0].flg & 1)) {
-		    printk( "\nFirst sub-partition in extended partition is not valid!\n" );
-		    break;
-		  }
-
-		  add_partition(hd, minor, partsect + xrs->part[0].st,
-				xrs->part[0].siz);
-
-		  if (!(xrs->part[1].flg & 1)) {
-		    /* end of linked partition list */
-		    brelse( xbh );
-		    break;
-		  }
-		  if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
-		    printk( "\nID of extended partition is not XGM!\n" );
-		    brelse( xbh );
-		    break;
-		  }
-
-		  partsect = xrs->part[1].st + extensect;
-		  brelse (xbh);
-		  minor++;
-		  if (minor >= m_lim) {
-		    printk( "\nMaximum number of partitions reached!\n" );
-		    break;
-		  }
-		}
-	      printk(" >");
-	    }
-	  else
-	    {
-	      /* we don't care about other id's */
-	      add_partition (hd, minor, pi->st, pi->siz);
-	    }
-	}
-    }
-#ifdef ICD_PARTS
-  if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
-  {
-    pi = &rs->icdpart[0];
-    /* sanity check: no ICD format if first partition invalid */
-    if (memcmp (pi->id, "GEM", 3) == 0 ||
-        memcmp (pi->id, "BGM", 3) == 0 ||
-        memcmp (pi->id, "LNX", 3) == 0 ||
-        memcmp (pi->id, "SWP", 3) == 0 ||
-        memcmp (pi->id, "RAW", 3) == 0 )
-    {
-      printk(" ICD<");
-      for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
-      {
-        /* accept only GEM,BGM,RAW,LNX,SWP partitions */
-        if (pi->flg & 1 && 
-            (memcmp (pi->id, "GEM", 3) == 0 ||
-             memcmp (pi->id, "BGM", 3) == 0 ||
-             memcmp (pi->id, "LNX", 3) == 0 ||
-             memcmp (pi->id, "SWP", 3) == 0 ||
-             memcmp (pi->id, "RAW", 3) == 0) )
-        {
-          part_fmt = 2;
-	  add_partition (hd, minor, pi->st, pi->siz);
-        }
-      }
-      printk(" >");
-    }
-  }
-#endif
-  brelse (bh);
-
-  printk ("\n");
-
-  return 1;
-}
-#endif /* CONFIG_ATARI_PARTITION */
 
 static void check_partition(struct gendisk *hd, kdev_t dev)
 {
 	static int first_time = 1;
+	int tries = 0;
 	unsigned long first_sector;
 	char buf[8];
+	struct partition_parser *parser;
 
 	if (first_time)
 		printk("Partition check:\n");
@@ -958,34 +309,100 @@
 		return;
 	}
 
+    retry:
 	printk(" %s:", disk_name(hd, MINOR(dev), buf));
-#ifdef CONFIG_MSDOS_PARTITION
-	if (msdos_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_OSF_PARTITION
-	if (osf_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_SUN_PARTITION
-	if(sun_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_AMIGA_PARTITION
-	if(amiga_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_ATARI_PARTITION
-	if(atari_partition(hd, dev, first_sector))
-		return;
-#endif
-#ifdef CONFIG_MAC_PARTITION
-	if (mac_partition(hd, dev, first_sector))
-		return;
+	for( parser = partition_parsers; parser; parser = parser->next ) {
+		if (parser->func(hd, dev, first_sector))
+			return;
+	}
+	++tries;
+#if CONFIG_KERNELD && CONFIG_FOREIGN_PARTITIONS
+	if (tries == 1 && try_to_load_parser(hd, dev))
+		goto retry;
 #endif
 	printk(" unknown partition table\n");
 }
 
+int register_partbl( struct partition_parser *parser )
+{
+	struct partition_parser **p;
+    
+	if (!parser)
+		return -EINVAL;
+	if (parser->next)
+		return -EBUSY;
+	for( p = &partition_parsers; *p; p = &(*p)->next )
+		if (*p == parser)
+			return -EBUSY;
+
+	/* Insert new parser at front of list, so that a user-loaded module can
+	 * (in case of some misdetection) override other parsers */
+	parser->next = partition_parsers;
+	partition_parsers = parser;
+	return 0;
+}
+
+#ifdef CONFIG_MODULES
+int unregister_partbl( struct partition_parser *parser )
+{
+	struct partition_parser **p;
+    
+	for( p = &partition_parsers; *p; p = &(*p)->next ) {
+		if (*p == parser) {
+			*p = parser->next;
+			parser->next = NULL;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+#endif
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_partbl;
+
+static int partbl_read_proc(char *buf, char **start, off_t offset,
+			    int len, int *eof, void *private)
+{
+	struct partition_parser *p;
+
+	len = 0;
+	for( p = partition_parsers; p && len < 4000; p = p->next )
+		len += sprintf(buf + len, "%s\n", p->name );
+	*start = buf + offset;
+	return len > offset ? len - offset : 0;
+}
+#endif
+
+__initfunc(static void partbl_init( void ))
+{
+	extern void msdos_partbl_init(void);
+	extern void osf_partbl_init(void);
+	extern void sun_partbl_init(void);
+	extern void amiga_partbl_init(void);
+	extern void atari_partbl_init(void);
+	extern void mac_partbl_init(void);
+    
+	if (HAVE_MAC_PARTITION)
+		mac_partbl_init();
+	if (HAVE_ATARI_PARTITION)
+		atari_partbl_init();
+	if (HAVE_AMIGA_PARTITION)
+		amiga_partbl_init();
+	if (HAVE_SUN_PARTITION)
+		sun_partbl_init();
+	if (HAVE_OSF_PARTITION)
+		osf_partbl_init();
+	if (HAVE_MSDOS_PARTITION)
+		msdos_partbl_init();
+
+#ifdef CONFIG_PROC_FS
+	proc_partbl = create_proc_entry("partition-formats", 0, 0);
+	if (proc_partbl)
+		proc_partbl->read_proc = partbl_read_proc;
+#endif
+}
+
 /* This function is used to re-read partition tables for removable disks.
    Much of the cleanup from the old partition tables should have already been
    done */
@@ -1064,6 +481,7 @@
 	console_map_init();
 #endif
 
+	partbl_init();
 	for (p = gendisk_head ; p ; p=p->next) {
 		setup_dev(p);
 		nr += p->nr_real;
@@ -1076,3 +494,10 @@
 	rd_load();
 #endif
 }
+
+/* symbols visible for partbl_* modules */
+EXPORT_SYMBOL(add_partition);
+EXPORT_SYMBOL(get_ptable_blocksize);
+EXPORT_SYMBOL(current_minor);
+EXPORT_SYMBOL(register_partbl);
+EXPORT_SYMBOL(unregister_partbl);
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/partbl_amiga.c linux-2.1.57/drivers/block/partbl_amiga.c
--- linux-2.1.57.orig/drivers/block/partbl_amiga.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.57/drivers/block/partbl_amiga.c	Wed Oct  8 23:34:27 1997
@@ -0,0 +1,121 @@
+/*
+ *  partbl_amiga.c -- Amiga RDSK partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/affs_hardblocks.h>
+#include <asm/byteorder.h>
+
+static __inline__ u32
+checksum_block(u32 *m, int size)
+{
+	u32 sum = 0;
+
+	while (size--)
+		sum += be32_to_cpu(*m++);
+	return sum;
+}
+
+static int
+amiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+{
+	struct buffer_head	*bh;
+	struct RigidDiskBlock	*rdb;
+	struct PartitionBlock	*pb;
+	int			 start_sect;
+	int			 nr_sects;
+	int			 blk;
+	int			 part, res;
+
+	MOD_INC_USE_COUNT;
+	set_blocksize(dev,512);
+	res = 0;
+
+	for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) {
+		if(!(bh = bread(dev,blk,512))) {
+			printk("Dev %s: unable to read RDB block %d\n",
+			       kdevname(dev),blk);
+			res = -1;
+			goto rdb_done;
+		}
+		if (*(u32 *)bh->b_data == cpu_to_be32(IDNAME_RIGIDDISK)) {
+			rdb = (struct RigidDiskBlock *)bh->b_data;
+			if (checksum_block((u32 *)bh->b_data,be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)) {
+				printk("Dev %s: RDB in block %d has bad checksum\n",
+				       kdevname(dev),blk);
+				brelse(bh);
+				continue;
+			}
+			printk(" RDSK");
+			blk = be32_to_cpu(rdb->rdb_PartitionList);
+			brelse(bh);
+			for (part = 1; blk > 0 && part <= 16; part++) {
+				if (!(bh = bread(dev,blk,512))) {
+					printk("Dev %s: unable to read partition block %d\n",
+						       kdevname(dev),blk);
+					res = -1;
+					goto rdb_done;
+				}
+				pb  = (struct PartitionBlock *)bh->b_data;
+				blk = be32_to_cpu(pb->pb_Next);
+				if (pb->pb_ID == cpu_to_be32(IDNAME_PARTITION) && checksum_block(
+				    (u32 *)pb,be32_to_cpu(pb->pb_SummedLongs) & 0x7F) == 0 ) {
+					
+					/* Tell Kernel about it */
+
+					if (!(nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
+							  be32_to_cpu(pb->pb_Environment[9])) *
+							 be32_to_cpu(pb->pb_Environment[3]) *
+							 be32_to_cpu(pb->pb_Environment[5]))) {
+						continue;
+					}
+					start_sect = be32_to_cpu(pb->pb_Environment[9]) *
+						     be32_to_cpu(pb->pb_Environment[3]) *
+						     be32_to_cpu(pb->pb_Environment[5]);
+					add_partition(hd,current_minor,start_sect,nr_sects);
+					current_minor++;
+					res = 1;
+				}
+				brelse(bh);
+			}
+			printk("\n");
+			break;
+		}
+	}
+
+rdb_done:
+	set_blocksize(dev,BLOCK_SIZE);
+	MOD_DEC_USE_COUNT;
+	return res;
+}
+
+static struct partition_parser amiga_partition_parser =
+    { NULL, "amiga", amiga_partition };
+
+#ifndef MODULE
+__initfunc(void amiga_partbl_init( void ))
+{
+	(void)register_partbl( &amiga_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &amiga_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &amiga_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/partbl_atari.c linux-2.1.57/drivers/block/partbl_atari.c
--- linux-2.1.57.orig/drivers/block/partbl_atari.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.57/drivers/block/partbl_atari.c	Thu Oct  9 21:18:40 1997
@@ -0,0 +1,203 @@
+/*
+ *  partbl_atari.c -- Atari partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/atari_rootsec.h>
+#include <asm/byteorder.h>
+
+
+/* ++guenther: this should be settable by the user ("make config")?.
+ * roman: doesn't use much code, better always include it :-)
+ */
+#define ICD_PARTS
+
+/* check if a partition entry looks valid -- Atari format is assumed if at
+ * least one of the primary entries is ok this way */
+#define	VALID_PARTITION(pi,hdsiz)					     \
+    (((pi)->flg & 1) &&							     \
+     isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \
+     be32_to_cpu((pi)->st) <= (hdsiz) &&				     \
+     be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
+
+static int atari_partition (struct gendisk *hd, kdev_t dev,
+			    unsigned long first_sector)
+{
+  int minor = current_minor, m_lim = current_minor + hd->max_p;
+  int i;
+  struct buffer_head *bh;
+  struct rootsector *rs;
+  struct partition_info *pi;
+  u32 extensect;
+  u32 hd_size;
+#ifdef ICD_PARTS
+  int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
+#endif
+
+  MOD_INC_USE_COUNT;
+  bh = bread (dev, 0, get_ptable_blocksize(dev));
+  if (!bh)
+    {
+      printk (" unable to read block 0\n");
+      MOD_DEC_USE_COUNT;
+      return -1;
+    }
+
+  rs = (struct rootsector *) bh->b_data;
+  hd_size = hd->part[0].nr_sects;
+  if (!VALID_PARTITION( &rs->part[0], hd_size ) &&
+      !VALID_PARTITION( &rs->part[1], hd_size ) &&
+      !VALID_PARTITION( &rs->part[2], hd_size ) &&
+      !VALID_PARTITION( &rs->part[3], hd_size )) {
+      /* if there's no valid primary partition, assume that no Atari format
+       * partition table (there's no reliable magic or the like :-() */
+      MOD_DEC_USE_COUNT;
+      return 0;
+  }
+
+  printk (" AHDI");
+  pi = &rs->part[0];
+  for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++)
+    {
+      if (pi->flg & 1)
+	/* active partition */
+	{
+	  if (memcmp (pi->id, "XGM", 3) == 0)
+	    /* extension partition */
+	    {
+	      struct rootsector *xrs;
+	      struct buffer_head *xbh;
+	      u32 partsect;
+
+#ifdef ICD_PARTS
+	      part_fmt = 1;
+#endif
+	      printk(" XGM<");
+	      partsect = extensect = be32_to_cpu(pi->st);
+	      while (1)
+		{
+		  xbh = bread (dev, partsect / 2, 1024);
+		  if (!xbh)
+		    {
+		      printk (" block %u read failed\n", partsect);
+		      brelse(bh);
+		      MOD_DEC_USE_COUNT;
+		      return -1;
+		    }
+		  if (partsect & 1)
+		    xrs = (struct rootsector *) &xbh->b_data[512];
+		  else
+		    xrs = (struct rootsector *) &xbh->b_data[0];
+
+		  /* ++roman: valid bit must be set in one of the first 3
+		   * slots */
+		  for( i = 0; i < 3; ++i )
+		      if (xrs->part[0].flg & 1)
+			  break;
+		  if (i == 3) {
+		    printk( "\nNo valid subpartition in extended "
+			    "partition!\n" );
+		    break;
+		  }
+		  
+		  add_partition(hd, minor,
+				partsect + be32_to_cpu(xrs->part[i].st),
+				be32_to_cpu(xrs->part[i].siz));
+
+		  /* the slot following must be either invalid (end of list)
+		   * or another XGM entry */
+		  if (!(xrs->part[i+1].flg & 1)) {
+		    brelse( xbh );
+		    break;
+		  }
+		  if (memcmp( xrs->part[i+1].id, "XGM", 3 ) != 0) {
+		    printk( "\nLink ID in extended partition is not XGM!\n" );
+		    brelse( xbh );
+		    break;
+		  }
+
+		  partsect = xrs->part[i+1].st + extensect;
+		  brelse (xbh);
+		  minor++;
+		  if (minor >= m_lim) {
+		    printk( "\nMaximum number of partitions reached!\n" );
+		    break;
+		  }
+		}
+	      printk(" >");
+	    }
+	  else
+	    {
+	      /* we don't care about other id's */
+	      add_partition (hd, minor, be32_to_cpu(pi->st),
+			     be32_to_cpu(pi->siz));
+	    }
+	}
+    }
+#ifdef ICD_PARTS
+  if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */
+  {
+    pi = &rs->icdpart[0];
+    /* sanity check: no ICD format if first partition invalid */
+    if (memcmp (pi->id, "GEM", 3) == 0 ||
+        memcmp (pi->id, "BGM", 3) == 0 ||
+        memcmp (pi->id, "LNX", 3) == 0 ||
+        memcmp (pi->id, "SWP", 3) == 0 ||
+        memcmp (pi->id, "RAW", 3) == 0 )
+    {
+      printk(" ICD<");
+      for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++)
+      {
+        /* accept only GEM,BGM,RAW,LNX,SWP partitions */
+        if (pi->flg & 1 && 
+            (memcmp (pi->id, "GEM", 3) == 0 ||
+             memcmp (pi->id, "BGM", 3) == 0 ||
+             memcmp (pi->id, "LNX", 3) == 0 ||
+             memcmp (pi->id, "SWP", 3) == 0 ||
+             memcmp (pi->id, "RAW", 3) == 0) )
+        {
+          part_fmt = 2;
+	  add_partition (hd, minor, be32_to_cpu(pi->st), be32_to_cpu(pi->siz));
+        }
+      }
+      printk(" >");
+    }
+  }
+#endif
+  brelse (bh);
+  printk ("\n");
+  MOD_DEC_USE_COUNT;
+  return 1;
+}
+
+static struct partition_parser atari_partition_parser =
+    { NULL, "atari", atari_partition };
+
+#ifndef MODULE
+__initfunc(void atari_partbl_init( void ))
+{
+	(void)register_partbl( &atari_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &atari_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &atari_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/partbl_mac.c linux-2.1.57/drivers/block/partbl_mac.c
--- linux-2.1.57.orig/drivers/block/partbl_mac.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.57/drivers/block/partbl_mac.c	Wed Oct  8 23:34:45 1997
@@ -0,0 +1,170 @@
+/*
+ *  partbl_mac.c -- Mac partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+
+
+/*
+ * Code to understand MacOS partition tables.
+ */
+
+#define MAC_PARTITION_MAGIC	0x504d
+
+/* type field value for A/UX or other Unix partitions */
+#define APPLE_AUX_TYPE	"Apple_UNIX_SVR2"
+
+struct mac_partition {
+	__u16	signature;	/* expected to be MAC_PARTITION_MAGIC */
+	__u16	res1;
+	__u32	map_count;	/* # blocks in partition map */
+	__u32	start_block;	/* absolute starting block # of partition */
+	__u32	block_count;	/* number of blocks in partition */
+	char	name[32];	/* partition name */
+	char	type[32];	/* string type description */
+	__u32	data_start;	/* rel block # of first data block */
+	__u32	data_count;	/* number of data blocks */
+	__u32	status;		/* partition status bits */
+	__u32	boot_start;
+	__u32	boot_size;
+	__u32	boot_load;
+	__u32	boot_load2;
+	__u32	boot_entry;
+	__u32	boot_entry2;
+	__u32	boot_cksum;
+	char	processor[16];	/* identifies ISA of boot */
+	/* there is more stuff after this that we don't need */
+};
+
+#define MAC_STATUS_BOOTABLE	8	/* partition is bootable */
+
+#define MAC_DRIVER_MAGIC	0x4552
+
+/* Driver descriptor structure, in block 0 */
+struct mac_driver_desc {
+	__u16	signature;	/* expected to be MAC_DRIVER_MAGIC */
+	__u16	block_size;
+	__u32	block_count;
+    /* ... more stuff */
+};
+
+static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec)
+{
+	struct buffer_head *bh;
+	int blk, blocks_in_map;
+	int dev_bsize, dev_pos, pos;
+	unsigned secsize;
+#ifdef CONFIG_PMAC
+	int first_bootable = 1;
+#endif
+	struct mac_partition *part;
+	struct mac_driver_desc *md;
+
+	MOD_INC_USE_COUNT;
+	dev_bsize = get_ptable_blocksize(dev);
+	dev_pos = 0;
+	/* Get 0th block and look at the first partition map entry. */
+	if ((bh = bread(dev, 0, dev_bsize)) == 0) {
+	    printk("%s: error reading partition table\n",
+		   kdevname(dev));
+	    MOD_DEC_USE_COUNT;
+	    return -1;
+	}
+	md = (struct mac_driver_desc *) bh->b_data;
+	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC) {
+		brelse(bh);
+		MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	secsize = be16_to_cpu(md->block_size);
+	if (secsize >= dev_bsize) {
+		brelse(bh);
+		dev_pos = secsize;
+		if ((bh = bread(dev, secsize/dev_bsize, dev_bsize)) == 0) {
+			printk("%s: error reading partition table\n",
+			       kdevname(dev));
+			MOD_DEC_USE_COUNT;
+			return -1;
+		}
+	}
+	part = (struct mac_partition *) (bh->b_data + secsize - dev_pos);
+	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC) {
+		brelse(bh);
+		MOD_DEC_USE_COUNT;
+		return 0;		/* not a MacOS disk */
+	}
+	printk(" MAC");
+	blocks_in_map = be32_to_cpu(part->map_count);
+	for (blk = 1; blk <= blocks_in_map; ++blk) {
+		pos = blk * secsize;
+		if (pos >= dev_pos + dev_bsize) {
+			brelse(bh);
+			dev_pos = pos;
+			if ((bh = bread(dev, pos/dev_bsize, dev_bsize)) == 0) {
+				printk("%s: error reading partition table\n",
+				       kdevname(dev));
+				MOD_DEC_USE_COUNT;
+				return -1;
+			}
+		}
+		part = (struct mac_partition *) (bh->b_data + pos - dev_pos);
+		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
+			break;
+		blocks_in_map = be32_to_cpu(part->map_count);
+		add_partition(hd, current_minor,
+			fsec + be32_to_cpu(part->start_block) * (secsize/512),
+			be32_to_cpu(part->block_count) * (secsize/512));
+
+#ifdef CONFIG_PMAC
+		/*
+		 * If this is the first bootable partition, tell the
+		 * setup code, in case it wants to make this the root.
+		 */
+		if (first_bootable
+		    && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
+		    && strcasecmp(part->processor, "powerpc") == 0) {
+			note_bootable_part(dev, blk);
+			first_bootable = 0;
+		}
+#endif /* CONFIG_PMAC */
+
+		++current_minor;
+	}
+	brelse(bh);
+	printk("\n");
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static struct partition_parser mac_partition_parser =
+    { NULL, "mac", mac_partition };
+
+#ifndef MODULE
+__initfunc(void mac_partbl_init( void ))
+{
+	(void)register_partbl( &mac_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &mac_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &mac_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/partbl_msdos.c linux-2.1.57/drivers/block/partbl_msdos.c
--- linux-2.1.57.orig/drivers/block/partbl_msdos.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.57/drivers/block/partbl_msdos.c	Wed Oct  8 23:34:19 1997
@@ -0,0 +1,368 @@
+/*
+ *  partbl_msdos.c -- MSDOS partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991, 1992  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
+ */
+
+#include <linux/module.h>
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+
+/*
+ * Many architectures don't like unaligned accesses, which is
+ * frequently the case with the nr_sects and start_sect partition
+ * table entries.
+ */
+#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) == LINUX_EXTENDED_PARTITION);
+}
+
+/*
+ * 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.
+ */
+
+#define MSDOS_LABEL_MAGIC		0xAA55
+
+static void extended_partition(struct gendisk *hd, kdev_t dev)
+{
+	struct buffer_head *bh;
+	struct partition *p;
+	unsigned long first_sector, first_size, this_sector, this_size;
+	int mask = (1 << hd->minor_shift) - 1;
+	int i;
+
+	first_sector = hd->part[MINOR(dev)].start_sect;
+	first_size = hd->part[MINOR(dev)].nr_sects;
+	this_sector = first_sector;
+
+	while (1) {
+		if ((current_minor & mask) == 0)
+			return;
+		if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+			return;
+	  /*
+	   * This block is from a device that we're about to stomp on.
+	   * So make sure nobody thinks this block is usable.
+	   */
+		bh->b_state = 0;
+
+		if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC))
+			goto done;
+
+		p = (struct partition *) (0x1BE + bh->b_data);
+
+		this_size = hd->part[MINOR(dev)].nr_sects;
+
+		/*
+		 * 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++) {
+		    if (!NR_SECTS(p) || is_extended_partition(p))
+		      continue;
+
+		    /* Check the 3rd and 4th entries -
+		       these sometimes contain random garbage */
+		    if (i >= 2
+			&& START_SECT(p) + NR_SECTS(p) > this_size
+			&& (this_sector + START_SECT(p) < first_sector ||
+			    this_sector + START_SECT(p) + NR_SECTS(p) >
+			     first_sector + first_size))
+		      continue;
+
+		    add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
+		    current_minor++;
+		    if ((current_minor & mask) == 0)
+		      goto done;
+		}
+		/*
+		 * Next, process the (first) extended partition, if present.
+		 * (So far, there seems to be no reason to make
+		 *  extended_partition()  recursive and allow a tree
+		 *  of extended partitions.)
+		 * It should be a link to the next logical partition.
+		 * Create a minor for this just long enough to get the next
+		 * partition table.  The minor will be reused for the next
+		 * data 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 */
+
+		hd->part[current_minor].nr_sects = NR_SECTS(p);
+		hd->part[current_minor].start_sect = first_sector + START_SECT(p);
+		this_sector = first_sector + START_SECT(p);
+		dev = MKDEV(hd->major, current_minor);
+		brelse(bh);
+	}
+done:
+	brelse(bh);
+}
+
+#ifdef CONFIG_BSD_DISKLABEL
+/* 
+ * Create devices for BSD partitions listed in a disklabel, under a
+ * dos-like partition. See extended_partition() for more information.
+ */
+static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev)
+{
+	struct buffer_head *bh;
+	struct bsd_disklabel *l;
+	struct bsd_partition *p;
+	int mask = (1 << hd->minor_shift) - 1;
+
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+		return;
+	bh->b_state = 0;
+	l = (struct bsd_disklabel *) (bh->b_data+512);
+	if (l->d_magic != BSD_DISKMAGIC) {
+		brelse(bh);
+		return;
+	}
+
+	p = &l->d_partitions[0];
+	while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) {
+		if ((current_minor & mask) >= (4 + hd->max_p))
+			break;
+
+		if (p->p_fstype != BSD_FS_UNUSED) {
+			add_partition(hd, current_minor, p->p_offset, p->p_size);
+			current_minor++;
+		}
+		p++;
+	}
+	brelse(bh);
+
+}
+#endif
+
+static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+{
+	int i, minor = current_minor;
+	struct buffer_head *bh;
+	struct partition *p;
+	unsigned char *data;
+	int mask = (1 << hd->minor_shift) - 1;
+#ifdef CONFIG_BLK_DEV_IDE
+	int tested_for_xlate = 0;
+
+	MOD_INC_USE_COUNT;
+read_mbr:
+#endif
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
+		printk(" unable to read partition table\n");
+	    MOD_DEC_USE_COUNT;
+		return -1;
+	}
+	data = bh->b_data;
+	/* In some cases we modify the geometry    */
+	/*  of the drive (below), so ensure that   */
+	/*  nobody else tries to re-use this data. */
+	bh->b_state = 0;
+#ifdef CONFIG_BLK_DEV_IDE
+check_table:
+#endif
+	if (*(unsigned short *)  (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	p = (struct partition *) (0x1be + data);
+
+#ifdef CONFIG_BLK_DEV_IDE
+	if (!tested_for_xlate++) {	/* Do this only once per disk */
+		/*
+		 * Look for various forms of IDE disk geometry translation
+		 */
+		extern int ide_xlate_1024(kdev_t, int, const char *);
+		unsigned int sig = le16_to_cpu(*(unsigned short *)(data + 2));
+		if (SYS_IND(p) == EZD_PARTITION) {
+			/*
+			 * The remainder of the disk must be accessed using
+			 * a translated geometry that reduces the number of 
+			 * apparent cylinders to less than 1024 if possible.
+			 *
+			 * ide_xlate_1024() will take care of the necessary
+			 * adjustments to fool fdisk/LILO and partition check.
+			 */
+			if (ide_xlate_1024(dev, -1, " [EZD]")) {
+				data += 512;
+				goto check_table;
+			}
+		} else if (SYS_IND(p) == DM6_PARTITION) {
+
+			/*
+			 * Everything on the disk is offset by 63 sectors,
+			 * including a "new" MBR with its own partition table,
+			 * and the remainder of the disk must be accessed using
+			 * a translated geometry that reduces the number of 
+			 * apparent cylinders to less than 1024 if possible.
+			 *
+			 * ide_xlate_1024() will take care of the necessary
+			 * adjustments to fool fdisk/LILO and partition check.
+			 */
+			if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
+				brelse(bh);
+				goto read_mbr;	/* start over with new MBR */
+			}
+		} else if (sig <= 0x1ae &&
+			   *(unsigned short *)(data + sig) == cpu_to_le16(0x55AA) &&
+			   (1 & *(unsigned char *)(data + sig + 2))) {
+			/* DM6 signature in MBR, courtesy of OnTrack */
+			(void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
+		} else if (SYS_IND(p) == DM6_AUX1PARTITION || SYS_IND(p) == DM6_AUX3PARTITION) {
+			/*
+			 * DM6 on other than the first (boot) drive
+			 */
+			(void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
+		} else {
+			/*
+			 * Examine the partition table for common translations.
+			 * This is necessary for drives for situations where
+			 * the translated geometry is unavailable from the BIOS.
+			 */
+			for (i = 0; i < 4 ; i++) {
+				struct partition *q = &p[i];
+				if (NR_SECTS(q)
+				   && (q->sector & 63) == 1
+				   && (q->end_sector & 63) == 63) {
+					unsigned int heads = q->end_head + 1;
+					if (heads == 32 || heads == 64 || heads == 128 || heads == 255) {
+
+						(void) ide_xlate_1024(dev, heads, " [PTBL]");
+						break;
+					}
+				}
+			}
+		}
+	}
+#endif	/* CONFIG_BLK_DEV_IDE */
+
+	printk(" DOS");	/* show partition type */
+	current_minor += 4;  /* first "extra" minor (for extended partitions) */
+	for (i=1 ; i<=4 ; minor++,i++,p++) {
+		if (!NR_SECTS(p))
+			continue;
+		add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
+		if (is_extended_partition(p)) {
+			printk(" <");
+			/*
+			 * If we are rereading the partition table, we need
+			 * to set the size of the partition so that we will
+			 * be able to bread the block containing the extended
+			 * partition info.
+			 */
+			hd->sizes[minor] = hd->part[minor].nr_sects 
+			  	>> (BLOCK_SIZE_BITS - 9);
+			extended_partition(hd, MKDEV(hd->major, minor));
+			printk(" >");
+			/* prevent someone doing mkfs or mkswap on an
+			   extended partition, but leave room for LILO */
+			if (hd->part[minor].nr_sects > 2)
+				hd->part[minor].nr_sects = 2;
+		}
+#ifdef CONFIG_BSD_DISKLABEL
+		if (SYS_IND(p) == BSD_PARTITION) {
+			printk(" BSD<");
+			bsd_disklabel_partition(hd, MKDEV(hd->major, minor));
+			printk(" >");
+		}
+#endif
+	}
+	/*
+	 *  Check for old-style Disk Manager partition table
+	 */
+	if (*(unsigned short *) (data+0xfc) == cpu_to_le16(MSDOS_LABEL_MAGIC)) {
+		p = (struct partition *) (0x1be + data);
+		for (i = 4 ; i < 16 ; i++, current_minor++) {
+			p--;
+			if ((current_minor & mask) == 0)
+				break;
+			if (!(START_SECT(p) && NR_SECTS(p)))
+				continue;
+			add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+		}
+	}
+	printk("\n");
+	brelse(bh);
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static struct partition_parser msdos_partition_parser =
+    { NULL, "msdos", msdos_partition };
+
+#ifndef MODULE
+__initfunc(void msdos_partbl_init( void ))
+{
+	(void)register_partbl( &msdos_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &msdos_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &msdos_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/partbl_osf.c linux-2.1.57/drivers/block/partbl_osf.c
--- linux-2.1.57.orig/drivers/block/partbl_osf.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.57/drivers/block/partbl_osf.c	Wed Oct  8 23:34:54 1997
@@ -0,0 +1,117 @@
+/*
+ *  partbl_osf.c -- partition table parser for OSF partitions (alpha)
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+
+static int osf_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+{
+	int i;
+	int mask = (1 << hd->minor_shift) - 1;
+	struct buffer_head *bh;
+	struct disklabel {
+		u32 d_magic;
+		u16 d_type,d_subtype;
+		u8 d_typename[16];
+		u8 d_packname[16];
+		u32 d_secsize;
+		u32 d_nsectors;
+		u32 d_ntracks;
+		u32 d_ncylinders;
+		u32 d_secpercyl;
+		u32 d_secprtunit;
+		u16 d_sparespertrack;
+		u16 d_sparespercyl;
+		u32 d_acylinders;
+		u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
+		u32 d_headswitch, d_trkseek, d_flags;
+		u32 d_drivedata[5];
+		u32 d_spare[5];
+		u32 d_magic2;
+		u16 d_checksum;
+		u16 d_npartitions;
+		u32 d_bbsize, d_sbsize;
+		struct d_partition {
+			u32 p_size;
+			u32 p_offset;
+			u32 p_fsize;
+			u8  p_fstype;
+			u8  p_frag;
+			u16 p_cpg;
+		} d_partitions[8];
+	} * label;
+	struct d_partition * partition;
+#define DISKLABELMAGIC (0x82564557UL)
+
+	MOD_INC_USE_COUNT;
+	if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
+		printk("unable to read partition table\n");
+	    MOD_DEC_USE_COUNT;
+		return -1;
+	}
+	label = (struct disklabel *) (bh->b_data+64);
+	partition = label->d_partitions;
+	if (label->d_magic != cpu_to_le32(DISKLABELMAGIC)) {
+#if 0
+		printk("magic: %08x\n", label->d_magic);
+#endif
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	if (label->d_magic2 != cpu_to_le32(DISKLABELMAGIC)) {
+#if 0
+		printk("magic2: %08x\n", label->d_magic2);
+#endif
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	printk(" OSF");
+	for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
+		if ((current_minor & mask) == 0)
+		        break;
+		if (partition->p_size)
+			add_partition(hd, current_minor,
+				first_sector+le32_to_cpu(partition->p_offset),
+				le32_to_cpu(partition->p_size));
+		current_minor++;
+	}
+	printk("\n");
+	brelse(bh);
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static struct partition_parser osf_partition_parser =
+    { NULL, "osf",  osf_partition };
+
+#ifndef MODULE
+__initfunc(void osf_partbl_init( void ))
+{
+	(void)register_partbl( &osf_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &osf_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &osf_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/drivers/block/partbl_sun.c linux-2.1.57/drivers/block/partbl_sun.c
--- linux-2.1.57.orig/drivers/block/partbl_sun.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.57/drivers/block/partbl_sun.c	Wed Oct  8 23:35:03 1997
@@ -0,0 +1,115 @@
+/*
+ *  partbl_sun.c -- Sun partition table parser
+ *
+ *  Code extracted from
+ *  linux/drivers/block/genhd.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/module.h>
+
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+
+static int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+{
+	int i, csum;
+	unsigned short *ush;
+	struct buffer_head *bh;
+	struct sun_disklabel {
+		unsigned char info[128];   /* Informative text string */
+		unsigned char spare[292];  /* Boot information etc. */
+		unsigned short rspeed;     /* Disk rotational speed */
+		unsigned short pcylcount;  /* Physical cylinder count */
+		unsigned short sparecyl;   /* extra sects per cylinder */
+		unsigned char spare2[4];   /* More magic... */
+		unsigned short ilfact;     /* Interleave factor */
+		unsigned short ncyl;       /* Data cylinder count */
+		unsigned short nacyl;      /* Alt. cylinder count */
+		unsigned short ntrks;      /* Tracks per cylinder */
+		unsigned short nsect;      /* Sectors per track */
+		unsigned char spare3[4];   /* Even more magic... */
+		struct sun_partition {
+			__u32 start_cylinder;
+			__u32 num_sectors;
+		} partitions[8];
+		unsigned short magic;      /* Magic number */
+		unsigned short csum;       /* Label xor'd checksum */
+	} * label;		
+	struct sun_partition *p;
+	unsigned long spc;
+#define SUN_LABEL_MAGIC          0xDABE
+
+	MOD_INC_USE_COUNT;
+	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) {
+		printk("Dev %s: unable to read partition table\n",
+		       kdevname(dev));
+	    MOD_DEC_USE_COUNT;
+		return -1;
+	}
+	label = (struct sun_disklabel *) bh->b_data;
+	p = label->partitions;
+	if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
+#if 0
+		printk("Dev %s Sun disklabel: bad magic %04x\n",
+		       kdevname(dev), be16_to_cpu(label->magic));
+#endif
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	/* Look at the checksum */
+	ush = ((unsigned short *) (label+1)) - 1;
+	for(csum = 0; ush >= ((unsigned short *) label);)
+		csum ^= *ush--;
+	if(csum) {
+		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
+		       kdevname(dev));
+		brelse(bh);
+	    MOD_DEC_USE_COUNT;
+		return 0;
+	}
+	printk(" UFS");
+	/* All Sun disks have 8 partition entries */
+	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
+	for(i=0; i < 8; i++, p++) {
+		unsigned long st_sector;
+		int num_sectors;
+
+		st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc;
+		num_sectors = be32_to_cpu(p->num_sectors);
+		if (num_sectors)
+			add_partition(hd, current_minor, st_sector, num_sectors);
+		current_minor++;
+	}
+	printk("\n");
+	brelse(bh);
+	MOD_DEC_USE_COUNT;
+	return 1;
+}
+
+static struct partition_parser sun_partition_parser =
+    { NULL, "sun", sun_partition };
+
+#ifndef MODULE
+__initfunc(void sun_partbl_init( void ))
+{
+	(void)register_partbl( &sun_partition_parser );
+}
+#else
+int init_module(void)
+{
+	return register_partbl( &sun_partition_parser );
+}
+
+void cleanup_module(void)
+{
+	(void)unregister_partbl( &sun_partition_parser );
+}
+#endif
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/fs/Config.in linux-2.1.57/fs/Config.in
--- linux-2.1.57.orig/fs/Config.in	Wed Sep 10 21:16:43 1997
+++ linux-2.1.57/fs/Config.in	Wed Oct  8 23:38:18 1997
@@ -14,9 +14,6 @@
 dep_tristate 'MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS
 dep_tristate 'VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS
 dep_tristate 'umsdos: Unix like fs on top of std MSDOS FAT fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
-if [ "$ARCH" = "m68k" ]; then
-  bool 'MSDOS partition support' CONFIG_MSDOS_PARTITION
-fi
 
 bool '/proc filesystem support' CONFIG_PROC_FS
 if [ "$CONFIG_INET" = "y" ]; then
@@ -55,14 +52,73 @@
 tristate 'Amiga FFS filesystem support' CONFIG_AFFS_FS
 tristate 'ROM filesystem support' CONFIG_ROMFS_FS
 tristate 'Kernel automounter support (experimental)' CONFIG_AUTOFS_FS
-if [ "$CONFIG_AFFS_FS" != "n" ]; then
-  define_bool CONFIG_AMIGA_PARTITION y
-fi
 tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS
-if [ "$CONFIG_UFS_FS" != "n" ]; then
+
+comment 'Partition Tables'
+if [ "$ARCH" = "i386" ]; then
+  define_bool CONFIG_MSDOS_PARTITION y
+fi
+if [ "$ARCH" = "alpha" ]; then
+  define_bool CONFIG_OSF_PARTITION y
+fi
+if [ "$ARCH" = "m68k" ]; then
+  if [ "$CONFIG_AMIGA" = "y" ]; then
+    define_bool CONFIG_AMIGA_PARTITION y
+  fi
+  if [ "$CONFIG_ATARI" = "y" ]; then
+    define_bool CONFIG_ATARI_PARTITION y
+  fi
+  if [ "$CONFIG_MAC" = "y" ]; then
+    define_bool CONFIG_MAC_PARTITION y
+  fi
+fi
+if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+  define_bool CONFIG_SUN_PARTITION y
+fi
+if [ "$ARCH" = "ppc" ]; then
+  if [ "$CONFIG_MACH_SPECIFIC" = "y" ]; then
+    if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_CHRP" = "y" ]; then
+      define_bool CONFIG_MAC_PARTITION y
+    fi
+    if [ "$CONFIG_PREP" = "y" -o "$CONFIG_CHRP" = "y" ]; then
+      define_bool CONFIG_MSDOS_PARTITION y
+    fi
+  else
+    define_bool CONFIG_MAC_PARTITION y
+    define_bool CONFIG_MSDOS_PARTITION y
+  fi
+fi
+
+bool 'Support for foreign partition tables' CONFIG_FOREIGN_PARTITIONS
+if [ "$CONFIG_FOREIGN_PARTITIONS" = "y" ]; then
+  if [ ! \( "$ARCH" = "i386" -o \
+            \( "$ARCH" = "ppc" -a \
+               \( "$CONFIG_MACH_SPECIFIC" = "n" -o "$CONFIG_PREP" = "y" -o \
+                  "$CONFIG_CHRP" = "y" \) \) \) ]; then
+  	tristate 'MS-DOS partition support' CONFIG_MSDOS_PARTITION
+  fi
+  if [ "$ARCH" != "alpha" ]; then
+  	tristate 'OSF partition support' CONFIG_OSF_PARTITION
+  fi
+  if [ "$ARCH" != "sparc" -a "$ARCH" != "sparc64" ]; then
+  	tristate 'Sun partition support' CONFIG_SUN_PARTITION
+  fi
+  if [ "$CONFIG_AMIGA" != "y" ]; then
+  	tristate 'Amiga RDB partition support' CONFIG_AMIGA_PARTITION
+  fi
+  if [ "$CONFIG_ATARI" != "y" ]; then
+  	tristate 'Atari partition support' CONFIG_ATARI_PARTITION
+  fi
+  if [ ! \( \( "$ARCH" = "m68k" -a "$CONFIG_MAC" = "y" \) -o \
+            \( "$ARCH" = "ppc" -a \
+               \( "$CONFIG_MACH_SPECIFIC" = "n" -o "$CONFIG_PMAC" = "y" -o \
+                  "$CONFIG_CHRP" = "y" \) \) \) ]; then
+  	tristate 'Mac partition support' CONFIG_MAC_PARTITION
+  fi
+fi
+if [ "$CONFIG_MSDOS_PARTITION" != "n" ]; then
   bool 'BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
-  bool 'SMD disklabel (Sun partition tables) support' CONFIG_SMD_DISKLABEL
 fi
-bool 'Macintosh partition map support' CONFIG_MAC_PARTITION
+
 endmenu
 
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/include/asm-m68k/atari_rootsec.h linux-2.1.57/include/asm-m68k/atari_rootsec.h
--- linux-2.1.57.orig/include/asm-m68k/atari_rootsec.h	Wed Sep 18 19:03:36 1996
+++ linux-2.1.57/include/asm-m68k/atari_rootsec.h	Thu Jan  1 01:00:00 1970
@@ -1,34 +0,0 @@
-#ifndef _LINUX_ATARI_ROOTSEC_H
-#define _LINUX_ATARI_ROOTSEC_H
-
-/*
- * linux/include/linux/atari_rootsec.h
- * definitions for Atari Rootsector layout
- * by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de)
- *
- * modified for ICD/Supra partitioning scheme restricted to at most 12
- * partitions
- * by Guenther Kelleter (guenther@pool.informatik.rwth-aachen.de)
- */
-
-struct partition_info
-{
-  u_char flg;			/* bit 0: active; bit 7: bootable */
-  char id[3];			/* "GEM", "BGM", "XGM", or other */
-  u_long st;			/* start of partition */
-  u_long siz;			/* length of partition */
-};
-
-struct rootsector
-{
-  char unused[0x156];		/* room for boot code */
-  struct partition_info icdpart[8];	/* info for ICD-partitions 5..12 */
-  char unused2[0xc];
-  u_long hd_siz;		/* size of disk in blocks */
-  struct partition_info part[4];
-  u_long bsl_st;		/* start of bad sector list */
-  u_long bsl_cnt;		/* length of bad sector list */
-  u_short checksum;		/* checksum for bootable disks */
-} __attribute__((__packed__));
-
-#endif /* _LINUX_ATARI_ROOTSEC_H */
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/include/linux/atari_rootsec.h linux-2.1.57/include/linux/atari_rootsec.h
--- linux-2.1.57.orig/include/linux/atari_rootsec.h	Thu Jan  1 01:00:00 1970
+++ linux-2.1.57/include/linux/atari_rootsec.h	Thu Oct  9 21:19:03 1997
@@ -0,0 +1,34 @@
+#ifndef _LINUX_ATARI_ROOTSEC_H
+#define _LINUX_ATARI_ROOTSEC_H
+
+/*
+ * linux/include/linux/atari_rootsec.h
+ * definitions for Atari Rootsector layout
+ * by Andreas Schwab (schwab@ls5.informatik.uni-dortmund.de)
+ *
+ * modified for ICD/Supra partitioning scheme restricted to at most 12
+ * partitions
+ * by Guenther Kelleter (guenther@pool.informatik.rwth-aachen.de)
+ */
+
+struct partition_info
+{
+  u_char flg;			/* bit 0: active; bit 7: bootable */
+  char id[3];			/* "GEM", "BGM", "XGM", or other */
+  u32 st;			/* start of partition */
+  u32 siz;			/* length of partition */
+};
+
+struct rootsector
+{
+  char unused[0x156];			/* room for boot code */
+  struct partition_info icdpart[8];	/* info for ICD-partitions 5..12 */
+  char unused2[0xc];
+  u32 hd_siz;				/* size of disk in blocks */
+  struct partition_info part[4];
+  u32 bsl_st;				/* start of bad sector list */
+  u32 bsl_cnt;				/* length of bad sector list */
+  u16 checksum;				/* checksum for bootable disks */
+} __attribute__ ((__packed__));
+
+#endif /* _LINUX_ATARI_ROOTSEC_H */
diff -u --recursive --exclude-from=diff-excludes --new-file linux-2.1.57.orig/include/linux/genhd.h linux-2.1.57/include/linux/genhd.h
--- linux-2.1.57.orig/include/linux/genhd.h	Wed Oct  1 21:24:10 1997
+++ linux-2.1.57/include/linux/genhd.h	Thu Oct  9 20:37:16 1997
@@ -10,25 +10,42 @@
  */
 
 #include <linux/config.h>
+#include <linux/kdev_t.h>
 
-#if !defined (__mc68000__)
-#define CONFIG_MSDOS_PARTITION 1
+#ifdef CONFIG_MSDOS_PARTITION
+# define HAVE_MSDOS_PARTITION 1
+#else
+# define HAVE_MSDOS_PARTITION 0
 #endif
 
-#ifdef __alpha__
-#define CONFIG_OSF_PARTITION 1
+#ifdef CONFIG_OSF_PARTITION
+# define HAVE_OSF_PARTITION 1
+#else
+# define HAVE_OSF_PARTITION 0
 #endif
 
-#if defined(__sparc__) || defined(CONFIG_SMD_DISKLABEL)
-#define CONFIG_SUN_PARTITION 1
+#ifdef CONFIG_SUN_PARTITION
+# define HAVE_SUN_PARTITION 1
+#else
+# define HAVE_SUN_PARTITION 0
 #endif
 
-#if defined(CONFIG_AMIGA) && !defined(CONFIG_AMIGA_PARTITION)
-#define CONFIG_AMIGA_PARTITION 1
+#ifdef CONFIG_AMIGA_PARTITION
+# define HAVE_AMIGA_PARTITION 1
+#else
+# define HAVE_AMIGA_PARTITION 0
 #endif
 
-#if defined(CONFIG_ATARI) && !defined(CONFIG_ATARI_PARTITION)
-#define CONFIG_ATARI_PARTITION 1
+#ifdef CONFIG_ATARI_PARTITION
+# define HAVE_ATARI_PARTITION 1
+#else
+# define HAVE_ATARI_PARTITION 0
+#endif
+
+#ifdef CONFIG_MAC_PARTITION
+# define HAVE_MAC_PARTITION 1
+#else
+# define HAVE_MAC_PARTITION 0
 #endif
 
 /* These two have identical behaviour; use the second one if DOS fdisk gets
@@ -140,5 +157,18 @@
  * to that same buffer (for convenience).
  */
 char *disk_name (struct gendisk *hd, int minor, char *buf);
+void add_partition (struct gendisk *hd, int minor, int start, int size);
+unsigned int get_ptable_blocksize(kdev_t dev);
+extern int current_minor;
+
+struct partition_parser {
+	struct partition_parser *next;
+	char *name;
+	int (*func)(struct gendisk *hd, kdev_t dev,
+		    unsigned long first_sector);
+};
+
+int register_partbl( struct partition_parser *parser );
+int unregister_partbl( struct partition_parser *parser );
 
 #endif

