1 /* deviceiter.c - iterate over system devices */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
32 #include <grub/util/misc.h>
33 #include <grub/util/deviceiter.h>
36 # if !defined(__GLIBC__) || \
37 ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
38 /* Maybe libc doesn't have large file support. */
39 # include <linux/unistd.h> /* _llseek */
40 # endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
41 # include <sys/ioctl.h> /* ioctl */
43 # define HDIO_GETGEO 0x0301 /* get device geometry */
44 /* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
49 unsigned char sectors
;
50 unsigned short cylinders
;
53 # endif /* ! HDIO_GETGEO */
55 # define FLOPPY_MAJOR 2 /* the major number for floppy */
56 # endif /* ! FLOPPY_MAJOR */
60 unsigned long long __dev = (dev); \
61 (unsigned) ((__dev >> 8) & 0xfff) \
62 | ((unsigned int) (__dev >> 32) & ~0xfff); \
65 # ifndef CDROM_GET_CAPABILITY
66 # define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
67 # endif /* ! CDROM_GET_CAPABILITY */
69 # define BLKGETSIZE _IO(0x12,96) /* return device size */
70 # endif /* ! BLKGETSIZE */
71 #endif /* __linux__ */
73 /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
74 kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */
75 #if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__)
76 # define __FreeBSD_kernel__
78 #ifdef __FreeBSD_kernel__
79 /* Obtain version of kFreeBSD headers */
80 # include <osreldate.h>
81 # ifndef __FreeBSD_kernel_version
82 # define __FreeBSD_kernel_version __FreeBSD_version
85 /* Runtime detection of kernel */
86 # include <sys/utsname.h>
88 get_kfreebsd_version (void)
96 sscanf (uts
.release
, "%d.%d", &major
, &minor
);
102 v
[0] = minor
/10; v
[1] = minor
%10;
106 v
[0] = minor
%10; v
[1] = minor
/10;
108 return major
*100000+v
[0]*10000+v
[1]*1000;
110 #endif /* __FreeBSD_kernel__ */
112 #if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
113 # include <sys/ioctl.h> /* ioctl */
114 # include <sys/disklabel.h>
115 # include <sys/cdio.h> /* CDIOCCLRDEBUG */
116 # if defined(__FreeBSD_kernel__)
117 # include <sys/param.h>
118 # if __FreeBSD_kernel_version >= 500040
119 # include <sys/disk.h>
121 # endif /* __FreeBSD_kernel__ */
122 #endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
126 #endif /* HAVE_OPENDISK */
129 /* Check if we have devfs support. */
134 return stat ("/dev/.devfsd", &st
) == 0;
136 #endif /* __linux__ */
138 /* These three functions are quite different among OSes. */
140 get_floppy_disk_name (char *name
, int unit
)
142 #if defined(__linux__)
145 sprintf (name
, "/dev/floppy/%d", unit
);
147 sprintf (name
, "/dev/fd%d", unit
);
148 #elif defined(__GNU__)
150 sprintf (name
, "/dev/fd%d", unit
);
151 #elif defined(__FreeBSD_kernel__)
153 if (get_kfreebsd_version () >= 400000)
154 sprintf (name
, "/dev/fd%d", unit
);
156 sprintf (name
, "/dev/rfd%d", unit
);
157 #elif defined(__NetBSD__)
159 /* opendisk() doesn't work for floppies. */
160 sprintf (name
, "/dev/rfd%da", unit
);
161 #elif defined(__OpenBSD__)
163 sprintf (name
, "/dev/rfd%dc", unit
);
164 #elif defined(__QNXNTO__)
166 sprintf (name
, "/dev/fd%d", unit
);
167 #elif defined(__CYGWIN__)
169 sprintf (name
, "/dev/fd%d", unit
);
170 #elif defined(__MINGW32__)
174 # warning "BIOS floppy drives cannot be guessed in your operating system."
175 /* Set NAME to a bogus string. */
181 get_ide_disk_name (char *name
, int unit
)
183 #if defined(__linux__)
185 sprintf (name
, "/dev/hd%c", unit
+ 'a');
186 #elif defined(__GNU__)
188 sprintf (name
, "/dev/hd%d", unit
);
189 #elif defined(__FreeBSD_kernel__)
191 if (get_kfreebsd_version () >= 400000)
192 sprintf (name
, "/dev/ad%d", unit
);
194 sprintf (name
, "/dev/rwd%d", unit
);
195 #elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
200 sprintf (shortname
, "wd%d", unit
);
201 fd
= opendisk (shortname
, O_RDONLY
, name
,
202 16, /* length of NAME */
206 #elif defined(__OpenBSD__)
208 sprintf (name
, "/dev/rwd%dc", unit
);
209 #elif defined(__QNXNTO__)
211 /* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
212 contain SCSI disks. */
213 sprintf (name
, "/dev/hd%d", unit
);
214 #elif defined(__CYGWIN__)
215 /* Cygwin emulates all disks as /dev/sdX. */
218 #elif defined(__MINGW32__)
219 sprintf (name
, "//./PHYSICALDRIVE%d", unit
);
221 # warning "BIOS IDE drives cannot be guessed in your operating system."
222 /* Set NAME to a bogus string. */
228 get_scsi_disk_name (char *name
, int unit
)
230 #if defined(__linux__)
232 sprintf (name
, "/dev/sd%c", unit
+ 'a');
233 #elif defined(__GNU__)
235 sprintf (name
, "/dev/sd%d", unit
);
236 #elif defined(__FreeBSD_kernel__)
238 if (get_kfreebsd_version () >= 400000)
239 sprintf (name
, "/dev/da%d", unit
);
241 sprintf (name
, "/dev/rda%d", unit
);
242 #elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
247 sprintf (shortname
, "sd%d", unit
);
248 fd
= opendisk (shortname
, O_RDONLY
, name
,
249 16, /* length of NAME */
253 #elif defined(__OpenBSD__)
255 sprintf (name
, "/dev/rsd%dc", unit
);
256 #elif defined(__QNXNTO__)
258 /* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
259 disable the detection of SCSI disks here. */
261 #elif defined(__CYGWIN__)
262 /* Cygwin emulates all disks as /dev/sdX. */
263 sprintf (name
, "/dev/sd%c", unit
+ 'a');
264 #elif defined(__MINGW32__)
268 # warning "BIOS SCSI drives cannot be guessed in your operating system."
269 /* Set NAME to a bogus string. */
276 get_virtio_disk_name (char *name
, int unit
)
279 sprintf (name
, "/dev/vdisk%c", unit
+ 'a');
281 sprintf (name
, "/dev/vd%c", unit
+ 'a');
286 get_dac960_disk_name (char *name
, int controller
, int drive
)
288 sprintf (name
, "/dev/rd/c%dd%d", controller
, drive
);
292 get_ataraid_disk_name (char *name
, int unit
)
294 sprintf (name
, "/dev/ataraid/d%c", unit
+ '0');
298 get_i2o_disk_name (char *name
, char unit
)
300 sprintf (name
, "/dev/i2o/hd%c", unit
);
304 get_cciss_disk_name (char *name
, int controller
, int drive
)
306 sprintf (name
, "/dev/cciss/c%dd%d", controller
, drive
);
310 get_ida_disk_name (char *name
, int controller
, int drive
)
312 sprintf (name
, "/dev/ida/c%dd%d", controller
, drive
);
316 get_mmc_disk_name (char *name
, int unit
)
318 sprintf (name
, "/dev/mmcblk%d", unit
);
322 get_xvd_disk_name (char *name
, int unit
)
324 sprintf (name
, "/dev/xvd%c", unit
+ 'a');
328 /* Check if DEVICE can be read. If an error occurs, return zero,
329 otherwise return non-zero. */
331 check_device (const char *device
)
336 /* If DEVICE is empty, just return error. */
340 fp
= fopen (device
, "r");
348 /* At the moment, this finds only CDROMs, which can't be
349 read anyway, so leave it out. Code should be
350 reactivated if `removable disks' and CDROMs are
352 /* Accept it, it may be inserted. */
356 #endif /* ENOMEDIUM */
358 /* Break case and leave. */
361 /* Error opening the device. */
365 /* Make sure CD-ROMs don't get assigned a BIOS disk number
366 before SCSI disks! */
368 # ifdef CDROM_GET_CAPABILITY
369 if (ioctl (fileno (fp
), CDROM_GET_CAPABILITY
, 0) >= 0)
371 # else /* ! CDROM_GET_CAPABILITY */
372 /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */
374 struct hd_geometry hdg
;
377 if (fstat (fileno (fp
), &st
))
380 /* If it is a block device and isn't a floppy, check if HDIO_GETGEO
382 if (S_ISBLK (st
.st_mode
)
383 && MAJOR (st
.st_rdev
) != FLOPPY_MAJOR
384 && ioctl (fileno (fp
), HDIO_GETGEO
, &hdg
))
387 # endif /* ! CDROM_GET_CAPABILITY */
388 #endif /* __linux__ */
390 #if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
391 # ifdef CDIOCCLRDEBUG
392 if (ioctl (fileno (fp
), CDIOCCLRDEBUG
, 0) >= 0)
394 # endif /* CDIOCCLRDEBUG */
395 #endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
397 /* Attempt to read the first sector. */
398 if (fread (buf
, 1, 512, fp
) != 512)
409 grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook
) (const char *, int),
415 for (i
= 0; i
< floppy_disks
; i
++)
420 get_floppy_disk_name (name
, i
);
421 if (stat (name
, &st
) < 0)
423 /* In floppies, write the map, whether check_device succeeds
424 or not, because the user just may not insert floppies. */
439 /* Linux creates symlinks "/dev/discs/discN" for convenience.
440 The way to number disks is the same as GRUB's. */
441 sprintf (discn
, "/dev/discs/disc%d", i
++);
442 if (stat (discn
, &st
) < 0)
445 if (realpath (discn
, name
))
447 strcat (name
, "/disc");
454 #endif /* __linux__ */
457 for (i
= 0; i
< 26; i
++)
461 get_ide_disk_name (name
, i
);
462 if (check_device (name
))
471 for (i
= 0; i
< 26; i
++)
475 get_virtio_disk_name (name
, i
);
476 if (check_device (name
))
484 for (i
= 0; i
< 8; i
++)
488 get_ataraid_disk_name (name
, i
);
489 if (check_device (name
))
496 /* Xen virtual block devices. */
497 for (i
= 0; i
< 26; i
++)
501 get_xvd_disk_name (name
, i
);
502 if (check_device (name
))
508 #endif /* __linux__ */
510 /* The rest is SCSI disks. */
511 for (i
= 0; i
< 26; i
++)
515 get_scsi_disk_name (name
, i
);
516 if (check_device (name
))
524 /* This is for DAC960 - we have
525 /dev/rd/c<controller>d<logical drive>p<partition>.
527 DAC960 driver currently supports up to 8 controllers, 32 logical
528 drives, and 7 partitions. */
530 int controller
, drive
;
532 for (controller
= 0; controller
< 8; controller
++)
534 for (drive
= 0; drive
< 15; drive
++)
538 get_dac960_disk_name (name
, controller
, drive
);
539 if (check_device (name
))
548 /* This is for CCISS - we have
549 /dev/cciss/c<controller>d<logical drive>p<partition>. */
551 int controller
, drive
;
553 for (controller
= 0; controller
< 3; controller
++)
555 for (drive
= 0; drive
< 16; drive
++)
559 get_cciss_disk_name (name
, controller
, drive
);
560 if (check_device (name
))
569 /* This is for Compaq Intelligent Drive Array - we have
570 /dev/ida/c<controller>d<logical drive>p<partition>. */
572 int controller
, drive
;
574 for (controller
= 0; controller
< 3; controller
++)
576 for (drive
= 0; drive
< 16; drive
++)
580 get_ida_disk_name (name
, controller
, drive
);
581 if (check_device (name
))
590 /* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
594 for (unit
= 'a'; unit
< 'f'; unit
++)
598 get_i2o_disk_name (name
, unit
);
599 if (check_device (name
))
607 /* MultiMediaCard (MMC). */
608 for (i
= 0; i
< 10; i
++)
612 get_mmc_disk_name (name
, i
);
613 if (check_device (name
))
619 #endif /* __linux__ */