📄 genhd.c
字号:
#include <linux/ctype.h>/* * Code to understand MacOS partition tables. */#define MAC_PARTITION_MAGIC 0x504d/* type field value for A/UX or other Unix partitions */#define APPLE_AUX_TYPE "Apple_UNIX_SVR2"struct mac_partition { __u16 signature; /* expected to be MAC_PARTITION_MAGIC */ __u16 res1; __u32 map_count; /* # blocks in partition map */ __u32 start_block; /* absolute starting block # of partition */ __u32 block_count; /* number of blocks in partition */ char name[32]; /* partition name */ char type[32]; /* string type description */ __u32 data_start; /* rel block # of first data block */ __u32 data_count; /* number of data blocks */ __u32 status; /* partition status bits */ __u32 boot_start; __u32 boot_size; __u32 boot_load; __u32 boot_load2; __u32 boot_entry; __u32 boot_entry2; __u32 boot_cksum; char processor[16]; /* identifies ISA of boot */ /* there is more stuff after this that we don't need */};#define MAC_STATUS_BOOTABLE 8 /* partition is bootable */#define MAC_DRIVER_MAGIC 0x4552/* Driver descriptor structure, in block 0 */struct mac_driver_desc { __u16 signature; /* expected to be MAC_DRIVER_MAGIC */ __u16 block_size; __u32 block_count; /* ... more stuff */};static int mac_partition(struct gendisk *hd, kdev_t dev, unsigned long fsec){ struct buffer_head *bh; int blk, blocks_in_map; int dev_bsize, dev_pos, pos; unsigned secsize;#ifdef CONFIG_PPC int first_bootable = 1;#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_partition(hd, current_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) && first_bootable && (be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE) && strcasecmp(part->processor, "powerpc") == 0) { note_bootable_part(dev, blk); first_bootable = 0; }#endif /* CONFIG_PPC */ ++current_minor; } brelse(bh); printk("\n"); return 1;}#endif /* CONFIG_MAC_PARTITION */#ifdef CONFIG_ATARI_PARTITION#include <asm/atari_rootsec.h>/* ++guenther: this should be settable by the user ("make config")?. */#define ICD_PARTSstatic int atari_partition (struct gendisk *hd, kdev_t dev, unsigned long first_sector){ int minor = current_minor, m_lim = current_minor + hd->max_p; struct buffer_head *bh; struct rootsector *rs; struct partition_info *pi; ulong extensect;#ifdef ICD_PARTS int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */#endif bh = bread (dev, 0, get_ptable_blocksize(dev)); if (!bh) { printk (" unable to read block 0\n"); return -1; } rs = (struct rootsector *) bh->b_data; pi = &rs->part[0]; printk (" AHDI"); for (; pi < &rs->part[4] && minor < m_lim; minor++, pi++) { if (pi->flg & 1) /* active partition */ { if (memcmp (pi->id, "XGM", 3) == 0) /* extension partition */ { struct rootsector *xrs; struct buffer_head *xbh; ulong partsect;#ifdef ICD_PARTS part_fmt = 1;#endif printk(" XGM<"); partsect = extensect = pi->st; while (1) { xbh = bread (dev, partsect / 2, get_ptable_blocksize(dev)); if (!xbh) { printk (" block %ld read failed\n", partsect); brelse(bh); return 0; } if (partsect & 1) xrs = (struct rootsector *) &xbh->b_data[512]; else xrs = (struct rootsector *) &xbh->b_data[0]; /* ++roman: sanity check: bit 0 of flg field must be set */ if (!(xrs->part[0].flg & 1)) { printk( "\nFirst sub-partition in extended partition is not valid!\n" ); break; } add_partition(hd, minor, partsect + xrs->part[0].st, xrs->part[0].siz, 0); if (!(xrs->part[1].flg & 1)) { /* end of linked partition list */ brelse( xbh ); break; } if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) { printk( "\nID of extended partition is not XGM!\n" ); brelse( xbh ); break; } partsect = xrs->part[1].st + extensect; brelse (xbh); minor++; if (minor >= m_lim) { printk( "\nMaximum number of partitions reached!\n" ); break; } } printk(" >"); } else { /* we don't care about other id's */ add_partition (hd, minor, pi->st, pi->siz, 0); } } }#ifdef ICD_PARTS if ( part_fmt!=1 ) /* no extended partitions -> test ICD-format */ { pi = &rs->icdpart[0]; /* sanity check: no ICD format if first partition invalid */ if (memcmp (pi->id, "GEM", 3) == 0 || memcmp (pi->id, "BGM", 3) == 0 || memcmp (pi->id, "LNX", 3) == 0 || memcmp (pi->id, "SWP", 3) == 0 || memcmp (pi->id, "RAW", 3) == 0 ) { printk(" ICD<"); for (; pi < &rs->icdpart[8] && minor < m_lim; minor++, pi++) { /* accept only GEM,BGM,RAW,LNX,SWP partitions */ if (pi->flg & 1 && (memcmp (pi->id, "GEM", 3) == 0 || memcmp (pi->id, "BGM", 3) == 0 || memcmp (pi->id, "LNX", 3) == 0 || memcmp (pi->id, "SWP", 3) == 0 || memcmp (pi->id, "RAW", 3) == 0) ) { part_fmt = 2; add_partition (hd, minor, pi->st, pi->siz, 0); } } printk(" >"); } }#endif brelse (bh); printk ("\n"); return 1;}#endif /* CONFIG_ATARI_PARTITION */#ifdef CONFIG_ULTRIX_PARTITIONstatic int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector){ int i, minor = current_minor; struct buffer_head *bh; struct ultrix_disklabel { long pt_magic; /* magic no. indicating part. info exits */ int pt_valid; /* set by driver if pt is current */ struct pt_info { int pi_nblocks; /* no. of sectors */ unsigned long 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) { 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++, minor++) if (label->pt_part[i].pi_nblocks) add_partition(hd, minor, label->pt_part[i].pi_blkoff, label->pt_part[i].pi_nblocks); brelse(bh); printk ("\n"); return 1; } else { brelse(bh); return 0; }}#endif /* CONFIG_ULTRIX_PARTITION */static void check_partition(struct gendisk *hd, kdev_t dev){ static int first_time = 1; unsigned long first_sector; char buf[MAX_DISKNAME_LEN]; if (first_time) printk("Partition check:\n"); first_time = 0; first_sector = hd->part[MINOR(dev)].start_sect; /* * This is a kludge to allow the partition check to be * skipped for specific drives (e.g. IDE CD-ROM drives) */ if ((int)first_sector == -1) { hd->part[MINOR(dev)].start_sect = 0; return; } printk(" %s:", disk_name(hd, MINOR(dev), buf));#ifdef CONFIG_MSDOS_PARTITION if (msdos_partition(hd, dev, first_sector)) return;#endif#ifdef CONFIG_OSF_PARTITION if (osf_partition(hd, dev, first_sector)) return;#endif#ifdef CONFIG_SUN_PARTITION if(sun_partition(hd, dev, first_sector)) return;#endif#ifdef CONFIG_AMIGA_PARTITION if(amiga_partition(hd, dev, first_sector)) return;#endif#ifdef CONFIG_ATARI_PARTITION if(atari_partition(hd, dev, first_sector)) return;#endif#ifdef CONFIG_MAC_PARTITION if (mac_partition(hd, dev, first_sector)) return;#endif#ifdef CONFIG_SGI_PARTITION if(sgi_partition(hd, dev, first_sector)) return;#endif#ifdef CONFIG_ULTRIX_PARTITION if(ultrix_partition(hd, dev, first_sector)) return;#endif printk(" unknown partition table\n");}/* This function is used to re-read partition tables for removable disks. Much of the cleanup from the old partition tables should have already been done *//* This function will re-read the partition tables for a given device,and set things back up again. There are some important caveats,however. You must ensure that no one is using the device, and no onecan start using the device while this function is being executed. */void resetup_one_dev(struct gendisk *dev, int drive){ int i; int first_minor = drive << dev->minor_shift; int end_minor = first_minor + dev->max_p; blk_size[dev->major] = NULL; current_minor = 1 + first_minor; check_partition(dev, MKDEV(dev->major, first_minor)); /* * We need to set the sizes array before we will be able to access * any of the partitions on this device. */ if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ for (i = first_minor; i < end_minor; i++) dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); blk_size[dev->major] = dev->sizes; }}static inline void setup_dev(struct gendisk *dev){ int i, drive; int end_minor = dev->max_nr * dev->max_p; blk_size[dev->major] = NULL; for (i = 0 ; i < end_minor; i++) { dev->part[i].start_sect = 0; dev->part[i].nr_sects = 0; } dev->init(dev); for (drive = 0 ; drive < dev->nr_real ; drive++) { int first_minor = drive << dev->minor_shift; current_minor = 1 + first_minor; check_partition(dev, MKDEV(dev->major, first_minor)); } if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */ for (i = 0; i < end_minor; i++) dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9); blk_size[dev->major] = dev->sizes; }}__initfunc(void device_setup(void)){ extern void console_map_init(void); extern void cpqarray_init(void);#ifdef CONFIG_PARPORT extern int parport_init(void);#endif#ifdef CONFIG_MD_BOOT extern void md_setup_drive(void) __init;#endif#ifdef CONFIG_FC4_SOC extern int soc_probe(void);#endif struct gendisk *p;#ifdef CONFIG_PARPORT parport_init();#endif chr_dev_init(); blk_dev_init(); sti();#ifdef CONFIG_BLK_DEV_DAC960 DAC960_Initialize();#endif#ifdef CONFIG_FC4_SOC /* This has to be done before scsi_dev_init */ soc_probe();#endif#ifdef CONFIG_SCSI scsi_dev_init();#endif#ifdef CONFIG_BLK_CPQ_DA cpqarray_init();#endif#ifdef CONFIG_INET net_dev_init();#endif#ifdef CONFIG_VT console_map_init();#endif for (p = gendisk_head ; p ; p=p->next) setup_dev(p);#ifdef CONFIG_BLK_DEV_RAM#ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && mount_initrd) initrd_load(); else#endif rd_load();#endif#ifdef CONFIG_MD_BOOT md_setup_drive();#endif}#ifdef CONFIG_PROC_FSint get_partition_list(char * page){ struct gendisk *p; char buf[MAX_DISKNAME_LEN]; int n, len; len = sprintf(page, "major minor #blocks name\n\n"); for (p = gendisk_head; p; p = p->next) { for (n=0; n < (p->nr_real << p->minor_shift); n++) { if (p->part[n].nr_sects && len < PAGE_SIZE - 80) { len += sprintf(page+len, "%4d %4d %10d %s\n", p->major, n, p->sizes[n], disk_name(p, n, buf)); } } } return len;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -