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

📄 geometry.c

📁 linux 的引导程序源码The Microsoft&reg Windows&reg Software Development Kit (SDK) provides the documentation
💻 C
📖 第 1 页 / 共 2 页
字号:
		die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,		  strerror(errno));	    if (all && !hdprm.sectors)		die("HDIO_REQ not supported for your DAC960/IBM controller. "		  "Please use a DISK section");	    geo->heads = hdprm.heads;	    geo->cylinders = hdprm.cylinders;	    geo->sectors = hdprm.sectors;	    geo->start = hdprm.start;	    if ((geo->device = bios_device(geo, device)) < 0)		geo->device = 0x80 + last_dev(MAJOR_HD,64) + (MINOR(device) >> 3);	    break;	case MAJOR_AMI_HYP:	case MAJOR_HPT370:	case MAJOR_FL:	case MAJOR_NFTL:	case MAJOR_SMART2+0:	case MAJOR_SMART2+1:	case MAJOR_SMART2+2:	case MAJOR_SMART2+3:	case MAJOR_SMART2+4:	case MAJOR_SMART2+5:	case MAJOR_SMART2+6:	case MAJOR_SMART2+7:	case MAJOR_CISS+0:	case MAJOR_CISS+1:	case MAJOR_CISS+2:	case MAJOR_CISS+3:	case MAJOR_CISS+4:	case MAJOR_CISS+5:	case MAJOR_CISS+6:	case MAJOR_CISS+7:	case MAJOR_I2O:	case MAJOR_I2O+1:	case MAJOR_I2O+2:	case MAJOR_I2O+3:	case MAJOR_I2O+4:	case MAJOR_I2O+5:	case MAJOR_I2O+6:	case MAJOR_I2O+7:	    if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)		die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,		  strerror(errno));	    if (all && !hdprm.sectors)		die("HDIO_REQ not supported for your Array controller. Please "		  "use a DISK section");	    geo->heads = hdprm.heads;	    geo->cylinders = hdprm.cylinders;	    geo->sectors = hdprm.sectors;	    geo->start = hdprm.start;	    if ((geo->device = bios_device(geo, device)) < 0)		geo->device = 0x80 + last_dev(MAJOR_HD,64) + (MINOR(device) >> 4);	    break;	default:	    die("Sorry, don't know how to handle device 0x%04x",device);    }    if (get_all) dev_close(&dev);}int is_first(int device){    DT_ENTRY *walk;    for (walk = disktab; walk; walk = walk->next)	if (walk->device == device) break;    if (!walk && !old_disktab)	for (walk = disktab; walk; walk = walk->next)	    if (walk->device == (device & D_MASK(device))) break;    if (walk && !walk->heads)	die("Device 0x%04X: Configured as inaccessible.\n",device);    if (walk && walk->bios != -1) return !(walk->bios & 0x7f);    switch (MAJOR(device)) {	case MAJOR_FD:	    return !(device & 3);	case MAJOR_HD:	    return !(MINOR(device) >> 6);	case MAJOR_IDE2:	    /* fall through */	case MAJOR_IDE3:	    /* fall through */	case MAJOR_IDE4:	    /* fall through */	case MAJOR_IDE5:	    /* fall through */	case MAJOR_IDE6:	case MAJOR_IDE7:	case MAJOR_IDE8:	case MAJOR_IDE9:	case MAJOR_IDE10:	    /* fall through */	case MAJOR_ESDI:	    /* fall through */	case MAJOR_XT:	    /* fall through */	    return MINOR(device) >> 6 ? 0 : !last_dev(MAJOR_HD,64);	case MAJOR_SD:	case MAJOR_SD2:	case MAJOR_SD3:	case MAJOR_SD4:	case MAJOR_SD5:	case MAJOR_SD6:	case MAJOR_SD7:	case MAJOR_SD8:	case MAJOR_AMI_HYP:	case MAJOR_HPT370:	case MAJOR_FL:	case MAJOR_NFTL:	case MAJOR_SMART2+0:	case MAJOR_SMART2+1:	case MAJOR_SMART2+2:	case MAJOR_SMART2+3:	case MAJOR_SMART2+4:	case MAJOR_SMART2+5:	case MAJOR_SMART2+6:	case MAJOR_SMART2+7:	case MAJOR_CISS+0:	case MAJOR_CISS+1:	case MAJOR_CISS+2:	case MAJOR_CISS+3:	case MAJOR_CISS+4:	case MAJOR_CISS+5:	case MAJOR_CISS+6:	case MAJOR_CISS+7:	case MAJOR_I2O:	case MAJOR_I2O+1:	case MAJOR_I2O+2:	case MAJOR_I2O+3:	case MAJOR_I2O+4:	case MAJOR_I2O+5:	case MAJOR_I2O+6:	case MAJOR_I2O+7:	    return MINOR(device) >> 4 ? 0 : !last_dev(MAJOR_HD,64);	case MAJOR_DAC960:	case MAJOR_DAC960+1:	case MAJOR_DAC960+2:	case MAJOR_DAC960+3:	case MAJOR_DAC960+4:	case MAJOR_DAC960+5:	case MAJOR_DAC960+6:	case MAJOR_DAC960+7:	case MAJOR_IBM_iSER:	    return MINOR(device) >> 3 ? 0 : !last_dev(MAJOR_HD,64);	default:	    return 1; /* user knows what (s)he's doing ... I hope */    }}void geo_get(GEOMETRY *geo,int device,int user_device,int all){    DT_ENTRY *walk;    int inherited,keep_cyls;#ifdef LCF_LVM    /*     * Find underlying device (PV) for LVM.  It is OK if the underlying PV is     * really an MD RAID1 device, because the geometry of the RAID1 device is     * exactly the same as the underlying disk, so FIBMAP and LV_BMAP should     * return the correct block numbers regardless of MD.     *     * We do a quick test to see if the LVM LV_BMAP ioctl is working correctly.     * It should map the two blocks with the same difference as they were input,     * with a constant offset from their original block numbers.  If this is not     * the case then LV_BMAP is not working correctly (some widely distributed     * kernels did not have working LV_BMAP support, some just oops here).     */    if (MAJOR(device) == MAJOR_LVM)    {	struct lv_bmap lbmA, lbmB;#define DIFF 255	lbmA.lv_dev = lbmB.lv_dev = device;	lbmA.lv_block = 0;	lbmB.lv_block = DIFF;	lvm_bmap(&lbmA);	lvm_bmap(&lbmB);	if (lbmB.lv_block - lbmA.lv_block != DIFF)	    die("This version of LVM does not support boot LVs");	device = geo->base_dev = lbmA.lv_dev;    }#endif#ifdef LCF_EVMS    if (MAJOR(device) == MAJOR_EVMS) {        struct evms_get_bmap_t ebm;                ebm.rsector = 0;        ebm.dev = device;        ebm.status = 0;                evms_bmap(&ebm);                device = geo->base_dev = ebm.dev;    }#endif    /* Find underlying device for MD RAID */    if (MAJOR(device) == MD_MAJOR) {        char mdxxx[16];	int md_fd, pass;	md_array_info_t md_array_info;	md_disk_info_t md_disk_info;	int raid_limit;	sprintf(mdxxx, "/dev/md%d", MINOR(device));	if ((md_fd=open(mdxxx,O_NOACCESS)) < 0)	{	    sprintf(mdxxx, "/dev/md/%d", MINOR(device));	    if ((md_fd=open(mdxxx,O_NOACCESS)) < 0)		die("Unable to open %s", mdxxx);	}	if (ioctl(md_fd,GET_ARRAY_INFO,&md_array_info) < 0)	    die("Unable to get RAID info on %s", mdxxx);	if ((md_array_info.major_version == 0) && (md_array_info.minor_version < 90))	    die("Raid versions < 0.90 are not supported");	if (md_array_info.level != 1)	    die("Only RAID1 devices are supported for boot images");	raid_limit = md_array_info.raid_disks + md_array_info.spare_disks;   	for (pass = 0; pass < raid_limit; pass++) {	    md_disk_info.number = pass;	    if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0)	        die("GET_DISK_INFO: %s", mdxxx);	    if (!(md_disk_info.state & (1 << MD_DISK_FAULTY))) {	        device = (md_disk_info.major << 8) | md_disk_info.minor;		break;	    }	}	close(md_fd);    }    for (walk = disktab; walk; walk = walk->next)	if (walk->device == device) break;    inherited = !walk && !old_disktab;    if (inherited)	for (walk = disktab; walk; walk = walk->next)	    if (walk->device == (device & D_MASK(device))) break;/* add 'all' to conditional below -- JRC 2002-08-20 */    if (walk && !walk->heads && all)	die("Device 0x%04X: Configured as inaccessible.\n",device);    keep_cyls = !walk || walk->bios == -1 || walk->heads == -1 ||      walk->sectors == -1 || inherited || walk->start == -1;/* add 'all' to conditional below -- JRC 2002-08-20 */    if (keep_cyls && (all || MAJOR(device)==MAJOR_FD) ) {	geo_query_dev(geo,device,all);	if (!nowarn && (geo->device & 0x7f) >= bios_max_devs() &&	  user_device == -1 && (!walk || walk->bios == -1))	    fprintf(errstd,"Warning: BIOS drive 0x%02x may not be accessible\n",	      geo->device);    }    if (walk) {	if (walk->bios != -1) geo->device = walk->bios;	if (walk->heads != -1) geo->heads = walk->heads;	if (walk->cylinders != -1 || !keep_cyls)	    geo->cylinders = walk->cylinders;	if (walk->sectors != -1) geo->sectors = walk->sectors;	if (walk->start != -1 && !inherited) geo->start = walk->start;    }    if (user_device != -1) geo->device = user_device;    if (!all) {	if (verbose > 2)	    printf("Device 0x%04x: BIOS drive 0x%02x, no geometry.\n",device,	      geo->device);	return;    }    if (!geo->heads || !geo->cylinders || !geo->sectors)	die("Device 0x%04X: Got bad geometry %d/%d/%d\n",device,	  geo->sectors,geo->heads,geo->cylinders);    if (geo->heads > BIOS_MAX_HEADS)	die("Device 0x%04X: Maximum number of heads is %d, not %d\n",device,	  BIOS_MAX_HEADS,geo->heads);    if (geo->heads == BIOS_MAX_HEADS && !nowarn)	fprintf(errstd, "Warning: Maximum number of heads = %d (as specified)\n"			"   exceeds standard BIOS maximum of 255.\n", geo->heads);    if (geo->sectors > BIOS_MAX_SECS)	die("Device 0x%04X: Maximum number of sectors is %d, not %d\n",	  device,BIOS_MAX_SECS,geo->sectors);    if (!lba32 &&      (geo->start+geo->sectors-1)/geo->heads/geo->sectors >= BIOS_MAX_CYLS &&      !nowarn) {	fprintf(errstd,"Warning: device 0x%04x exceeds %d cylinder limit.\n"        "   Use of the 'lba32' option may help on newer (EDD BIOS) systems.\n",	  device,BIOS_MAX_CYLS);    }    if (verbose > 2) {	printf("Device 0x%04x: BIOS drive 0x%02x, %d heads, %d cylinders,\n",	  device,geo->device,geo->heads,geo->cylinders == -1 ? BIOS_MAX_CYLS :	  geo->cylinders);	printf("%15s%d sectors. Partition offset: %d sectors.\n","",	  geo->sectors,geo->start);    }}int geo_open(GEOMETRY *geo,char *name,int flags){    char *here;    int user_dev,block_size;    struct stat st;    if ((here = strrchr(name,':')) == NULL) user_dev = -1;    else {	fprintf(errstd,":BIOS syntax is no longer supported. Please use a "	  "DISK section\n");	*here++ = 0;	user_dev = to_number(here);    }    if ((geo->fd = open(name,flags)) < 0)	die("open %s: %s",name,strerror(errno));    if (fstat(geo->fd,&st) < 0) die("fstat %s: %s",name,strerror(errno));    if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))	die("%s: neither a reg. file nor a block dev.",name);    geo->dev = S_ISREG(st.st_mode) ? st.st_dev : st.st_rdev;    geo_get(geo, geo->dev, user_dev, 1);    geo->file = S_ISREG(st.st_mode) ? st.st_dev : 0;    geo->boot = 0;#ifndef FIGETBSZ    geo->spb = 2;#else    if (!geo->file) geo->spb = 2;    else {	if (ioctl(geo->fd,FIGETBSZ,&block_size) < 0) {	    fprintf(errstd,"FIGETBSZ %s: %s\n",name,strerror(errno));	    geo->spb = 2;	}	else {	    if (!block_size || (block_size & (SECTOR_SIZE-1)))		die("Incompatible block size: %d\n",block_size);	    geo->spb = block_size/SECTOR_SIZE;	}    }#endif    return geo->fd;}int geo_open_boot(GEOMETRY *geo,char *name){    struct stat st;    if (stat(name,&st) < 0) die("stat %s: %s",name,strerror(errno));    if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))	die("%s: neither a reg. file nor a block dev.",name);    geo->dev = S_ISREG(st.st_mode) ? st.st_dev : st.st_rdev;#if 0    if (MAJOR(geo->dev) == MAJOR_FD) geo->fd = 0;    else if ((geo->fd = open(name,O_NOACCESS)) < 0)	    die("open %s: %s",name,strerror(errno));#else    if (MAJOR(geo->dev) != MAJOR_FD) {	if ((P_MASK(geo->dev) & geo->dev) != 0)	    die("UNSAFE may be used with floppy or MBR only");    }    geo->fd = 0;#endif    geo_get(geo, geo->dev, -1, 0);    geo->file = S_ISREG(st.st_mode);    geo->boot = 1;    geo->spb = 1;    return geo->fd;}void geo_close(GEOMETRY *geo){    if (geo->fd) (void) close(geo->fd);}#ifndef FIBMAP#define FIBMAP BMAP_IOCTL#endifint geo_comp_addr(GEOMETRY *geo,int offset,SECTOR_ADDR *addr){    int block,sector;    static int warnings = 0;    if (linear && lba32)       die("'linear' and 'lba32' (-l and -L) are mutually exclusive.");    if (geo->boot && offset >= SECTOR_SIZE)	die("Internal error: sector > 0 after geo_open_boot");    block = offset/geo->spb/SECTOR_SIZE;    if (geo->file) {#ifdef LCF_REISERFS	    struct statfs buf;	    fstatfs(geo->fd, &buf);	    if (buf.f_type == REISERFS_SUPER_MAGIC) {		if (ioctl (geo->fd, REISERFS_IOC_UNPACK, 1) == ENOSPC)			die("Cannot unpack ReiserFS file");		if (verbose > 3) printf("fd %d: REISERFS_IOC_UNPACK\n", geo->fd);	    }#endif	if (ioctl(geo->fd,FIBMAP,&block) < 0) pdie("ioctl FIBMAP");	if (!block) {	    return 0;	}    }#ifdef LCF_LVM    if (MAJOR(geo->dev) == MAJOR_LVM) {	struct lv_bmap lbm;	lbm.lv_dev = geo->dev;	lbm.lv_block = block;	lvm_bmap(&lbm);	if (lbm.lv_dev != geo->base_dev)	    die("LVM boot LV cannot be on multiple PVs\n");	block = lbm.lv_block;    }#endif#ifdef LCF_EVMS    if (MAJOR(geo->dev) == MAJOR_EVMS) {        struct evms_get_bmap_t ebm;                                  ebm.rsector = block * geo->spb;        ebm.dev = geo->dev;        ebm.status = 0;                                    evms_bmap(&ebm);        if (ebm.dev != geo->base_dev)            die("EVMS boot volume cannot be on multiple disks.\n");        sector = ebm.rsector + ((offset/SECTOR_SIZE) % geo->spb) + geo->start;    }    else {        sector = block*geo->spb+((offset/SECTOR_SIZE) % geo->spb);        sector += geo->start;    }#else    sector = block*geo->spb+((offset/SECTOR_SIZE) % geo->spb);    sector += geo->start;#endif /*   Always use CHS addressing on floppies:     JRC   */    if ((geo->device & 0x80) && (linear || lba32)) {        addr->device = geo->device | (linear ? LINEAR_FLAG : (LBA32_FLAG|LBA32_NOCOUNT))       		| (do_md_install && geo->file==boot_dev_nr ? RAID_REL_FLAG : 0);        addr->num_sect = linear ? 1 : (sector >> 24);	addr->sector = sector & 0xff;	addr->track = (sector >> 8) & 0xff;	addr->head = sector >> 16;	if (linear) {	    int cyl = sector;	    if (geo->sectors>0 && geo->heads>0) {	    	cyl /= geo->sectors;	    	cyl /= geo->heads;	    	if (cyl >= BIOS_MAX_CYLS && !nowarn && warnings++ < 8) {		    fprintf(errstd,			"Warning:  LINEAR may generate cylinder# above 1023 at boot-time.\n");	    	}	    }            if (sector/(63*255) >= BIOS_MAX_CYLS)		die("Sector address %d too large for LINEAR"					" (try LBA32 instead).", sector);	}	if (verbose > 4)	    printf("fd %d: offset %d -> dev 0x%02x, %s %d\n",		         geo->fd, offset, addr->device,		         lba32 ? "LBA" : "linear",		         sector);    }    else {	addr->device = geo->device;	addr->sector = (sector % geo->sectors)+1;	sector /= geo->sectors;	addr->head = sector % geo->heads;	sector /= geo->heads;	if (sector >= BIOS_MAX_CYLS)	    die("geo_comp_addr: Cylinder number is too big (%d > %d)",sector,	      BIOS_MAX_CYLS-1);	if (sector >= geo->cylinders && geo->cylinders != -1)	    die("geo_comp_addr: Cylinder %d beyond end of media (%d)",sector,	      geo->cylinders);	if (verbose > 4)	    printf("fd %d: offset %d -> dev 0x%02x, head %d, track %d, sector %d\n",	      geo->fd,offset,addr->device,addr->head,sector,addr->sector);	addr->track = sector & 255;	addr->sector |= (sector >> 8) << 6;        addr->num_sect = 1;    }    return 1;}int geo_find(GEOMETRY *geo,SECTOR_ADDR addr){    SECTOR_ADDR here;    struct stat st;    int i;    if (fstat(geo->fd,&st) < 0) return 0;    geo_get(geo,st.st_dev,-1,1);    for (i = 0; i < (st.st_size+SECTOR_SIZE-1)/SECTOR_SIZE; i++)	if (geo_comp_addr(geo,i*SECTOR_SIZE,&here))	    if (here.sector == addr.sector && here.track == addr.track &&	      here.device == addr.device && here.head == addr.head) {		if (lseek(geo->fd,i*SECTOR_SIZE,0) < 0) return 0;		else return 1;	    }    return 1;}

⌨️ 快捷键说明

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