/* * 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(" >"); }
/* * 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); }
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; } }
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(" >"); }
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); }
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 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; }