📄 genhd.c
字号:
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_IDEcheck_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_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size, ptype(SYS_IND(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 /* 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 /* james@bpgc.com: 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_partition(hd, current_minor, START_SECT(p), NR_SECTS(p), 0); } } printk("\n"); brelse(bh); return 1;}#endif /* CONFIG_MSDOS_PARTITION */#ifdef CONFIG_OSF_PARTITIONstatic int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector){ int i; int mask = (1 << hd->minor_shift) - 1; struct buffer_head *bh; struct disklabel { u32 d_magic; u16 d_type,d_subtype; u8 d_typename[16]; u8 d_packname[16]; u32 d_secsize; u32 d_nsectors; u32 d_ntracks; u32 d_ncylinders; u32 d_secpercyl; u32 d_secprtunit; u16 d_sparespertrack; u16 d_sparespercyl; u32 d_acylinders; u16 d_rpm, d_interleave, d_trackskew, d_cylskew; u32 d_headswitch, d_trkseek, d_flags; u32 d_drivedata[5]; u32 d_spare[5]; u32 d_magic2; u16 d_checksum; u16 d_npartitions; u32 d_bbsize, d_sbsize; struct d_partition { u32 p_size; u32 p_offset; u32 p_fsize; u8 p_fstype; u8 p_frag; u16 p_cpg; } d_partitions[8]; } * label; struct d_partition * partition;#define DISKLABELMAGIC (0x82564557UL) if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) { printk("unable to read partition table\n"); return -1; } label = (struct disklabel *) (bh->b_data+64); partition = label->d_partitions; if (label->d_magic != DISKLABELMAGIC) { brelse(bh); return 0; } if (label->d_magic2 != DISKLABELMAGIC) { brelse(bh); return 0; } for (i = 0 ; i < label->d_npartitions; i++, partition++) { if ((current_minor & mask) == 0) break; if (partition->p_size) add_partition(hd, current_minor, first_sector+partition->p_offset, partition->p_size, 0); current_minor++; } printk("\n"); brelse(bh); return 1;}#endif /* CONFIG_OSF_PARTITION */#ifdef CONFIG_SUN_PARTITIONstatic int sun_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector){ int i, csum; unsigned short *ush; struct buffer_head *bh; struct sun_disklabel { unsigned char info[128]; /* Informative text string */ unsigned char spare0[14]; struct sun_disklabelinfo { unsigned char spare1; unsigned char id; unsigned char spare2; unsigned char flags; } infos[8]; unsigned char spare1[246]; /* Boot information etc. */ unsigned short rspeed; /* Disk rotational speed */ unsigned short pcylcount; /* Physical cylinder count */ unsigned short sparecyl; /* extra sects per cylinder */ unsigned char spare2[4]; /* More magic... */ unsigned short ilfact; /* Interleave factor */ unsigned short ncyl; /* Data cylinder count */ unsigned short nacyl; /* Alt. cylinder count */ unsigned short ntrks; /* Tracks per cylinder */ unsigned short nsect; /* Sectors per track */ unsigned char spare3[4]; /* Even more magic... */ struct sun_partition { __u32 start_cylinder; __u32 num_sectors; } partitions[8]; unsigned short magic; /* Magic number */ unsigned short csum; /* Label xor'd checksum */ } * label; struct sun_partition *p; unsigned long spc;#define SUN_LABEL_MAGIC 0xDABE if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) { printk("Dev %s: unable to read partition table\n", kdevname(dev)); return -1; } label = (struct sun_disklabel *) bh->b_data; p = label->partitions; if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) { printk("Dev %s Sun disklabel: bad magic %04x\n", kdevname(dev), be16_to_cpu(label->magic)); brelse(bh); return 0; } /* Look at the checksum */ ush = ((unsigned short *) (label+1)) - 1; for(csum = 0; ush >= ((unsigned short *) label);) csum ^= *ush--; if(csum) { printk("Dev %s Sun disklabel: Csum bad, label corrupted\n", kdevname(dev)); brelse(bh); return 0; } /* All Sun disks have 8 partition entries */ spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect); for(i=0; i < 8; i++, p++) { unsigned long st_sector; int num_sectors; st_sector = first_sector + be32_to_cpu(p->start_cylinder) * spc; num_sectors = be32_to_cpu(p->num_sectors); if (num_sectors) add_partition(hd, current_minor, st_sector, num_sectors, ptype(label->infos[i].id)); current_minor++; } printk("\n"); brelse(bh); return 1;}#endif /* CONFIG_SUN_PARTITION */#ifdef CONFIG_SGI_PARTITIONstatic int sgi_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector){ int i, csum, magic; unsigned int *ui, start, blocks, cs; struct buffer_head *bh; struct sgi_disklabel { int magic_mushroom; /* Big fat spliff... */ short root_part_num; /* Root partition number */ short swap_part_num; /* Swap partition number */ char boot_file[16]; /* Name of boot file for ARCS */ unsigned char _unused0[48]; /* Device parameter useless crapola.. */ struct sgi_volume { char name[8]; /* Name of volume */ int block_num; /* Logical block number */ int num_bytes; /* How big, in bytes */ } volume[15]; struct sgi_partition { int num_blocks; /* Size in logical blocks */ int first_block; /* First logical block */ int type; /* Type of this partition */ } partitions[16]; int csum; /* Disk label checksum */ int _unused1; /* Padding */ } *label; struct sgi_partition *p;#define SGI_LABEL_MAGIC 0x0be5a941 if(!(bh = bread(dev, 0, get_ptable_blocksize(dev)))) { printk("Dev %s: unable to read partition table\n", kdevname(dev)); return -1; } label = (struct sgi_disklabel *) bh->b_data; p = &label->partitions[0]; magic = label->magic_mushroom; if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) { printk("Dev %s SGI disklabel: bad magic %08x\n", kdevname(dev), magic); brelse(bh); return 0; } ui = ((unsigned int *) (label + 1)) - 1; for(csum = 0; ui >= ((unsigned int *) label);) { cs = *ui--; csum += be32_to_cpu(cs); } if(csum) { printk("Dev %s SGI disklabel: csum bad, label corrupted\n", kdevname(dev)); brelse(bh); return 0; } /* All SGI disk labels have 16 partitions, disks under Linux only * have 15 minor's. Luckily there are always a few zero length * partitions which we don't care about so we never overflow the * current_minor. */ for(i = 0; i < 16; i++, p++) { blocks = be32_to_cpu(p->num_blocks); start = be32_to_cpu(p->first_block); if(!blocks) continue; add_partition(hd, current_minor, start, blocks, 0); current_minor++; } printk("\n"); brelse(bh); return 1;}#endif#ifdef CONFIG_AMIGA_PARTITION#include <linux/affs_hardblocks.h>static __inline__ u32checksum_block(u32 *m, int size){ u32 sum = 0; while (size--) sum += htonl(*m++); return sum;}static intamiga_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector){ struct buffer_head *bh; struct RigidDiskBlock *rdb; struct PartitionBlock *pb; int start_sect; int nr_sects; int blk; int part, res; int old_blocksize; int blocksize; old_blocksize = get_ptable_blocksize(dev); if (hardsect_size[MAJOR(dev)] != NULL) blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)]; else blocksize = 512; set_blocksize(dev,blocksize); res = 0; for (blk = 0; blk < RDB_ALLOCATION_LIMIT; blk++) { if(!(bh = bread(dev,blk,blocksize))) { printk("Dev %s: unable to read RDB block %d\n", kdevname(dev),blk); goto rdb_done; } if (*(u32 *)bh->b_data == htonl(IDNAME_RIGIDDISK)) { rdb = (struct RigidDiskBlock *)bh->b_data; if (checksum_block((u32 *)bh->b_data,htonl(rdb->rdb_SummedLongs) & 0x7F)) { /* Try again with 0xdc..0xdf zeroed, Windows might have * trashed it. */ *(u32 *)(&bh->b_data[0xdc]) = 0; if (checksum_block((u32 *)bh->b_data, htonl(rdb->rdb_SummedLongs) & 0x7F)) { brelse(bh); printk("Dev %s: RDB in block %d has bad checksum\n", kdevname(dev),blk); continue; } printk("Warning: Trashed word at 0xd0 in block %d " "ignored in checksum calculation\n",blk); } printk(" RDSK"); blk = htonl(rdb->rdb_PartitionList); brelse(bh); for (part = 1; blk > 0 && part <= 16; part++) { if (!(bh = bread(dev,blk,blocksize))) { printk("Dev %s: unable to read partition block %d\n", kdevname(dev),blk); goto rdb_done; } pb = (struct PartitionBlock *)bh->b_data; blk = htonl(pb->pb_Next); if (pb->pb_ID == htonl(IDNAME_PARTITION) && checksum_block( (u32 *)pb,htonl(pb->pb_SummedLongs) & 0x7F) == 0 ) { /* Tell Kernel about it */ if (!(nr_sects = (htonl(pb->pb_Environment[10]) + 1 - htonl(pb->pb_Environment[9])) * htonl(pb->pb_Environment[3]) * htonl(pb->pb_Environment[5]))) { brelse(bh); continue; } start_sect = htonl(pb->pb_Environment[9]) * htonl(pb->pb_Environment[3]) * htonl(pb->pb_Environment[5]); add_partition(hd,current_minor, start_sect,nr_sects,0); current_minor++; res = 1; } brelse(bh); } printk("\n"); } else brelse(bh); }rdb_done: set_blocksize(dev,old_blocksize); return res;}#endif /* CONFIG_AMIGA_PARTITION */#ifdef CONFIG_MAC_PARTITION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -