Add externs to avoid multiple definitions, and then add missing definitions.
[rrq/maintain_lilo.git] / src / geometry.c
1 /* geometry.c  -  Device and file geometry computation
2  * 
3  * Copyright 1992-1998 Werner Almesberger
4  * Copyright 1999-2005 John Coffman
5  * Copyright 2009-2015 Joachim Wiedorn
6  * All rights reserved.
7  * 
8  * Licensed under the terms contained in the file 'COPYING'
9  * in the source directory.
10  */
11
12 #define _GNU_SOURCE
13 #include <unistd.h>
14 #include <stdio.h>
15 #include <fcntl.h>
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <limits.h>
19 #include <ctype.h>
20 #include <sys/types.h>
21
22 #ifdef LCF_REISERFS
23 #include <sys/statfs.h>
24
25 #ifdef  _SYS_STATFS_H
26 #define _I386_STATFS_H  /* two versions of statfs is not good ... */
27 #endif
28 #endif
29
30 #include <string.h>
31
32
33 #include "config.h"
34 #ifdef LCF_DEVMAPPER
35 # include <libdevmapper.h>
36 #endif
37 #include "lilo.h"
38 #include "common.h"
39 #include "device.h"
40 #include "raid.h"
41 #include "geometry.h"
42 #include "cfg.h"
43 #include "md-int.h"
44 #include "probe.h"
45
46 #ifdef LCF_REISERFS
47 #ifndef REISERFS_SUPER_MAGIC
48 #define REISERFS_SUPER_MAGIC 0x52654973
49 #endif
50
51 #if 0
52 #ifndef REISERFS_SUPER_MAGIC_STRING
53 #define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
54 #endif
55 #endif
56
57 #ifndef REISERFS_IOC_UNPACK
58 #define REISERFS_IOC_UNPACK             _IOW(0xCD,1,int32_t)
59 #endif
60
61 #ifndef REISER4_SUPER_MAGIC
62 #define REISER4_SUPER_MAGIC  0x52345362
63  /* (*(__u32 *)"R4Sb"); */
64 #endif
65 #ifndef REISER4_IOC_UNPACK
66 #define REISER4_IOC_UNPACK      _IOW(0xCD,1,int32_t)
67 #endif
68 #endif
69
70 #ifdef LCF_DEVMAPPER
71 typedef struct _dm_target {
72     struct _dm_target *next;
73     uint64_t start,length,offset;
74     int device;
75 } DM_TARGET;
76
77 typedef struct _dm_table {
78     struct _dm_table *next;
79     int device;
80     struct _dm_target *target;
81 } DM_TABLE;
82
83 DM_TABLE *dmtab = NULL;
84 int dm_version_nr = 0;
85 #endif
86
87 int dm_major_list[16];
88 int dm_major_nr;
89
90 #ifdef LCF_LVM
91 struct lv_bmap {
92     __u32 lv_block;
93     dev_t lv_dev;                       /* was __u16, which is wrong */
94 };
95
96 #ifndef LV_BMAP
97 /*      Should the definition be:                                       */
98 #define LV_BMAP                         _IOWR(0xfe, 0x30, int)
99 /*      As defined in the 2.4 kernels:                                  */
100 /*#define LV_BMAP                               _IOWR(0xfe, 0x30, 1)  */
101 #endif
102 #ifndef LVM_GET_IOP_VERSION
103 /*      Should the definition be:                                       */
104 #define LVM_GET_IOP_VERSION             _IOR(0xfe, 0x98, unsigned short)
105 /*      As defined in the 2.4 kernels:                                  */
106 /*#define LVM_GET_IOP_VERSION           _IOR(0xfe, 0x98, 1) */
107 #endif
108 #endif
109
110 #ifdef LCF_EVMS
111 struct evms_get_bmap_t {
112     __u64 rsector;
113     __u32 dev;
114     int status;
115 };
116
117 struct evms_version_t {
118     __u32 major;
119     __u32 minor;
120     __u32 patch;
121 };
122
123 #ifndef EVMS_GET_BMAP
124 #define EVMS_GET_BMAP           _IOWR(MAJOR_EVMS, 0xC7, struct evms_get_bmap_t)
125 #endif
126 #ifndef EVMS_GET_IOCTL_VERSION
127 #define EVMS_GET_IOCTL_VERSION  _IOR(MAJOR_EVMS, 0x0, struct evms_version_t)
128 #endif
129 #endif
130
131 #ifndef HDIO_GETGEO
132 #define HDIO_GETGEO HDIO_REQ
133 #endif
134
135
136 typedef struct _st_buf {
137     struct _st_buf *next;
138     struct stat st;
139 } ST_BUF;
140
141
142 DT_ENTRY *disktab = NULL;
143 int old_disktab = 0;
144
145
146 void geo_init(char *name)
147 {
148     FILE *file = NULL;
149     char line[MAX_LINE+1];
150 #ifdef LCF_DEVMAPPER
151     struct dm_task *dmt;
152     char dm_version[32];
153 #endif
154     char major_name[32];
155     int major;
156     char *here;
157     DT_ENTRY *entry;
158     int disk_section,items;
159
160     if (name) {
161         if ((file = fopen(name,"r")) == NULL)
162             die("open %s: %s",name,strerror(errno));
163     }
164     if (name || (file = fopen(DFL_DISKTAB,"r")) != NULL) {
165         disk_section = !!disktab;
166         while (fgets(line,MAX_LINE,file)) {
167             here = strchr(line,'\n');
168             if (here) *here = 0;
169             here = strchr(line,'#');
170             if (here) *here = 0;
171             if (strspn(line," \t") != strlen(line)) {
172                 entry = alloc_t(DT_ENTRY);
173                 items = sscanf(line,"0x%x 0x%x %d %d %d %d",&entry->device,
174                   (unsigned int*)&entry->bios,&entry->sectors,&entry->heads,&entry->cylinders,
175                   &entry->start);
176                 if (items == 5) entry->start = -1;
177                 if (items < 5)
178                     die("Invalid line in %s:\n\"%s\"",name ? name : DFL_DISKTAB,
179                       line);
180                 entry->next = disktab;
181                 disktab = entry;
182                 if (disk_section) die("DISKTAB and DISK are mutually exclusive");
183                 old_disktab = 1;
184             }
185         }
186         (void) fclose(file);
187     }
188
189     dm_major_nr = 0;
190     file = fopen("/proc/devices", "r");
191     if (!file) return;
192
193     do {
194         if (!fgets(line, (sizeof line)-1, file)) {
195             (void) fclose(file);
196             return;
197         }
198         line[(sizeof line)-1] = 0;
199     } while(strncmp(line, "Block", 5) != 0);
200
201     while(fgets(line, (sizeof line)-1, file)) {
202         if (sscanf(line, "%d %31s\n", &major, major_name) != 2) continue;
203         if (strcmp(major_name, "device-mapper") != 0) continue;
204         dm_major_list[dm_major_nr] = major;
205         if (verbose >= 3) {
206             printf("device-mapper major = %d\n", major);
207         }
208         if (++dm_major_nr > nelem(dm_major_list) ) break;
209     }
210
211     (void) fclose(file);
212
213
214 #ifdef LCF_DEVMAPPER
215     /* Suppress error message if the device doesn't exist. It is ugly */
216     struct stat fs;
217
218     if (stat ("/dev/mapper/control", &fs))
219         return;
220
221     if (!(dmt = dm_task_create(DM_DEVICE_VERSION)))
222         return;
223     if (!dm_task_run(dmt))
224         return;
225     if (!dm_task_get_driver_version(dmt, dm_version, sizeof dm_version))
226         return;
227
228     /*
229      * to not confuse returned device number formats %02x:%02x and %d:%d
230      * we assume here that the %02x:%02x format is only found in the ioctl
231      * interface version < 4 (this is really getting ugly...)
232      */
233     dm_version_nr = atoi(dm_version);
234
235     dm_task_destroy(dmt);
236 #endif
237 }
238
239
240 int is_dm_major(int major)
241 {
242     int i;
243     
244     for(i=0; i<dm_major_nr; i++) {
245         if (dm_major_list[i] == major) return 1;
246     }
247     return 0;
248 }
249
250
251
252 void do_partition(void)
253 {
254     DT_ENTRY *entry,*walk;
255     struct stat st;
256     char *partition,*start;
257
258     entry = alloc_t(DT_ENTRY);
259     *entry = *disktab;
260     entry->start = -1;
261     partition = cfg_get_strg(cf_partitions,"partition");
262     if (stat(partition,&st) < 0) die("stat %s: %s",partition,strerror(errno));
263     if (!S_ISBLK(st.st_mode) || ((st.st_rdev ^ disktab->device) & D_MASK(st.st_rdev)))
264         die("%s is not a valid partition device",partition);
265     entry->device = st.st_rdev;
266     cfg_init(cf_partition);
267     (void) cfg_parse(cf_partition);
268     start = cfg_get_strg(cf_partition,"start");
269     entry->start = start ? to_number(start) : -1;
270     for (walk = disktab; walk; walk = walk->next)
271         if (entry->device == walk->device)
272             die("Duplicate geometry definition for %s",partition);
273     entry->next = disktab;
274     disktab = entry;
275     cfg_init(cf_partitions);
276 }
277
278 #if BETA_TEST
279 int has_partitions_beta(dev_t dev)
280 {
281     int major = MAJOR(dev);
282     
283     if  (
284         major == MAJOR_IDE  ||
285         major == MAJOR_IDE2 ||
286         major == MAJOR_IDE3 ||
287         major == MAJOR_IDE4 ||
288         major == MAJOR_IDE5 ||
289         major == MAJOR_IDE6 ||
290         major == MAJOR_EMD  ||
291         (major >= MAJOR_IDE7 && major <= MAJOR_IDE10) ||
292         major == MAJOR_XT   ||
293         major == MAJOR_ESDI ||
294         major == MAJOR_ACORN
295         ) return 0xFFFFFFC0;    /* 6 bit partition mask */
296       
297     if  (
298         major == MAJOR_CARM1 ||
299         major == MAJOR_CARM2
300         )  return 0xFFFFFFE0;   /* 5 bit partition mask */
301
302     if  (
303         major == MAJOR_SD   ||
304         (major >= MAJOR_SD2 && major <= MAJOR_SD8) ||
305         (major >= MAJOR_SD9 && major <= MAJOR_SD16) ||
306         major == MAJOR_AMI  ||
307         major == MAJOR_HPT370 ||
308         (major >= MAJOR_EXPR && major <= MAJOR_EXPR4) ||
309         (major >= MAJOR_EXPR5 && major <= MAJOR_EXPR12) ||
310         (major >= MAJOR_I2O && major <= MAJOR_I2O7) ||
311         (major >= MAJOR_SMART && major <= MAJOR_SMART8) ||
312         (major >= MAJOR_CISS && major <= MAJOR_CISS8) ||
313         major == MAJOR_FTL  ||
314         major == MAJOR_NFTL ||
315         major == MAJOR_DOC  ||
316         major == MAJOR_PP   ||
317         major == MAJOR_PPCD ||
318         major == MAJOR_PPFD ||
319         (major >= MAJOR_SATA1 && major <= MAJOR_SATA2)
320         ) return 0xFFFFFFF0;    /* 4 bit partition mask */
321
322     if  (
323         major == MAJOR_IBM_ISER ||
324         (major >= MAJOR_DAC && major <= MAJOR_DAC8) ||
325         (major >= MAJOR_DAC9 && major <= MAJOR_DAC16)
326         )  return 0xFFFFFFF8;   /* 3 bit partition mask */
327
328     return 0;
329 }
330 #endif
331
332 static
333 unsigned char max_partno[512] = {
334 /*
335   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
336 */
337   0,  0,  0, 63,  0,  0,  0,  0, 15,  0,  0,  0,  0, 63,  0,  0,   /*  0x   */
338   0,  0,  0,  0,  0, 63, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,
339   0, 63, 63,  0, 63,  0,  0,  0,  0,  0,  0,  0, 15,  0,  0,  0,
340 #ifndef MAJOR_IDE5
341   7,  7,  7,  7,  7,  7,  7,  7,  0, 63,  0,  0, 15, 15, 15, 15,
342 #else
343   7,  7,  7,  7,  7,  7,  7,  7, 63, 63,  0,  0, 15, 15, 15, 15,
344 #endif
345
346   0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,   /*  4x   */
347  15, 15, 15, 15, 15, 15, 15, 15, 63, 63, 63, 63,  0, 15,  0,  0,
348   0,  0,  0,  0, 15, 15,  0,  0, 15, 15, 15, 15, 15, 15, 15, 15,
349   7,  0, 15,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
350 /*
351   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
352 */
353  15, 15, 15, 15, 15, 15, 15, 15,  7,  7,  7,  7,  7,  7,  7,  7,   /*  8x   */
354   0,  0,  0,  0,  0,  0,  0,  0,  0, 63,  0,  0,  0,  0,  0,  0,
355  31, 31,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
356   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
357
358   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   /*  Cx   */
359   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
360   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
361   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
362 /*                                                                 
363   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
364 */
365 };
366
367 int has_partitions(dev_t dev)
368 {
369    int major = MAJOR(dev);
370    int ret=0;
371    
372    if (major >= nelem(max_partno)) {
373         warn("Major Device (%d) > %d",
374                 major, nelem(max_partno)-1);
375    }
376    else if ( (ret=max_partno[major]) )  ret ^= 0xFFFFFFFF;
377    
378    return ret;
379 }
380
381
382 void do_disk(void)
383 {
384     DT_ENTRY *entry,*walk;
385     struct stat st;
386     char *disk,*bios,*sectors,*heads,*cylinders,*maxpart;
387     int major;
388
389     disk = cfg_get_strg(cf_options,"disk");
390     cfg_init(cf_disk);
391     (void) cfg_parse(cf_disk);
392     if (stat(disk,&st) < 0) {
393         if (cfg_get_flag(cf_disk,"inaccessible")) {
394             cfg_unset(cf_options,"disk");
395             return;
396         }
397         die("do_disk: stat %s: %s",disk,strerror(errno));
398     }
399     if (!S_ISBLK(st.st_mode) || 
400         (has_partitions(st.st_rdev) && (MINOR(st.st_rdev) & P_MASK(st.st_rdev))))
401                 die(" '%s' is not a whole disk device",disk);
402
403     entry = alloc_t(DT_ENTRY);
404     entry->device = st.st_rdev;
405     major = MAJOR(st.st_rdev);
406     bios = cfg_get_strg(cf_disk,"bios");
407     sectors = cfg_get_strg(cf_disk,"sectors");
408     heads = cfg_get_strg(cf_disk,"heads");
409     cylinders = cfg_get_strg(cf_disk,"cylinders");
410     maxpart = cfg_get_strg(cf_disk,"max-partitions");
411     if (maxpart) {
412       if (major<nelem(max_partno)) {
413         int i = to_number(maxpart);
414           if (max_partno[major] && max_partno[major]!=i) die("Cannot alter 'max-partitions' for known disk  %s", disk);
415           max_partno[major] = i;
416           if (i!=7 && i!=15 && i!=31 && i!=63 && i!=128) die("disk=%s:  illegal value for max-partitions(%d)", disk, i);
417       }
418       else {
419         die("Implementation restriction: max-partitions on major device > %d", (int)nelem(max_partno)-1);
420       }
421     }
422     entry->bios = bios ? to_number(bios) : -1;
423     if (!sectors && !heads) entry->sectors = entry->heads = -1;
424     else if (!(sectors && heads))
425             die("Must specify SECTORS and HEADS together");
426         else {
427             entry->sectors = to_number(sectors);
428             entry->heads = to_number(heads);
429         }
430     if (cfg_get_flag(cf_disk,"inaccessible")) {
431         entry->heads = 0;
432         if (bios) die("INACCESSIBLE and BIOS are mutually exclusive");
433         if ( sectors || heads || cylinders )
434             die("No geometry variables allowed if INACCESSIBLE");
435     }
436     entry->cylinders = cylinders ? to_number(cylinders) : -1;
437     entry->start = 0;
438     for (walk = disktab; walk; walk = walk->next) {
439         if (entry->device == walk->device)
440             die("Duplicate \"disk =\" definition for %s",disk);
441     }
442     entry->next = disktab;
443     disktab = entry;
444     if (verbose >= 6) {
445         printf("do_disk: %s %04X 0x%02X  %d:%d:%d\n",
446                 disk, entry->device, entry->bios, entry->cylinders,
447                 entry->heads, entry->sectors);
448     }
449     cfg_init(cf_partitions);
450     (void) cfg_parse(cf_partitions);
451     cfg_unset(cf_options,"disk");
452 }
453
454
455 static int exists(const char *name)
456 {
457     struct hd_geometry dummy;
458     int fd,yes;
459     char buff;
460
461     if ((fd = open(name,O_RDWR)) < 0) return 0; /* was O_RDONLY */
462     yes = read(fd,&buff,1) == 1 && ioctl(fd,HDIO_GETGEO,&dummy) >= 0;
463     (void) close(fd);
464     return yes;
465 }
466
467
468 #if 0
469
470 static int scan_last_dev(ST_BUF *next,char *parent,int major,int increment)
471 {
472     DIR *dp;
473     struct dirent *dir;
474     char name[PATH_MAX+1];
475     ST_BUF st,*walk;
476     int max,this;
477
478     st.next = next;
479     max = 0;
480     if ((dp = opendir(parent)) == NULL)
481         die("opendir %s: %s",parent,strerror(errno));
482     while ((dir = readdir(dp))) {
483         sprintf(name,"%s/%s",parent,dir->d_name);
484         if (stat(name,&st.st) >= 0) {
485             if (S_ISBLK(st.st.st_mode) && MAJOR(st.st.st_rdev) == major &&
486               (MINOR(st.st.st_rdev) & (increment-1)) == 0) {
487                 this = MINOR(st.st.st_rdev)/increment+1;
488                 if (this > max && exists(name)) max = this;
489             }
490             if (S_ISDIR(st.st.st_mode) && strcmp(dir->d_name,".") &&
491               strcmp(dir->d_name,"..")) {
492                 for (walk = next; walk; walk = walk->next)
493                     if (stat_equal(&walk->st,&st.st)) break;
494                 if (!walk) {
495                     this = scan_last_dev(&st,name,major,increment);
496                     if (this > max) max = this;
497                 }
498             }
499         }
500     }
501     (void) closedir(dp);
502     return max;
503 }
504
505 #endif
506
507
508 static int last_dev(int major,int increment)
509 {
510 /*
511  * Since last_dev is only used to count IDE drives anyway, we try 
512  * now only the first two devices and forget about scan_last_dev.
513  */
514     DEVICE dev;
515     int devs;
516     static int cached_major=-1, cached_increment=-1, cached_result=-1;
517     if(major == cached_major && increment == cached_increment)
518         return cached_result;
519     cached_major = major;
520     cached_increment = increment;
521
522
523     for (devs = 0;
524         devs < 2 && dev_open(&dev,MKDEV(major,increment*devs),O_BYPASS);
525             devs++)
526         if (exists(dev.name)) dev_close(&dev);
527         else {
528             dev_close(&dev);
529             break;
530         }
531     cached_result = devs;
532     return devs;
533 }
534
535
536 #ifdef LCF_LVM
537 void lvm_bmap(struct lv_bmap *lbm)
538 {
539     DEVICE dev;
540     static int lvmfd = -1;
541     static dev_t last_dev = 0;
542
543     if (lbm->lv_dev != last_dev) {
544         char lvm_char[] = DEV_DIR "/lvm";
545         unsigned short iop;
546
547         if (lvmfd != -1)
548             close(lvmfd);
549
550         if ((lvmfd = open(lvm_char, lbm->lv_dev, O_RDONLY)) < 0)
551             die("can't open LVM char device %s\n", lvm_char);
552
553         if (ioctl(lvmfd, LVM_GET_IOP_VERSION, &iop) < 0)
554             die("LVM_GET_IOP_VERSION failed on %s\n", lvm_char);
555
556         if (iop < 10)
557             die("LVM IOP %d not supported for booting\n", iop);
558         close(lvmfd);
559
560         lvmfd = dev_open(&dev, lbm->lv_dev, O_RDONLY);
561         if (lvmfd < 0)
562             die("can't open LVM block device %#x\n", (int)lbm->lv_dev);
563         last_dev = lbm->lv_dev;
564     }
565     if (ioctl(lvmfd, LV_BMAP, lbm) < 0) {
566         perror(__FUNCTION__);
567         pdie("LV_BMAP error or ioctl unsupported, can't have image in LVM.\n");
568     }
569 }
570 #endif
571
572
573 #ifdef LCF_EVMS
574 void evms_bmap(struct evms_get_bmap_t *ebm)
575 {                                  
576     DEVICE dev;
577     static int evms_fd = -1;
578     static dev_t evms_last_dev = 0;
579
580     if (ebm->dev != evms_last_dev) {
581         char evms_blk[] = DEV_DIR "/evms/block_device";
582         struct evms_version_t evms_ver;
583
584         /* Open the EVMS device */
585         if (evms_fd != -1)
586             close(evms_fd);
587
588         evms_fd = open(evms_blk, O_RDONLY);
589         if (evms_fd < 0)
590             die("Can't open EVMS block device %s.\n", evms_blk);
591
592         /* Get EVMS ioctl version number. */
593         if (ioctl(evms_fd, EVMS_GET_IOCTL_VERSION, &evms_ver) < 0)
594             die("EVMS_GET_IOCTL_VERSION failed on %s.\n", evms_blk);
595
596         /* Check that the ioctl version is >= 7.1.0 */
597         if (evms_ver.major < 7 ||
598             (evms_ver.major == 7 && evms_ver.minor < 1))
599             die("EVMS ioctl version %d.%d.%d does not support booting.\n",
600                 evms_ver.major, evms_ver.minor, evms_ver.patch);
601         close(evms_fd);
602
603         evms_fd = dev_open(&dev, ebm->dev, O_RDONLY);
604         if (evms_fd < 0)
605             die("Can't open EVMS block device %#x\n", ebm->dev);
606         evms_last_dev = ebm->dev;
607     }
608
609     if (ioctl(evms_fd, EVMS_GET_BMAP, ebm) < 0) {
610         perror(__FUNCTION__);
611         pdie("EVMS_GET_BMAP error or ioctl unsupported. Can't have image on EVMS volume.\n");
612     }
613 }
614 #endif
615
616
617 void geo_query_dev(GEOMETRY *geo,int device,int all)
618 {
619     DEVICE dev;
620     int fd,get_all,major;
621     struct floppy_struct fdprm;
622     struct hd_geometry hdprm;
623
624     if (verbose>=5) printf("geo_query_dev: device=%04X\n", device);
625     /* simplified condition -- JRC 2003-06-04 */
626     get_all = all;
627
628     if (!MAJOR(device))
629         die("Trying to map files from unnamed device 0x%04x (NFS/RAID mirror down ?)",device);
630     if (device == MAJMIN_RAM)
631         die("Trying to map files from your RAM disk. "
632           "Please check -r option or ROOT environment variable.");
633     if (get_all) {
634         fd = dev_open(&dev,device,O_NOACCESS);
635     }
636     else {
637         fd = -1; /* pacify GCC */
638         geo->heads = geo->cylinders = geo->sectors = 1;
639         geo->start = 0;
640         geo->device = -1;
641     }
642     switch ((major=MAJOR(device))) {
643         case MAJOR_FD:
644             geo->device = device & 3;
645             if (!get_all) break;
646             if (ioctl(fd,FDGETPRM,&fdprm) < 0)
647                 die("geo_query_dev FDGETPRM (dev 0x%04x): %s",device,
648                   strerror(errno));
649             geo->heads = fdprm.head;
650             geo->cylinders = fdprm.track;
651             geo->sectors = fdprm.sect;
652             geo->start = 0;
653             break;
654         case MAJOR_ACORN:
655         case MAJOR_ESDI:
656         case MAJOR_IDE:
657         case MAJOR_IDE2:
658         case MAJOR_IDE3:
659         case MAJOR_IDE4:
660         case MAJOR_IDE5:
661         case MAJOR_IDE6:
662         case MAJOR_IDE7:
663         case MAJOR_IDE8:
664         case MAJOR_IDE9:
665         case MAJOR_IDE10:
666         case MAJOR_XT:
667         MASK63:
668             geo->device = 0x80 + (MINOR(device) >> 6) +
669                     (MAJOR(device) == MAJOR_IDE ? 0 : last_dev(MAJOR_IDE,64));
670             if (!get_all) break;
671             if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
672                 die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
673                   strerror(errno));
674             geo->heads = hdprm.heads;
675             geo->cylinders = hdprm.cylinders;
676             geo->sectors = hdprm.sectors;
677             geo->start = hdprm.start;
678             break;
679         case MAJOR_SD:
680         case MAJOR_SD2:
681         case MAJOR_SD3:
682         case MAJOR_SD4:
683         case MAJOR_SD5:
684         case MAJOR_SD6:
685         case MAJOR_SD7:
686         case MAJOR_SD8:
687         case MAJOR_SD9:
688         case MAJOR_SD10:
689         case MAJOR_SD11:
690         case MAJOR_SD12:
691         case MAJOR_SD13:
692         case MAJOR_SD14:
693         case MAJOR_SD15:
694         case MAJOR_SD16:
695         case MAJOR_XVD:
696         MASK15:
697             geo->device = 0x80 + last_dev(MAJOR_IDE,64) + (MINOR(device) >> 4);
698             if (!get_all) break;
699             if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
700                 die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
701                   strerror(errno));
702             if (all && !hdprm.sectors)
703                 die("HDIO_REQ not supported for your SCSI controller. Please "
704                   "use a DISK section");
705             geo->heads = hdprm.heads;
706             geo->cylinders = hdprm.cylinders;
707             geo->sectors = hdprm.sectors;
708             geo->start = hdprm.start;
709             break;
710         case MAJOR_SATA1:
711         case MAJOR_SATA2:
712                 printf("WARNING: SATA partition in the high region (>15):\n");
713                 printf("LILO needs the kernel in one of the first 15 SATA partitions. If \n");
714                 printf("you need support for kernel in SATA partitions of the high region \n");
715                 printf("than try grub2 for this purpose! \n");
716                 die("Sorry, cannot handle device 0x%04x",device);
717             break;
718         MASK31:
719             geo->device = 0x80 + last_dev(MAJOR_IDE,64) + (MINOR(device) >> 5);
720             if (!get_all) break;
721             if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
722                 die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
723                   strerror(errno));
724             if (all && !hdprm.sectors)
725                 die("HDIO_REQ not supported for your Disk controller. Please "
726                   "use a DISK section");
727             geo->heads = hdprm.heads;
728             geo->cylinders = hdprm.cylinders;
729             geo->sectors = hdprm.sectors;
730             geo->start = hdprm.start;
731             break;
732         case MAJOR_DAC:
733         case MAJOR_DAC2:
734         case MAJOR_DAC3:
735         case MAJOR_DAC4:
736         case MAJOR_DAC5:
737         case MAJOR_DAC6:
738         case MAJOR_DAC7:
739         case MAJOR_DAC8:
740         case MAJOR_DAC9:
741         case MAJOR_DAC10:
742         case MAJOR_DAC11:
743         case MAJOR_DAC12:
744         case MAJOR_DAC13:
745         case MAJOR_DAC14:
746         case MAJOR_DAC15:
747         case MAJOR_DAC16:
748         case MAJOR_IBM_ISER:
749     case MAJOR_MMC:
750         MASK7:
751             geo->device = 0x80 + last_dev(MAJOR_IDE,64) + (MINOR(device) >> 3);
752             if (!get_all) break;
753             if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
754                 die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
755                   strerror(errno));
756             if (all && !hdprm.sectors)
757                 die("HDIO_REQ not supported for your DAC960/IBM controller. "
758                   "Please use a DISK section");
759             geo->heads = hdprm.heads;
760             geo->cylinders = hdprm.cylinders;
761             geo->sectors = hdprm.sectors;
762             geo->start = hdprm.start;
763             break;
764         case MAJOR_AMI:
765         case MAJOR_CISS:
766         case MAJOR_CISS2:
767         case MAJOR_CISS3:
768         case MAJOR_CISS4:
769         case MAJOR_CISS5:
770         case MAJOR_CISS6:
771         case MAJOR_CISS7:
772         case MAJOR_CISS8:
773         case MAJOR_DOC:
774         case MAJOR_EXPR:
775         case MAJOR_EXPR2:
776         case MAJOR_EXPR3:
777         case MAJOR_EXPR4:
778         case MAJOR_EXPR5:
779         case MAJOR_EXPR6:
780         case MAJOR_EXPR7:
781         case MAJOR_EXPR8:
782         case MAJOR_EXPR9:
783         case MAJOR_EXPR10:
784         case MAJOR_EXPR11:
785         case MAJOR_EXPR12:
786         case MAJOR_HPT370:
787         case MAJOR_FTL:
788         case MAJOR_NFTL:
789         case MAJOR_I2O:
790         case MAJOR_I2O2:
791         case MAJOR_I2O3:
792         case MAJOR_I2O4:
793         case MAJOR_I2O5:
794         case MAJOR_I2O6:
795         case MAJOR_I2O7:
796         case MAJOR_I2O8:
797         case MAJOR_PP:
798         case MAJOR_PPCD:
799         case MAJOR_PPFD:
800         case MAJOR_SMART:
801         case MAJOR_SMART2:
802         case MAJOR_SMART3:
803         case MAJOR_SMART4:
804         case MAJOR_SMART5:
805         case MAJOR_SMART6:
806         case MAJOR_SMART7:
807         case MAJOR_SMART8:
808             geo->device = 0x80 + last_dev(MAJOR_IDE,64) + (MINOR(device) >> 4);
809             if (!get_all) break;
810             if (ioctl(fd,HDIO_GETGEO,&hdprm) < 0)
811                 die("geo_query_dev HDIO_GETGEO (dev 0x%04x): %s",device,
812                   strerror(errno));
813             if (all && !hdprm.sectors)
814                 die("HDIO_REQ not supported for your Array controller. Please "
815                   "use a DISK section");
816             geo->heads = hdprm.heads;
817             geo->cylinders = hdprm.cylinders;
818             geo->sectors = hdprm.sectors;
819             geo->start = hdprm.start;
820             break;
821
822         default:
823             if (max_partno[major] && major==MAJOR_LOOP) break;
824             if (max_partno[major] == 63)  goto MASK63;
825             if (max_partno[major] == 31)  goto MASK31;
826             if (max_partno[major] == 15)  goto MASK15;
827             if (max_partno[major] == 7)   goto MASK7;
828             
829             if ((MAJOR(device)>=60 && MAJOR(device)<=63)  ||
830             (MAJOR(device)>=120 && MAJOR(device)<=127) ||
831                 (MAJOR(device)>=240 && MAJOR(device)<=254) )
832                 die("Linux experimental device 0x%04x needs to be defined.\n"
833                     "Check 'man lilo.conf' under 'disk=' and 'max-partitions='", device);
834             else die("Sorry, don't know how to handle device 0x%04x",device);
835     }
836     if (get_all) dev_close(&dev);
837     if (verbose>=5) printf("exit geo_query_dev\n");
838 }
839
840
841 int is_first(int device)
842 {
843     DT_ENTRY *walk;
844
845     for (walk = disktab; walk; walk = walk->next)
846         if (walk->device == device) break;
847     if (!walk && !old_disktab)
848         for (walk = disktab; walk; walk = walk->next)
849             if (walk->device == (device & D_MASK(device))) break;
850     if (walk && !walk->heads)
851         die("Device 0x%04X: Configured as inaccessible.\n",device);
852     if (walk && walk->bios != -1) return !(walk->bios & 0x7f);
853
854     switch (MAJOR(device)) {
855         case MAJOR_FD:
856             return !(device & 3);
857
858         case MAJOR_IDE:
859             return !(MINOR(device) >> 6);
860
861         case MAJOR_IDE2:
862         case MAJOR_IDE3:
863         case MAJOR_IDE4:
864         case MAJOR_IDE5:
865         case MAJOR_IDE6:
866         case MAJOR_IDE7:
867         case MAJOR_IDE8:
868         case MAJOR_IDE9:
869         case MAJOR_IDE10:
870         case MAJOR_ESDI:
871         case MAJOR_XT:
872             return MINOR(device) >> 6 ? 0 : !last_dev(MAJOR_IDE,64);
873
874         case MAJOR_SD:
875         case MAJOR_SD2:
876         case MAJOR_SD3:
877         case MAJOR_SD4:
878         case MAJOR_SD5:
879         case MAJOR_SD6:
880         case MAJOR_SD7:
881         case MAJOR_SD8:
882         case MAJOR_SD9:
883         case MAJOR_SD10:
884         case MAJOR_SD11:
885         case MAJOR_SD12:
886         case MAJOR_SD13:
887         case MAJOR_SD14:
888         case MAJOR_SD15:
889         case MAJOR_SD16:
890         case MAJOR_XVD:
891         case MAJOR_AMI:
892         case MAJOR_CISS:
893         case MAJOR_CISS2:
894         case MAJOR_CISS3:
895         case MAJOR_CISS4:
896         case MAJOR_CISS5:
897         case MAJOR_CISS6:
898         case MAJOR_CISS7:
899         case MAJOR_CISS8:
900         case MAJOR_DOC:
901         case MAJOR_HPT370:
902         case MAJOR_EXPR:
903         case MAJOR_EXPR2:
904         case MAJOR_EXPR3:
905         case MAJOR_EXPR4:
906         case MAJOR_EXPR5:
907         case MAJOR_EXPR6:
908         case MAJOR_EXPR7:
909         case MAJOR_EXPR8:
910         case MAJOR_EXPR9:
911         case MAJOR_EXPR10:
912         case MAJOR_EXPR11:
913         case MAJOR_EXPR12:
914         case MAJOR_I2O:
915         case MAJOR_I2O2:
916         case MAJOR_I2O3:
917         case MAJOR_I2O4:
918         case MAJOR_I2O5:
919         case MAJOR_I2O6:
920         case MAJOR_I2O7:
921         case MAJOR_I2O8:
922         case MAJOR_NFTL:
923         case MAJOR_PP:
924         case MAJOR_PPCD:
925         case MAJOR_PPFD:
926         case MAJOR_SMART:
927         case MAJOR_SMART2:
928         case MAJOR_SMART3:
929         case MAJOR_SMART4:
930         case MAJOR_SMART5:
931         case MAJOR_SMART6:
932         case MAJOR_SMART7:
933         case MAJOR_SMART8:
934             return MINOR(device) >> 4 ? 0 : !last_dev(MAJOR_IDE,64);
935
936         case MAJOR_DAC:
937         case MAJOR_DAC2:
938         case MAJOR_DAC3:
939         case MAJOR_DAC4:
940         case MAJOR_DAC5:
941         case MAJOR_DAC6:
942         case MAJOR_DAC7:
943         case MAJOR_DAC8:
944         case MAJOR_DAC9:
945         case MAJOR_DAC10:
946         case MAJOR_DAC11:
947         case MAJOR_DAC12:
948         case MAJOR_DAC13:
949         case MAJOR_DAC14:
950         case MAJOR_DAC15:
951         case MAJOR_DAC16:
952         case MAJOR_IBM_ISER:
953         case MAJOR_MMC:
954             return MINOR(device) >> 3 ? 0 : !last_dev(MAJOR_IDE,64);
955
956         default:
957             return 1; /* user knows what (s)he's doing ... I hope */
958     }
959 }
960
961
962 void geo_get(GEOMETRY *geo,int device,int user_device,int all)
963 {
964     DT_ENTRY *walk;
965     int inherited,keep_cyls,is_raid=0;
966 #ifdef LCF_DEVMAPPER
967     int i;
968
969     for(i = 0; i < dm_major_nr; i++)
970         if (MAJOR(device) == dm_major_list[i])
971             break;
972     while (i < dm_major_nr) {
973         DM_TABLE *dm_table;
974
975         for(dm_table = dmtab; dm_table; dm_table = dm_table->next)
976             if (dm_table->device == device)
977                 break;
978
979         if (dm_table) {
980             DM_TARGET *target;
981
982              device = 0;
983             for(target = dm_table->target; target; target = target->next)
984                 device = target->device;
985         } else {
986             DEVICE dev;
987             struct dm_task *dmt;
988             void *next = NULL;
989             char dmdev[PATH_MAX+1];
990             char buf[PATH_MAX+1];
991             char *slash;
992             int result;
993
994             dev_open(&dev, device, -1);
995             strncpy(dmdev, dev.name, PATH_MAX);
996             dmdev[PATH_MAX] = 0;
997             do {
998                 memset(buf, 0, PATH_MAX + 1);
999                 if ((result = readlink(dmdev, buf, PATH_MAX)) < 0 && errno != EINVAL)
1000                     die("device-mapper: readlink(\"%s\") failed with: %s",buf,
1001                         strerror(errno));
1002                 if (result >= 0) {
1003                     if (buf[0] != '/' && (slash = strrchr(dmdev, '/')) != NULL)
1004                         slash++;
1005                     else
1006                         slash = dmdev;
1007                     strncpy(slash, buf, PATH_MAX - (slash-dmdev));
1008                 }
1009                 if (realpath(dmdev, buf) == NULL)
1010                     die("device-mapper: realpath(\"%s\") failed with: %s",dmdev,
1011                         strerror(errno));
1012                 strncpy(dmdev, buf, PATH_MAX);
1013             } while (result >= 0);
1014             dmdev[PATH_MAX] = 0;
1015
1016             if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
1017                 die("device-mapper: dm_task_create(DM_DEVICE_TABLE) failed");
1018             slash = strrchr(dmdev, '/');
1019                 if (slash)
1020             slash++;
1021                 else
1022             slash = dmdev;
1023             if (!dm_task_set_major(dmt, MAJOR(device)) ||
1024                 !dm_task_set_minor(dmt, MINOR(device)))
1025                 die("device-mapper: dm_task_set_major() or dm_task_set_minor() failed");
1026             if (!dm_task_run(dmt))
1027                 die("device-mapper: dm_task_run(DM_DEVICE_TABLE) failed");
1028
1029             dm_table = alloc_t(DM_TABLE);
1030             dm_table->device = device;
1031             dm_table->target = NULL;
1032             dm_table->next = dmtab;
1033             dmtab = dm_table;
1034
1035             device = 0;
1036
1037             do {
1038                 DM_TARGET *target;
1039                 uint64_t start,length;
1040                 int major,minor;
1041                 char *target_type,*params;
1042                 char *p;
1043
1044                 next = dm_get_next_target(dmt, next, &start, &length,
1045                   &target_type, &params);
1046
1047                 if (!target_type) continue;
1048
1049                 if (strcmp(target_type, "linear") != 0)
1050                     die("device-mapper: only linear boot device supported");
1051
1052                 target = alloc_t(DM_TARGET);
1053                 target->start = start;
1054                 target->length = length;
1055                 if (dm_version_nr < 4 &&
1056                     isxdigit(params[0]) &&
1057                     isxdigit(params[1]) &&
1058                     params[2] == ':' &&
1059                     isxdigit(params[3]) &&
1060                     isxdigit(params[4])) { /* old 2.4 format */
1061                     if (sscanf(params, "%02x:%02x %"PRIu64, &major, &minor, &target->offset) != 3)
1062                         die("device-mapper: parse error in linear params (\"%s\")", params);
1063                 } else if (isdigit(params[0]) &&
1064                            strchr(params, ':')) { /* dm_bdevname/format_dev_t (>= 2.6.0-test4?) format */
1065                     if (sscanf(params, "%u:%u %"PRIu64, &major, &minor, &target->offset) != 3)
1066                         die("device-mapper: parse error in linear params (\"%s\")", params);
1067                 } else { /* >= 2.5.69 format, this should go away soon */
1068                     struct stat st;
1069                     FILE *file;
1070
1071                     p = strrchr(params, ' ');
1072                     if (p == NULL)
1073                         die("device-mapper: parse error in linear params (\"%s\")", params);
1074                     *p = 0;
1075                     sprintf(buf, DEV_DIR "/%s", params);        /* let's hope it's there */
1076                     if (stat(buf, &st) == 0) {
1077                         if (!S_ISBLK(st.st_mode))
1078                             die("device-mapper: %s is not a valid block device", buf);
1079                         major = MAJOR(st.st_rdev);
1080                         minor = MINOR(st.st_rdev);
1081                     } else {                            /* let's try sysfs */
1082                         int dev;
1083                         sprintf(buf, "/sys/block/%s/dev", params);
1084                         file = fopen(buf, "r");
1085                         if (!file)
1086                             die("device-mapper: \"%s\" could not be opened. /sys mounted?", buf);
1087                         if (!fgets(buf, PATH_MAX, file))
1088                             die("device-mapper: read error from \"/sys/block/%s/dev\"", params);
1089                         if (sscanf(buf, "%u:%u", &major, &minor) != 2) {
1090                             if (sscanf(buf, "%x", &dev) != 1)
1091                                 die("device-mapper: error getting device from \"%s\"", buf);
1092                             major = MAJOR(dev);
1093                             minor = MINOR(dev);
1094                         }
1095                         (void) fclose(file);
1096                     }
1097                     *p = ' ';
1098                     if (sscanf(p+1, "%"PRIu64, &target->offset) != 1)
1099                         die("device-mapper: parse error in linear params (\"%s\")", params);
1100                 }
1101                 target->device = (major << 8) | minor;
1102                 if (!device)
1103                     device = target->device;
1104                 target->next = dm_table->target;
1105                 dm_table->target = target;
1106             } while(next);
1107
1108             dm_task_destroy(dmt);
1109
1110             dev_close(&dev);
1111         }
1112
1113         if (!device)
1114             die("device-mapper: Error finding real device");
1115         geo->base_dev = device;
1116
1117         for(i = 0; i < dm_major_nr; i++)
1118             if (MAJOR(device) == dm_major_list[i])
1119                 break;
1120     }
1121 #endif
1122
1123     if (verbose>=5) printf("geo_get: device %04X, all=%d\n", device, all);
1124 #ifdef LCF_LVM
1125     /*
1126      * Find underlying device (PV) for LVM.  It is OK if the underlying PV is
1127      * really an MD RAID1 device, because the geometry of the RAID1 device is
1128      * exactly the same as the underlying disk, so FIBMAP and LV_BMAP should
1129      * return the correct block numbers regardless of MD.
1130      *
1131      * We do a quick test to see if the LVM LV_BMAP ioctl is working correctly.
1132      * It should map the two blocks with the same difference as they were input,
1133      * with a constant offset from their original block numbers.  If this is not
1134      * the case then LV_BMAP is not working correctly (some widely distributed
1135      * kernels did not have working LV_BMAP support, some just oops here).
1136      */
1137     if (MAJOR(device) == MAJOR_LVM)
1138     {
1139         struct lv_bmap lbmA, lbmB;
1140 #define DIFF 255
1141
1142         lbmA.lv_dev = lbmB.lv_dev = device;
1143         lbmA.lv_block = 0;
1144         lbmB.lv_block = DIFF;
1145
1146         lvm_bmap(&lbmA);
1147         lvm_bmap(&lbmB);
1148         if (lbmB.lv_block - lbmA.lv_block != DIFF)
1149             die("This version of LVM does not support boot LVs");
1150         device = geo->base_dev = lbmA.lv_dev;
1151     }
1152 #endif
1153
1154 #ifdef LCF_EVMS
1155     if (MAJOR(device) == MAJOR_EVMS) {
1156         struct evms_get_bmap_t ebm;
1157         
1158         ebm.rsector = 0;
1159         ebm.dev = device;
1160         ebm.status = 0;
1161         
1162         evms_bmap(&ebm);
1163         
1164         device = geo->base_dev = ebm.dev;
1165     }
1166 #endif
1167
1168     /* Find underlying device for MD RAID */
1169     if (MAJOR(device) == MD_MAJOR) {
1170         char mdxxx[16];
1171         int md_fd;
1172 /*      int pass;       */
1173         struct md_version md_version_info;
1174         md_array_info_t md_array_info;
1175         md_disk_info_t md_disk_info;
1176         int raid_limit;
1177         raid_limit = 0;
1178
1179         sprintf(mdxxx, DEV_DISK_DIR "/md%d", MINOR(device));
1180         if ((md_fd=open(mdxxx,O_NOACCESS)) < 0)
1181         {
1182             sprintf(mdxxx, DEV_DIR "/md/%d", MINOR(device));
1183             if ((md_fd=open(mdxxx,O_NOACCESS)) < 0)
1184                 die("Unable to open %s", mdxxx);
1185         }
1186         if (ioctl(md_fd,RAID_VERSION,&md_version_info) < 0)
1187             die("Unable to get RAID version on %s", mdxxx);
1188         if (md_version_info.major > 0)
1189             die("Raid major versions > 0 are not supported");
1190         if (md_version_info.minor < 90)
1191             die("Raid versions < 0.90 are not supported");
1192         
1193         if (ioctl(md_fd,GET_ARRAY_INFO,&md_array_info) < 0)
1194             die("Unable to get RAID info on %s", mdxxx);
1195         if (md_version_info.major != 0 || md_version_info.minor != 90 ||
1196             ((md_array_info.major_version != 0 ||
1197                 md_array_info.minor_version != 90) &&
1198              (md_array_info.major_version != 1 ||
1199                 md_array_info.minor_version != 0))
1200             ) {
1201             die("Incompatible Raid version information on %s   (RV=%d.%d GAI=%d.%d)",
1202                 mdxxx,
1203                 (int)md_version_info.major,
1204                 (int)md_version_info.minor,
1205                 (int)md_array_info.major_version,
1206                 (int)md_array_info.minor_version);
1207             }
1208         if (md_array_info.level != 1)
1209             die("Only RAID1 devices are supported for boot images");
1210         raid_limit = md_array_info.raid_disks + md_array_info.spare_disks;
1211
1212         /* version 22.7 */
1213 #if 1
1214         is_raid = (device==boot_dev_nr);
1215         md_disk_info.number = raid_index;
1216         if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0)
1217             die("GET_DISK_INFO: %s", mdxxx);
1218         device = MKDEV(md_disk_info.major, md_disk_info.minor);
1219
1220 #else           /* prior to 22.7 */
1221 {
1222 int pass;
1223         for (pass = 0; pass < raid_limit; pass++) {
1224             md_disk_info.number = pass;
1225             if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0)
1226 #if BETA_TEST
1227             {
1228                 printf("(raid) GET_DISK_INFO: failed for pass=%d\n", pass);
1229                 continue;
1230             }
1231 #else
1232                 die("GET_DISK_INFO: %s", mdxxx);
1233 #endif
1234             if (!(md_disk_info.state & (1 << MD_DISK_FAULTY))) {
1235 #if 1
1236                 is_raid = (device==boot_dev_nr);
1237 #else
1238 /* this change may be in error; the correct comparison is == */
1239                 is_raid = (device!=boot_dev_nr);
1240 #endif
1241                 device = MKDEV(md_disk_info.major, md_disk_info.minor);
1242                 break;
1243             }
1244         }
1245 }
1246 #endif  /* end of code prior to version 22.7 */
1247
1248         close(md_fd);
1249     }
1250
1251 #if BETA_TEST
1252         if (verbose>=5) printf("geo_get(2):  device=%04X, all=%d\n", device, all);
1253 #endif
1254
1255 /* if using hard disk, scan the devices in /proc/partitions */
1256     if (has_partitions(device) && all)   pf_hard_disk_scan();
1257
1258
1259
1260
1261     for (walk = disktab; walk; walk = walk->next)
1262         if (walk->device == device) break;
1263     inherited = !walk && !old_disktab;
1264 #if BETA_TEST
1265     if (verbose>=5) printf("inherited=%d\n", inherited);
1266 #endif
1267     if (inherited)
1268         for (walk = disktab; walk; walk = walk->next)
1269             if (walk->device == (device & D_MASK(device))) break;
1270 #if BETA_TEST
1271     if (verbose>=5) printf("walk=%0*" PRIxPTR "\n", PTR_WIDTH, (intptr_t)walk);
1272 #endif
1273
1274 #if 1
1275 /* add 'all' to conditional below -- JRC 2002-08-20 */
1276     if (walk && !walk->heads && all)
1277 #else
1278 /* Werner's original conditional */
1279     if (walk && !walk->heads)
1280 #endif
1281         die("Device 0x%04X: Configured as inaccessible.\n",device);
1282     keep_cyls = !walk || walk->bios == -1 || walk->heads == -1 ||
1283       walk->sectors == -1 || inherited || walk->start == -1;
1284 #if BETA_TEST
1285     if (verbose>=5) printf("inherited=%d  keep_cyls=%d\n", inherited, keep_cyls);
1286 #endif
1287
1288 #if 1
1289 /* add 'all' to conditional below -- JRC 2002-08-20 */
1290     if (keep_cyls && (all || MAJOR(device)==MAJOR_FD) ) {
1291 #else
1292 /* Werner's original conditional */
1293     if (keep_cyls) {
1294 #endif
1295         geo_query_dev(geo,device,all);
1296         
1297         if (all) bios_device(geo, device);
1298         
1299         if ((geo->device & 0x7f) >= bios_max_devs() &&
1300           user_device == -1 && (!walk || walk->bios == -1))
1301             warn("BIOS drive 0x%02x may not be accessible",
1302               geo->device);
1303     }
1304     if (walk) {
1305         if (walk->bios != -1) geo->device = walk->bios;
1306         if (walk->heads != -1) geo->heads = walk->heads;
1307         if (walk->cylinders != -1 || !keep_cyls)
1308             geo->cylinders = walk->cylinders;
1309         if (walk->sectors != -1) geo->sectors = walk->sectors;
1310         if (walk->start != -1 && !inherited) geo->start = walk->start;
1311     }
1312     if (user_device != -1) geo->device = user_device;
1313     if (!all) {
1314         if (verbose > 2)
1315             printf("Device 0x%04x: BIOS drive 0x%02x, no geometry.\n",device,
1316               geo->device);
1317         return;
1318     }
1319     if (!geo->heads || !geo->cylinders || !geo->sectors)
1320         die("Device 0x%04X: Got bad geometry %d/%d/%d\n",device,
1321           geo->sectors,geo->heads,geo->cylinders);
1322     if (geo->heads > BIOS_MAX_HEADS)
1323         die("Device 0x%04X: Maximum number of heads is %d, not %d\n",device,
1324           BIOS_MAX_HEADS,geo->heads);
1325     if (geo->heads == BIOS_MAX_HEADS)
1326         warn("Maximum number of heads = %d (as specified)\n"
1327                         "   exceeds standard BIOS maximum of 255.", geo->heads);
1328     if (geo->sectors > BIOS_MAX_SECS)
1329         die("Device 0x%04X: Maximum number of sectors is %d, not %d\n",
1330           device,BIOS_MAX_SECS,geo->sectors);
1331     if (geo->sectors == BIOS_MAX_SECS)
1332         warn("Maximum number of heads = %d (as specified)\n"
1333                         "   exceeds standard BIOS maximum of 63.", geo->sectors);
1334     if (!lba32 &&
1335       (geo->start+geo->sectors-1)/geo->heads/geo->sectors >= BIOS_MAX_CYLS
1336     ) {
1337         warn("device 0x%04x exceeds %d cylinder limit.\n"
1338         "   Use of the 'lba32' option may help on newer (EDD-BIOS) systems.",
1339           device, BIOS_MAX_CYLS);
1340     }
1341     if (verbose >= 3) {
1342         printf("Device 0x%04x: BIOS drive 0x%02x, %d heads, %d cylinders,\n",
1343           device,geo->device,geo->heads,geo->cylinders == -1 ? BIOS_MAX_CYLS :
1344           geo->cylinders);
1345         printf("%15s%d sectors. Partition offset: %d sectors.\n","",
1346           geo->sectors,geo->start);
1347     }
1348     geo->raid = is_raid;
1349
1350 /* make the serial number association */
1351     if (!is_raid) register_bios(geo->device, device);
1352     else geo->device = md_bios;         /* 22.5.7 add this else */
1353     
1354     return;
1355 } /* end of geo_get */
1356
1357
1358 int geo_open(GEOMETRY *geo,const char *name,int flags)
1359 {
1360     char *here;
1361     int user_dev,block_size;
1362     struct stat st;
1363
1364     if ((here = strrchr(name,':')) == NULL) user_dev = -1;
1365     else {
1366         *here++ = 0;
1367         warn("%s:BIOS syntax is no longer supported.\n    Please use a "
1368           "DISK section.", name);
1369         user_dev = to_number(here);
1370     }
1371     if ((geo->fd = open(name,flags)) < 0)
1372         die("open %s: %s",name,strerror(errno));
1373     if (fstat(geo->fd,&st) < 0) die("fstat %s: %s",name,strerror(errno));
1374     if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
1375         die("%s: neither a reg. file nor a block dev.",name);
1376     geo->dev = S_ISREG(st.st_mode) ? st.st_dev : st.st_rdev;
1377 #if BETA_TEST
1378         if (verbose>=4) {
1379                 printf("geo_open: (%s) st_dev(file)=%04X  st_rdev(blk)=%04X\n",
1380                 name,
1381                 (int)st.st_dev,
1382                 (int)st.st_rdev );
1383         }
1384 #endif
1385
1386     geo_get(geo, geo->dev, user_dev, 1);
1387     geo->file = S_ISREG(st.st_mode) ? st.st_dev : 0;
1388     geo->boot = 0;
1389 #ifndef FIGETBSZ
1390     geo->spb = 2;
1391 #else
1392     if (!geo->file) geo->spb = 2;
1393     else {
1394         if (ioctl(geo->fd,FIGETBSZ,&block_size) < 0) {
1395             warn("FIGETBSZ %s: %s",name,strerror(errno));
1396             geo->spb = 2;
1397         }
1398         else {
1399             if (!block_size || (block_size & (SECTOR_SIZE-1)))
1400                 die("Incompatible block size: %d\n",block_size);
1401             geo->spb = block_size/SECTOR_SIZE;
1402         }
1403     }
1404 #endif
1405     return geo->fd;
1406 }
1407
1408
1409 int geo_open_boot(GEOMETRY *geo,char *name)
1410 {
1411     struct stat st;
1412
1413     if (verbose>=5) printf("geo_open_boot: %s\n", name);
1414     if (stat(name,&st) < 0) die("stat %s: %s",name,strerror(errno));
1415     if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
1416         die("%s: neither a reg. file nor a block dev.",name);
1417     geo->dev = S_ISREG(st.st_mode) ? st.st_dev : st.st_rdev;
1418 #if 1
1419     if (MAJOR(geo->dev) == MAJOR_FD) geo->fd = 0;
1420     else if ((geo->fd = open(name,O_NOACCESS)) < 0)
1421             die("open %s: %s",name,strerror(errno));
1422 #else
1423     if (MAJOR(geo->dev) != MAJOR_FD) {
1424         if ((P_MASK(geo->dev) & geo->dev) != 0)
1425             die("UNSAFE may be used with floppy or MBR only");
1426     }
1427     geo->fd = 0;
1428 #endif
1429     geo_get(geo, geo->dev, -1, 0);
1430     geo->file = S_ISREG(st.st_mode);
1431     geo->raid = 0;
1432     geo->boot = 1;
1433     geo->spb = 1;
1434     return geo->fd;
1435 }
1436
1437
1438 void geo_close(GEOMETRY *geo)
1439 {
1440     if (geo->fd) (void) close(geo->fd);
1441     geo->fd = 0;
1442 }
1443
1444
1445 #ifndef FIBMAP
1446 #define FIBMAP BMAP_IOCTL
1447 #endif
1448
1449
1450 int geo_comp_addr(GEOMETRY *geo,int offset,SECTOR_ADDR *addr)
1451 {
1452     int block,sector;
1453     static int linear_warnings = 0;
1454
1455 #if BETA_TEST
1456     if (verbose>=6)
1457         printf("geo_comp_addr: dev = %x, offset=%d\n",
1458                 geo->device, offset);
1459 #endif
1460
1461 #if 0
1462     if (linear && lba32)
1463        die("'linear' and 'lba32' (-l and -L) are mutually exclusive.");
1464 #endif
1465     if (geo->boot && offset >= SECTOR_SIZE)
1466         die("Internal error: sector > 0 after geo_open_boot");
1467     block = offset/geo->spb/SECTOR_SIZE;
1468     if (geo->file) {
1469 #ifdef LCF_REISERFS
1470             struct statfs buf;
1471
1472             fstatfs(geo->fd, &buf);
1473             if (buf.f_type == REISERFS_SUPER_MAGIC) {
1474                 if (ioctl (geo->fd, REISERFS_IOC_UNPACK, 1) == ENOSPC)
1475                         die("Cannot unpack ReiserFS file");
1476                 if (verbose > 3) printf("fd %d: REISERFS_IOC_UNPACK\n", geo->fd);
1477             }
1478         /* Forcing reiser4 to perform tail2extent converstion */
1479            if (buf.f_type == REISER4_SUPER_MAGIC) {
1480                if (ioctl (geo->fd, REISER4_IOC_UNPACK, 1) != 0)
1481                        die("Cannot unpack Reiser4 file");
1482                if (verbose > 3) printf("fd %d: REISER4_IOC_UNPACK\n", geo->fd);
1483
1484            /* 
1485                As we may have the situation when extent will be included
1486                into transaction, and its item(s) will not be have the real block
1487                numbers assigned, we should perform fsync() in order to guarantee,
1488                that current atom is flushed and real block numbers assigned to 
1489                the extent(s) file was converted in.
1490            */
1491                 if (fdatasync(geo->fd) != 0)
1492                     die("Cannot perform fdatasync");
1493            
1494                 if (verbose > 3) printf("fd %d: fdatasync()\n", geo->fd);
1495            }
1496 #endif
1497         if (ioctl(geo->fd,FIBMAP,&block) < 0) pdie("ioctl FIBMAP");
1498         if (!block) {
1499             return 0;
1500         }
1501     }
1502 #ifdef LCF_LVM
1503     if (MAJOR(geo->dev) == MAJOR_LVM) {
1504         struct lv_bmap lbm;
1505
1506         lbm.lv_dev = geo->dev;
1507         lbm.lv_block = block;
1508
1509         lvm_bmap(&lbm);
1510         if (lbm.lv_dev != geo->base_dev)
1511             die("LVM boot LV cannot be on multiple PVs\n");
1512         block = lbm.lv_block;
1513     }
1514 #endif
1515
1516 #ifdef LCF_EVMS
1517     if (MAJOR(geo->dev) == MAJOR_EVMS) {
1518         struct evms_get_bmap_t ebm;
1519                           
1520         ebm.rsector = block * geo->spb;
1521         ebm.dev = geo->dev;
1522         ebm.status = 0;
1523                             
1524         evms_bmap(&ebm);
1525         if (ebm.dev != geo->base_dev)
1526             die("EVMS boot volume cannot be on multiple disks.\n");
1527         sector = ebm.rsector + ((offset/SECTOR_SIZE) % geo->spb) + geo->start;
1528     }
1529     else
1530 #endif
1531     {
1532 #ifdef LCF_DEVMAPPER 
1533         int dev = geo->dev;
1534         int i;
1535 #endif
1536         sector = block*geo->spb+((offset/SECTOR_SIZE) % geo->spb);
1537 #ifdef LCF_DEVMAPPER 
1538         for(i = 0; i < dm_major_nr; i++)
1539             if (MAJOR(dev) == dm_major_list[i])
1540                 break;
1541         while (i < dm_major_nr) {
1542             DM_TABLE *dm_table;
1543             DM_TARGET *dm_target;
1544
1545             for(dm_table = dmtab; dm_table; dm_table = dm_table->next)
1546                 if (dm_table->device == dev)
1547                     break;
1548             if (!dm_table)
1549                 die("device-mapper: Mapped device suddenly lost? (%d)", dev);
1550
1551             for(dm_target = dm_table->target; dm_target; dm_target = dm_target->next)
1552                 if (dm_target->start <= sector && sector < (dm_target->start+dm_target->length))
1553                     break;
1554             if (!dm_target)
1555                 die("device-mapper: Sector outside mapped device? (%d: %u/%"PRIu64")",
1556                     (int) geo->base_dev, sector, (uint64_t)(dm_table->target ?
1557                       (dm_table->target->start+dm_table->target->length) : 0));
1558
1559             dev = dm_target->device;
1560             sector = dm_target->offset+(sector-dm_target->start);
1561
1562             for(i = 0; i < dm_major_nr; i++)
1563                 if (MAJOR(dev) == dm_major_list[i])
1564                     break;
1565         }
1566
1567         if (dev != geo->dev && dev != geo->base_dev)
1568             die("device-mapper: mapped boot device cannot be on multiple real devices\n");
1569 #endif
1570         sector += geo->start;
1571     }
1572
1573  /*   DON'T always use CHS addressing on floppies:     JRC   */
1574 /*    if ((geo->device & 0x80) && (linear || lba32)) {  */
1575     if ((linear || lba32)) {
1576         addr->device = geo->device | (linear ? LINEAR_FLAG : (LBA32_FLAG|LBA32_NOCOUNT))
1577 #if 0
1578                 | (do_md_install && geo->file==boot_dev_nr ? RAID_REL_FLAG : 0);
1579 #else
1580                 | (do_md_install && geo->raid ? RAID_REL_FLAG : 0);
1581 #endif
1582         addr->num_sect = linear ? 1 : (sector >> 24);
1583         addr->sector = sector & 0xff;
1584         addr->track = (sector >> 8) & 0xff;
1585         addr->head = sector >> 16;
1586         if (linear) {
1587             int cyl = sector;
1588             if (geo->sectors>0 && geo->heads>0) {
1589                 cyl /= geo->sectors;
1590                 cyl /= geo->heads;
1591                 if (cyl >= BIOS_MAX_CYLS && linear_warnings++ < 8) {
1592                     warn("LINEAR may generate cylinder# above 1023 at boot-time.");
1593                 }
1594             }
1595             if (sector/(63*255) >= BIOS_MAX_CYLS)
1596                 die("Sector address %d too large for LINEAR"
1597                                         " (try LBA32 instead).", sector);
1598         }
1599         if (verbose > 4)
1600             printf("fd %d: offset %d -> dev 0x%02x, %s %d\n",
1601                          geo->fd, offset, addr->device,
1602                          lba32 ? "LBA" : "linear",
1603                          sector);
1604     }
1605     else {
1606         addr->device = geo->device;
1607         addr->sector = 1;
1608         addr->head = 0;
1609         if (sector) {
1610             if (geo->heads == 0)
1611                 die("BIOS device 0x%02x is inaccessible", geo->device);
1612             addr->sector = (sector % geo->sectors)+1;
1613             sector /= geo->sectors;
1614             addr->head = sector % geo->heads;
1615             sector /= geo->heads;
1616         }
1617         if (sector >= BIOS_MAX_CYLS)
1618             die("geo_comp_addr: Cylinder number is too big (%d > %d)",sector,
1619               BIOS_MAX_CYLS-1);
1620         if (sector >= geo->cylinders && geo->cylinders != -1)
1621             die("geo_comp_addr: Cylinder %d beyond end of media (%d)",sector,
1622               geo->cylinders);
1623         if (verbose > 4)
1624             printf("fd %d: offset %d -> dev 0x%02x, head %d, track %d, sector %d\n",
1625               geo->fd,offset,addr->device,addr->head,sector,addr->sector);
1626         addr->track = sector & 255;
1627         addr->sector |= (sector >> 8) << 6;
1628         addr->num_sect = 1;
1629     }
1630
1631     return 1;
1632 }
1633
1634
1635 int geo_find(GEOMETRY *geo,SECTOR_ADDR addr)
1636 {
1637     SECTOR_ADDR here;
1638     struct stat st;
1639     int i;
1640
1641 #if DEBUG_NEW
1642     if (verbose>=2) {
1643         printf("Find:  AL=%02x  CX=%04x  DX=%04x  LBA=%d\n", (int)addr.num_sect,
1644                 addr.sector + (addr.track<<8),
1645                 addr.device + (addr.head<<8),
1646                 addr.sector + (addr.track<<8) + (addr.head<<16) +
1647                 (addr.device&(LBA32_FLAG|LBA32_NOCOUNT)?addr.num_sect<<24:0) );
1648     }
1649 #endif
1650     if (fstat(geo->fd,&st) < 0) return 0;
1651     geo_get(geo,st.st_dev,-1,1);
1652     for (i = 0; i < (st.st_size+SECTOR_SIZE-1)/SECTOR_SIZE; i++)
1653         if (geo_comp_addr(geo,i*SECTOR_SIZE,&here))
1654             if (here.sector == addr.sector && here.track == addr.track &&
1655               here.device == addr.device && here.head == addr.head &&
1656               here.num_sect == addr.num_sect ) {
1657                 if (lseek(geo->fd,i*SECTOR_SIZE,SEEK_SET) < 0) return 0;
1658                 else return 1;
1659             }
1660     return 1;
1661 }
1662
1663
1664 #if 0
1665 int geo_devscan(int device)
1666 {
1667     DT_ENTRY *walk;
1668     unsigned int mask, codes = 0;
1669     int bios;
1670     int maxbios = 0;
1671     
1672     device &= D_MASK(device);
1673
1674 /* mark those BIOS codes that are already used */
1675     for (walk=disktab; walk; walk=walk->next) {
1676         if (has_partitions(walk->device) && walk->bios != -1) {
1677             bios = walk->bios & 0x7F;
1678             if (bios >= 4*sizeof(codes) ) die("BIOS code %02X is too big (device %04X)", bios, device);
1679             codes |= 1 << bios; 
1680         }
1681     }
1682
1683     bios = -1;
1684 /* extract BIOS code of master device, or -1 */
1685     for (walk=disktab; walk; walk=walk->next) {
1686         if (device == walk->device) {
1687             bios = walk->bios;
1688         }
1689     }
1690     if (bios > maxbios) maxbios = bios;
1691
1692 /* if device has no BIOS code assigned, assign the next one */
1693     if (bios == -1)
1694         for (bios=0x80, mask=1; mask; mask<<=1, bios++)
1695                 if (!(mask&codes)) break;
1696     
1697     if (bios > DEV_MASK) die("geo_devscan:  ran out of device codes");
1698     
1699     for (walk=disktab; walk; walk=walk->next) {
1700         if (device == walk->device) {
1701             if (walk->bios == -1) walk->bios = bios;
1702             else bios = walk->bios;
1703             break;
1704         }
1705     }
1706     if (bios > maxbios) maxbios = bios;
1707     
1708     if (verbose >= 2) printf("geo_devscan:  maxbios = %02X\n", maxbios);
1709     
1710     if (walk) return maxbios;   /* there was an entry in the disktab */
1711     
1712     walk = alloc_t(DT_ENTRY);
1713     walk->device = device;
1714     walk->bios = bios;
1715     walk->sectors = walk->heads = walk->cylinders = walk->start = -1;
1716     walk->next = disktab;
1717     disktab = walk;
1718     if (verbose>=2)
1719         printf("geo_devscan: arbitrary bios assignment  dev=%04X  bios=0x%02X\n",
1720                         device, bios);
1721
1722     for (walk=disktab; walk; walk=walk->next) {
1723         if (device == (walk->device & D_MASK(walk->device))) {
1724             if (walk->bios != -1) walk->bios = bios;
1725         }
1726     }
1727
1728     return maxbios;
1729 }
1730
1731 #endif
1732