|  | @@ -0,0 +1,174 @@
 | 
	
		
			
				|  |  | +# DP: Add support for specifying the root device using UUIDs on the
 | 
	
		
			
				|  |  | +# DP: kernel command line like this without the need for an initrd:
 | 
	
		
			
				|  |  | +# DP: linux ... root=UUID=ce40d6b2-18eb-4a75-aefe-7ddb0995ce63
 | 
	
		
			
				|  |  | +# DP:
 | 
	
		
			
				|  |  | +# DP: Written © 2010 by Thorsten Glaser <tg@debian.org>
 | 
	
		
			
				|  |  | +# DP: Idea from 1999 by David Balazic <david.balazic@uni-mb.si>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +--- linux-2.6.36/block/genhd.c~	Wed Oct 20 22:30:22 2010
 | 
	
		
			
				|  |  | ++++ linux-2.6.36/block/genhd.c	Sat Nov 20 23:14:03 2010
 | 
	
		
			
				|  |  | +@@ -35,7 +35,7 @@ struct kobject *block_depr;
 | 
	
		
			
				|  |  | + static DEFINE_MUTEX(ext_devt_mutex);
 | 
	
		
			
				|  |  | + static DEFINE_IDR(ext_devt_idr);
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | +-static struct device_type disk_type;
 | 
	
		
			
				|  |  | ++struct device_type disk_type;
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | + /**
 | 
	
		
			
				|  |  | +  * disk_get_part - get partition
 | 
	
		
			
				|  |  | +@@ -1019,7 +1019,7 @@ static char *block_devnode(struct device *dev, mode_t 
 | 
	
		
			
				|  |  | + 	return NULL;
 | 
	
		
			
				|  |  | + }
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | +-static struct device_type disk_type = {
 | 
	
		
			
				|  |  | ++struct device_type disk_type = {
 | 
	
		
			
				|  |  | + 	.name		= "disk",
 | 
	
		
			
				|  |  | + 	.groups		= disk_attr_groups,
 | 
	
		
			
				|  |  | + 	.release	= disk_release,
 | 
	
		
			
				|  |  | +--- linux-2.6.36/init/do_mounts.c~	Wed Oct 20 22:30:22 2010
 | 
	
		
			
				|  |  | ++++ linux-2.6.36/init/do_mounts.c	Sat Nov 20 23:16:07 2010
 | 
	
		
			
				|  |  | +@@ -32,6 +32,84 @@ static int __initdata root_wait;
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | + dev_t ROOT_DEV;
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | ++#ifdef CONFIG_EXT2_FS
 | 
	
		
			
				|  |  | ++/* support for root=UUID=ce40d6b2-18eb-4a75-aefe-7ddb0995ce63 bootargs */
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++#include <linux/buffer_head.h>
 | 
	
		
			
				|  |  | ++#include <linux/ext2_fs.h>
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++__u8 root_dev_label[16];
 | 
	
		
			
				|  |  | ++int root_dev_type;	/* 0 = normal (/dev/hda1, 0301); 1 = UUID; 3 = bad */
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++/* imported from block/genhd.c after removing its static qualifier */
 | 
	
		
			
				|  |  | ++extern struct device_type disk_type;
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++static __u8 __init fromhex(char c)
 | 
	
		
			
				|  |  | ++{
 | 
	
		
			
				|  |  | ++	if (c >= '0' && c <= '9')
 | 
	
		
			
				|  |  | ++		return (c - '0');
 | 
	
		
			
				|  |  | ++	c &= ~32;
 | 
	
		
			
				|  |  | ++	if (c >= 'A' && c <= 'F')
 | 
	
		
			
				|  |  | ++		return (c - 'A' + 10);
 | 
	
		
			
				|  |  | ++	return (0xFF);
 | 
	
		
			
				|  |  | ++}
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++static void __init parse_uuid(const char *s)
 | 
	
		
			
				|  |  | ++{
 | 
	
		
			
				|  |  | ++	int i;
 | 
	
		
			
				|  |  | ++	__u8 j, k;
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++	if (strlen(s) != 36 || s[8] != '-' || s[13] != '-' ||
 | 
	
		
			
				|  |  | ++	    s[18] != '-' || s[23] != '-')
 | 
	
		
			
				|  |  | ++		goto bad_uuid;
 | 
	
		
			
				|  |  | ++	for (i = 0; i < 16; i++) {
 | 
	
		
			
				|  |  | ++		if (*s == '-')
 | 
	
		
			
				|  |  | ++			++s;
 | 
	
		
			
				|  |  | ++		j = fromhex(*s++);
 | 
	
		
			
				|  |  | ++		k = fromhex(*s++);
 | 
	
		
			
				|  |  | ++		if (j == 0xFF || k == 0xFF)
 | 
	
		
			
				|  |  | ++			goto bad_uuid;
 | 
	
		
			
				|  |  | ++		root_dev_label[i] = (j << 4) | k;
 | 
	
		
			
				|  |  | ++	}
 | 
	
		
			
				|  |  | ++	return;
 | 
	
		
			
				|  |  | ++ bad_uuid:
 | 
	
		
			
				|  |  | ++	/* we cannot panic here, defer */
 | 
	
		
			
				|  |  | ++	root_dev_type = 3;
 | 
	
		
			
				|  |  | ++}
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++static int __init check_dev(dev_t devt, int blocksize)
 | 
	
		
			
				|  |  | ++{
 | 
	
		
			
				|  |  | ++	/* most of this taken from fs/ext2/super.c */
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++	struct buffer_head * bh;
 | 
	
		
			
				|  |  | ++	struct ext2_super_block * es;
 | 
	
		
			
				|  |  | ++	struct block_device *bdev;
 | 
	
		
			
				|  |  | ++	unsigned long sb_block = 1;
 | 
	
		
			
				|  |  | ++	unsigned long logic_sb_block;
 | 
	
		
			
				|  |  | ++	unsigned long offset = 0;
 | 
	
		
			
				|  |  | ++	int rv = 0;
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++	bdev = bdget(devt);
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++	if (blocksize != BLOCK_SIZE) {
 | 
	
		
			
				|  |  | ++		logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize;
 | 
	
		
			
				|  |  | ++		offset = (sb_block*BLOCK_SIZE) % blocksize;
 | 
	
		
			
				|  |  | ++	} else {
 | 
	
		
			
				|  |  | ++		logic_sb_block = sb_block;
 | 
	
		
			
				|  |  | ++	}
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++	if (!(bh = __bread(bdev, logic_sb_block, blocksize)))
 | 
	
		
			
				|  |  | ++		return (0);
 | 
	
		
			
				|  |  | ++	es = (struct ext2_super_block *)(((char *)bh->b_data) + offset);
 | 
	
		
			
				|  |  | ++	if (le16_to_cpu(es->s_magic) == EXT2_SUPER_MAGIC) {
 | 
	
		
			
				|  |  | ++		if (!memcmp(es->s_uuid, root_dev_label, 16))
 | 
	
		
			
				|  |  | ++			rv = 1;
 | 
	
		
			
				|  |  | ++	}
 | 
	
		
			
				|  |  | ++	brelse(bh);
 | 
	
		
			
				|  |  | ++	return (rv);
 | 
	
		
			
				|  |  | ++}
 | 
	
		
			
				|  |  | ++#endif /* CONFIG_EXT2_FS for UUID support */
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | + static int __init load_ramdisk(char *str)
 | 
	
		
			
				|  |  | + {
 | 
	
		
			
				|  |  | + 	rd_doload = simple_strtol(str,NULL,0) & 3;
 | 
	
		
			
				|  |  | +@@ -148,6 +226,13 @@ done:
 | 
	
		
			
				|  |  | + static int __init root_dev_setup(char *line)
 | 
	
		
			
				|  |  | + {
 | 
	
		
			
				|  |  | + 	strlcpy(saved_root_name, line, sizeof(saved_root_name));
 | 
	
		
			
				|  |  | ++#ifdef CONFIG_EXT2_FS
 | 
	
		
			
				|  |  | ++	root_dev_type = 0;
 | 
	
		
			
				|  |  | ++	if (!strncmp(line, "UUID=", 5)) {
 | 
	
		
			
				|  |  | ++		root_dev_type = 1;
 | 
	
		
			
				|  |  | ++		parse_uuid(line + 5);
 | 
	
		
			
				|  |  | ++	}
 | 
	
		
			
				|  |  | ++#endif /* CONFIG_EXT2_FS for UUID support */
 | 
	
		
			
				|  |  | + 	return 1;
 | 
	
		
			
				|  |  | + }
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | +@@ -333,6 +418,45 @@ void __init change_floppy(char *fmt, ...)
 | 
	
		
			
				|  |  | + 
 | 
	
		
			
				|  |  | + void __init mount_root(void)
 | 
	
		
			
				|  |  | + {
 | 
	
		
			
				|  |  | ++#ifdef CONFIG_EXT2_FS
 | 
	
		
			
				|  |  | ++	/* UUID support */
 | 
	
		
			
				|  |  | ++	if (root_dev_type == 1) {
 | 
	
		
			
				|  |  | ++		int blocksize;
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++		/* from block/genhd.c printk_all_partitions */
 | 
	
		
			
				|  |  | ++		struct class_dev_iter iter;
 | 
	
		
			
				|  |  | ++		struct device *dev;
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++		class_dev_iter_init(&iter, &block_class, NULL, &disk_type);
 | 
	
		
			
				|  |  | ++		while (root_dev_type && (dev = class_dev_iter_next(&iter))) {
 | 
	
		
			
				|  |  | ++			struct gendisk *disk = dev_to_disk(dev);
 | 
	
		
			
				|  |  | ++			struct disk_part_iter piter;
 | 
	
		
			
				|  |  | ++			struct hd_struct *part;
 | 
	
		
			
				|  |  | ++			if (get_capacity(disk) == 0 ||
 | 
	
		
			
				|  |  | ++			    (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
 | 
	
		
			
				|  |  | ++				continue;
 | 
	
		
			
				|  |  | ++			blocksize = queue_logical_block_size(disk->queue);
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | ++			disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0);
 | 
	
		
			
				|  |  | ++			while (root_dev_type && (part = disk_part_iter_next(&piter))) {
 | 
	
		
			
				|  |  | ++				/* avoid empty or too small partitions */
 | 
	
		
			
				|  |  | ++				if (part->nr_sects < 8)
 | 
	
		
			
				|  |  | ++					continue;
 | 
	
		
			
				|  |  | ++				if (check_dev(part_devt(part), blocksize)) {
 | 
	
		
			
				|  |  | ++					ROOT_DEV = part_devt(part);
 | 
	
		
			
				|  |  | ++					root_dev_type = 0;
 | 
	
		
			
				|  |  | ++				}
 | 
	
		
			
				|  |  | ++			}
 | 
	
		
			
				|  |  | ++			disk_part_iter_exit(&piter);
 | 
	
		
			
				|  |  | ++		}
 | 
	
		
			
				|  |  | ++		class_dev_iter_exit(&iter);
 | 
	
		
			
				|  |  | ++	}
 | 
	
		
			
				|  |  | ++	if (root_dev_type == 1)
 | 
	
		
			
				|  |  | ++		printk(KERN_ERR "VFS: Unable to find root by UUID %s.\n", saved_root_name + 5);
 | 
	
		
			
				|  |  | ++	else if (root_dev_type == 3)
 | 
	
		
			
				|  |  | ++		panic("Badly formatted UUID %s was supplied as kernel parameter root", saved_root_name + 5);
 | 
	
		
			
				|  |  | ++#endif /* CONFIG_EXT2_FS for UUID support */
 | 
	
		
			
				|  |  | ++
 | 
	
		
			
				|  |  | + #ifdef CONFIG_ROOT_NFS
 | 
	
		
			
				|  |  | + 	if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
 | 
	
		
			
				|  |  | + 		if (mount_nfs_root())
 |