diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/Documentation/Configure.help linux-2.4.12.gpt/Documentation/Configure.help
--- linux-2.4.12/Documentation/Configure.help	Tue Oct  9 17:13:03 2001
+++ linux-2.4.12.gpt/Documentation/Configure.help	Thu Oct 11 12:49:36 2001
@@ -12771,6 +12771,18 @@ CONFIG_SGI_PARTITION
   Say Y here if you would like to be able to read the hard disk
   partition table format used by SGI machines.
 
+Intel EFI GUID partition support
+CONFIG_EFI_PARTITION
+  Say Y here if you would like to use hard disks under Linux which
+  were partitioned using EFI GPT.  Presently only useful on the
+  IA-64 platform.
+
+/dev/volumes/uuids support (EXPERIMENTAL)
+CONFIG_DEVFS_VOLUMES_UUIDS
+  Say Y here if you would like to access disks and partitions by
+  their Globally Unique Identifiers (GUIDs) which will appear as
+  symbolic links in /dev/volumes/uuids.
+
 Ultrix partition support
 CONFIG_ULTRIX_PARTITION
   Say Y here if you would like to be able to read the hard disk
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/Documentation/kernel-parameters.txt linux-2.4.12.gpt/Documentation/kernel-parameters.txt
--- linux-2.4.12/Documentation/kernel-parameters.txt	Wed Jun 20 13:21:33 2001
+++ linux-2.4.12.gpt/Documentation/kernel-parameters.txt	Thu Oct 11 12:49:36 2001
@@ -17,6 +17,7 @@ restrictions referred to are that the re
 	CD	Appropriate CD support is enabled.
 	DEVFS   devfs support is enabled. 
 	DRM	Direct Rendering Management support is enabled. 
+	EFI	EFI Partitioning (GPT) is enabled
 	EIDE	EIDE/ATAPI support is enabled.
 	FB	The frame buffer device is enabled.
 	HW	Appropriate hardware is enabled.
@@ -212,6 +213,9 @@ running once the system is up.
  
 	gdth=		[HW,SCSI]
 
+	gpt             [EFI] Forces disk with valid GPT signature but
+			invalid Protective MBR to be treated as GPT.
+
 	gscd=		[HW,CD]
 
 	gus=		[HW,SOUND] 
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/fs/partitions/Config.in linux-2.4.12.gpt/fs/partitions/Config.in
--- linux-2.4.12/fs/partitions/Config.in	Sun Aug 12 13:13:59 2001
+++ linux-2.4.12.gpt/fs/partitions/Config.in	Thu Oct 11 12:49:37 2001
@@ -24,6 +24,8 @@ if [ "$CONFIG_PARTITION_ADVANCED" = "y" 
       bool '    Minix subpartition support' CONFIG_MINIX_SUBPARTITION
       bool '    Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
       bool '    Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
+      bool '    EFI GUID Partition support' CONFIG_EFI_PARTITION
+      dep_bool '      /dev/volumes/uuids support (EXPERIMENTAL)' CONFIG_DEVFS_VOLUMES_UUIDS $CONFIG_DEVFS_FS $CONFIG_EFI_PARTITION
    fi
    dep_bool '  Windows Logical Disk Manager (Dynamic Disk) support' CONFIG_LDM_PARTITION $CONFIG_EXPERIMENTAL
    if [ "$CONFIG_LDM_PARTITION" = "y" ]; then
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/fs/partitions/Makefile linux-2.4.12.gpt/fs/partitions/Makefile
--- linux-2.4.12/fs/partitions/Makefile	Thu Jul 26 18:30:04 2001
+++ linux-2.4.12.gpt/fs/partitions/Makefile	Thu Oct 11 12:49:37 2001
@@ -24,6 +24,7 @@ obj-$(CONFIG_SGI_PARTITION) += sgi.o
 obj-$(CONFIG_SUN_PARTITION) += sun.o
 obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
 obj-$(CONFIG_IBM_PARTITION) += ibm.o
+obj-$(CONFIG_EFI_PARTITION) += efi.o
 
 include $(TOPDIR)/Rules.make
 
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/fs/partitions/check.c linux-2.4.12.gpt/fs/partitions/check.c
--- linux-2.4.12/fs/partitions/check.c	Mon Oct  1 22:03:26 2001
+++ linux-2.4.12.gpt/fs/partitions/check.c	Thu Oct 11 12:49:37 2001
@@ -19,6 +19,7 @@
 #include <linux/blk.h>
 #include <linux/init.h>
 #include <linux/raid/md.h>
+#include <linux/uuid.h>
 
 #include "check.h"
 
@@ -33,6 +34,7 @@
 #include "sun.h"
 #include "ibm.h"
 #include "ultrix.h"
+#include "efi.h"
 
 extern int *blk_size[];
 
@@ -42,6 +44,9 @@ static int (*check_part[])(struct gendis
 #ifdef CONFIG_ACORN_PARTITION
 	acorn_partition,
 #endif
+#ifdef CONFIG_EFI_PARTITION
+	efi_partition,		/* this must come before msdos */
+#endif
 #ifdef CONFIG_LDM_PARTITION
 	ldm_partition,		/* this must come before msdos */
 #endif
@@ -266,6 +271,111 @@ setup_devfs:
 	devfs_register_partitions (hd, i, hd->sizes ? 0 : 1);
 }
 
+#ifdef CONFIG_DEVFS_VOLUMES_UUIDS
+static devfs_handle_t volumes_handle;
+static devfs_handle_t volumes_uuids_handle;
+
+/*
+  devfs_register_guid: create a /dev/volumes/uuid entry for a disk or partition
+                       if it has a GUID.
+
+  The /dev/volumes/uuid entry will be a symlink to the "real" devfs device.
+  It is marked as "slave" of the real device,
+  to be automatically unregistered by devfs if that device is unregistered.
+
+  If the partition already had a /dev/volumes/uuid entry, delete
+  (unregister) it.  (If the disk was repartitioned, it's likely the old
+  GUID entry will be wrong).
+
+  dev, minor:  Device for which an entry is to be created.
+
+  Prerequisites: dev->part[minor].guid must be either NULL or point
+                 to a valid kmalloc'ed GUID.
+*/
+
+static void devfs_register_guid (struct gendisk *dev, int minor)
+{
+	efi_guid_t *guid = dev->part[minor].guid;
+	devfs_handle_t guid_handle, slave,
+		real_master = dev->part[minor].de;
+	devfs_handle_t master = real_master;
+	char guid_link[UUID_UNPARSED_LEN + 1];
+	char dirname[128];
+	int pos, st;
+
+	if (!volumes_handle)
+		volumes_handle = devfs_mk_dir (NULL, "volumes", NULL);
+	if (volumes_handle && !volumes_uuids_handle)
+		volumes_uuids_handle = devfs_mk_dir (volumes_handle,
+						    "uuids", NULL);
+	
+
+	if (!guid || !master) return;
+
+	do {
+		slave = devfs_get_unregister_slave (master);
+		if (slave) {
+			if (slave == master || slave == real_master) {
+				printk (KERN_WARNING
+					"devfs_register_guid: infinite slave loop!\n");
+				return;
+			} else if (devfs_get_parent (slave) == volumes_uuids_handle) {
+				printk (KERN_INFO
+					"devfs_register_guid: unregistering %s\n",
+					devfs_get_name (slave, NULL));
+				devfs_unregister_slave (master);
+				slave = NULL;
+			} else
+				master = slave;
+		};
+	} while (slave);
+
+	uuid_unparse((uuid_t *)guid, guid_link);
+	pos = devfs_generate_path (real_master, dirname + 6,
+				   sizeof (dirname) - 6);
+	if (pos < 0) {
+		printk (KERN_WARNING
+			"devfs_register_guid: error generating path: %d\n",
+			pos);
+		return;
+	};
+
+	strncpy (dirname + pos, "../../", 6);
+
+	st = devfs_mk_symlink (volumes_uuids_handle, guid_link,
+			       DEVFS_FL_DEFAULT,
+			       dirname + pos, &guid_handle, NULL);
+
+	if (st < 0) {
+		printk ("Error %d creating symlink\n", st);
+	} else {
+		devfs_auto_unregister (master, guid_handle);
+	};
+};
+
+/*
+  free_disk_guids: kfree all guid data structures alloced for
+  the disk device specified by (dev, minor) and all its partitions.
+
+  This function does not remove symlinks in /dev/guid.
+*/
+static void free_disk_guids (struct gendisk *dev, int minor)
+{
+	int i;
+	efi_guid_t *guid;
+
+	for (i = 0; i < dev->max_p; i++) {
+		guid = dev->part[minor + i].guid;
+		if (!guid) continue;
+		kfree (guid);
+		dev->part[minor + i].guid = NULL;
+	};
+}
+#else
+#define devfs_register_guid(dev, minor)
+#define free_disk_guids(dev, minor)
+#endif /* CONFIG_DEVFS_VOLUMES_UUIDS */
+
 #ifdef CONFIG_DEVFS_FS
 static void devfs_register_partition (struct gendisk *dev, int minor, int part)
 {
@@ -274,7 +384,11 @@ static void devfs_register_partition (st
 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
 	char devname[16];
 
-	if (dev->part[minor + part].de) return;
+	/* Even if the devfs handle is still up-to-date,
+	   the GUID entry probably isn't */
+	if (dev->part[minor + part].de)
+		goto do_guid;
+
 	dir = devfs_get_parent (dev->part[minor].de);
 	if (!dir) return;
 	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
@@ -285,6 +399,9 @@ static void devfs_register_partition (st
 			    dev->major, minor + part,
 			    S_IFBLK | S_IRUSR | S_IWUSR,
 			    dev->fops, NULL);
+ do_guid:
+	devfs_register_guid (dev, minor + part);
+	return;
 }
 
 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
@@ -298,7 +415,9 @@ static void devfs_register_disc (struct 
 	char dirname[64], symlink[16];
 	static devfs_handle_t devfs_handle;
 
-	if (dev->part[minor].de) return;
+	if (dev->part[minor].de)
+		goto do_guid;
+
 	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
 		devfs_flags |= DEVFS_FL_REMOVABLE;
 	if (dev->de_arr) {
@@ -326,6 +445,10 @@ static void devfs_register_disc (struct 
 	devfs_auto_unregister (dev->part[minor].de, slave);
 	if (!dev->de_arr)
 		devfs_auto_unregister (slave, dir);
+
+ do_guid:
+	devfs_register_guid (dev, minor);
+	return;
 }
 #endif  /*  CONFIG_DEVFS_FS  */
 
@@ -349,6 +472,7 @@ void devfs_register_partitions (struct g
 		dev->part[minor].de = NULL;
 		devfs_dealloc_unique_number (&disc_numspace,
 					     dev->part[minor].number);
+		free_disk_guids (dev, minor);
 	}
 #endif  /*  CONFIG_DEVFS_FS  */
 }
@@ -366,8 +490,21 @@ void devfs_register_partitions (struct g
 void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
 	struct block_device_operations *ops, long size)
 {
+	int i;
+
 	if (!gdev)
 		return;
+
+#ifdef CONFIG_DEVFS_VOLUMES_UUIDS
+	/* Initialize all guid fields to NULL (=^ not kmalloc'ed).
+	   It is assumed that drivers call register_disk after
+	   allocating the gen_hd structure, and call grok_partitions
+	   directly for a revalidate event, as those drives I've inspected
+	   (among which hd and sd) do. */
+	for (i = 0; i < gdev->max_p; i++)
+		gdev->part[MINOR(dev) + i].guid = NULL;
+#endif
+
 	grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
 }
 
@@ -385,6 +522,12 @@ void grok_partitions(struct gendisk *dev
 	if (!size || minors == 1)
 		return;
 
+	/* In case this is a revalidation, free GUID memory.
+	   On the first call for this device,
+	   register_disk has set all entries to NULL,
+	   and nothing will happen. */
+	free_disk_guids (dev, first_minor);
+
 	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
 
  	/*
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/fs/partitions/efi.c linux-2.4.12.gpt/fs/partitions/efi.c
--- linux-2.4.12/fs/partitions/efi.c	Wed Dec 31 18:00:00 1969
+++ linux-2.4.12.gpt/fs/partitions/efi.c	Thu Oct 11 14:58:19 2001
@@ -0,0 +1,762 @@
+/************************************************************
+ * EFI GUID Partition Table handling
+ * Per Intel EFI Specification v1.02
+ * http://developer.intel.com/technology/efi/efi.htm
+ * efi.[ch] by Matt Domsch <Matt_Domsch@dell.com>
+ *   Copyright 2000,2001 Dell Computer Corporation
+ *
+ * Note, the EFI Specification, v1.02, has a reference to
+ * Dr. Dobbs Journal, May 1994 (actually it's in May 1992)
+ * but that isn't the CRC function being used by EFI.  Intel's
+ * EFI Sample Implementation shows that they use the same function
+ * as was COPYRIGHT (C) 1986 Gary S. Brown.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * TODO:
+ *
+ * Changelog:
+ * Wed Oct 10 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Changed function comments to DocBook style per Andreas Dilger suggestion.
+ *
+ * Mon Oct 08 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Change read_lba() to use the page cache per Al Viro's work.
+ * - print u64s properly on all architectures
+ * - fixed debug_printk(), now Dprintk()
+ *
+ * Mon Oct 01 2001 Matt Domsch <Matt_Domsch@dell.com>
+ * - Style cleanups
+ * - made most functions static
+ * - Endianness addition
+ * - remove test for second alternate header, as it's not per spec,
+ *   and is unnecessary.  There's now a method to read/write the last
+ *   sector of an odd-sized disk from user space.  No tools have ever
+ *   been released which used this code, so it's effectively dead.
+ * - Per Asit Mallick of Intel, added a test for a valid PMBR.
+ * - Added kernel command line option 'gpt' to override valid PMBR test.
+ *
+ * Wed Jun  6 2001 Martin Wilck <Martin.Wilck@Fujitsu-Siemens.com>
+ * - added devfs volume UUID support (/dev/volumes/uuids) for
+ *   mounting file systems by the partition GUID. 
+ *
+ * Tue Dec  5 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Moved crc32() to linux/lib, added efi_crc32().
+ *
+ * Thu Nov 30 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Replaced Intel's CRC32 function with an equivalent
+ *   non-license-restricted version.
+ *
+ * Wed Oct 25 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Fixed the last_lba() call to return the proper last block
+ *
+ * Thu Oct 12 2000 Matt Domsch <Matt_Domsch@dell.com>
+ * - Thanks to Andries Brouwer for his debugging assistance.
+ * - Code works, detects all the partitions.
+ *
+ ************************************************************/
+#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/blkpg.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/uuid.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include "check.h"
+#include "efi.h"
+
+#if CONFIG_BLK_DEV_MD
+extern void md_autodetect_dev(kdev_t dev);
+#endif
+
+/* Handle printing of 64-bit values */
+#if BITS_PER_LONG == 64
+#define PU64X "%lx"
+#else
+#define PU64X "%llx"
+#endif
+
+
+#undef EFI_DEBUG
+#ifdef EFI_DEBUG
+#define Dprintk(x...) printk(KERN_DEBUG x)
+#else
+#define Dprintk(x...)
+#endif
+
+/* This allows a kernel command line option 'gpt' to override
+ * the test for invalid PMBR.  Not __initdata because reloading
+ * the partition tables happens after init too.
+ */
+static int forcegpt;
+static int __init force_gpt(char *str)
+{
+	forcegpt = 1;
+	return 1;
+}
+
+__setup("gpt", force_gpt);
+
+/**
+ * efi_crc32() - EFI version of crc32 function
+ * @buf: buffer to calculate crc32 of
+ * @len - length of buf
+ *
+ * Description: Returns EFI-style CRC32 value for @buf
+ *
+ * This function uses the crc32 function by Gary S. Brown,
+ * but seeds the function with ~0, and xor's with ~0 at the end.
+ */
+static inline u32 efi_crc32(const void *buf, unsigned long len)
+{
+	return (crc32(~0L, buf, len) ^ ~0L);
+}
+
+/**
+ * le_part_attributes_to_cpus(): converts LE attributes to CPU type in situ
+ * @attributes - ptr to partition attributes
+ * 
+ * Description:  modifies attributes in situ, returns nothing.
+ * Converts a little endian partition attributes struct to the
+ * native cpu representation.  Good for reading attributes off of a disk.
+ */
+static void le_part_attributes_to_cpus(GuidPartitionEntryAttributes_t * a)
+{
+	u64 *b = (u64 *) a;
+	*b = le64_to_cpu(*b);
+}
+
+/**
+ * is_pmbr_valid(): test Protective MBR for validity
+ * @mbr: pointer to a legacy mbr structure
+ *
+ * Description: Returns 1 if PMBR is valid, 0 otherwise.
+ * Validity depends on two things:
+ *  1) MSDOS signature is in the last two bytes of the MBR
+ *  2) One partition of type 0xEE is found
+ */
+static int is_pmbr_valid(LegacyMBR_t * mbr)
+{
+	int i, found = 0, signature = 0;
+	if (!mbr)
+		return 0;
+	signature = (le16_to_cpu(mbr->Signature) == MSDOS_MBR_SIGNATURE);
+	for (i = 0; signature && i < 4; i++) {
+		if (mbr->PartitionRecord[i].sys_ind ==
+		    EFI_PMBR_OSTYPE_EFI_GPT) {
+			found = 1;
+			break;
+		}
+	}
+	return (signature && found);
+}
+
+
+/**
+ * last_lba(): return number of last logical block of device
+ * @hd: gendisk with partition list
+ * @bdev: block device
+ * 
+ * Description: Returns last LBA value on success, 0 on error.
+ * This is stored (by sd and ide-geometry) in
+ * the part[0] entry for this disk, and is the number of
+ * physical sectors available on the disk.
+ */
+static u64 last_lba(struct gendisk *hd, struct block_device *bdev)
+{
+	if (!hd || !hd->part || !bdev)
+		return 0;
+	return hd->part[MINOR(to_kdev_t(bdev->bd_dev))].nr_sects - 1;
+}
+
+/**
+ * read_lba(): Read bytes from disk, starting at given LBA
+ * @hd
+ * @bdev
+ * @lba
+ * @buffer
+ * @size_t
+ *
+ * Description:  Reads @count bytes from @bdev into @buffer.
+ * Returns number of bytes read on success, 0 on error.
+ */
+static size_t
+read_lba(struct gendisk *hd, struct block_device *bdev, u64 lba,
+	 u8 * buffer, size_t count)
+{
+
+	size_t totalreadcount = 0, bytesread = 0;
+	unsigned long blocksize;
+	int i;
+	Sector sect;
+	unsigned char *data = NULL;
+
+	if (!hd || !bdev || !buffer || !count)
+		return 0;
+
+	blocksize = get_hardsect_size(to_kdev_t(bdev->bd_dev));
+	if (!blocksize)
+		blocksize = 512;
+
+	for (i = 0; count > 0; i++) {
+		data = read_dev_sector(bdev, lba, &sect);
+		if (!data)
+			return totalreadcount;
+
+		bytesread =
+		    PAGE_CACHE_SIZE - (data -
+				       (unsigned char *) page_address(sect.
+								      v));
+		bytesread = min(bytesread, count);
+		memcpy(buffer, data, bytesread);
+		put_dev_sector(sect);
+
+		buffer += bytesread;
+		totalreadcount += bytesread;
+		count -= bytesread;
+		lba += (bytesread / blocksize);
+	}
+	return totalreadcount;
+}
+
+
+/**
+ * print_gpt_header(): unparses gpt header to console
+ * @gpt: gpt header
+ */
+static void print_gpt_header(GuidPartitionTableHeader_t * gpt)
+{
+	Dprintk("GUID Partition Table Header\n");
+	if (!gpt)
+		return;
+	Dprintk("Signature      : " PU64X "\n", gpt->Signature);
+	Dprintk("Revision       : %x\n", gpt->Revision);
+	Dprintk("HeaderSize     : %x\n", gpt->HeaderSize);
+	Dprintk("HeaderCRC32    : %x\n", gpt->HeaderCRC32);
+	Dprintk("MyLBA          : " PU64X "\n", gpt->MyLBA);
+	Dprintk("AlternateLBA   : " PU64X "\n", gpt->AlternateLBA);
+	Dprintk("FirstUsableLBA : " PU64X "\n", gpt->FirstUsableLBA);
+	Dprintk("LastUsableLBA  : " PU64X "\n", gpt->LastUsableLBA);
+
+	Dprintk("PartitionEntryLBA : " PU64X "\n", gpt->PartitionEntryLBA);
+	Dprintk("NumberOfPartitionEntries : %x\n",
+		gpt->NumberOfPartitionEntries);
+	Dprintk("SizeOfPartitionEntry : %x\n", gpt->SizeOfPartitionEntry);
+	Dprintk("PartitionEntryArrayCRC32 : %x\n",
+		gpt->PartitionEntryArrayCRC32);
+
+	return;
+}
+
+
+
+/**
+ * alloc_read_gpt_entries(): reads partition entries from disk
+ * @hd
+ * @bdev
+ * @gpt - GPT header
+ * 
+ * Description: Returns ptes on success,  NULL on error.
+ * Allocates space for PTEs based on information found in @gpt.
+ * Notes: remember to free pte when you're done!
+ */
+static GuidPartitionEntry_t *
+alloc_read_gpt_entries(struct gendisk *hd,
+                       struct block_device *bdev,
+                       GuidPartitionTableHeader_t *gpt)
+{
+	u32 i, j;
+	size_t count;
+	GuidPartitionEntry_t *pte;
+	if (!hd || !bdev || !gpt)
+		return NULL;
+
+	count = gpt->NumberOfPartitionEntries * gpt->SizeOfPartitionEntry;
+	Dprintk("ReadGPTEs() kmallocing %x bytes\n", count);
+	if (!count)
+		return NULL;
+	pte = kmalloc(count, GFP_KERNEL);
+	if (!pte)
+		return NULL;
+	memset(pte, 0, count);
+
+	if (read_lba(hd, bdev, gpt->PartitionEntryLBA, (u8 *) pte,
+		     count) < count) {
+		kfree(pte);
+		return NULL;
+	}
+	/* Fixup endianness */
+	for (i = 0; i < gpt->NumberOfPartitionEntries; i++) {
+		le_uuid_to_cpus((uuid_t *)&pte[i].PartitionTypeGuid);
+		le_uuid_to_cpus((uuid_t *)&pte[i].UniquePartitionGuid);
+		le64_to_cpus(pte[i].StartingLBA);
+		le64_to_cpus(pte[i].EndingLBA);
+		le_part_attributes_to_cpus(&pte[i].Attributes);
+		for (j = 0; j < (72 / sizeof(efi_char16_t)); j++) {
+			le16_to_cpus((u16) (pte[i].PartitionName[j]));
+		}
+	}
+
+	return pte;
+}
+
+
+
+/**
+ * alloc_read_gpt_header(): Allocates GPT header, reads into it from disk
+ * @hd
+ * @bdev
+ * @lba is the Logical Block Address of the partition table
+ * 
+ * Description: returns GPT header on success, NULL on error.   Allocates
+ * and fills a GPT header starting at @ from @bdev.
+ * Note: remember to free gpt when finished with it.
+ */
+static GuidPartitionTableHeader_t *alloc_read_gpt_header(struct gendisk
+							 *hd,
+							 struct
+							 block_device
+							 *bdev, u64 lba)
+{
+	GuidPartitionTableHeader_t *gpt;
+	if (!hd || !bdev)
+		return NULL;
+
+	gpt = kmalloc(sizeof(GuidPartitionTableHeader_t), GFP_KERNEL);
+	if (!gpt)
+		return NULL;
+	memset(gpt, 0, sizeof(GuidPartitionTableHeader_t));
+
+	Dprintk("GPTH() calling read_lba().\n");
+	if (read_lba(hd, bdev, lba, (u8 *) gpt,
+		     sizeof(GuidPartitionTableHeader_t)) <
+	    sizeof(GuidPartitionTableHeader_t)) {
+		Dprintk("ReadGPTH(" PU64X ") read failed.\n", lba);
+		kfree(gpt);
+		return NULL;
+	}
+
+	/* Fixup endianness */
+	le64_to_cpus(gpt->Signature);
+	le32_to_cpus(gpt->Revision);
+	le32_to_cpus(gpt->HeaderSize);
+	le32_to_cpus(gpt->HeaderCRC32);
+	le32_to_cpus(gpt->Reserved1);
+	le64_to_cpus(gpt->MyLBA);
+	le64_to_cpus(gpt->AlternateLBA);
+	le64_to_cpus(gpt->FirstUsableLBA);
+	le64_to_cpus(gpt->LastUsableLBA);
+	le_uuid_to_cpus((uuid_t *)&gpt->DiskGUID);
+	le64_to_cpus(gpt->PartitionEntryLBA);
+	le32_to_cpus(gpt->NumberOfPartitionEntries);
+	le32_to_cpus(gpt->SizeOfPartitionEntry);
+	le32_to_cpus(gpt->PartitionEntryArrayCRC32);
+
+	print_gpt_header(gpt);
+
+	return gpt;
+}
+
+
+
+/**
+ * is_gpt_valid() - tests one GPT header and PTEs for validity
+ * @hd
+ * @bdev
+ * @lba is the logical block address of the GPT header to test
+ * @gpt is a GPT header ptr, filled on return.
+ * @ptes is a PTEs ptr, filled on return.
+ *
+ * Description: returns 1 if valid,  0 on error.
+ * If valid, returns pointers to newly allocated GPT header and PTEs.
+ */
+static int
+is_gpt_valid(struct gendisk *hd, struct block_device *bdev, u64 lba,
+	     GuidPartitionTableHeader_t ** gpt,
+	     GuidPartitionEntry_t ** ptes)
+{
+	u32 crc, origcrc;
+
+	if (!hd || !bdev || !gpt || !ptes)
+		return 0;
+	if (!(*gpt = alloc_read_gpt_header(hd, bdev, lba)))
+		return 0;
+
+	/* Check the GUID Partition Table Signature */
+	if ((*gpt)->Signature != GPT_HEADER_SIGNATURE) {
+		Dprintk("GUID Partition Table Header Signature is wrong: "
+			PU64X " != " PU64X "\n", (*gpt)->Signature,
+			GPT_HEADER_SIGNATURE);
+		kfree(*gpt);
+		*gpt = NULL;
+		return 0;
+	}
+
+	/* Check the GUID Partition Table CRC */
+	origcrc = (*gpt)->HeaderCRC32;
+	(*gpt)->HeaderCRC32 = 0;
+	crc =
+	    efi_crc32((const unsigned char *) (*gpt), (*gpt)->HeaderSize);
+
+
+	if (crc != origcrc) {
+		Dprintk
+		    ("GUID Partition Table Header CRC is wrong: %x != %x\n",
+		     (*gpt)->HeaderCRC32, origcrc);
+		kfree(*gpt);
+		*gpt = NULL;
+		return 0;
+	}
+	(*gpt)->HeaderCRC32 = origcrc;
+
+	/* Check that the MyLBA entry points to the LBA that contains
+	 * the GUID Partition Table */
+	if ((*gpt)->MyLBA != lba) {
+		Dprintk("GPT MyLBA incorrect: " PU64X " != " PU64X "\n",
+			(*gpt)->MyLBA, lba);
+		kfree(*gpt);
+		*gpt = NULL;
+		return 0;
+	}
+
+	if (!(*ptes = alloc_read_gpt_entries(hd, bdev, *gpt))) {
+		Dprintk("read PTEs failed.\n");
+		kfree(*gpt);
+		*gpt = NULL;
+		return 0;
+	}
+
+	/* Check the GUID Partition Entry Array CRC */
+	crc = efi_crc32((const unsigned char *) (*ptes),
+			(*gpt)->NumberOfPartitionEntries *
+			(*gpt)->SizeOfPartitionEntry);
+
+	if (crc != (*gpt)->PartitionEntryArrayCRC32) {
+		Dprintk
+		    ("GUID Partitition Entry Array CRC check failed.\n");
+		kfree(*gpt);
+		*gpt = NULL;
+		kfree(*ptes);
+		*ptes = NULL;
+		return 0;
+	}
+
+
+	/* We're done, all's well */
+	return 1;
+}
+
+
+
+/**
+ * find_valid_gpt() - Search disk for valid GPT headers and PTEs
+ * @hd
+ * @bdev
+ * @gpt is a GPT header ptr, filled on return.
+ * @ptes is a PTEs ptr, filled on return.
+ * Description: Returns 1 if valid, 0 on error.
+ * If valid, returns pointers to newly allocated GPT header and PTEs.
+ * Validity depends on finding either the Primary GPT header and PTEs valid,
+ * or the Alternate GPT header and PTEs valid, and the PMBR valid.
+ */
+static int
+find_valid_gpt(struct gendisk *hd, struct block_device *bdev,
+	       GuidPartitionTableHeader_t ** gpt,
+	       GuidPartitionEntry_t ** ptes)
+{
+	int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
+	GuidPartitionTableHeader_t *pgpt = NULL, *agpt = NULL;
+	GuidPartitionEntry_t *pptes = NULL, *aptes = NULL;
+	LegacyMBR_t *legacyMbr = NULL;
+	u64 lastlba;
+	if (!hd || !bdev || !gpt || !ptes)
+		return 0;
+
+	lastlba = last_lba(hd, bdev);
+	/* Check the Primary GPT */
+	good_pgpt = is_gpt_valid(hd, bdev, GPT_PRIMARY_PARTITION_TABLE_LBA,
+				 &pgpt, &pptes);
+	if (good_pgpt) {
+		/* Primary GPT is OK, check the alternate and warn if bad */
+		good_agpt = is_gpt_valid(hd, bdev, pgpt->AlternateLBA,
+					 &agpt, &aptes);
+		if (!good_agpt) {
+			printk(KERN_WARNING
+			       "Alternate GPT is invalid, using primary GPT.\n");
+		}
+
+		*gpt = pgpt;
+		*ptes = pptes;
+		if (agpt)
+			kfree(agpt);
+		if (aptes)
+			kfree(aptes);
+	} /* if primary is valid */
+	else {
+		/* Primary GPT is bad, check the Alternate GPT */
+		good_agpt = is_gpt_valid(hd, bdev, lastlba, &agpt, &aptes);
+		if (good_agpt) {
+			/* Primary is bad, alternate is good.
+			   Return values from the alternate and warn.
+			 */
+			printk(KERN_WARNING
+			       "Primary GPT is invalid, using alternate GPT.\n");
+			*gpt = agpt;
+			*ptes = aptes;
+		}
+	}
+
+	/* Now test for valid PMBR */
+	/* This will be added to the EFI Spec. per Intel after v1.02. */
+	if (good_pgpt || good_agpt) {
+		legacyMbr = kmalloc(sizeof(*legacyMbr), GFP_KERNEL);
+		if (legacyMbr) {
+			memset(legacyMbr, 0, sizeof(*legacyMbr));
+			read_lba(hd, bdev, 0, (u8 *) legacyMbr,
+				 sizeof(*legacyMbr));
+			good_pmbr = is_pmbr_valid(legacyMbr);
+			kfree(legacyMbr);
+		}
+		if (good_pmbr)
+			return 1;
+		if (!forcegpt) {
+			printk
+			    (" Warning: Disk has a valid GPT signature but invalid PMBR.\n");
+			printk(KERN_WARNING
+			       "  Assuming this disk is *not* a GPT disk anymore.\n");
+			printk(KERN_WARNING
+			       "  Use gpt kernel option to override.  Use GNU Parted to correct disk.\n");
+		} else {
+			printk(KERN_WARNING
+			       "  Warning: Disk has a valid GPT signature but invalid PMBR.\n");
+			printk(KERN_WARNING
+			       "  Use GNU Parted to correct disk.\n");
+			printk(KERN_WARNING
+			       "  gpt option taken, disk treated as GPT.\n");
+			return 1;
+		}
+	}
+
+	/* Both primary and alternate GPTs are bad, and/or PMBR is invalid.
+	 * This isn't our disk, return 0.
+	 */
+	if (pgpt) {
+		kfree(pgpt);
+		pgpt = NULL;
+	}
+	if (agpt) {
+		kfree(agpt);
+		agpt = NULL;
+	}
+	if (pptes) {
+		kfree(pptes);
+		pptes = NULL;
+	}
+	if (aptes) {
+		kfree(aptes);
+		aptes = NULL;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_DEVFS_VOLUMES_UUIDS
+/**
+ * set_partition_guid(): Sets the devfs uuid value
+ * @hd
+ * @minor
+ * @guid
+ * Description: 
+ * Sets the devfs /dev/volumes/uuid/ value for @minor to be @guid.
+ * It is set to NULL by register_disk before.
+ */
+static void
+set_partition_guid(struct gendisk *hd,
+		   const int minor, const efi_guid_t * guid)
+{
+	efi_guid_t *part_guid = hd->part[minor].guid;
+
+	if (!guid || !hd)
+		return;
+
+	part_guid = kmalloc(sizeof(efi_guid_t), GFP_KERNEL);
+
+	if (part_guid) {
+		memcpy(part_guid, guid, sizeof(efi_guid_t));
+	} else {
+		printk(KERN_WARNING
+		       "add_gpt_partitions: cannot allocate GUID memory!\n");
+	};
+
+	hd->part[minor].guid = part_guid;
+}
+#else
+#define set_partition_guid(hd, minor, guid)
+#endif				/* CONFIG_DEVFS_VOLUMES_UUIDS */
+
+/**
+ * add_gpt_partitions(struct gendisk *hd, struct block_device *bdev,
+ * @hd
+ * @bdev
+ *
+ * Description: Create devices for each entry in the GUID Partition Table
+ * Entries.
+ *
+ * We do not create a Linux partition for GPT, but
+ * only for the actual data partitions.
+ * Returns:
+ * -1 if unable to read the partition table
+ *  0 if this isn't our partition table
+ *  1 if successful
+ *
+ */
+
+static int
+add_gpt_partitions(struct gendisk *hd, struct block_device *bdev,
+		   int nextminor)
+{
+	GuidPartitionTableHeader_t *gpt = NULL;
+	GuidPartitionEntry_t *ptes = NULL;
+	u32 i, nummade = 0;
+
+	efi_guid_t unusedGuid = UNUSED_ENTRY_GUID;
+#if CONFIG_BLK_DEV_MD
+	efi_guid_t raidGuid = PARTITION_LINUX_RAID_GUID;
+#endif
+
+	if (!hd || !bdev)
+		return -1;
+
+	if (!find_valid_gpt(hd, bdev, &gpt, &ptes) || !gpt || !ptes) {
+		if (gpt)
+			kfree(gpt);
+		if (ptes)
+			kfree(ptes);
+		return 0;
+	}
+
+	Dprintk("GUID Partition Table is valid!  Yea!\n");
+
+	set_partition_guid(hd, nextminor - 1, &(gpt->DiskGUID));
+
+	for (i = 0; i < gpt->NumberOfPartitionEntries &&
+	     nummade < (hd->max_p - 1); i++) {
+		if (!efi_guidcmp(unusedGuid, ptes[i].PartitionTypeGuid))
+			continue;
+
+		add_gd_partition(hd, nextminor, ptes[i].StartingLBA,
+				 (ptes[i].EndingLBA - ptes[i].StartingLBA +
+				  1));
+
+		set_partition_guid(hd, nextminor,
+				   &(ptes[i].UniquePartitionGuid));
+
+		/* If there's this is a RAID volume, tell md */
+#if CONFIG_BLK_DEV_MD
+		if (!efi_guidcmp(raidGuid, ptes[i].PartitionTypeGuid)) {
+			md_autodetect_dev(MKDEV
+					  (MAJOR(to_kdev_t(bdev->bd_dev)),
+					   nextminor));
+		}
+#endif
+		nummade++;
+		nextminor++;
+
+	}
+	kfree(ptes);
+	kfree(gpt);
+	printk("\n");
+	return 1;
+
+}
+
+
+/**
+ * efi_partition(): EFI GPT partition handling entry function
+ * @hd
+ * @bdev
+ * @first_sector: unused
+ * @first_part_minor: minor number assigned to first GPT partition found
+ *
+ * Description: called from check.c, if the disk contains GPT
+ * partitions, sets up partition entries in the kernel.
+ *
+ * If the first block on the disk is a legacy MBR,
+ * it will get handled by msdos_partition().
+ * If it's a Protective MBR, we'll handle it here.
+ *
+ * set_blocksize() calls are necessary to be able to read
+ * a disk with an odd number of 512-byte sectors, as the
+ * default BLOCK_SIZE of 1024 bytes won't let that last
+ * sector be read otherwise.
+ *
+ * Returns:
+ * -1 if unable to read the partition table
+ *  0 if this isn't our partitoin table
+ *  1 if successful
+ */
+int
+efi_partition(struct gendisk *hd, struct block_device *bdev,
+	      unsigned long first_sector, int first_part_minor)
+{
+
+	kdev_t dev = to_kdev_t(bdev->bd_dev);
+	int hardblocksize = get_hardsect_size(dev);
+	int orig_blksize_size = BLOCK_SIZE;
+	int rc = 0;
+
+	/* Need to change the block size that the block layer uses */
+	if (blksize_size[MAJOR(dev)]) {
+		orig_blksize_size = blksize_size[MAJOR(dev)][MINOR(dev)];
+	}
+
+	if (orig_blksize_size != hardblocksize)
+		set_blocksize(dev, hardblocksize);
+
+	rc = add_gpt_partitions(hd, bdev, first_part_minor);
+
+	/* change back */
+	if (orig_blksize_size != hardblocksize)
+		set_blocksize(dev, orig_blksize_size);
+
+	return rc;
+}
+
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/fs/partitions/efi.h linux-2.4.12.gpt/fs/partitions/efi.h
--- linux-2.4.12/fs/partitions/efi.h	Wed Dec 31 18:00:00 1969
+++ linux-2.4.12.gpt/fs/partitions/efi.h	Thu Oct 11 13:05:15 2001
@@ -0,0 +1,138 @@
+/************************************************************
+ * EFI GUID Partition Table
+ * Per Intel EFI Specification v1.02
+ * http://developer.intel.com/technology/efi/efi.htm
+ *
+ * By Matt Domsch <Matt_Domsch@dell.com>  Fri Sep 22 22:15:56 CDT 2000  
+ *   Copyright 2000,2001 Dell Computer Corporation
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ * 
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ ************************************************************/
+
+#ifndef FS_PART_EFI_H_INCLUDED
+#define FS_PART_EFI_H_INCLUDED
+
+#include <linux/types.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>
+/*
+ * Yes, specifying asm-ia64 is ugly, but this lets it build on
+ * other platforms too, until efi.h moves to include/linux.
+ */
+#include <asm-ia64/efi.h>
+
+
+#define MSDOS_MBR_SIGNATURE 0xaa55
+#define EFI_PMBR_OSTYPE_EFI 0xEF
+#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE
+
+#define GPT_BLOCK_SIZE 512
+#define GPT_HEADER_SIGNATURE 0x5452415020494645L
+#define GPT_HEADER_REVISION_V1 0x00010000
+#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
+
+#define UNUSED_ENTRY_GUID    \
+    ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }})
+#define PARTITION_SYSTEM_GUID \
+((efi_guid_t) { 0xC12A7328, 0xF81F, 0x11d2, { 0xBA, 0x4B, 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }})
+#define LEGACY_MBR_PARTITION_GUID \
+    ((efi_guid_t) { 0x024DEE41, 0x33E7, 0x11d3, { 0x9D, 0x69, 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }})
+#define PARTITION_MSFT_RESERVED_GUID \
+    ((efi_guid_t) { 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }})
+#define PARTITION_BASIC_DATA_GUID \
+    ((efi_guid_t) { 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }})
+#define PARTITION_LINUX_RAID_GUID \
+    ((efi_guid_t) { 0xa19d880f, 0x05fc, 0x4d3b, { 0xa0, 0x06, 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e  }})
+#define PARTITION_LINUX_SWAP_GUID \
+    ((efi_guid_t) { 0x0657fd6d, 0xa4ab, 0x43c4, { 0x84, 0xe5, 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f  }})
+#define PARTITION_LINUX_LVM_GUID \
+    ((efi_guid_t) { 0xe6d6d379, 0xf507, 0x44c2, { 0xa2, 0x3c, 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28 }})
+
+typedef struct _GuidPartitionTableHeader_t {
+	u64 Signature;
+	u32 Revision;
+	u32 HeaderSize;
+	u32 HeaderCRC32;
+	u32 Reserved1;
+	u64 MyLBA;
+	u64 AlternateLBA;
+	u64 FirstUsableLBA;
+	u64 LastUsableLBA;
+	efi_guid_t DiskGUID;
+	u64 PartitionEntryLBA;
+	u32 NumberOfPartitionEntries;
+	u32 SizeOfPartitionEntry;
+	u32 PartitionEntryArrayCRC32;
+	u8 Reserved2[GPT_BLOCK_SIZE - 92];
+} __attribute__ ((packed)) GuidPartitionTableHeader_t;
+
+typedef struct _GuidPartitionEntryAttributes_t {
+	u64 RequiredToFunction:1;
+	u64 Reserved:63;
+} __attribute__ ((packed)) GuidPartitionEntryAttributes_t;
+
+typedef struct _GuidPartitionEntry_t {
+	efi_guid_t PartitionTypeGuid;
+	efi_guid_t UniquePartitionGuid;
+	u64 StartingLBA;
+	u64 EndingLBA;
+	GuidPartitionEntryAttributes_t Attributes;
+	efi_char16_t PartitionName[72 / sizeof(efi_char16_t)];
+} __attribute__ ((packed)) GuidPartitionEntry_t;
+
+typedef struct _LegacyMBR_t {
+	u8 BootCode[440];
+	u32 UniqueMBRSignature;
+	u16 Unknown;
+	struct partition PartitionRecord[4];
+	u16 Signature;
+} __attribute__ ((packed)) LegacyMBR_t;
+
+
+
+/* Functions */
+extern int
+efi_partition(struct gendisk *hd, struct block_device *bdev,
+	      unsigned long first_sector, int first_part_minor);
+
+
+
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * --------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/fs/partitions/msdos.c linux-2.4.12.gpt/fs/partitions/msdos.c
--- linux-2.4.12/fs/partitions/msdos.c	Mon Oct  1 22:03:26 2001
+++ linux-2.4.12.gpt/fs/partitions/msdos.c	Thu Oct 11 12:49:37 2001
@@ -36,6 +36,10 @@
 #include "check.h"
 #include "msdos.h"
 
+#ifdef CONFIG_EFI_PARTITION
+#include "efi.h"
+#endif
+
 #if CONFIG_BLK_DEV_MD
 extern void md_autodetect_dev(kdev_t dev);
 #endif
@@ -566,6 +570,16 @@ int msdos_partition(struct gendisk *hd, 
 		return 0;
 	}
 	p = (struct partition *) (data + 0x1be);
+#ifdef CONFIG_EFI_PARTITION
+	for (i=1 ; i<=4 ; i++,p++) {
+		/* If this is an EFI GPT disk, msdos should ignore it. */
+		if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
+			put_dev_sector(sect);
+			return 0;
+		}
+	}
+	p = (struct partition *) (data + 0x1be);
+#endif
 
 	/*
 	 * Look for partitions in two passes:
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/include/linux/devfs_fs_kernel.h linux-2.4.12.gpt/include/linux/devfs_fs_kernel.h
--- linux-2.4.12/include/linux/devfs_fs_kernel.h	Thu Oct 11 01:46:04 2001
+++ linux-2.4.12.gpt/include/linux/devfs_fs_kernel.h	Thu Oct 11 13:03:28 2001
@@ -97,6 +97,7 @@ extern devfs_handle_t devfs_get_first_ch
 extern devfs_handle_t devfs_get_next_sibling (devfs_handle_t de);
 extern void devfs_auto_unregister (devfs_handle_t master,devfs_handle_t slave);
 extern devfs_handle_t devfs_get_unregister_slave (devfs_handle_t master);
+extern void devfs_unregister_slave (devfs_handle_t master);
 extern const char *devfs_get_name (devfs_handle_t de, unsigned int *namelen);
 extern int devfs_register_chrdev (unsigned int major, const char *name,
 				  struct file_operations *fops);
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/include/linux/genhd.h linux-2.4.12.gpt/include/linux/genhd.h
--- linux-2.4.12/include/linux/genhd.h	Thu Oct 11 01:46:11 2001
+++ linux-2.4.12.gpt/include/linux/genhd.h	Thu Oct 11 13:03:28 2001
@@ -13,6 +13,10 @@
 #include <linux/types.h>
 #include <linux/major.h>
 
+#ifdef CONFIG_DEVFS_VOLUMES_UUIDS
+#include <asm-ia64/efi.h>
+#endif
+
 enum {
 /* These three have identical behaviour; use the second one if DOS fdisk gets
    confused about extended/logical partitions starting past cylinder 1023. */
@@ -42,16 +46,16 @@ enum {
 };
 
 struct partition {
-	unsigned char boot_ind;		/* 0x80 - active */
-	unsigned char head;		/* starting head */
-	unsigned char sector;		/* starting sector */
-	unsigned char cyl;		/* starting cylinder */
-	unsigned char sys_ind;		/* What partition type */
-	unsigned char end_head;		/* end head */
-	unsigned char end_sector;	/* end sector */
-	unsigned char end_cyl;		/* end cylinder */
-	unsigned int start_sect;	/* starting sector counting from 0 */
-	unsigned int nr_sects;		/* nr of sectors in partition */
+	u8  boot_ind;		/* 0x80 - active */
+	u8  head;		/* starting head */
+	u8  sector;		/* starting sector */
+	u8  cyl;		/* starting cylinder */
+	u8  sys_ind;		/* What partition type */
+	u8  end_head;		/* end head */
+	u8  end_sector;         /* end sector */
+	u8  end_cyl;		/* end cylinder */
+	u32 start_sect;         /* starting sector counting from 0 */
+	u32 nr_sects;		/* nr of sectors in partition */
 } __attribute__((packed));
 
 #ifdef __KERNEL__
@@ -62,6 +66,9 @@ struct hd_struct {
 	long nr_sects;
 	devfs_handle_t de;              /* primary (master) devfs entry  */
 	int number;                     /* stupid old code wastes space  */
+#ifdef CONFIG_DEVFS_VOLUMES_UUIDS
+	efi_guid_t *guid;
+#endif
 };
 
 #define GENHD_FL_REMOVABLE  1
diff -burNp --exclude='*~' --exclude='*.orig' linux-2.4.12/fs/devfs/base.c linux-2.4.12.gpt/fs/devfs/base.c
--- linux-2.4.12/fs/devfs/base.c	Thu Oct 11 01:23:24 2001
+++ linux-2.4.12.gpt/fs/devfs/base.c	Thu Oct 11 12:49:37 2001
@@ -1944,6 +1944,25 @@ devfs_handle_t devfs_get_unregister_slav
     return master->slave;
 }   /*  End Function devfs_get_unregister_slave  */
 
+/**
+ *	devfs_unregister_slave - remove the slave that is unregistered when @master is unregistered.
+ *      Destroys the connection established by devfs_auto_unregister.
+ *
+ *	@master: The master devfs entry.
+ */
+
+void devfs_unregister_slave (devfs_handle_t master)
+{
+	devfs_handle_t slave;
+
+	if (master == NULL) return;
+
+	slave = master->slave;
+	if (slave) {
+		master->slave = NULL;
+		unregister (slave);
+	};
+}
 
 /**
  *	devfs_get_name - Get the name for a device entry in its parent directory.
@@ -2121,7 +2140,7 @@ EXPORT_SYMBOL(devfs_register_chrdev);
 EXPORT_SYMBOL(devfs_register_blkdev);
 EXPORT_SYMBOL(devfs_unregister_chrdev);
 EXPORT_SYMBOL(devfs_unregister_blkdev);
-
+EXPORT_SYMBOL(devfs_unregister_slave);
 
 /**
  *	try_modload - Notify devfsd of an inode lookup.
