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

📄 geometry.c

📁 linux 的引导程序源码The Microsoft&reg Windows&reg Software Development Kit (SDK) provides the documentation
💻 C
📖 第 1 页 / 共 2 页
字号:
/* geometry.c  -  Device and file geometry computation *//*Copyright 1992-1998 Werner Almesberger.Copyright 1999-2001 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.*//* Patched for linux-2.4.0 - Glibc-2.2 by Sergey Ostrovsky 11/16/2000 */#include <unistd.h>#include <stdio.h>#include <fcntl.h>#include <errno.h>#include <sys/types.h>#ifdef LCF_REISERFS#include <sys/statfs.h>#ifdef	_SYS_STATFS_H#define	_I386_STATFS_H	/* two versions of statfs is not good ... */#endif#endif#include <linux/fs.h>#include <linux/hdreg.h>#include <linux/fd.h>#include <string.h>#include "config.h"#include "lilo.h"#include "common.h"#include "device.h"#include "geometry.h"#include "cfg.h"#include "md-int.h"#include "probe.h"#ifdef LCF_REISERFS#ifndef REISERFS_SUPER_MAGIC#define REISERFS_SUPER_MAGIC 0x52654973#endif#ifndef REISERFS_SUPER_MAGIC_STRING#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"#endif#ifndef REISERFS_IOC_UNPACK#define REISERFS_IOC_UNPACK		_IOW(0xCD,1,long)#endif#endif#ifdef LCF_LVMstruct lv_bmap {    __u32 lv_block;    __u16 lv_dev;};#ifndef LV_BMAP#define LV_BMAP				_IOWR(0xfe, 0x30, 1)#endif#ifndef LVM_GET_IOP_VERSION#define LVM_GET_IOP_VERSION		_IOR(0xfe, 0x98, 1)#endif#endif#ifdef LCF_EVMSstruct evms_get_bmap_t {    __u64 rsector;    __u32 dev;    int status;};struct evms_version_t {    __u32 major;    __u32 minor;    __u32 patch;};#ifndef EVMS_GET_BMAP#define EVMS_GET_BMAP		_IOWR(MAJOR_EVMS, 0xC7, struct evms_get_bmap_t)#endif#ifndef EVMS_GET_IOCTL_VERSION#define EVMS_GET_IOCTL_VERSION	_IOR(MAJOR_EVMS, 0x0, struct evms_version_t)#endif#endif#ifndef HDIO_GETGEO#define HDIO_GETGEO HDIO_REQ#endiftypedef struct _st_buf {    struct _st_buf *next;    struct stat st;} ST_BUF;DT_ENTRY *disktab = NULL;int old_disktab = 0;void geo_init(char *name){    FILE *file;    char line[MAX_LINE+1];    char *here;    DT_ENTRY *entry;    int disk_section,items;    if (name) {	if ((file = fopen(name,"r")) == NULL)	    die("open %s: %s",name,strerror(errno));    }    else if ((file = fopen(DFL_DISKTAB,"r")) == NULL) return;    disk_section = !!disktab;    while (fgets(line,MAX_LINE,file)) {	here = strchr(line,'\n');	if (here) *here = 0;	here = strchr(line,'#');	if (here) *here = 0;	if (strspn(line," \t") != strlen(line)) {	    entry = alloc_t(DT_ENTRY);	    items = sscanf(line,"0x%x 0x%x %d %d %d %d",&entry->device,	      &entry->bios,&entry->sectors,&entry->heads,&entry->cylinders,	      &entry->start);	    if (items == 5) entry->start = -1;	    if (items < 5)		die("Invalid line in %s:\n\"%s\"",name ? name : DFL_DISKTAB,		  line);	    entry->next = disktab;	    disktab = entry;	    if (disk_section) die("DISKTAB and DISK are mutually exclusive");	    old_disktab = 1;	}    }    (void) fclose(file);}void do_partition(void){    DT_ENTRY *entry,*walk;    struct stat st;    char *partition,*start;    entry = alloc_t(DT_ENTRY);    *entry = *disktab;    entry->start = -1;    partition = cfg_get_strg(cf_partitions,"partition");    if (stat(partition,&st) < 0) die("stat %s: %s",partition,strerror(errno));    if (!S_ISBLK(st.st_mode) || ((st.st_rdev ^ disktab->device) & D_MASK(st.st_rdev)))	die("%s is not a valid partition device",partition);    entry->device = st.st_rdev;    cfg_init(cf_partition);    (void) cfg_parse(cf_partition);    start = cfg_get_strg(cf_partition,"start");    entry->start = start ? to_number(start) : -1;    for (walk = disktab; walk; walk = walk->next)	if (entry->device == walk->device)	    die("Duplicate geometry definition for %s",partition);    entry->next = disktab;    disktab = entry;    cfg_init(cf_partitions);}int has_partitions(dev_t dev){    int major = MAJOR(dev);        if (      major == MAJOR_HD || major == MAJOR_IDE2 ||      major == MAJOR_IDE3 || major == MAJOR_IDE4 ||      major == MAJOR_IDE5 || major == MAJOR_IDE6 ||      (major >= MAJOR_IDE7 && major <= MAJOR_IDE10) ||      major == MAJOR_XT || major == MAJOR_ESDI      	) return 0xFFC0;          if (      major == MAJOR_SD || (major >= MAJOR_SD2 && major <= MAJOR_SD8) ||      major == MAJOR_AMI_HYP || major == MAJOR_HPT370 ||      major == MAJOR_FL || major == MAJOR_NFTL ||      (major >= MAJOR_I2O && major <= MAJOR_I2O+7) ||      (major >= MAJOR_SMART2 && major <= MAJOR_SMART2+7) ||      (major >= MAJOR_CISS && major <= MAJOR_CISS+7)        ) return 0xFFF0;	/* 4 bit partition mask */    if ( major == MAJOR_IBM_iSER ||      (major >= MAJOR_DAC960 && major <= MAJOR_DAC960+7)        )  return 0xFFF8;	/* 3 bit partition mask */    return 0;}void do_disk(void){    DT_ENTRY *entry,*walk;    struct stat st;    char *disk,*bios,*sectors,*heads,*cylinders;    entry = alloc_t(DT_ENTRY);    disk = cfg_get_strg(cf_options,"disk");    if (stat(disk,&st) < 0) die("stat %s: %s",disk,strerror(errno));    if (!S_ISBLK(st.st_mode) || ((MINOR(st.st_rdev) & P_MASK(st.st_rdev)) &&      has_partitions(st.st_rdev)))	die("RSN: %s is not a whole disk device",disk);    entry->device = st.st_rdev;    cfg_init(cf_disk);    (void) cfg_parse(cf_disk);    bios = cfg_get_strg(cf_disk,"bios");    sectors = cfg_get_strg(cf_disk,"sectors");    heads = cfg_get_strg(cf_disk,"heads");    cylinders = cfg_get_strg(cf_disk,"cylinders");    entry->bios = bios ? to_number(bios) : -1;    if (!sectors && !heads) entry->sectors = entry->heads = -1;    else if (!(sectors && heads))	    die("Must specify SECTORS and HEADS together");	else {	    entry->sectors = to_number(sectors);	    entry->heads = to_number(heads);	}    if (cfg_get_flag(cf_disk,"inaccessible")) {	entry->heads = 0;	if (#if 0		cfg_get_strg(cf_disk,"bios") || #endif		cfg_get_strg(cf_disk,"sectors") ||	  cfg_get_strg(cf_disk,"heads") || cfg_get_strg(cf_disk,"cylinders"))	    die("No geometry variables allowed if INACCESSIBLE");    }    entry->cylinders = cylinders ? to_number(cylinders) : -1;    entry->start = 0;    for (walk = disktab; walk; walk = walk->next)	if (entry->device == walk->device)	    die("Duplicate geometry definition for %s",disk);    entry->next = disktab;    disktab = entry;    cfg_init(cf_partitions);    (void) cfg_parse(cf_partitions);    cfg_unset(cf_options,"disk");}static int exists(const char *name){    struct hd_geometry dummy;    int fd,yes;    char buff;    if ((fd = open(name,O_RDWR)) < 0) return 0; /* was O_RDONLY */    yes = read(fd,&buff,1) == 1 && ioctl(fd,HDIO_GETGEO,&dummy) >= 0;    (void) close(fd);    return yes;}#if 0static int scan_last_dev(ST_BUF *next,char *parent,int major,int increment){    DIR *dp;    struct dirent *dir;    char name[PATH_MAX+1];    ST_BUF st,*walk;    int max,this;    st.next = next;    max = 0;    if ((dp = opendir(parent)) == NULL)	die("opendir %s: %s",parent,strerror(errno));    while ((dir = readdir(dp))) {	sprintf(name,"%s/%s",parent,dir->d_name);	if (stat(name,&st.st) >= 0) {	    if (S_ISBLK(st.st.st_mode) && MAJOR(st.st.st_rdev) == major &&	      (MINOR(st.st.st_rdev) & (increment-1)) == 0) {		this = MINOR(st.st.st_rdev)/increment+1;		if (this > max && exists(name)) max = this;	    }	    if (S_ISDIR(st.st.st_mode) && strcmp(dir->d_name,".") &&	      strcmp(dir->d_name,"..")) {		for (walk = next; walk; walk = walk->next)		    if (stat_equal(&walk->st,&st.st)) break;		if (!walk) {		    this = scan_last_dev(&st,name,major,increment);		    if (this > max) max = this;		}	    }	}    }    (void) closedir(dp);    return max;}#endifstatic int last_dev(int major,int increment){/* * In version 12 to 18, LILO only relied on scan_last_dev (or last_dev). This * obviously didn't work if entries in /dev were missing. Versions 18 and 19 * added the probe loop, which seems to be okay, but which may probe for * invalid minor numbers. The IDE driver objects to that. Since last_dev is * only used to count IDE drives anyway, we try now only the first two devices * and forget about scan_last_dev. */#if 0    DEVICE dev;    int minor;    for (minor = 0; dev_open(&dev,(major << 8) | minor,-1); minor += increment)	if (exists(dev.name)) dev_close(&dev);        else {	    dev_close(&dev);	    return minor/increment;	}    return scan_last_dev(NULL,DEV_DIR,major,increment);#else    DEVICE dev;    int devs;    for (devs = 0; devs < 2 && dev_open(&dev,(major << 8) | (increment*devs),      -1); devs++)	if (exists(dev.name)) dev_close(&dev);        else {	    dev_close(&dev);	    break;	}    return devs;#endif}#ifdef LCF_LVMvoid lvm_bmap(struct lv_bmap *lbm){    DEVICE dev;    static int lvmfd = -1;    static dev_t last_dev = 0;    if (lbm->lv_dev != last_dev) {	char lvm_char[] = "/dev/lvm";	unsigned short iop;	if (lvmfd != -1)	    close(lvmfd);	if ((lvmfd = open(lvm_char, lbm->lv_dev, O_RDONLY)) < 0)	    die("can't open LVM char device %s\n", lvm_char);	if (ioctl(lvmfd, LVM_GET_IOP_VERSION, &iop) < 0)	    die("LVM_GET_IOP_VERSION failed on %s\n", lvm_char);	if (iop < 10)	    die("LVM IOP %d not supported for booting\n", iop);	close(lvmfd);	lvmfd = dev_open(&dev, lbm->lv_dev, O_RDONLY);	if (lvmfd < 0)	    die("can't open LVM block device %#x\n", lbm->lv_dev);	last_dev = lbm->lv_dev;    }    if (ioctl(lvmfd, LV_BMAP, lbm) < 0) {	perror(__FUNCTION__);	pdie("LV_BMAP error or ioctl unsupported, can't have image in LVM.\n");    }}#endif#ifdef LCF_EVMSvoid evms_bmap(struct evms_get_bmap_t *ebm){                                      DEVICE dev;    static int evms_fd = -1;    static dev_t evms_last_dev = 0;    if (ebm->dev != evms_last_dev) {        char evms_blk[] = "/dev/evms/block_device";        struct evms_version_t evms_ver;        // Open the EVMS device        if (evms_fd != -1)            close(evms_fd);        evms_fd = open(evms_blk, O_RDONLY);        if (evms_fd < 0)            die("Can't open EVMS block device %s.\n", evms_blk);        // Get EVMS ioctl version number.        if (ioctl(evms_fd, EVMS_GET_IOCTL_VERSION, &evms_ver) < 0)            die("EVMS_GET_IOCTL_VERSION failed on %s.\n", evms_blk);        // Check that the ioctl version is >= 7.1.0        if (evms_ver.major < 7 ||            (evms_ver.major == 7 && evms_ver.minor < 1))            die("EVMS ioctl version %d.%d.%d does not support booting.\n",                evms_ver.major, evms_ver.minor, evms_ver.patch);        close(evms_fd);        evms_fd = dev_open(&dev, ebm->dev, O_RDONLY);        if (evms_fd < 0)            die("Can't open EVMS block device %#x\n", ebm->dev);        evms_last_dev = ebm->dev;    }    if (ioctl(evms_fd, EVMS_GET_BMAP, ebm) < 0) {        perror(__FUNCTION__);        pdie("EVMS_GET_BMAP error or ioctl unsupported. Can't have image on EVMS volume.\n");    }}#endifstatic void geo_query_dev(GEOMETRY *geo,int device,int all){    DEVICE dev;    int fd,get_all;    struct floppy_struct fdprm;    struct hd_geometry hdprm;    get_all = all || MAJOR(device) != MAJOR_FD;    if (!MAJOR(device))	die("Trying to map files from unnamed device 0x%04x (NFS ?)",device);    if (device == MAJMIN_RAM)	die("Trying to map files from your RAM disk. "	  "Please check -r option or ROOT environment variable.");    if (get_all) fd = dev_open(&dev,device,O_NOACCESS);    else fd = -1; /* pacify GCC */    switch (MAJOR(device)) {	case MAJOR_FD:	    geo->device = device & 3;	    if (!get_all) {		geo->heads = geo->cylinders = geo->sectors = 1;		geo->start = 0;		break;	    }	    if (ioctl(fd,FDGETPRM,&fdprm) < 0)		die("geo_query_dev FDGETPRM (dev 0x%04x): %s",device,		  strerror(errno));	    geo->heads = fdprm.head;	    geo->cylinders = fdprm.track;	    geo->sectors = fdprm.sect;	    geo->start = 0;	    break;	case MAJOR_HD:	    /* fall through */	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 */	    if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)		die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,		  strerror(errno));	    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 + (MINOR(device) >> 6) +		    (MAJOR(device) == MAJOR_HD ? 0 : last_dev(MAJOR_HD,64));	    break;	case MAJOR_SD:	case MAJOR_SD2:	case MAJOR_SD3:	case MAJOR_SD4:	case MAJOR_SD5:	case MAJOR_SD6:	case MAJOR_SD7:	case MAJOR_SD8:	    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 SCSI 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;	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:	    if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)

⌨️ 快捷键说明

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