Example #1
0
static void parse_minix(struct parsed_partitions *state,
			sector_t offset, sector_t size, int origin)
{
#ifdef CONFIG_MINIX_SUBPARTITION
	Sector sect;
	unsigned char *data;
	struct partition *p;
	int i;

	data = read_part_sector(state, 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 */
}
Example #2
0
int tegra_msdos_parse(struct parsed_partitions *state, struct block_device *bdev, u64 mbr_offset)
{
	int sector_size = bdev_logical_block_size(bdev) / 512;
	Sector sect;
	unsigned char *data;
	struct partition *p;
	int slot;

	printk(KERN_INFO "tegra_msdos_parse: mbr_offset=%llu\n", mbr_offset);

	data = read_dev_sector(bdev, mbr_offset, &sect);
	if (!data) {
		printk(KERN_INFO "tegra_msdos_parse: read error. exit\n");
		return -1;
	}
	if (!msdos_magic_present(data + 510)) {
		printk(KERN_INFO "tegra_msdos_parse: no msdos magic\n");
		put_dev_sector(sect);
		return 0;
	}

	p = (struct partition *) (data + 0x1be);
	for (slot = 1; slot <= 4; slot++, p++) {
		if (p->boot_ind != 0 && p->boot_ind != 0x80) {  // 0x1be,0x1ce,0x1de,0x1fe
			printk("tegra_msdos_parse: slot %d, boot_ind=0x%x. exit\n", slot, p->boot_ind);
			put_dev_sector(sect);
			return 0;
		}
	}

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

	for (slot = 1 ; slot <= 4 ; slot++, p++) {
		u64 start = START_SECT(p)*sector_size; // 0015f800	1439744
		u64 size = NR_SECTS(p)*sector_size;    // 01c41400	29627392
		printk(KERN_INFO "tegra_msdos_parse: slot %d, start=%llu size=%llu\n", slot, start, size);
		if (!size)
			continue;
		if (is_extended_partition(p)) {
			printk(KERN_INFO "tegra_msdos_parse: slot %d extended partition\n", slot);
			//put_partition(state, state->next++, start+mbr_offset, size == 1 ? 1 : 2);
			printk(" <");
			tegra_msdos_parse_extended(state, state->bdev, mbr_offset, start, size); 
			printk(" >");
			continue;
		}
		printk(KERN_INFO "tegra_msdos_parse: put_partition\n");
		put_partition(state, state->next++, start+mbr_offset, size);
	}

	printk("\n");
	printk(KERN_INFO "tegra_msdos_parse: done\n");

	put_dev_sector(sect);
	return 1;
}
Example #3
0
/*
 * Minix 2.0.0/2.0.2 subpartition support.
 * Anand Krishnamurthy <*****@*****.**>
 * Rajeev V. Pillai    <*****@*****.**>
 */
static void minix_partition(struct gendisk *hd, struct block_device *bdev,
		int minor, int *current_minor)
{
#ifdef CONFIG_MINIX_SUBPARTITION
	long offset = hd->part[minor].start_sect;
	Sector sect;
	unsigned char *data;
	struct partition *p;
	int mask = (1 << hd->minor_shift) - 1;
	int i;
	char buf[40];

	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: <minix:", partition_name(hd, minor, buf));
		for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
			if ((*current_minor & mask) == 0)
				break;
			/* add each partition in use */
			if (SYS_IND(p) == MINIX_PARTITION) {
				add_gd_partition(hd, *current_minor,
					      START_SECT(p), NR_SECTS(p));
				(*current_minor)++;
			}
		}
		printk(" >\n");
	}
	put_dev_sector(sect);
#endif /* CONFIG_MINIX_SUBPARTITION */
}
Example #4
0
static void parse_extended(struct parsed_partitions *state,
			   sector_t first_sector, sector_t first_size)
{
	struct partition *p;
	Sector sect;
	unsigned char *data;
	sector_t this_sector, this_size;
	sector_t sector_size = bdev_logical_block_size(state->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_part_sector(state, 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++) {
			sector_t 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);
}
Example #5
0
int msdos_partition(struct parsed_partitions *state)
{
	sector_t sector_size = bdev_logical_block_size(state->bdev) / 512;
	Sector sect;
	unsigned char *data;
	struct partition *p;
	struct fat_boot_sector *fb;
	int slot;

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

	if (aix_magic_present(state, data)) {
		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) {
			/*
			 * Even without a valid boot inidicator value
			 * its still possible this is valid FAT filesystem
			 * without a partition table.
			 */
			fb = (struct fat_boot_sector *) data;
			if (slot == 1 && fb->reserved && fb->fats
				&& fat_valid_media(fb->media)) {
				printk("\n");
				put_dev_sector(sect);
				return 1;
			} else {
				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++) {
		sector_t start = start_sect(p)*sector_size;
		sector_t 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
			 * FIXME: this uses one logical sector for > 512b
			 * sector, although it may not be enough/proper.
			 */
			sector_t n = 2;
			n = min(size, max(sector_size, n));
			put_partition(state, slot, start, n);

			printk(" <");
			parse_extended(state, start, size);
			printk(" >");
			continue;
		}
		put_partition(state, slot, start, size);
		if (SYS_IND(p) == LINUX_RAID_PARTITION)
			state->parts[slot].flags = ADDPART_FLAG_RAID;
		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, start_sect(p) * sector_size,
				  nr_sects(p) * sector_size, slot);
	}
	put_dev_sector(sect);
	return 1;
}
Example #6
0
static int __update_msdos_partition(int px, unsigned long long start, unsigned long long size)
{
    int err = 0;

	int i, slot; 
	int xbr_idx = 0;
	char *this_name = NULL;
	unsigned long long this_addr;

	unsigned char *buf = NULL;
	struct partition *p;
		
	buf = kzalloc(512, GFP_KERNEL);
	if (!buf) {
		err = -ENOMEM;
		pmt_err("update_msdos_partition: malloc buf fail\n");
		goto fail_malloc;
	}
	
	//find px in which mbr/ebr.
	for (i = 0;i < MBR_COUNT; i++) {
		for (slot = 0; slot < 4; slot++) {
			if (MBR_EBR_px[i].part_index[slot] == px) {
                /* this_name is mbr or ebrx */
				xbr_idx = i;
				this_name = MBR_EBR_px[i].part_name;  
                goto found;
			}
		}
	}

	if (slot >= 4) {
		pmt_err("p%d can not be found in mbr\n", px);
		err = -EINVAL;
		goto out;
	}

found:
	pmt_info("update %s\n", this_name);

    /* check mbr or ebrx partition info */
	for (i = 0; i < PART_NUM; i++) {
		if (!strcmp(this_name, PartInfo[i].name)) {
			this_addr = PartInfo[i].start_address;
			pmt_info("update %s addr %llx\n", this_name, this_addr);
			break;
		}
	}

	if (i == PART_NUM) {
		pmt_err("can not find %s\n", this_name);
		err = -EINVAL;
		goto out;
	} 

    /* read mbr or ebr into buf */
	err = eMMC_rw_x(this_addr, (u32*)buf, 0, 0, 512, 1, EMMC_PART_USER);
	if (err || !msdos_magic_present(buf + 510)) {
		pmt_err("read %s error\n", this_name);
        err = -EIO;
		goto out;
	}

	if (!msdos_magic_present(buf + 510)) {
		pmt_err("read MBR/EBR fail\n");
		err = -1;
		goto out;
	}

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

	p[slot].start_sect = (unsigned int)((start - this_addr) / 512);
	p[slot].nr_sects = (unsigned int)(size / 512);

	err = eMMC_rw_x(this_addr, (u32*)buf, 0, 1, 512, 1, EMMC_PART_USER);
	if (err) {
		pmt_err("write %s error\n", this_name);
        err = -EIO;
		goto out;
	}

out:
	kfree(buf);
fail_malloc:
	return err;
}
Example #7
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;
}
Example #8
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);
}
Example #9
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;
}
Example #10
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;
}
Example #11
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);
}
Example #12
0
static int update_MBR_or_EBR(int px, u64 start_addr, u64 length)
{
	int i,ret,j;
	int found_mbr = 0;
	loff_t update_addr = 0;
	int index_in_mbr = 0;
	int mbr_index = 0;
	char *change_pt_name = NULL;
	struct partition *p;
	u8 *page_buf = NULL;
	ret =0;
		
	page_buf = kmalloc(512, GFP_KERNEL);
	if (!page_buf) {
		ret = -ENOMEM;
		printk("update_MBR_or_EBR: malloc page_buf fail\n");
		goto fail_malloc;
	}
	//data -1MB
/*	for(i=0;i<PART_NUM;i++){
		if((PartInfo[i].partition_idx == px)&&((!strncmp(PartInfo[i].name,"usrdata",7))||(!strncmp(PartInfo[i].name,"sec_ro",6))||(!strncmp(PartInfo[i].name,"android",7))||(!strncmp(PartInfo[i].name,"cache",5)))){
			printk("update %s,need reduce 1MB in MBR\n",PartInfo[i].name);
			length -= 0x100000;
		}
	}*/
	
	
	//find px in which mbr/ebr.
	for(i=0;i<MBR_COUNT;i++){
		for(j=0;j<SLOT_PER_MBR;j++){
			if(MBR_EBR_px[i].part_index[j]==px){
				found_mbr = 1;
				change_pt_name = MBR_EBR_px[i].part_name;
				index_in_mbr = j;
				mbr_index = i;
			}
		}
	}
	if(found_mbr!=1){
		printk("p%d can not be found in mbr\n",px);
		ret = -1;
		goto end;
	}
	printk("update %s\n",change_pt_name);

	for(i=0; i<PART_NUM;i++){
		if(!strcmp(change_pt_name,PartInfo[i].name)){
			update_addr = PartInfo[i].start_address - MBR_START_ADDR;
			printk("update %s addr %llx\n",change_pt_name,update_addr);
			break;
		}
	}
	if(i==PART_MAX_COUNT){
		printk("can not find %s\n",change_pt_name);
		ret = -1;
		goto end;
	}
	ret = eMMC_rw_x(update_addr,(u32*)page_buf,0,0,512,1,USER);
	if(ret){
		printk("read %s error\n",change_pt_name);
		goto end;
	}
	if (!msdos_magic_present(page_buf + 510)) {
		printk("read MBR/EBR fail\n");
		ret = -1;
		goto end;
	}
	p = (struct partition *) (page_buf + 0x1be);

	for(i=0;i<4;i++){
		if(MBR_EBR_px[mbr_index].part_index[i]!=0){
			printk("p%d: %x %x\n",MBR_EBR_px[mbr_index].part_index[i],p[i].start_sect,p[i].nr_sects);
			if(i==index_in_mbr){
				printk("p%d: change to %x %x\n",MBR_EBR_px[mbr_index].part_index[i],(u32)((start_addr-update_addr)/512),(u32)(length/512));
				p[i].start_sect = (u32)((start_addr-update_addr)/512);
				p[i].nr_sects = (u32)(length/512);
			}
		}
	}

	ret = eMMC_rw_x(update_addr,(u32*)page_buf,0,1,512,1,USER);
	if(ret){
		printk("write %s error\n",change_pt_name);
		goto end;
	}
end:
	kfree(page_buf);
fail_malloc:
	return ret;
}
Example #13
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;
}
Example #14
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;
}