⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genhd.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Code extracted from *  linux/kernel/hd.c * *  Copyright (C) 1991, 1992  Linus Torvalds * * *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug *  in the early extended-partition checks and added DM partitions * *  Support for DiskManager v6.0x added by Mark Lord, *  with information provided by OnTrack.  This now works for linux fdisk *  and LILO, as well as loadlin and bootln.  Note that disks other than *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1). * *  More flexible handling of extended partitions - aeb, 950831 * *  Check partition table on IDE disks for common CHS translations */#include <linux/config.h>#include <linux/fs.h>#include <linux/genhd.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/string.h>#ifdef CONFIG_BLK_DEV_INITRD#include <linux/blk.h>#endif#include <asm/system.h>/* * Many architectures don't like unaligned accesses, which is * frequently the case with the nr_sects and start_sect partition * table entries. */#include <asm/unaligned.h>#ifdef MACH#include <machine/spl.h>#endif#define SYS_IND(p)	get_unaligned(&p->sys_ind)#define NR_SECTS(p)	get_unaligned(&p->nr_sects)#define START_SECT(p)	get_unaligned(&p->start_sect)struct gendisk *gendisk_head = NULL;static int current_minor = 0;extern int *blk_size[];extern void rd_load(void);extern void initrd_load(void);extern int chr_dev_init(void);extern int blk_dev_init(void);extern int scsi_dev_init(void);extern int net_dev_init(void);/* * disk_name() is used by genhd.c and md.c. * It formats the devicename of the indicated disk * into the supplied buffer, and returns a pointer * to that same buffer (for convenience). */char *disk_name (struct gendisk *hd, int minor, char *buf){	unsigned int part;	const char *maj = hd->major_name;#ifdef MACH	char unit = (minor >> hd->minor_shift) + '0';#else	char unit = (minor >> hd->minor_shift) + 'a';#endif#ifdef CONFIG_BLK_DEV_IDE	/*	 * IDE devices use multiple major numbers, but the drives	 * are named as:  {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..	 * This requires special handling here.	 */	switch (hd->major) {		case IDE3_MAJOR:			unit += 2;		case IDE2_MAJOR:			unit += 2;		case IDE1_MAJOR:			unit += 2;		case IDE0_MAJOR:			maj = "hd";	}#endif	part = minor & ((1 << hd->minor_shift) - 1);	if (part)#ifdef MACH		sprintf(buf, "%s%cs%d", maj, unit, part);#else		sprintf(buf, "%s%c%d", maj, unit, part);#endif	else		sprintf(buf, "%s%c", maj, unit);	return buf;}static void add_partition (struct gendisk *hd, int minor, int start, int size){	char buf[8];	hd->part[minor].start_sect = start;	hd->part[minor].nr_sects   = size;	printk(" %s", disk_name(hd, minor, buf));}#ifdef MACHstatic int mach_minor;static voidadd_bsd_partition (struct gendisk *hd, int minor, int slice,		   int start, int size){  char buf[16];  hd->part[minor].start_sect = start;  hd->part[minor].nr_sects = size;  printk (" %s%c", disk_name (hd, mach_minor, buf), slice);}#endifstatic inline int is_extended_partition(struct partition *p){	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||		SYS_IND(p) == LINUX_EXTENDED_PARTITION);}#ifdef CONFIG_MSDOS_PARTITION/* * Create devices for each logical partition in an extended partition. * The logical partitions form a linked list, with each entry being * a partition table with two entries.  The first entry * is the real data partition (with a start relative to the partition * table start).  The second is a pointer to the next logical partition * (with a start relative to the entire extended partition). * We do not create a Linux partition for the partition tables, but * only for the actual data partitions. */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 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,1024)))			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 (*(unsigned short *) (bh->b_data+510) != 0xAA55)			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_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));		    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);		hd->part[current_minor].start_sect = first_sector + START_SECT(p);		this_sector = first_sector + START_SECT(p);		dev = MKDEV(hd->major, current_minor);		brelse(bh);	}done:	brelse(bh);}#ifdef CONFIG_BSD_DISKLABEL/* * 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){	struct buffer_head *bh;	struct bsd_disklabel *l;	struct bsd_partition *p;	int mask = (1 << hd->minor_shift) - 1;	if (!(bh = bread(dev,0,1024)))		return;	bh->b_state = 0;	l = (struct bsd_disklabel *) (bh->b_data+512);	if (l->d_magic != BSD_DISKMAGIC) {		brelse(bh);		return;	}	p = &l->d_partitions[0];	while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) {		if ((current_minor & mask) >= (4 + hd->max_p))			break;		if (p->p_fstype != BSD_FS_UNUSED) {#ifdef MACH		  add_bsd_partition (hd, current_minor,				     p - &l->d_partitions[0] + 'a',				     p->p_offset, p->p_size);#else			add_partition(hd, current_minor, p->p_offset, p->p_size);#endif			current_minor++;		}		p++;	}	brelse(bh);}#endifstatic 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 CONFIG_BLK_DEV_IDEcheck_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(" <");#ifdef MACH			mach_minor = minor;#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -