Exemple #1
0
/*
 * Create devices for Unixware partitions listed in a disklabel, under a
 * dos-like partition. See extended_partition() for more information.
 */
static void unixware_partition(struct gendisk *hd, kdev_t dev)
{
	struct buffer_head *bh;
	struct unixware_disklabel *l;
	struct unixware_slice *p;
	int mask = (1 << hd->minor_shift) - 1;

	if (!(bh = bread(dev, 14, get_ptable_blocksize(dev))))
		return;
	bh->b_state = 0;
	l = (struct unixware_disklabel *) (bh->b_data+512);
	if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
	    le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
		brelse(bh);
		return;
	}
	printk(" <unixware:");
	p = &l->vtoc.v_slice[1];
	/* I omit the 0th slice as it is the same as whole disk. */
	while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
		if ((current_minor & mask) == 0)
			break;

		if (p->s_label != UNIXWARE_FS_UNUSED) {
			add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p), 0);
			current_minor++;
		}
		p++;
	}
	brelse(bh);
	printk(" >");
}
Exemple #2
0
/* 
 * 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,
    int max_partitions)
{
	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;
	}

	if (l->d_npartitions < max_partitions)
		max_partitions = l->d_npartitions;
	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
		if ((current_minor & mask) >= (4 + hd->max_p))
			break;

		if (p->p_fstype != BSD_FS_UNUSED) 
			check_and_add_bsd_partition(hd, p, dev);
	}
	brelse(bh);

}
Exemple #3
0
int ultrix_partition(struct gendisk *hd, kdev_t dev,
                            unsigned long first_sector, int first_part_minor)
{
	int i;
	struct buffer_head *bh;
	struct ultrix_disklabel {
		s32	pt_magic;	/* magic no. indicating part. info exits */
		s32	pt_valid;	/* set by driver if pt is current */
		struct  pt_info {
			s32		pi_nblocks; /* no. of sectors */
			u32		pi_blkoff;  /* block offset for start */
		} pt_part[8];
	} *label;

#define PT_MAGIC	0x032957	/* Partition magic number */
#define PT_VALID	1		/* Indicates if struct is valid */

#define	SBLOCK	((unsigned long)((16384 - sizeof(struct ultrix_disklabel)) \
                  /get_ptable_blocksize(dev)))

	bh = bread (dev, SBLOCK, get_ptable_blocksize(dev));
	if (!bh) {
		if (warn_no_part) printk (" unable to read block 0x%lx\n", SBLOCK);
		return -1;
	}
	
	label = (struct ultrix_disklabel *)(bh->b_data
                                            + get_ptable_blocksize(dev)
                                            - sizeof(struct ultrix_disklabel));

	if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
		for (i=0; i<8; i++, first_part_minor++)
			if (label->pt_part[i].pi_nblocks)
				add_gd_partition(hd, first_part_minor, 
					      label->pt_part[i].pi_blkoff,
					      label->pt_part[i].pi_nblocks);
		brelse(bh);
		printk ("\n");
		return 1;
	} else {
		brelse(bh);
		return 0;
	}
}
Exemple #4
0
static void
solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {

	struct buffer_head *bh;
	struct solaris_x86_vtoc *v;
	struct solaris_x86_slice *s;
	int i;

	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev))))
		return;
	v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
	if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
		brelse(bh);
		return;
	}
	printk(" <solaris:");
	if(v->v_version != 1) {
		printk("  cannot handle version %ld vtoc>", v->v_version);
		brelse(bh);
		return;
	}
	for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
		s = &v->v_slice[i];

		if (s->s_tag == 0)
			continue;
		printk(" [s%d]", i);
		/* solaris partitions are relative to current MS-DOS
		 * one but add_gd_partition starts relative to sector
		 * zero of the disk.  Therefore, must add the offset
		 * of the current partition */
		add_gd_partition(hd, current_minor,
					s->s_start+offset, s->s_size, 0);
		current_minor++;
	}
	brelse(bh);
	printk(" >");
}
Exemple #5
0
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 sector_size = sector_partition_scale(dev);
	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 ((*(__u16 *) (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_gd_partition(hd, current_minor, this_sector+START_SECT(p)*sector_size,
				      NR_SECTS(p)*sector_size, ptype(SYS_IND(p)));
			hd->part[current_minor].sys_ind = SYS_IND(p);	// Hijack
			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) * sector_size; /* JSt */
		hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size;
		this_sector = first_sector + START_SECT(p) * sector_size;
		dev = MKDEV(hd->major, current_minor);
		brelse(bh);
	}
done:
	brelse(bh);
}
Exemple #6
0
int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
{
	int i, minor = current_minor = first_part_minor;
	struct buffer_head *bh;
	struct partition *p;
	unsigned char *data;
	int mask = (1 << hd->minor_shift) - 1;
	int sector_size = sector_partition_scale(dev);
#ifdef CONFIG_BSD_DISKLABEL
	/* no bsd disklabel as a default */
	kdev_t bsd_kdev = 0;
	int bsd_maxpart = BSD_MAXPARTITIONS;
#endif
#ifdef CONFIG_BLK_DEV_IDE
	int tested_for_xlate = 0;

read_mbr:
#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:
#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 useful for drives in 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 == 240 ||
					    heads == 255) {
						(void) ide_xlate_1024(dev, heads, " [PTBL]");
						break;
					}
				}
			}
		}
	}
#endif	/* CONFIG_BLK_DEV_IDE */

	current_minor += 4;  /* first "extra" minor (for extended partitions) */
	for (i=1 ; i<=4 ; minor++,i++,p++) {
		if (!NR_SECTS(p))
			continue;
		add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size,
				ptype(SYS_IND(p)));
		hd->part[minor].sys_ind = SYS_IND(p);	// Hijack
		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
			/* tag first disklabel for late recognition */
		if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) {
			printk("!");
			if (!bsd_kdev)
				bsd_kdev = MKDEV(hd->major, minor);
		} else if (SYS_IND(p) == OPENBSD_PARTITION) {
			printk("!");
			if (!bsd_kdev) {
				bsd_kdev = MKDEV(hd->major, minor);
				bsd_maxpart = OPENBSD_MAXPARTITIONS;
			}
		}
#endif
#ifdef CONFIG_UNIXWARE_DISKLABEL
		if (SYS_IND(p) == UNIXWARE_PARTITION)
			unixware_partition(hd, MKDEV(hd->major, minor));
#endif
#ifdef CONFIG_SOLARIS_X86_PARTITION

		/* [email protected]: Solaris has a nasty indicator: 0x82
		 * which also means linux swap.  For that reason, all
		 * of the prints are done inside the
		 * solaris_x86_partition routine */

		if(SYS_IND(p) == SOLARIS_X86_PARTITION) {
			solaris_x86_partition(hd, MKDEV(hd->major, minor),
					      first_sector+START_SECT(p));
		}
#endif
	}
#ifdef CONFIG_BSD_DISKLABEL
	if (bsd_kdev) {
		printk(" <");
		bsd_disklabel_partition(hd, bsd_kdev, bsd_maxpart);
		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_gd_partition(hd, current_minor, START_SECT(p),
					NR_SECTS(p), 0);
		}
	}
	printk("\n");
	brelse(bh);
	return 1;
}
Exemple #7
0
int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec, int first_part_minor)
{
	struct buffer_head *bh;
	int blk, blocks_in_map;
	int dev_bsize, dev_pos, pos;
	unsigned secsize;
#ifdef CONFIG_PPC
	int found_root = 0;
	int found_root_goodness = 0;
#endif
	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)
			break;
		blocks_in_map = be32_to_cpu(part->map_count);
		add_gd_partition(hd, first_part_minor,
			fsec + be32_to_cpu(part->start_block) * (secsize/512),
			be32_to_cpu(part->block_count) * (secsize/512), 0);

#ifdef CONFIG_PPC
		/*
		 * If this is the first bootable partition, tell the
		 * setup code, in case it wants to make this the root.
		 */
		if (_machine == _MACH_Pmac) {
			int goodness = 0;
		    
			if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
			    && strcasecmp(part->processor, "powerpc") == 0)
				goodness++;

			if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0) {
				goodness++;
				if ((strcmp(part->name, "/") == 0) ||
				    (strstr(part->name, "root") != 0)) {
					goodness++;
				}
				if (strncmp(part->name, "swap", 4) == 0)
					goodness--;
			}

			if (goodness > found_root_goodness) {
				found_root = blk;
				found_root_goodness = goodness;
			}
		}
#endif /* CONFIG_PPC */

		++first_part_minor;
	}
#ifdef CONFIG_PPC
	if (found_root_goodness)
		note_bootable_part(dev, found_root);
#endif
	brelse(bh);
	printk("\n");
	return 1;
}