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; }
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, §); 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, ¤t_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, ¤t_minor); } put_dev_sector(sect); return 1; }
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; }
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, §); 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, §); if (msdos_magic_present(partdata + 510)) sector_mult = 4; partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*2, §); if (msdos_magic_present(partdata + 510)) sector_mult = 2; partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size, §); 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, §); if (ext3_magic_present(partdata + 56)) sector_mult = 4; partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size*2+2, §); if (ext3_magic_present(partdata + 56)) sector_mult = 2; partdata = read_dev_sector(bdev, first_sector+START_SECT(p)*sector_size+2, §); 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, ¤t_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, ¤t_minor); } put_dev_sector(sect); return 1; }