Esempio n. 1
0
/*
 * Minix 2.0.0/2.0.2 subpartition support.
 * Anand Krishnamurthy <*****@*****.**>
 * Rajeev V. Pillai    <*****@*****.**>
 */
static void
parse_minix(struct parsed_partitions *state, struct block_device *bdev,
		u32 offset, u32 size, int origin)
{
#ifdef CONFIG_MINIX_SUBPARTITION
	Sector sect;
	unsigned char *data;
	struct partition *p;
	int i;

	data = read_dev_sector(bdev, offset, &sect);
	if (!data)
		return;

	p = (struct partition *)(data + 0x1be);

	/* The first sector of a Minix partition can have either
	 * a secondary MBR describing its subpartitions, or
	 * the normal boot sector. */
	if (msdos_magic_present (data + 510) &&
	    SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */

		printk(" %s%d: <minix:", state->name, origin);
		for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
			if (state->next == state->limit)
				break;
			/* add each partition in use */
			if (SYS_IND(p) == MINIX_PARTITION)
				put_partition(state, state->next++,
					      START_SECT(p), NR_SECTS(p));
		}
		printk(" >\n");
	}
	put_dev_sector(sect);
#endif /* CONFIG_MINIX_SUBPARTITION */
}
Esempio n. 2
0
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
{
	int sector_size = bdev_hardsect_size(bdev) / 512;
	Sector sect;
	unsigned char *data;
	struct partition *p;
	int slot;

	data = read_dev_sector(bdev, 0, &sect);
	if (!data)
		return -1;
	if (!msdos_magic_present(data + 510)) {
		put_dev_sector(sect);
		return 0;
	}

	if (aix_magic_present(data, bdev)) {
		put_dev_sector(sect);
		printk( " [AIX]");
		return 0;
	}

	/*
	 * Now that the 55aa signature is present, this is probably
	 * either the boot sector of a FAT filesystem or a DOS-type
	 * partition table. Reject this in case the boot indicator
	 * is not 0 or 0x80.
	 */
	p = (struct partition *) (data + 0x1be);
	for (slot = 1; slot <= 4; slot++, p++) {
		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
			put_dev_sector(sect);
			return 0;
		}
	}

#ifdef CONFIG_EFI_PARTITION
	p = (struct partition *) (data + 0x1be);
	for (slot = 1 ; slot <= 4 ; slot++, 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;
		}
	}
#endif
	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.
	 */

	state->next = 5;
	for (slot = 1 ; slot <= 4 ; slot++, p++) {
		u32 start = START_SECT(p)*sector_size;
		u32 size = NR_SECTS(p)*sector_size;
		if (!size)
			continue;
		if (is_extended_partition(p)) {
			/* prevent someone doing mkfs or mkswap on an
			   extended partition, but leave room for LILO */
			put_partition(state, slot, start, size == 1 ? 1 : 2);
			printk(" <");
			parse_extended(state, bdev, start, size);
			printk(" >");
			continue;
		}
		put_partition(state, slot, start, size);
		if (SYS_IND(p) == LINUX_RAID_PARTITION)
			state->parts[slot].flags = 1;
		if (SYS_IND(p) == DM6_PARTITION)
			printk("[DM]");
		if (SYS_IND(p) == EZD_PARTITION)
			printk("[EZD]");
	}

	printk("\n");

	/* second pass - output for each on a separate line */
	p = (struct partition *) (0x1be + data);
	for (slot = 1 ; slot <= 4 ; slot++, 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)
			continue;
		subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
						NR_SECTS(p)*sector_size, slot);
	}
	put_dev_sector(sect);
	return 1;
}
Esempio n. 3
0
static void
parse_extended(struct parsed_partitions *state, struct block_device *bdev,
			u32 first_sector, u32 first_size)
{
	struct partition *p;
	Sector sect;
	unsigned char *data;
	u32 this_sector, this_size;
	int sector_size = bdev_hardsect_size(bdev) / 512;
	int loopct = 0;		/* number of links followed
				   without finding a data partition */
	int i;

	this_sector = first_sector;
	this_size = first_size;

	while (1) {
		if (++loopct > 100)
			return;
		if (state->next == state->limit)
			return;
		data = read_dev_sector(bdev, this_sector, &sect);
		if (!data)
			return;

		if (!msdos_magic_present(data + 510))
			goto done; 

		p = (struct partition *) (data + 0x1be);

		/*
		 * 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++) {
			u32 offs, size, next;
			if (!NR_SECTS(p) || is_extended_partition(p))
				continue;

			/* Check the 3rd and 4th entries -
			   these sometimes contain random garbage */
			offs = START_SECT(p)*sector_size;
			size = NR_SECTS(p)*sector_size;
			next = this_sector + offs;
			if (i >= 2) {
				if (offs + size > this_size)
					continue;
				if (next < first_sector)
					continue;
				if (next + size > first_sector + first_size)
					continue;
			}

			put_partition(state, state->next, next, size);
			if (SYS_IND(p) == LINUX_RAID_PARTITION)
				state->parts[state->next].flags = ADDPART_FLAG_RAID;
			loopct = 0;
			if (++state->next == state->limit)
				goto done;
		}
		/*
		 * Next, process the (first) extended partition, if present.
		 * (So far, there seems to be no reason to make
		 *  parse_extended()  recursive and allow a tree
		 *  of extended partitions.)
		 * It should be a link to the next logical 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 */

		this_sector = first_sector + START_SECT(p) * sector_size;
		this_size = NR_SECTS(p) * sector_size;
		put_dev_sector(sect);
	}
done:
	put_dev_sector(sect);
}
Esempio n. 4
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);
}
Esempio n. 5
0
static void
tegra_msdos_parse_extended(struct parsed_partitions *state, struct block_device *bdev,
		               u64 mbr_offset, u64 first_sector, u64 first_size)
{
	struct partition *p;
	Sector sect;
	unsigned char *data;
	u64 this_sector, this_size;
	int sector_size = bdev_logical_block_size(bdev) / 512;
	int loopct = 0;		/* number of links followed
				   without finding a data partition */
	int i;

	this_sector = first_sector;
	this_size = first_size;

	while (1) {
		if (++loopct > 2) {
			printk(KERN_INFO "tegra_msdos_parse_extended: loopcnt>2. exit\n");
			return;
		}

		printk(KERN_INFO "tegra_msdos_parse_extended: read part sector, start=%llu+%llu size=%llu\n",
				mbr_offset, this_sector, this_size);

		data = read_dev_sector(bdev, mbr_offset+this_sector, &sect);
		if (!data) {
			printk(KERN_INFO "tegra_msdos_parse_extended: read error. exit\n");
			return; 
		}

		if (!msdos_magic_present(data + 510)) {
			printk(KERN_INFO "tegra_msdos_parse_extended: no msdos magic. exit\n");
			goto done;
		}

		p = (struct partition *) (data + 0x1be);

		/* 
		 * First process the data partition(s)
		 */
		for (i=0; i<4; i++, p++) {
			u64 offs, size, next;

			if (!NR_SECTS(p) || is_extended_partition(p))
				continue;

			offs = START_SECT(p)*sector_size;
			size = NR_SECTS(p)*sector_size;
			next = this_sector + offs;
			if (i >= 2) {
				if (offs + size > this_size)
					continue;
				if (next < first_sector)
					continue;
				if (next + size > first_sector + first_size)
					continue;
			}

			printk(KERN_INFO "tegra_msdos_parse_extended: put_partition %d start=%llu+%llu size=%llu\n",
					state->next, mbr_offset, next, size);
			put_partition(state, state->next++, mbr_offset+next, size);
			loopct = 0;
		}
	
		printk(KERN_INFO "tegra_msdos_parse_extended: done with this sector\n");

		p -= 4;
		for (i=0; i<4; i++, p++)
			if (NR_SECTS(p) && is_extended_partition(p)) {
				printk(KERN_INFO "tegra_msdos_parse_extended: extended part slot %d\n", i+1);
				break;
			}

		if (i == 4)
			goto done;	 /* nothing left to do */

		this_sector = first_sector + START_SECT(p) * sector_size;
		this_size = NR_SECTS(p) * sector_size;
		put_dev_sector(sect);
	}
done:
	printk(KERN_INFO "tegra_msdos_parse_extended: done\n");
	put_dev_sector(sect);
}
Esempio n. 6
0
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;

read_mbr:
#endif
	if (!(bh = bread(dev,0,1024))) {
		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 __powerpc__
	if (*(unsigned short *) (bh->b_data+510) == 0x55AA)
	{ /* Little-endian partition table - adjust in place */
		p = (struct partition *) (0x1BE + bh->b_data);
		for (i=1 ; i<=4 ; i++,p++)
		{
			if (!p->nr_sects)
				continue;
			p->start_sect = _LE_to_BE_long(p->start_sect);
			p->nr_sects = _LE_to_BE_long(p->nr_sects);
		}
		*(unsigned short *) (bh->b_data+510) = 0xAA55;
	}
#endif	
#ifdef CONFIG_BLK_DEV_IDE
check_table:
#endif
	if (*(unsigned short *)  (0x1fe + data) != 0xAA55) {
		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 = *(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) == 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 */

	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_disklabel_partition(hd, MKDEV(hd->major, minor));
			printk(" >");
		}
#endif
	}
	/*
	 *  Check for old-style Disk Manager partition table
	 */
	if (*(unsigned short *) (data+0xfc) == 0x55AA) {
		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;
}
Esempio n. 7
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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
/*
 * Look for various forms of IDE disk geometry translation
 */
static int handle_ide_mess(struct block_device *bdev)
{
#ifdef CONFIG_BLK_DEV_IDE
	Sector sect;
	unsigned char *data;
	kdev_t dev = to_kdev_t(bdev->bd_dev);
	unsigned int sig;
	int heads = 0;
	struct partition *p;
	int i;
	/*
	 * The i386 partition handling programs very often
	 * make partitions end on cylinder boundaries.
	 * There is no need to do so, and Linux fdisk doesnt always
	 * do this, and Windows NT on Alpha doesnt do this either,
	 * but still, this helps to guess #heads.
	 */
	data = read_dev_sector(bdev, 0, &sect);
	if (!data)
		return -1;
	if (!msdos_magic_present(data + 510)) {
		put_dev_sector(sect);
		return 0;
	}
	sig = le16_to_cpu(*(unsigned short *)(data + 2));
	p = (struct partition *) (data + 0x1be);
	for (i = 0; i < 4; i++) {
		struct partition *q = &p[i];
		if (NR_SECTS(q)) {
			if ((q->sector & 63) == 1 &&
			    (q->end_sector & 63) == 63)
				heads = q->end_head + 1;
			break;
		}
	}
	if (SYS_IND(p) == EZD_PARTITION) {
		/*
		 * Accesses to sector 0 must go to sector 1 instead.
		 */
		if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
			goto reread;
	} 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.
		 */
		if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
			goto reread;
	} else if (sig <= 0x1ae &&
		   data[sig] == 0xAA && data[sig+1] == 0x55 &&
		   (data[sig+2] & 1)) {
		/* DM6 signature in MBR, courtesy of OnTrack */
		(void) ide_xlate_1024 (dev, 0, heads, " [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, heads, " [DM6:AUX]");
	} else {
		(void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
	}
	put_dev_sector(sect);
	return 1;

reread:
	put_dev_sector(sect);
	/* Flush the cache */
	invalidate_bdev(bdev, 1);
	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
#endif /* CONFIG_BLK_DEV_IDE */
	return 1;
}
Esempio n. 10
0
static void extended_partition(struct gendisk *hd, struct block_device *bdev,
			int minor, unsigned long first_size, int *current_minor)
{
	struct partition *p;
	Sector sect;
	unsigned char *data;
	unsigned long first_sector, this_sector, this_size;
	int mask = (1 << hd->minor_shift) - 1;
	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
	int loopct = 0;		/* number of links followed
				   without finding a data partition */
	int i;

	this_sector = first_sector = hd->part[minor].start_sect;
	this_size = first_size;

	while (1) {
		if (++loopct > 100)
			return;
		if ((*current_minor & mask) == 0)
			return;
		data = read_dev_sector(bdev, this_sector, &sect);
		if (!data)
			return;

		if (!msdos_magic_present(data + 510))
			goto done; 

		p = (struct partition *) (data + 0x1be);

		/*
		 * 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++) {
			unsigned long offs, size, next;
			if (!NR_SECTS(p) || is_extended_partition(p))
				continue;

			/* Check the 3rd and 4th entries -
			   these sometimes contain random garbage */
			offs = START_SECT(p)*sector_size;
			size = NR_SECTS(p)*sector_size;
			next = this_sector + offs;
			if (i >= 2) {
				if (offs + size > this_size)
					continue;
				if (next < first_sector)
					continue;
				if (next + size > first_sector + first_size)
					continue;
			}

			add_gd_partition(hd, *current_minor, next, size);
#if CONFIG_BLK_DEV_MD
			if (SYS_IND(p) == LINUX_RAID_PARTITION) {
			    md_autodetect_dev(MKDEV(hd->major,*current_minor));
			}
#endif

			(*current_minor)++;
			loopct = 0;
			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 */

		this_sector = first_sector + START_SECT(p) * sector_size;
		this_size = NR_SECTS(p) * sector_size;
		minor = *current_minor;
		put_dev_sector(sect);
	}
done:
	put_dev_sector(sect);
}
Esempio n. 11
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;
}
Esempio n. 12
0
int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
{
	int sector_size = bdev_hardsect_size(bdev) / 512;
	Sector sect;
	unsigned char *data;
	struct partition *p;
	int slot;
#ifdef HACK_PARTITION_TABLE_BOOT_IND
	int check_times = 0;
#endif

	data = read_dev_sector(bdev, 0, &sect);
	if (!data)
		return -1;
	if (!msdos_magic_present(data + 510)) {
		put_dev_sector(sect);
		return 0;
	}

	/*
	 * Now that the 55aa signature is present, this is probably
	 * either the boot sector of a FAT filesystem or a DOS-type
	 * partition table. Reject this in case the boot indicator
	 * is not 0 or 0x80.
	 */
	p = (struct partition *) (data + 0x1be);
	for (slot = 1; slot <= 4; slot++, p++) {
		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
#ifdef HACK_PARTITION_TABLE_BOOT_IND // hack for boot_ind != 0 && boot_ind != 0x80
			printk("\n[cfyeh-hack] %s(%d) partition->boot_ind = 0x%.2x (should be 0x0 or 0x80)\n", __func__, __LINE__, p->boot_ind);
			check_times++;
#else
			put_dev_sector(sect);
			return 0;
#endif
		}
	}

#ifdef HACK_PARTITION_TABLE_BOOT_IND // hack for boot_ind != 0 && boot_ind != 0x80
	if(check_times > 1)
	{
		printk("[cfyeh-hack] %s(%d) partition->boot_ind fail %d times !!!\n", __func__, __LINE__, check_times);
		put_dev_sector(sect);
		return 0;
	}

#endif

#ifdef CONFIG_EFI_PARTITION
	p = (struct partition *) (data + 0x1be);
	for (slot = 1 ; slot <= 4 ; slot++, 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;
		}
	}
#endif
	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.
	 */

	state->next = 5;
	for (slot = 1 ; slot <= 4 ; slot++, p++) {
		u32 start = START_SECT(p)*sector_size;
		u32 size = NR_SECTS(p)*sector_size;
		if (!size)
			continue;
		if (is_extended_partition(p)) {
			// add to know which partition is a extended partition
			// by cfyeh 2007/11/13 +
			state->parts[slot].is_part_extended = 1;
			// by cfyeh 2007/11/13 -

			/* prevent someone doing mkfs or mkswap on an
			   extended partition, but leave room for LILO */
			put_partition(state, slot, start, size == 1 ? 1 : 2);
			printk(" <");
			parse_extended(state, bdev, start, size);
			printk(" >");
			continue;
		}
		put_partition(state, slot, start, size);
		if (SYS_IND(p) == LINUX_RAID_PARTITION)
			state->parts[slot].flags = 1;
		if (SYS_IND(p) == DM6_PARTITION)
			printk("[DM]");
		if (SYS_IND(p) == EZD_PARTITION)
			printk("[EZD]");
	}

	printk("\n");

	/* second pass - output for each on a separate line */
	p = (struct partition *) (0x1be + data);
	for (slot = 1 ; slot <= 4 ; slot++, 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)
			continue;
		subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
						NR_SECTS(p)*sector_size, slot);
	}
	put_dev_sector(sect);
	return 1;
}