geometry.c
来自「LINUX lilo-22.7.1 源代码。」· C语言 代码 · 共 1,339 行 · 第 1/3 页
C
1,339 行
#if BETA_TEST if (verbose>=5) printf("geo_get(2): device=%04X, all=%d\n", device, all);#endif/* if using hard disk, scan the devices in /proc/partitions */ if (has_partitions(device) && all) pf_hard_disk_scan(); for (walk = disktab; walk; walk = walk->next) if (walk->device == device) break; inherited = !walk && !old_disktab;#if BETA_TEST if (verbose>=5) printf("inherited=%d\n", inherited);#endif if (inherited) for (walk = disktab; walk; walk = walk->next) if (walk->device == (device & D_MASK(device))) break;#if BETA_TEST if (verbose>=5) printf("walk=%08lx\n", (long)walk);#endif#if 1/* add 'all' to conditional below -- JRC 2002-08-20 */ if (walk && !walk->heads && all)#else/* Werner's original conditional */ if (walk && !walk->heads)#endif 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;#if BETA_TEST if (verbose>=5) printf("inherited=%d keep_cyls=%d\n", inherited, keep_cyls);#endif#if 1/* add 'all' to conditional below -- JRC 2002-08-20 */ if (keep_cyls && (all || MAJOR(device)==MAJOR_FD) ) {#else/* Werner's original conditional */ if (keep_cyls) {#endif geo_query_dev(geo,device,all); if (all) bios_device(geo, device); 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 >= 3) { 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); } geo->raid = is_raid;/* make the serial number association */ if (!is_raid) register_bios(geo->device, device); else geo->device = md_bios; /* 22.5.7 add this else */ return;} /* end of geo_get */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;#if BETA_TEST if (verbose>=4) { printf("geo_open: (%s) st_dev(file)=%04X st_rdev(blk)=%04X\n", name, (int)st.st_dev, (int)st.st_rdev ); }#endif 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 (verbose>=5) printf("geo_open_boot: %s\n", name); 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 1 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->raid = 0; geo->boot = 1; geo->spb = 1; return geo->fd;}void geo_close(GEOMETRY *geo){ if (geo->fd) (void) close(geo->fd); geo->fd = 0;}#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 BETA_TEST if (verbose>=6) printf("geo_comp_addr: dev = %x, offset=%d\n", geo->device, offset);#endif#if 0 if (linear && lba32) die("'linear' and 'lba32' (-l and -L) are mutually exclusive.");#endif 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); } /* Forcing reiser4 to perform tail2extent converstion */ if (buf.f_type == REISER4_SUPER_MAGIC) { if (ioctl (geo->fd, REISER4_IOC_UNPACK, 1) != 0) die("Cannot unpack Reiser4 file"); if (verbose > 3) printf("fd %d: REISER4_IOC_UNPACK\n", geo->fd); /* As we may have the situation when extent will be included into transaction, and its item(s) will not be have the real block numbers assigned, we should perform fsync() in order to guarantee, that current atom is flushed and real block numbers assigned to the extent(s) file was converted in. */ if (fdatasync(geo->fd) != 0) die("Cannot perform fdatasync"); if (verbose > 3) printf("fd %d: fdatasync()\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 /* DON'T always use CHS addressing on floppies: JRC *//* if ((geo->device & 0x80) && (linear || lba32)) { */ if ((linear || lba32)) { addr->device = geo->device | (linear ? LINEAR_FLAG : (LBA32_FLAG|LBA32_NOCOUNT))#if 0 | (do_md_install && geo->file==boot_dev_nr ? RAID_REL_FLAG : 0);#else | (do_md_install && geo->raid ? RAID_REL_FLAG : 0);#endif 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 = 1; addr->head = 0; if (sector) { if (geo->heads == 0) die("BIOS device 0x%02x is inaccessible", 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 DEBUG_NEW if (verbose>=2) { printf("Find: AL=%02x CX=%04x DX=%04x LBA=%d\n", (int)addr.num_sect, addr.sector + (addr.track<<8), addr.device + (addr.head<<8), addr.sector + (addr.track<<8) + (addr.head<<16) + (addr.device&(LBA32_FLAG|LBA32_NOCOUNT)?addr.num_sect<<24:0) ); }#endif 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 && here.num_sect == addr.num_sect ) { if (lseek(geo->fd,i*SECTOR_SIZE,SEEK_SET) < 0) return 0; else return 1; } return 1;}#if 0int geo_devscan(int device){ DT_ENTRY *walk; unsigned int mask, codes = 0; int bios; int maxbios = 0; device &= D_MASK(device);/* mark those BIOS codes that are already used */ for (walk=disktab; walk; walk=walk->next) { if (has_partitions(walk->device) && walk->bios != -1) { bios = walk->bios & 0x7F; if (bios >= 4*sizeof(codes) ) die("BIOS code %02X is too big (device %04X)", bios, device); codes |= 1 << bios; } } bios = -1;/* extract BIOS code of master device, or -1 */ for (walk=disktab; walk; walk=walk->next) { if (device == walk->device) { bios = walk->bios; } } if (bios > maxbios) maxbios = bios;/* if device has no BIOS code assigned, assign the next one */ if (bios == -1) for (bios=0x80, mask=1; mask; mask<<=1, bios++) if (!(mask&codes)) break; if (bios > DEV_MASK) die("geo_devscan: ran out of device codes"); for (walk=disktab; walk; walk=walk->next) { if (device == walk->device) { if (walk->bios == -1) walk->bios = bios; else bios = walk->bios; break; } } if (bios > maxbios) maxbios = bios; if (verbose >= 2) printf("geo_devscan: maxbios = %02X\n", maxbios); if (walk) return maxbios; /* there was an entry in the disktab */ walk = alloc_t(DT_ENTRY); walk->device = device; walk->bios = bios; walk->sectors = walk->heads = walk->cylinders = walk->start = -1; walk->next = disktab; disktab = walk; if (verbose>=2) printf("geo_devscan: arbitrary bios assignment dev=%04X bios=0x%02X\n", device, bios); for (walk=disktab; walk; walk=walk->next) { if (device == (walk->device & D_MASK(walk->device))) { if (walk->bios != -1) walk->bios = bios; } } return maxbios;}#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?