1 /* device.c - Device access
3 * Copyright 1992-1997 Werner Almesberger
4 * Copyright 1999-2006 John Coffman
5 * Copyright 2009-2015 Joachim Wiedorn
8 * Licensed under the terms contained in the file 'COPYING'
9 * in the source directory.
22 #include <sys/types.h>
32 #include "partition.h"
38 typedef struct _cache_entry {
41 struct _cache_entry *next;
44 typedef struct _st_buf {
50 static CACHE_ENTRY *cache = NULL;
54 int yesno(char *prompt, int expect)
60 if (expect) pr2 = "[Y/n]";
65 fprintf(stderr, "%s%s", prompt, pr2);
69 i = getline(&line, &n, stdin);
71 if (i==1) ret=expect|2;
73 if (*line=='y'||*line=='Y') ret=1;
74 if (*line=='n'||*line=='N') ret=2;
84 static int scan_dir(ST_BUF *next,DEVICE *dev,char *parent,int number)
91 if (verbose >= 5) printf("scan_dir: %s\n", parent);
93 if ((dp = opendir(parent)) == NULL)
94 die("opendir %s: %s",parent,strerror(errno));
95 *(start = strchr(parent,0)) = '/';
96 while ((dir = readdir(dp))) {
97 strcpy(start+1,dir->d_name);
98 if (stat(parent,&st.st) >= 0) {
100 if (S_ISBLK(dev->st.st_mode) && dev->st.st_rdev == number) {
105 if (S_ISDIR(dev->st.st_mode) && strcmp(dir->d_name,".") &&
106 strcmp(dir->d_name,"..")) {
108 /* stay out of all hidden directories (good for 2.6 kernel) */
109 if (S_ISDIR(dev->st.st_mode) && (dir->d_name)[0] != '.' &&
110 strcmp(dir->d_name, ".udev") && strcmp(dir->d_name, "fd")) {
112 for (walk = next; walk; walk = walk->next)
113 if (stat_equal(&walk->st,&st.st)) break;
114 if (!walk && scan_dir(&st,dev,parent,number)) {
127 static int lookup_dev(char *name,DEVICE *dev,int number)
131 if (verbose>=5) printf("lookup_dev: number=%04X\n", number);
132 for (walk = &cache; *walk; walk = &(*walk)->next)
133 if ((*walk)->number == number) {
137 if (stat((*walk)->name,&dev->st) >= 0)
138 if (S_ISBLK(dev->st.st_mode) && dev->st.st_rdev == number) {
139 strcpy(name,(*walk)->name);
142 here = *walk; /* remove entry from cache */
144 printf("Invalidating cache entry for %s (0x%04X)\n",here->name,
147 free((char *) here->name);
151 strcpy(name,(*walk)->name);
159 static int is_devfs(void)
161 static int yesno = 0;
165 if (stat(DEV_DIR "/.devfsd", &st) < 0) yesno=1;
174 static void cache_add(const char *name,int number)
180 if (strcmp(entry->name, name) == 0) {
181 if (entry->number != number) die("cache_add: LILO internal error");
186 if (verbose >= 5) printf("Caching device %s (0x%04X)\n",name,number);
187 entry = alloc_t(CACHE_ENTRY);
188 entry->name = stralloc(name);
189 entry->number = number;
195 int dev_open(DEVICE *dev,int number,int flags)
202 if (lookup_dev(name,dev,number)) dev->delete = 0;
204 if (stat(DEV_DIR,&st.st) < 0)
205 die("stat " DEV_DIR ": %s",strerror(errno));
207 dev->delete = !scan_dir(&st,dev,strcpy(name,DEV_DIR),number);
209 for (count = 0; count <= MAX_TMP_DEV; count++) {
210 #ifdef LCF_USE_TMPDIR
211 if (!strncmp(TMP_DEV,"/tmp/",5) && getenv("TMPDIR")) {
212 strcpy(name,getenv("TMPDIR"));
213 sprintf(name+strlen(name),TMP_DEV+4,count);
217 sprintf(name,TMP_DEV,count);
218 if (stat(name,&dev->st) < 0) break;
220 if (count > MAX_TMP_DEV)
221 die("Failed to create a temporary device");
222 if (mknod(name,0600 | S_IFBLK,number) < 0)
223 die("mknod %s: %s",name,strerror(errno));
224 if (stat(name,&dev->st) < 0)
225 die("stat %s: %s",name,strerror(errno));
227 printf("Created temporary device %s (0x%04X)\n",name,number);
230 else cache_add(name,number);
233 if (verbose >= 4) printf("stat-ing %s\n", name);
237 if (flags == O_BYPASS) dev->fd = -1;
238 else if ((dev->fd = open(name,flags)) < 0) {
240 fprintf (errstd, "Cannot proceed. Maybe you need to add "
241 "this to your lilo.conf:\n"
242 "\tdisk=%s inaccessible\n"
243 "(real error shown below)\n", name);
244 die("open %s: %s",name,strerror(err));
246 dev->name = stralloc(name);
251 void dev_close(DEVICE *dev)
254 if (close(dev->fd) < 0) die("close %s: %s",dev->name,strerror(errno));
257 printf("Removed temporary device %s (0x%04X)\n",dev->name,
258 (unsigned int) dev->st.st_rdev);
259 (void) remove(dev->name);
260 temp_unregister(dev->name);
267 void cache_scsi (char *name, int major)
269 char tem[PATH_MAX], format[PATH_MAX];
271 int k = strlen(DEV_DISK_DIR) + 3;
273 for (i=15; i>=0; i--) {
274 dev = MKDEV(major,(i<<4));
277 sprintf(tem,"/dev/scsi/host%d/bus0/target0/lun0/", i);
278 strcat(strcpy(format,tem),"disc");
279 cache_add(format, dev);
280 strcat(strcpy(format,tem),"part%d");
285 strcpy(format, name);
287 cache_add(format, dev);
288 strcat(format, "%d");
290 for (j = MAX; j; j--) {
291 sprintf(tem, format, j);
292 cache_add(tem, dev | j);
298 void cache_ide (char *name, int major)
300 char tem[PATH_MAX], tem2[PATH_MAX];
301 char format[PATH_MAX];
303 int i, dev, minor, host, bus, target;
304 int j = strlen(DEV_DISK_DIR) + 3;
313 sprintf(tem2, DEV_DIR "/ide/host%d/bus%d/target%d/lun0/", host, bus, target);
314 strcat(strcpy(format,tem2), "part%d");
315 disc = strcat(tem2, "disc");
318 strcat(strcpy(format, name), "%d");
321 dev = MKDEV(major,minor);
322 for (i = MAX; i; i--) {
323 sprintf(tem, format, i);
324 cache_add(tem, dev | i);
326 cache_add(disc, dev);
329 void preload_dev_cache(void)
338 if (verbose>0) verbose--;
342 cache_add(DEV_DIR "/floppy/0", 0x0200);
343 cache_add(DEV_DIR "/floppy/1", 0x0201);
346 cache_add(DEV_DIR "/fd0", 0x0200);
347 cache_add(DEV_DIR "/fd1", 0x0201);
350 cache_ide(DEV_DISK_DIR "/hdt", MAJOR_IDE10);
351 cache_ide(DEV_DISK_DIR "/hds", MAJOR_IDE10);
352 cache_ide(DEV_DISK_DIR "/hdr", MAJOR_IDE9);
353 cache_ide(DEV_DISK_DIR "/hdq", MAJOR_IDE9);
355 cache_ide(DEV_DISK_DIR "/hdp", MAJOR_IDE8);
356 cache_ide(DEV_DISK_DIR "/hdo", MAJOR_IDE8);
357 cache_ide(DEV_DISK_DIR "/hdn", MAJOR_IDE7);
358 cache_ide(DEV_DISK_DIR "/hdm", MAJOR_IDE7);
360 cache_ide(DEV_DISK_DIR "/hdl", MAJOR_IDE6);
361 cache_ide(DEV_DISK_DIR "/hdk", MAJOR_IDE6);
363 cache_ide(DEV_DISK_DIR "/hdj", MAJOR_IDE5);
364 cache_ide(DEV_DISK_DIR "/hdi", MAJOR_IDE5);
366 for (i = MAX; i >= 0; i--) {
367 sprintf(tmp, is_devfs() ? DEV_DISK_DIR "/md/%d" : DEV_DISK_DIR "/md%d", i);
368 cache_add(tmp, MKDEV(MAJOR_MD,i));
371 if (!is_devfs()) cache_scsi(DEV_DISK_DIR "/sda", MAJOR_SD);
373 cache_ide(DEV_DISK_DIR "/hdh", MAJOR_IDE4);
374 cache_ide(DEV_DISK_DIR "/hdg", MAJOR_IDE4);
375 cache_ide(DEV_DISK_DIR "/hdf", MAJOR_IDE3);
376 cache_ide(DEV_DISK_DIR "/hde", MAJOR_IDE3);
378 for (i = 0; i <= 7; i++) {
379 sprintf(tmp, is_devfs() ? DEV_DIR "/loop/%d" : DEV_DIR "/loop%d", i);
380 cache_add(tmp,0x700+i);
383 cache_ide(DEV_DISK_DIR "/hdd", MAJOR_IDE2);
384 cache_ide(DEV_DISK_DIR "/hdc", MAJOR_IDE2);
385 cache_ide(DEV_DISK_DIR "/hdb", MAJOR_IDE);
386 cache_ide(DEV_DISK_DIR "/hda", MAJOR_IDE);
394 static unsigned int idevices[NDEVICE];
395 static int maxdev = 0;
397 /* return 0 if device has not been backed up, */
398 /* 1 if it has been backed up */
400 static int dev_listed(unsigned short dev)
404 /* scan the device list */
405 for (i=0; i<maxdev; i++) {
406 if (dev==idevices[i]) return 1; /* already backed up */
409 if (maxdev < NDEVICE-1) idevices[maxdev++] = dev;
411 return 0; /* new to the list, not listed if too many devices */
415 /* make a backup, returning the timestamp of the backup file */
416 /* 0 if no timestamp returned, and no backup file created */
418 int make_backup(char *backup_file, int force_backup, BOOT_SECTOR *bsect,
419 unsigned int device, char *id)
422 char temp_name[PATH_MAX];
425 char *filename = "boot";
431 if ((cp=cfg_get_strg(cf_options,"force-backup"))) force=1;
432 else cp=cfg_get_strg(cf_options,"backup");
435 force_backup = force;
438 if (backup_file && stat(backup_file, &st) >= 0) {
439 /* file or directory exists */
440 if (S_ISDIR(st.st_mode)) {
441 if (strcmp(backup_file,"/")==0) backup_file = "";
442 sprintf(temp_name, "%s/%s.%04X", backup_file, filename, device);
443 backup_file = temp_name;
445 /* test for /dev/null */
446 else if (S_ISCHR(st.st_mode) && st.st_rdev==0x0103) return 0;
447 else if (!S_ISREG(st.st_mode))
448 die("make_backup: %s not a directory or regular file", backup_file);
451 /* could not stat it, or it was a directory, or it was a regular file */
454 char *name, *dir, suffix[16];
456 backup_file = strcpy(temp_name, backup_file);
457 sprintf(suffix, "%04X", device);
458 dir = strrchr(backup_file, '/');
459 if (!dir) dir = backup_file;
460 name = strrchr(dir, '.');
461 if (name) { /* there is a '.' in the name */
462 if (strcmp(name+1, suffix)==0) ; /* do nothing */
463 else if (strlen(name+1)==4) { /* && the suffix doesn't match */
464 strcpy(name+1,suffix);
466 else if (name[1]==0) strcat(name,suffix); /* ended with '.' */
469 strcat(backup_file,suffix);
471 /* we now have the filename with the correct suffix */
474 /* no '.' in the name, take it as a template */
475 strcat(backup_file,".");
476 strcat(backup_file,suffix);
480 /* if (!backup_file) */ {
481 sprintf(temp_name, BACKUP_DIR "/%s.%04X", filename, device);
482 backup_file = temp_name;
485 bck_file = open(backup_file, O_RDONLY);
486 if (bck_file >= 0 && force_backup) {
487 (void) close(bck_file);
492 printf("%s exists - no %s backup copy made.\n", backup_file, id);
495 if (dev_listed(device)) {
497 printf("Backup copy of %s has already been made in %s\n",
501 if ((bck_file = creat(backup_file, 0644)) < 0)
502 die("creat %s: %s",backup_file, strerror(errno));
503 if (write(bck_file, (char *)bsect, SECTOR_SIZE) != SECTOR_SIZE)
504 die("write %s: %s", backup_file, strerror(errno));
506 printf("Backup copy of %s in %s\n", id, backup_file);
507 if (fstat(bck_file, &st) < 0)
508 die("fstat %s: %s",backup_file,strerror(errno));
509 timestamp = st.st_mtime;
513 printf("Backup copy of %s in %s (test mode)\n", id, backup_file);
516 if (bck_file >= 0 && close(bck_file) < 0) die("close %s: %s",backup_file,strerror(errno));
524 int serial_valid(unsigned int serial, int disk_bios)
527 return (serial != 0);
529 if (serial == -1 || serial == 0) return 0;
532 /* if ID is replicated characters, it is invalid */
533 /* Examples of invalid Volume ID's are:
537 BUT: any Volume ID (except 0 or -1) is valid on drive C:
538 - - - - - - - - - - - - - - - - - - - - - - - - - - */
541 temp = serial & 0xFF;
545 return (serial != temp ||
546 (serial!=0 && serial!=0xFFFFFFFFUL && disk_bios==0x80));
550 int new_serial(int dev)
552 static int inited = 0;
557 #define RANDOM DEV_DIR "/urandom"
560 if ( stat(RANDOM, &st)==0 && S_ISCHR(st.st_mode)
561 && (fd = open(RANDOM, O_RDONLY)) > 0
562 && read(fd, &random, sizeof(random)) == sizeof(random) ) {
564 if(verbose>=5) printf("Using " RANDOM " for seeding random number generator\n");
572 dev = dev % PRIME + SMALL_PRIME;
573 while(dev--) inited = rand();
582 static int inited = 0;
583 unsigned int serial_no[MAX_BIOS_DEVICES];
584 static int device_code[MAX_BIOS_DEVICES];
586 /* register references to various bios devices
587 * compiles the list of volume IDs
588 * returns volume ID on success
592 unsigned int register_bios(int bios, int device)
594 int i, fd, valid, disk_bios;
597 unsigned int serial = -1;
601 for (i=0; i<MAX_BIOS_DEVICES; i++) {
611 if (!do_md_install && cfg_get_flag(cf_options, "static-bios-codes")) return 0;
614 printf("registering bios=0x%02X device=0x%04X\n", bios, device);
618 if (bios>=0x80 && bios<0x80+MAX_BIOS_DEVICES &&
619 (i=has_partitions(device))) {
620 bios &= 0x7F; /* mask to index */
621 device &= i; /* mask to master device */
622 if (device_code[bios]==0 && serial_no[bios]==0) { /* slot empty */
623 fd = dev_open(&dev, device, O_RDWR);
624 if (lseek(fd, 0L, SEEK_SET) < 0)
625 die("master boot record seek %04X: %s", device, strerror(errno));
626 if (read(fd, (char*)&buff, SECTOR_SIZE)!=SECTOR_SIZE)
627 die("read master boot record %04X: %s", device, strerror(errno));
628 serial = *(int*)&buff.sector[PART_TABLE_OFFSET-6];
629 valid = serial_valid(serial, disk_bios);
630 if ((!valid || (VERSION_MINOR>=50)) && !test)
631 make_backup(NULL, 0, &buff, device,
632 "master disk volume ID record");
634 i = device % PRIME + SMALL_PRIME;
635 while(i--) serial = rand();
636 for (; i<5 && !serial_valid(serial, disk_bios); i++) serial = rand();
637 if (!serial_valid(serial, disk_bios)) die("Volume ID generation error");
639 *(int*)&buff.sector[PART_TABLE_OFFSET-6] = serial;
640 if (*(short*)&buff.sector[PART_TABLE_OFFSET - 2] == 0)
641 *(unsigned short*)&buff.sector[PART_TABLE_OFFSET - 2] = MAGIC_SERIAL;
643 printf("Assigning new Volume ID to (%04X) '%s' ID = %08X\n",
644 device, dev.name, (int)serial);
646 i = lseek(fd, 0L, SEEK_SET);
647 if (i<0) die("master boot record2 seek %04X: %s", device, strerror(errno));
648 if (write(fd, (char*)&buff, SECTOR_SIZE)!=SECTOR_SIZE)
649 die("write master boot record %04X: %s", device, strerror(errno));
653 for (i=0; i<MAX_BIOS_DEVICES; i++) {
654 if (device_code[i]==device)
655 die("register_bios: device code duplicated: %04X", device);
656 if (serial_no[i]==serial)
657 die("register_bios: volume ID serial no. duplicated: %08X", serial);
659 device_code[bios] = device;
660 serial_no[bios] = serial;
664 if (device_code[bios]==device) serial = serial_no[bios];
668 dev_open(&dev, device_code[bios], O_BYPASS);
669 dev_open(&deva, device, O_BYPASS);
671 die("Bios device code 0x%02X is being used by two disks\n\t%s (0x%04X) and %s (0x%04X)",
672 bios|0x80, dev.name, device_code[bios], deva.name, device);
675 printf("Using Volume ID %08X on bios %02X\n", (int)serial, bios+0x80);
678 else if (bios>=0 && bios <=3) serial = 0;
685 void dump_serial_nos(void)
689 printf(" BIOS VolumeID Device\n");
691 for (j=nelem(serial_no); serial_no[--j]==0; ) ;
693 printf(" %02X %08X %04X\n",
701 enum {ID_GET=0, ID_SET};
703 static int volid_get_set(int device, int vol_in, int option)
711 if (!has_partitions(device) && (device & P_MASK(device)) )
712 die("VolumeID set/get bad device %04X\n", device);
714 fd = dev_open(&dev, device, option ? O_RDWR : O_RDONLY);
715 if (read(fd, &buf, sizeof(buf)) != sizeof(buf)) {
716 fprintf (errstd, "Cannot proceed. Maybe you need to add "
717 "this to your lilo.conf:\n"
718 "\tdisk=%s inaccessible\n"
719 "(real error shown below)\n", dev.name);
720 die("VolumeID read error: sector 0 of %s not readable", dev.name);
722 if (option==ID_SET) {
723 make_backup(NULL, 0, &buf, device,
724 "master disk volume ID record");
725 word = temp = buf.boot.volume_id & 0xFF; /* one char */
729 if (buf.boot.mbz==word
730 && buf.boot.volume_id==temp
731 && buf.boot.marker==word) {
732 buf.boot.mbz = buf.boot.marker = 0;
734 buf.boot.volume_id = vol_in;
735 if (buf.boot.marker == 0) buf.boot.marker = MAGIC_SERIAL;
737 if (lseek(fd, 0L, SEEK_SET) != 0L ||
738 write(fd, &buf, PART_TABLE_OFFSET) != PART_TABLE_OFFSET )
739 die("volid write error");
743 sync(); /* critical that this be done here */
745 return buf.boot.volume_id;
751 /* count the number of slashes in a pathname */
752 static int slashes(char *cp)
756 while ( (cp=strchr(++cp,'/')) ) n++;
763 enum {INVALID=1, DUPLICATE=2, REGENERATE=3, NTCAUTION=4};
766 char *name; /* the name of the disk; e.g. "/dev/hda" */
767 unsigned int device; /* the device number (major, minor) */
768 int sort; /* the device number used for sorting */
769 int flag; /* various flag bits */
770 char nt[PART_MAX]; /* flag partitions which might be NT */
771 DT_ENTRY *dt; /* pointer to any disktab entry */
773 int kernel; /* volume ID as read using kernel I/O */
774 int probe; /* volume ID as probed */
777 int user; /* user used a disk= bios= section */
778 int probe; /* passed in from the BIOS data check */
779 int actual; /* this is what we finally decide upon */
780 } bios; /* BIOS device codes */
785 /* return boolean if VM is a component drive of MDP-RAID */
787 static int is_mdp(struct VolumeMgmt *vm, struct VolumeMgmt *mdp)
791 struct md_version md_version_info;
792 md_array_info_t raid;
795 if (verbose>=2) printf("is_mdp: %04X : %04X\n",
796 vm->device, mdp->device);
798 if ((mdp_fd=dev_open(&dev, mdp->device, O_NOACCESS) ) < 0)
799 die("Unable to open %s", mdp->name);
801 if (ioctl(mdp_fd, RAID_VERSION, &md_version_info) < 0) ret = -1;
802 else if (md_version_info.major > 0 ||
803 md_version_info.minor < 90) {
806 warn("RAID versions other than 0.90 are not supported");
808 else if (ioctl(mdp_fd, GET_ARRAY_INFO, &raid) < 0) ret = -1;
809 else if (raid.level == 1) {
813 for (i=0; ret==0 && i<raid.active_disks; i++) {
815 if (ioctl(mdp_fd, GET_DISK_INFO, &disk) < 0) ret = -1;
816 if (vm->device == MKDEV(disk.major, disk.minor)) ret = 1;
819 /* else ret = 0; already */
822 if (verbose>=2) printf("is_mdp: returns %d\n", ret);
829 Returns 0 if not an NT, 2000, or XP boot disk (query user)
830 returns 1 if it is an NT ... boot disk; abort if fatal set
832 static int winnt_check(struct VolumeMgmt *vm, int fatal)
836 if ( !(vm->flag & NTCAUTION) ) return 0;
843 fprintf(stderr, "\n\nReference: disk \"%s\" (%d,%d) %04X\n\n"
844 "LILO wants to assign a new Volume ID to this disk drive. However, changing\n"
845 "the Volume ID of a Windows NT, 2000, or XP boot disk is a fatal Windows error.\n"
846 "This caution does not apply to Windows 95 or 98, or to NT data disks.\n"
847 , vm->name, MAJOR(dev), MINOR(dev), dev);
850 ret = yesno("\nIs the above disk an NT boot disk? ", 1);
853 fprintf(stderr, "Aborting ...\n");
863 #define SORT(d) (MAJOR(d)==MAJOR_SD?MKDEV(MAJOR_SD_SORT,MINOR(d)):\
864 MAJOR(d)==MAJOR_MDP?MKDEV(MAJOR_MDP_SORT,MINOR(d)):\
865 MAJOR(d)==MAJOR_EMD?MKDEV(MAJOR_EMD_SORT,MINOR(d)):\
866 MAJOR(d)==MAJOR_HPT370?MKDEV(MAJOR_HPT370_SORT,MINOR(d)):\
869 #define SORT(d) (MAJOR(d)==MAJOR_SD?MKDEV(MAJOR_SD_SORT,MINOR(d)):\
870 MAJOR(d)==MAJOR_EMD?MKDEV(MAJOR_EMD_SORT,MINOR(d)):\
871 MAJOR(d)==MAJOR_HPT370?MKDEV(MAJOR_HPT370_SORT,MINOR(d)):\
875 int pf_hard_disk_scan(void)
877 struct VolumeMgmt vm [MAX_DEVICES];
878 static int warned = 0, called = 0;
879 char *line, *next, *name;
880 int major, minor, i, ipart;
887 int duplicate = 0, invalid = 0, ret = 0, ntcaution = 0;
891 /* called from raid_setup & from geo_open */
892 /* allow only 1 call */
893 if (called || cfg_get_flag(cf_options,"static-bios-codes")) return ret;
895 memset(vm,0,sizeof(vm)); /* for consistency */
898 if (!pp_fd && (pp_fd = fopen(PARTITIONS, "r"))==NULL) {
900 if ((pp_fd = fopen(PARTITIONS, "r"))==NULL || fetch()) {
902 warn("'" PARTITIONS "' does not exist, disk scan bypassed");
908 while (!feof(pp_fd)) {
914 if (getline(&line, &n, pp_fd) <= 0) break;
916 major = strtoul(line, &next, 10);
917 if (major==0 || line==next) continue;
919 if (is_dm_major(major)) {
920 #ifndef LCF_DEVMAPPER
921 warn("device-mapper (%d) referenced in " PARTITIONS ",\n"
922 " but LILO is configured without DEVMAPPER option. Skipping device.", major);
926 else if ((major>=60 && major<=63) || (major>=120 && major<=127) ) {
927 warn(PARTITIONS " references Experimental major device %d.", major);
929 else if (major==255) {
930 warn(PARTITIONS " references Reserved device 255.");
933 else if (major>=240 && major<255) {
934 warn(PARTITIONS " references Experimental major device %d.", major);
937 minor = strtoul(next, &name, 10);
938 if (next==name) continue;
939 /* skip */ strtoull(name,&next,10);
941 while (isspace(*next)) next++;
943 while (*name && !isspace(*name)) name++;
945 if (strncmp(DEV_DISK_DIR "/", next, strlen(DEV_DISK_DIR)+1) != 0) name = next-(strlen(DEV_DISK_DIR)+1);
947 if (*name=='/') name++;
948 strncpy(name, DEV_DISK_DIR "/", strlen(DEV_DISK_DIR)+1);
950 printf("pf_hard_disk_scan: (%d,%d) %s\n", major, minor, name);
953 device = MKDEV(major, minor);
956 if (stat(name, &st) < 0) {
957 dev_open(&Dev, device, O_BYPASS);
959 warn("'" PARTITIONS "' does not match '" DEV_DISK_DIR "' directory structure.\n"
960 " Name change: '%s' -> '%s'%s"
962 slashes(name) > 3 && slashes(Dev.name) < 3 ? "\n"
963 " The kernel was compiled with DEVFS_FS, but 'devfs=mount' was omitted\n"
964 " as a kernel command-line boot parameter; hence, the '" DEV_DISK_DIR "' directory\n"
965 " structure does not reflect DEVFS_FS device names."
966 : slashes(name) < 3 && slashes(Dev.name) > 3 ? "\n"
967 " The kernel was compiled without DEVFS, but the '" DEV_DISK_DIR "' directory structure\n"
968 " implements the DEVFS filesystem."
975 warn("Name change: '%s' -> '%s'", name, Dev.name);
979 warn("'" DEV_DISK_DIR "' directory structure is incomplete; device (%d, %d) is missing.",
981 cache_add(name, device);
984 else cache_add(name, device);
986 mask = has_partitions(device);
987 dev = device & mask; /* dev is the master device */
988 ipart = device & P_MASK(device); /* ipart is the partition number */
991 for (walk=disktab; walk; walk=walk->next) {
992 if (walk->device == dev) {
993 if (walk->heads == 0 /* inaccessible */) {
994 if (ipart==0 && !identify)
995 warn("bypassing VolumeID scan of drive flagged INACCESSIBLE: %s", name);
996 ipart = -1; /* causes skip below */
1002 if (mask && ipart>0) {
1006 for (found=i=0; i<ndevs && !found; i++) {
1007 if (dev==vm[i].device) found = i+1;
1011 serial = volid_get_set(dev, 0, ID_GET);
1014 /* take care of uninitialized Volume IDs with no fanfare */
1016 serial = volid_get_set(dev, new_serial(dev), ID_SET);
1020 if (verbose>=3) printf("**ndevs=%d\n", ndevs);
1022 if (ndevs>=MAX_DEVICES) {
1023 die("More than %d hard disks are listed in '" PARTITIONS "'.\n"
1024 " Disks beyond the %dth must be marked:\n"
1025 " disk=" DEV_DISK_DIR "/XXXX inaccessible\n"
1026 " in the configuration file (" DFL_CONFIG ").\n"
1027 , MAX_DEVICES, MAX_DEVICES);
1033 dev_open(&Dev2,dev,O_BYPASS);
1035 vm[ndevs].device = dev;
1037 vm[ndevs].sort = SORT(dev);
1039 vm[ndevs].vol_id.kernel = serial;
1041 vm[ndevs].name = stralloc(Dev2.name);
1044 printf("pf: dev=%04X id=%08X name=%s\n", dev, (int)serial, Dev2.name);
1046 for (walk = disktab; walk; walk = walk->next) {
1047 if (walk->device == dev) {
1049 vm[ndevs].dt = walk; /* record disktab link */
1050 if (bios >= 0x80 && bios <= DEV_MASK) {
1051 vm[ndevs].bios.actual =
1052 vm[ndevs].bios.user = bios;
1054 if (codes & (1L<<bios)) {
1057 while (vm[i].bios.user != bios) i--;
1058 die("Disks '%s' and '%s' are both assigned 'bios=0x%02X'",
1059 vm[ndevs].name, vm[i].name, bios);
1061 codes |= 1L << bios; /* mark BIOS code in use */
1063 else if (bios != -1)
1064 die("Hard disk '%s' bios= specification out of the range [0x80..0x%02X]", Dev2.name, DEV_MASK);
1072 geo_query_dev(&geo, dev,
1073 MAJOR(dev)!=MAJOR_LOOP
1075 && MAJOR(dev)!=MAJOR_DM
1079 vm[ndevs].bios.probe = bios_device(&geo, dev);
1081 if (serial_valid(serial, DEV_MASK)) {
1082 for (i=0; i<ndevs; i++) {
1083 if (vm[i].vol_id.kernel==serial) {
1085 vm[i].flag |= DUPLICATE;
1086 vm[ndevs].flag |= DUPLICATE; /* mark both of them */
1091 vm[ndevs].flag |= INVALID;
1095 } /* if (open, lseek, read ) */
1099 if (ipart>0 && ipart<=PART_MAX) {
1101 if (part_nowrite(name) & PTW_NTFS) {
1102 vm[found].flag |= NTCAUTION;
1103 vm[found].nt[ipart-1] = NTCAUTION;
1105 if (verbose>=4) printf("NT partition: %s %d %s\n",
1106 vm[found].name, ipart, name);
1110 } /* if (mask && (device & P_MASK(device)) ) */
1112 } /* while (!feof()) */
1114 if (line) free(line);
1121 for (i=0; i<ndevs; i++)
1122 printf(" %04X %08X %s\n", vm[i].device, vm[i].vol_id.kernel, vm[i].name);
1125 if (verbose>=2) printf("pf_hard_disk_scan: ndevs=%d\n", ndevs);
1127 /* now sort the volumes into canonical order */
1131 for (j=ndevs-1; j>0; j--)
1133 if (vm[i].sort > vm[i+1].sort) {
1134 struct VolumeMgmt temp;
1140 /* now automatically treat MDP-RAID devices as inaccessible */
1141 for (k=0; k<ndevs; k++) {
1143 if (MAJOR(vm[k].device) == MAJOR_MDP ||
1144 MAJOR(vm[k].device) == MAJOR_EMD ) {
1146 if (verbose>=2) printf("MDP-RAID detected, k=%d\n", k);
1147 if (cfg_get_flag(cf_options, "noraid") ) {
1149 warn("RAID controller present, with \"noraid\" keyword used.\n"
1150 " Underlying drives individually must be marked INACCESSIBLE." );
1152 for (j=0; j<ndevs; j++) {
1153 if (j==k) break; /* skip ourselves */
1155 if ((i=is_mdp(&vm[j], &vm[k]))<0) {
1156 if (!identify) warn("(MDP-RAID driver) the kernel does not support underlying\n"
1157 " device inquiries. Each underlying drive of %s must\n"
1158 " individually be marked INACCESSIBLE.", vm[k].name
1160 j=ndevs; /* terminate loop */
1164 walk = alloc_t(DT_ENTRY);
1165 walk->device = vm[j].device;
1166 walk->cylinders = walk->heads = walk->sectors = walk->start = -1;
1167 walk->next = disktab;
1168 vm[j].dt = disktab = walk;
1170 if (verbose >= 4) printf("Allocated DT entry for device %04X ptr=%0*" PRIxPTR "\n", vm[j].device, , PTR_WIDTH, (intptr_t)walk);
1174 if (vm[j].dt->heads != 0) {
1175 vm[j].dt->heads = 0;
1176 warn("(MDP-RAID) underlying device flagged INACCESSIBLE: %s",
1180 warn("bypassing VolumeID check of underlying MDP-RAID drive:\n"
1182 vm[j].device, vm[j].vol_id.kernel, vm[j].name);
1183 for (i=j; i<ndevs; i++) vm[i] = vm[i+1];
1191 if (MAJOR(vm[k].device) == MAJOR_EMD ||
1192 MAJOR(vm[k].device) == MAJOR_MDP ) {
1194 warn("MDP-RAID controller present; underlying drives individually\n"
1195 " must be marked INACCESSIBLE." );
1201 if ((mdp_fd=dev_open(&dev, vm[k].device, O_NOACCESS) ) < 0)
1202 die("Unable to open %s",vm[k].name);
1210 if ( MAJOR(vm[k].device) == MAJOR_DM ) {
1211 if (verbose>=2) printf("ATA-RAID detected, k=%d\n", k);
1213 warn("ATA-RAID controller present;\n"
1214 " Underlying drives individually must be marked INACCESSIBLE." );
1221 for (i=0; i<ndevs; i++)
1222 printf(" %04X %08X %s\n", vm[i].device, vm[i].vol_id.kernel, vm[i].name);
1223 printf("Resolve invalid VolumeIDs\n");
1226 /* now go thru and resolve any invalid VolumeIDs */
1229 for (i=0; i<ndevs; i++)
1230 if (vm[i].flag & INVALID) {
1231 if (ndevs>1) winnt_check(&vm[i], 1);
1232 else if (vm[i].flag & NTCAUTION) break;
1235 vm[i].vol_id.kernel = volid_get_set(dev, new_serial(dev), ID_SET);
1236 vm[i].flag &= ~INVALID;
1240 printf("Resolve duplicate VolumeIDs\n");
1242 /* now check for duplicates */
1244 while (duplicate) { /* loop until there are none */
1248 raidcaution = 0; /* print comment only once */
1249 warn("Duplicated VolumeID's will be overwritten;\n"
1250 " With RAID present, this may defeat all boot redundancy.\n"
1251 " Underlying RAID-1 drives should be marked INACCESSIBLE.\n"
1252 " Check 'man lilo.conf' under 'disk=', 'inaccessible' option."
1256 for (j=ndevs-1; j>0; j--) {
1257 for (i=0; i<j; i++) {
1258 if (vm[i].vol_id.kernel == vm[j].vol_id.kernel) {
1259 if (vm[i].flag & vm[j].flag & NTCAUTION) {
1260 if (!winnt_check(&vm[j], 0)) k = j;
1261 else winnt_check(&vm[k=i], 1);
1263 else if (vm[i].flag & NTCAUTION) k = j;
1264 else if (vm[j].flag & NTCAUTION) k = i;
1268 vm[k].vol_id.kernel = volid_get_set(dev, new_serial(dev), ID_SET);
1273 } /* while (duplicate) */
1278 for (i=0; i<ndevs; i++)
1279 printf(" %04X %08X %s\n", vm[i].device, vm[i].vol_id.kernel, vm[i].name);
1284 if (verbose>=2) printf("device codes (user assigned pf) = %" PRIX32 "\n", codes);
1286 /* mark those BIOS codes that are already used in the disk=/bios= table */
1288 for (walk=disktab; walk; walk=walk->next) {
1289 if (walk->bios >= 0x80) { /* eliminate -1 and floppies */
1290 if (MAJOR(walk->device)==MAJOR_MD) continue;
1291 bios = walk->bios & 0x7F;
1292 if (bios >= 8*sizeof(codes) || bios >= MAX_BIOS_DEVICES)
1293 die("BIOS code %02X is too big (device %04X)", bios+0x80, walk->device);
1294 if (codes & (1L<<bios)) {
1298 for (i=0; i<ndevs; i++) {
1299 if (vm[i].device == walk->device) j = i;
1300 else if (vm[i].bios.user == bios+0x80) k = i;
1303 if (verbose>=3) printf("J=%d K=%d\n", j, k);
1306 die("Devices %04X and %04X are assigned to BIOS 0x%02X",
1307 vm[k].device, walk->device, bios+0x80);
1310 codes |= 1L << bios;
1314 if (verbose>=2) printf("device codes (user assigned) = %" PRIX32 "\n", codes);
1316 for (i=0; i<ndevs; i++) {
1317 bios = vm[i].bios.probe;
1319 if (vm[i].bios.actual < 0x80 && !(codes & (1L<<(bios&0x7F)))) {
1320 vm[i].bios.actual = bios;
1322 codes |= 1L << bios;
1327 if (verbose>=2) printf("device codes (BIOS assigned) = %" PRIX32 "\n", codes);
1329 for (bios=i=0; i<ndevs; i++) {
1333 if (vm[i].bios.actual < 0x80) {
1334 while ( codes & (1L<<bios) ) bios++;
1335 if (bios < MAX_BIOS_DEVICES) {
1337 vm[i].bios.actual = 0x80+bios;
1338 if (verbose>=3) printf("Filling in '%s' = 0x%02X\n", vm[i].name, bios+0x80);
1340 else vm[i].bios.actual = -1;
1343 walk = alloc_t(DT_ENTRY);
1344 walk->device = vm[i].device;
1345 walk->cylinders = walk->bios = walk->heads = walk->sectors = walk->start = -1;
1346 walk->next = disktab;
1347 vm[i].dt = disktab = walk;
1349 if (verbose >= 4) printf("Allocated DT entry for device %04X ptr=%0*" PRIxPTR "\n", vm[i].device, PTR_WIDTH, (intptr_t)walk);
1352 j = vm[i].dt->bios = vm[i].bios.actual;
1355 if (j < MAX_BIOS_DEVICES) {
1356 serial_no[j] = vm[i].vol_id.kernel;
1357 device_code[j] = vm[i].device;
1360 printf("Generated: %02X %04X %08X\n", j+0x80, device_code[j], (int)serial_no[j]);
1365 vm[i].dt->heads = 0; /* mark inaccessible */
1368 if (!(i++)) warn("Internal implementation restriction. Boot may occur from the first\n"
1369 " %d disks only. Disks beyond the %dth will be flagged INACCESSIBLE."
1370 , MAX_BIOS_DEVICES, MAX_BIOS_DEVICES);
1371 warn("'disk=%s inaccessible' is being assumed. (%04X)",
1372 vm[i].name, vm[i].device);
1379 if (verbose>=2) printf("device codes (canonical) = %" PRIX32 "\n", codes);
1381 for (bios=8*sizeof(codes)-1; !(codes&(1L<<bios)) && bios>=0; ) bios--;
1384 warn("BIOS device code 0x%02X is used (>0x%02X). It indicates more disks\n"
1385 " than those represented in '/proc/partitions' having actual partitions.\n"
1386 " Booting results may be unpredictable.", bios+0x80, ndevs+0x80-1);