📄 geometry.c
字号:
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 + -