Ejemplo n.º 1
0
int msdos_partition(struct gendisk *hd, struct block_device *bdev,
		    unsigned long first_sector, int first_part_minor)
{
	int i, minor = first_part_minor;
	Sector sect;
	struct partition *p;
	unsigned char *data;
	int mask = (1 << hd->minor_shift) - 1;
	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
	int current_minor = first_part_minor;
	int err;

	err = handle_ide_mess(bdev);
	if (err <= 0)
		return err;
	data = read_dev_sector(bdev, 0, &sect);
	if (!data)
		return -1;
	if (!msdos_magic_present(data + 510)) {
		put_dev_sector(sect);
		return 0;
	}
	p = (struct partition *) (data + 0x1be);

	/*
	 * Look for partitions in two passes:
	 * First find the primary and DOS-type extended partitions.
	 * On the second pass look inside *BSD, Unixware and Solaris partitions.
	 */

	current_minor += 4;
	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);
#if CONFIG_BLK_DEV_MD
		if (SYS_IND(p) == LINUX_RAID_PARTITION) {
			md_autodetect_dev(MKDEV(hd->major,minor));
		}
#endif
		if (is_extended_partition(p)) {
			unsigned long size = hd->part[minor].nr_sects;
			printk(" <");
			/* prevent someone doing mkfs or mkswap on an
			   extended partition, but leave room for LILO */
			if (size > 2)
				hd->part[minor].nr_sects = 2;
			extended_partition(hd, bdev, minor, size, &current_minor);
			printk(" >");
		}
	}

	/*
	 *  Check for old-style Disk Manager partition table
	 */
	if (msdos_magic_present(data + 0xfc)) {
		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));
		}
	}
	printk("\n");

	/* second pass - output for each on a separate line */
	minor -= 4;
	p = (struct partition *) (0x1be + data);
	for (i=1 ; i<=4 ; minor++,i++,p++) {
		unsigned char id = SYS_IND(p);
		int n;

		if (!NR_SECTS(p))
			continue;

		for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
			;

		if (subtypes[n].parse)
			subtypes[n].parse(hd, bdev, minor, &current_minor);
	}
	put_dev_sector(sect);
	return 1;
}
Ejemplo n.º 2
0
int msdos_partition(struct gendisk *hd, struct block_device *bdev,
		    unsigned long first_sector, int first_part_minor)
{
	int i, minor = first_part_minor;
	Sector sect;
	struct partition *p;
	unsigned char *data;
	int mask = (1 << hd->minor_shift) - 1;
	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
	int current_minor = first_part_minor;
	int err;
#ifdef CONFIG_IDE_IPOD
	int sector_mult = 1;
#endif

	err = handle_ide_mess(bdev);
	if (err <= 0)
		return err;
	data = read_dev_sector(bdev, 0, &sect);
	if (!data)
		return -1;
	if (!msdos_magic_present(data + 510)) {
		put_dev_sector(sect);
		return 0;
	}
	p = (struct partition *) (data + 0x1be);

#ifdef CONFIG_IDE_IPOD
	/*
	 * Addition for iPods: check for actual filesystems to figure out the correct partition layout
	 */
	for (i=1 ; i<=4 ; i++,p++) {
		unsigned char *partdata;

		if (!NR_SECTS(p))
			continue;
		if (SYS_IND(p) == 0xb) {
			partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*4, &sect);
			if (msdos_magic_present(partdata + 510))
				sector_mult = 4;

			partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*2, &sect);
			if (msdos_magic_present(partdata + 510))
				sector_mult = 2;

			partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size, &sect);
			if (msdos_magic_present(partdata + 510))
				sector_mult = 1;
        
		} else if (SYS_IND(p) == 0x83) {
			partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*4+2, &sect);
			if (ext3_magic_present(partdata + 56))
				sector_mult = 4;

			partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*2+2, &sect);
			if (ext3_magic_present(partdata + 56))
				sector_mult = 2;

			partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size+2, &sect);
			if (ext3_magic_present(partdata + 56))
				sector_mult = 1;
		}
	}

	printk("Experimental partition and filesystem detection code by Vincent Huisman ([email protected])\n"); 
	printk("Partition sector size: %d\n", sector_mult);

	sector_size *= sector_mult;
	p = (struct partition *) (data + 0x1be); // Reinitialize, duh
#endif

	/*
	 * Look for partitions in two passes:
	 * First find the primary and DOS-type extended partitions.
	 * On the second pass look inside *BSD, Unixware and Solaris partitions.
	 */

	current_minor += 4;
	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);
#if CONFIG_BLK_DEV_MD
		if (SYS_IND(p) == LINUX_RAID_PARTITION) {
			md_autodetect_dev(MKDEV(hd->major,minor));
		}
#endif
		if (is_extended_partition(p)) {
			unsigned long size = hd->part[minor].nr_sects;
			printk(" <");
			/* prevent someone doing mkfs or mkswap on an
			   extended partition, but leave room for LILO */
			if (size > 2)
				hd->part[minor].nr_sects = 2;
			extended_partition(hd, bdev, minor, size, &current_minor);
			printk(" >");
		}
	}

	/*
	 *  Check for old-style Disk Manager partition table
	 */
	if (msdos_magic_present(data + 0xfc)) {
		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));
		}
	}
	printk("\n");

	/* second pass - output for each on a separate line */
	minor -= 4;
	p = (struct partition *) (0x1be + data);
	for (i=1 ; i<=4 ; minor++,i++,p++) {
		unsigned char id = SYS_IND(p);
		int n;

		if (!NR_SECTS(p))
			continue;

		for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
			;

		if (subtypes[n].parse)
			subtypes[n].parse(hd, bdev, minor, &current_minor);
	}
	put_dev_sector(sect);
	return 1;
}