2007-05-16 Robert Millan <rmh@aybabtu.com>
* include/grub/i386/pc/util/biosdisk.h: Moved to ... * include/grub/util/biosdisk.h: ... here. * util/i386/pc/biosdisk.c: Moved to ... * util/biosdisk.c: ... here. * util/i386/pc/getroot.c: Moved to ... * util/getroot.c: ... here. * util/i386/pc/grub-mkdevicemap.c: Moved to ... * util/grub-mkdevicemap.c: ... here. * util/i386/pc/grub-probe.c: Moved to ... * util/grub-probe.c: ... here.
This commit is contained in:
parent
bdc79cd1b3
commit
2d1a40a90c
6 changed files with 13 additions and 0 deletions
|
@ -1,876 +0,0 @@
|
|||
/* biosdisk.c - emulate biosdisk */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <grub/machine/biosdisk.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/pc_partition.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/util/misc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef __linux__
|
||||
# include <sys/ioctl.h> /* ioctl */
|
||||
# if !defined(__GLIBC__) || \
|
||||
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
|
||||
/* Maybe libc doesn't have large file support. */
|
||||
# include <linux/unistd.h> /* _llseek */
|
||||
# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
|
||||
# ifndef BLKFLSBUF
|
||||
# define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */
|
||||
# endif /* ! BLKFLSBUF */
|
||||
# include <sys/ioctl.h> /* ioctl */
|
||||
# ifndef HDIO_GETGEO
|
||||
# define HDIO_GETGEO 0x0301 /* get device geometry */
|
||||
/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
|
||||
defined. */
|
||||
struct hd_geometry
|
||||
{
|
||||
unsigned char heads;
|
||||
unsigned char sectors;
|
||||
unsigned short cylinders;
|
||||
unsigned long start;
|
||||
};
|
||||
# endif /* ! HDIO_GETGEO */
|
||||
# ifndef BLKGETSIZE
|
||||
# define BLKGETSIZE _IO(0x12,96) /* return device size */
|
||||
# endif /* ! BLKGETSIZE */
|
||||
# ifndef MAJOR
|
||||
# ifndef MINORBITS
|
||||
# define MINORBITS 8
|
||||
# endif /* ! MINORBITS */
|
||||
# define MAJOR(dev) ((unsigned) ((dev) >> MINORBITS))
|
||||
# endif /* ! MAJOR */
|
||||
# ifndef FLOPPY_MAJOR
|
||||
# define FLOPPY_MAJOR 2
|
||||
# endif /* ! FLOPPY_MAJOR */
|
||||
# ifndef LOOP_MAJOR
|
||||
# define LOOP_MAJOR 7
|
||||
# endif /* ! LOOP_MAJOR */
|
||||
#endif /* __linux__ */
|
||||
|
||||
static char *map[256];
|
||||
|
||||
#ifdef __linux__
|
||||
/* Check if we have devfs support. */
|
||||
static int
|
||||
have_devfs (void)
|
||||
{
|
||||
static int dev_devfsd_exists = -1;
|
||||
|
||||
if (dev_devfsd_exists < 0)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0;
|
||||
}
|
||||
|
||||
return dev_devfsd_exists;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
static int
|
||||
get_drive (const char *name)
|
||||
{
|
||||
unsigned long drive;
|
||||
char *p;
|
||||
|
||||
if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
|
||||
goto fail;
|
||||
|
||||
drive = strtoul (name + 2, &p, 10);
|
||||
if (p == name + 2)
|
||||
goto fail;
|
||||
|
||||
if (name[0] == 'h')
|
||||
drive += 0x80;
|
||||
|
||||
if (drive > sizeof (map) / sizeof (map[0]))
|
||||
goto fail;
|
||||
|
||||
return (int) drive;
|
||||
|
||||
fail:
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a biosdisk");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
call_hook (int (*hook) (const char *name), int drive)
|
||||
{
|
||||
char name[10];
|
||||
|
||||
sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
|
||||
return hook (name);
|
||||
}
|
||||
|
||||
static int
|
||||
grub_util_biosdisk_iterate (int (*hook) (const char *name))
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||||
if (map[i] && call_hook (hook, i))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||
{
|
||||
int drive;
|
||||
struct stat st;
|
||||
|
||||
drive = get_drive (name);
|
||||
if (drive < 0)
|
||||
return grub_errno;
|
||||
|
||||
if (! map[drive])
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"no mapping exists for `%s'", name);
|
||||
|
||||
disk->has_partitions = (drive & 0x80);
|
||||
disk->id = drive;
|
||||
|
||||
/* Get the size. */
|
||||
#ifdef __linux__
|
||||
{
|
||||
unsigned long nr;
|
||||
int fd;
|
||||
|
||||
fd = open (map[drive], O_RDONLY);
|
||||
if (! fd)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[drive]);
|
||||
|
||||
if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
|
||||
{
|
||||
close (fd);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ioctl (fd, BLKGETSIZE, &nr))
|
||||
{
|
||||
close (fd);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
disk->total_sectors = nr;
|
||||
|
||||
grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
fail:
|
||||
/* In GNU/Hurd, stat() will return the right size. */
|
||||
#elif !defined (__GNU__)
|
||||
# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
|
||||
#endif
|
||||
if (stat (map[drive], &st) < 0)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive]);
|
||||
|
||||
disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
|
||||
|
||||
grub_util_info ("the size of %s is %lu", name, disk->total_sectors);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static int
|
||||
linux_find_partition (char *dev, unsigned long sector)
|
||||
{
|
||||
size_t len = strlen (dev);
|
||||
const char *format;
|
||||
char *p;
|
||||
int i;
|
||||
char *real_dev;
|
||||
|
||||
real_dev = xstrdup (dev);
|
||||
|
||||
if (have_devfs () && strcmp (real_dev + len - 5, "/disc") == 0)
|
||||
{
|
||||
p = real_dev + len - 4;
|
||||
format = "part%d";
|
||||
}
|
||||
else if ((strncmp (real_dev + 5, "hd", 2) == 0
|
||||
|| strncmp (real_dev + 5, "sd", 2) == 0)
|
||||
&& real_dev[7] >= 'a' && real_dev[7] <= 'z')
|
||||
{
|
||||
p = real_dev + 8;
|
||||
format = "%d";
|
||||
}
|
||||
else if (strncmp (real_dev + 5, "rd/c", 4) == 0)
|
||||
{
|
||||
p = strchr (real_dev + 9, 'd');
|
||||
if (! p)
|
||||
{
|
||||
free (real_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p++;
|
||||
while (*p && isdigit (*p))
|
||||
p++;
|
||||
|
||||
format = "p%d";
|
||||
}
|
||||
else
|
||||
{
|
||||
free (real_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i < 10000; i++)
|
||||
{
|
||||
int fd;
|
||||
struct hd_geometry hdg;
|
||||
|
||||
sprintf (p, format, i);
|
||||
fd = open (real_dev, O_RDONLY);
|
||||
if (! fd)
|
||||
{
|
||||
free (real_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ioctl (fd, HDIO_GETGEO, &hdg))
|
||||
{
|
||||
close (fd);
|
||||
free (real_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
if (hdg.start == sector)
|
||||
{
|
||||
strcpy (dev, real_dev);
|
||||
free (real_dev);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
free (real_dev);
|
||||
return 0;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
static int
|
||||
open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||
{
|
||||
int fd;
|
||||
|
||||
#ifdef O_LARGEFILE
|
||||
flags |= O_LARGEFILE;
|
||||
#endif
|
||||
#ifdef O_SYNC
|
||||
flags |= O_SYNC;
|
||||
#endif
|
||||
#ifdef O_FSYNC
|
||||
flags |= O_FSYNC;
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
/* Linux has a bug that the disk cache for a whole disk is not consistent
|
||||
with the one for a partition of the disk. */
|
||||
{
|
||||
int is_partition = 0;
|
||||
char dev[PATH_MAX];
|
||||
|
||||
strcpy (dev, map[disk->id]);
|
||||
if (disk->partition && strncmp (map[disk->id], "/dev/", 5) == 0)
|
||||
is_partition = linux_find_partition (dev, disk->partition->start);
|
||||
|
||||
/* Open the partition. */
|
||||
grub_util_info ("opening the device `%s'", dev);
|
||||
fd = open (dev, flags);
|
||||
if (fd < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make the buffer cache consistent with the physical disk. */
|
||||
ioctl (fd, BLKFLSBUF, 0);
|
||||
|
||||
if (is_partition)
|
||||
sector -= disk->partition->start;
|
||||
}
|
||||
#else /* ! __linux__ */
|
||||
fd = open (map[disk->id], flags);
|
||||
if (fd < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[disk->id]);
|
||||
return -1;
|
||||
}
|
||||
#endif /* ! __linux__ */
|
||||
|
||||
#if defined(__linux__) && (!defined(__GLIBC__) || \
|
||||
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
|
||||
/* Maybe libc doesn't have large file support. */
|
||||
{
|
||||
loff_t offset, result;
|
||||
static int _llseek (uint filedes, ulong hi, ulong lo,
|
||||
loff_t *res, uint wh);
|
||||
_syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
|
||||
loff_t *, res, uint, wh);
|
||||
|
||||
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
|
||||
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id]);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
off_t offset = (off_t) sector << GRUB_DISK_SECTOR_BITS;
|
||||
|
||||
if (lseek (fd, offset, SEEK_SET) != offset)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id]);
|
||||
close (fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
|
||||
error occurs, otherwise return LEN. */
|
||||
static ssize_t
|
||||
nread (int fd, char *buf, size_t len)
|
||||
{
|
||||
ssize_t size = len;
|
||||
|
||||
while (len)
|
||||
{
|
||||
ssize_t ret = read (fd, buf, len);
|
||||
|
||||
if (ret <= 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
len -= ret;
|
||||
buf += ret;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
|
||||
error occurs, otherwise return LEN. */
|
||||
static ssize_t
|
||||
nwrite (int fd, const char *buf, size_t len)
|
||||
{
|
||||
ssize_t size = len;
|
||||
|
||||
while (len)
|
||||
{
|
||||
ssize_t ret = write (fd, buf, len);
|
||||
|
||||
if (ret <= 0)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
len -= ret;
|
||||
buf += ret;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, char *buf)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open_device (disk, sector, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return grub_errno;
|
||||
|
||||
#ifdef __linux__
|
||||
if (sector == 0 && size > 1)
|
||||
{
|
||||
/* Work around a bug in linux's ez remapping. Linux remaps all
|
||||
sectors that are read together with the MBR in one read. It
|
||||
should only remap the MBR, so we split the read in two
|
||||
parts. -jochen */
|
||||
if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
|
||||
{
|
||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id]);
|
||||
close (fd);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
buf += GRUB_DISK_SECTOR_SIZE;
|
||||
size--;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
||||
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id]);
|
||||
|
||||
close (fd);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, const char *buf)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open_device (disk, sector, O_WRONLY);
|
||||
if (fd < 0)
|
||||
return grub_errno;
|
||||
|
||||
if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
||||
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id]);
|
||||
|
||||
close (fd);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static struct grub_disk_dev grub_util_biosdisk_dev =
|
||||
{
|
||||
.name = "biosdisk",
|
||||
.id = GRUB_DISK_DEVICE_BIOSDISK_ID,
|
||||
.iterate = grub_util_biosdisk_iterate,
|
||||
.open = grub_util_biosdisk_open,
|
||||
.close = 0,
|
||||
.read = grub_util_biosdisk_read,
|
||||
.write = grub_util_biosdisk_write,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
static void
|
||||
read_device_map (const char *dev_map)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[1024]; /* XXX */
|
||||
int lineno = 0;
|
||||
auto void show_error (const char *msg);
|
||||
|
||||
void show_error (const char *msg)
|
||||
{
|
||||
grub_util_error ("%s:%d: %s", dev_map, lineno, msg);
|
||||
}
|
||||
|
||||
fp = fopen (dev_map, "r");
|
||||
if (! fp)
|
||||
grub_util_error ("Cannot open `%s'", dev_map);
|
||||
|
||||
while (fgets (buf, sizeof (buf), fp))
|
||||
{
|
||||
char *p = buf;
|
||||
char *e;
|
||||
int drive;
|
||||
|
||||
lineno++;
|
||||
|
||||
/* Skip leading spaces. */
|
||||
while (*p && isspace (*p))
|
||||
p++;
|
||||
|
||||
/* If the first character is `#' or NUL, skip this line. */
|
||||
if (*p == '\0' || *p == '#')
|
||||
continue;
|
||||
|
||||
if (*p != '(')
|
||||
show_error ("No open parenthesis found");
|
||||
|
||||
p++;
|
||||
drive = get_drive (p);
|
||||
if (drive < 0 || drive >= (int) (sizeof (map) / sizeof (map[0])))
|
||||
show_error ("Bad device name");
|
||||
|
||||
p = strchr (p, ')');
|
||||
if (! p)
|
||||
show_error ("No close parenthesis found");
|
||||
|
||||
p++;
|
||||
/* Skip leading spaces. */
|
||||
while (*p && isspace (*p))
|
||||
p++;
|
||||
|
||||
if (*p == '\0')
|
||||
show_error ("No filename found");
|
||||
|
||||
/* NUL-terminate the filename. */
|
||||
e = p;
|
||||
while (*e && ! isspace (*e))
|
||||
e++;
|
||||
*e = '\0';
|
||||
|
||||
/* Multiple entries for a given drive is not allowed. */
|
||||
if (map[drive])
|
||||
show_error ("Duplicated entry found");
|
||||
|
||||
#ifdef __linux__
|
||||
/* On Linux, the devfs uses symbolic links horribly, and that
|
||||
confuses the interface very much, so use realpath to expand
|
||||
symbolic links. */
|
||||
map[drive] = xmalloc (PATH_MAX);
|
||||
if (! realpath (p, map[drive]))
|
||||
grub_util_error ("Cannot get the real path of `%s'", p);
|
||||
#else
|
||||
map[drive] = xstrdup (p);
|
||||
#endif
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
void
|
||||
grub_util_biosdisk_init (const char *dev_map)
|
||||
{
|
||||
read_device_map (dev_map);
|
||||
grub_disk_dev_register (&grub_util_biosdisk_dev);
|
||||
}
|
||||
|
||||
void
|
||||
grub_util_biosdisk_fini (void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||||
free (map[i]);
|
||||
|
||||
grub_disk_dev_unregister (&grub_util_biosdisk_dev);
|
||||
}
|
||||
|
||||
static char *
|
||||
make_device_name (int drive, int dos_part, int bsd_part)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = xmalloc (30);
|
||||
sprintf (p, (drive & 0x80) ? "hd%d" : "fd%d", drive & ~0x80);
|
||||
|
||||
if (dos_part >= 0)
|
||||
sprintf (p + strlen (p), ",%d", dos_part + 1);
|
||||
|
||||
if (bsd_part >= 0)
|
||||
sprintf (p + strlen (p), ",%c", bsd_part + 'a');
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_os_disk (const char *os_dev)
|
||||
{
|
||||
char *path, *p;
|
||||
|
||||
#if defined(__linux__)
|
||||
path = xmalloc (PATH_MAX);
|
||||
if (! realpath (os_dev, path))
|
||||
return 0;
|
||||
|
||||
if (strncmp ("/dev/", path, 5) == 0)
|
||||
{
|
||||
p = path + 5;
|
||||
|
||||
if (have_devfs ())
|
||||
{
|
||||
/* If this is an IDE disk. */
|
||||
if (strncmp ("/dev/ide/", p, 9) == 0)
|
||||
{
|
||||
p = strstr (p, "part");
|
||||
if (p)
|
||||
strcpy (p, "disc");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/* If this is a SCSI disk. */
|
||||
if (strncmp ("/dev/scsi/", p, 10) == 0)
|
||||
{
|
||||
p = strstr (p, "part");
|
||||
if (p)
|
||||
strcpy (p, "disc");
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/* If this is a DAC960 disk. */
|
||||
if (strncmp ("rd/c", p, 4) == 0)
|
||||
{
|
||||
/* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */
|
||||
p = strchr (p, 'p');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/* If this is an IDE disk or a SCSI disk. */
|
||||
if ((strncmp ("hd", p, 2) == 0
|
||||
|| strncmp ("sd", p, 2) == 0)
|
||||
&& p[2] >= 'a' && p[2] <= 'z')
|
||||
{
|
||||
/* /dev/[hs]d[a-z][0-9]* */
|
||||
p[3] = '\0';
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
|
||||
#elif defined(__GNU__)
|
||||
path = xstrdup (os_dev);
|
||||
if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0)
|
||||
{
|
||||
p = strchr (path, 's');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
}
|
||||
return path;
|
||||
|
||||
#else
|
||||
# warning "The function `get_os_disk' might not work on your OS correctly."
|
||||
return xstrdup (os_dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
find_drive (const char *os_dev)
|
||||
{
|
||||
int i;
|
||||
char *os_disk;
|
||||
|
||||
os_disk = get_os_disk (os_dev);
|
||||
if (! os_disk)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < (int) (sizeof (map) / sizeof (map[0])); i++)
|
||||
if (map[i] && strcmp (map[i], os_disk) == 0)
|
||||
{
|
||||
free (os_disk);
|
||||
return i;
|
||||
}
|
||||
|
||||
free (os_disk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
||||
{
|
||||
struct stat st;
|
||||
int drive;
|
||||
|
||||
if (stat (os_dev, &st) < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
drive = find_drive (os_dev);
|
||||
if (drive < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"no mapping exists for `%s'", os_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (! S_ISBLK (st.st_mode))
|
||||
return make_device_name (drive, -1, -1);
|
||||
|
||||
#if defined(__linux__)
|
||||
/* Linux counts partitions uniformly, whether a BSD partition or a DOS
|
||||
partition, so mapping them to GRUB devices is not trivial.
|
||||
Here, get the start sector of a partition by HDIO_GETGEO, and
|
||||
compare it with each partition GRUB recognizes. */
|
||||
{
|
||||
char *name;
|
||||
grub_disk_t disk;
|
||||
int fd;
|
||||
struct hd_geometry hdg;
|
||||
int dos_part = -1;
|
||||
int bsd_part = -1;
|
||||
auto int find_partition (grub_disk_t disk,
|
||||
const grub_partition_t partition);
|
||||
|
||||
int find_partition (grub_disk_t disk __attribute__ ((unused)),
|
||||
const grub_partition_t partition)
|
||||
{
|
||||
struct grub_pc_partition *pcdata = 0;
|
||||
int gpt = 0;
|
||||
|
||||
if (strcmp (partition->partmap->name, "pc_partition_map") == 0)
|
||||
pcdata = partition->data;
|
||||
else if (strcmp (partition->partmap->name, "gpt_partition_map") == 0)
|
||||
gpt = 1;
|
||||
|
||||
if (pcdata)
|
||||
{
|
||||
if (pcdata->bsd_part < 0)
|
||||
grub_util_info ("DOS partition %d starts from %lu",
|
||||
pcdata->dos_part, partition->start);
|
||||
else
|
||||
grub_util_info ("BSD partition %d,%c starts from %lu",
|
||||
pcdata->dos_part, pcdata->bsd_part + 'a',
|
||||
partition->start);
|
||||
}
|
||||
else if (gpt)
|
||||
{
|
||||
grub_util_info ("GPT partition %d starts from %lu",
|
||||
partition->index, partition->start);
|
||||
}
|
||||
|
||||
if (hdg.start == partition->start)
|
||||
{
|
||||
if (pcdata)
|
||||
{
|
||||
dos_part = pcdata->dos_part;
|
||||
bsd_part = pcdata->bsd_part;
|
||||
}
|
||||
else if (gpt)
|
||||
{
|
||||
dos_part = grub_cpu_to_le32 (partition->index);
|
||||
bsd_part = grub_cpu_to_le32 (-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
dos_part = 0;
|
||||
bsd_part = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
name = make_device_name (drive, -1, -1);
|
||||
|
||||
if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
|
||||
return name;
|
||||
|
||||
fd = open (os_dev, O_RDONLY);
|
||||
if (! fd)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", os_dev);
|
||||
free (name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ioctl (fd, HDIO_GETGEO, &hdg))
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"cannot get geometry of `%s'", os_dev);
|
||||
close (fd);
|
||||
free (name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
grub_util_info ("%s starts from %lu", os_dev, hdg.start);
|
||||
|
||||
if (hdg.start == 0)
|
||||
return name;
|
||||
|
||||
grub_util_info ("opening the device %s", name);
|
||||
disk = grub_disk_open (name);
|
||||
free (name);
|
||||
|
||||
if (! disk)
|
||||
return 0;
|
||||
|
||||
if (grub_partition_iterate (disk, find_partition) != GRUB_ERR_NONE)
|
||||
{
|
||||
grub_disk_close (disk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dos_part < 0)
|
||||
{
|
||||
grub_disk_close (disk);
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"cannot find the partition of `%s'", os_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return make_device_name (drive, dos_part, bsd_part);
|
||||
}
|
||||
|
||||
#elif defined(__GNU__)
|
||||
/* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?". */
|
||||
{
|
||||
char *p;
|
||||
int dos_part = -1;
|
||||
int bsd_part = -1;
|
||||
|
||||
p = strrchr (os_dev, 's');
|
||||
if (p)
|
||||
{
|
||||
long int n;
|
||||
char *q;
|
||||
|
||||
p++;
|
||||
n = strtol (p, &q, 10);
|
||||
if (p != q && n != LONG_MIN && n != LONG_MAX)
|
||||
{
|
||||
dos_part = (int) n;
|
||||
|
||||
if (*q >= 'a' && *q <= 'g')
|
||||
bsd_part = *q - 'a';
|
||||
}
|
||||
}
|
||||
|
||||
return make_device_name (drive, dos_part, bsd_part);
|
||||
}
|
||||
|
||||
#else
|
||||
# warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly."
|
||||
return make_device_name (drive, -1, -1);
|
||||
#endif
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
/* getroot.c - Get root device */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2006 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <grub/util/misc.h>
|
||||
#include <grub/i386/pc/util/biosdisk.h>
|
||||
|
||||
static void
|
||||
strip_extra_slashes (char *dir)
|
||||
{
|
||||
char *p = dir;
|
||||
|
||||
while ((p = strchr (p, '/')) != 0)
|
||||
{
|
||||
if (p[1] == '/')
|
||||
{
|
||||
memmove (p, p + 1, strlen (p));
|
||||
continue;
|
||||
}
|
||||
else if (p[1] == '\0')
|
||||
{
|
||||
p[0] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
xgetcwd (void)
|
||||
{
|
||||
size_t size = 10;
|
||||
char *path;
|
||||
|
||||
path = xmalloc (size);
|
||||
while (! getcwd (path, size))
|
||||
{
|
||||
size <<= 1;
|
||||
path = xrealloc (path, size);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_get_prefix (const char *dir)
|
||||
{
|
||||
char *saved_cwd;
|
||||
char *abs_dir, *prev_dir;
|
||||
char *prefix;
|
||||
struct stat st, prev_st;
|
||||
|
||||
/* Save the current directory. */
|
||||
saved_cwd = xgetcwd ();
|
||||
|
||||
if (chdir (dir) < 0)
|
||||
grub_util_error ("Cannot change directory to `%s'", dir);
|
||||
|
||||
abs_dir = xgetcwd ();
|
||||
strip_extra_slashes (abs_dir);
|
||||
prev_dir = xstrdup (abs_dir);
|
||||
|
||||
if (stat (".", &prev_st) < 0)
|
||||
grub_util_error ("Cannot stat `%s'", dir);
|
||||
|
||||
if (! S_ISDIR (prev_st.st_mode))
|
||||
grub_util_error ("`%s' is not a directory", dir);
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (chdir ("..") < 0)
|
||||
grub_util_error ("Cannot change directory to the parent");
|
||||
|
||||
if (stat (".", &st) < 0)
|
||||
grub_util_error ("Cannot stat current directory");
|
||||
|
||||
if (! S_ISDIR (st.st_mode))
|
||||
grub_util_error ("Current directory is not a directory???");
|
||||
|
||||
if (prev_st.st_dev != st.st_dev || prev_st.st_ino == st.st_ino)
|
||||
break;
|
||||
|
||||
free (prev_dir);
|
||||
prev_dir = xgetcwd ();
|
||||
prev_st = st;
|
||||
}
|
||||
|
||||
strip_extra_slashes (prev_dir);
|
||||
prefix = xmalloc (strlen (abs_dir) - strlen (prev_dir) + 2);
|
||||
prefix[0] = '/';
|
||||
strcpy (prefix + 1, abs_dir + strlen (prev_dir));
|
||||
strip_extra_slashes (prefix);
|
||||
|
||||
if (chdir (saved_cwd) < 0)
|
||||
grub_util_error ("Cannot change directory to `%s'", dir);
|
||||
|
||||
free (saved_cwd);
|
||||
free (abs_dir);
|
||||
free (prev_dir);
|
||||
|
||||
grub_util_info ("prefix = %s", prefix);
|
||||
return prefix;
|
||||
}
|
||||
|
||||
static char *
|
||||
find_root_device (const char *dir, dev_t dev)
|
||||
{
|
||||
DIR *dp;
|
||||
char *saved_cwd;
|
||||
struct dirent *ent;
|
||||
|
||||
dp = opendir (dir);
|
||||
if (! dp)
|
||||
return 0;
|
||||
|
||||
saved_cwd = xgetcwd ();
|
||||
|
||||
grub_util_info ("changing current directory to %s", dir);
|
||||
if (chdir (dir) < 0)
|
||||
{
|
||||
free (saved_cwd);
|
||||
closedir (dp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((ent = readdir (dp)) != 0)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (strcmp (ent->d_name, ".") == 0 || strcmp (ent->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
if (lstat (ent->d_name, &st) < 0)
|
||||
/* Ignore any error. */
|
||||
continue;
|
||||
|
||||
if (S_ISLNK (st.st_mode))
|
||||
/* Don't follow symbolic links. */
|
||||
continue;
|
||||
|
||||
if (S_ISDIR (st.st_mode) && ent->d_name[0] != '.')
|
||||
{
|
||||
/* Find it recursively, but avoid dotdirs (like ".static") since they
|
||||
could contain duplicates, which would later break the
|
||||
pathname-based check */
|
||||
char *res;
|
||||
|
||||
res = find_root_device (ent->d_name, dev);
|
||||
|
||||
if (res)
|
||||
{
|
||||
if (chdir (saved_cwd) < 0)
|
||||
grub_util_error ("Cannot restore the original directory");
|
||||
|
||||
free (saved_cwd);
|
||||
closedir (dp);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (S_ISBLK (st.st_mode) && st.st_rdev == dev)
|
||||
{
|
||||
/* Found! */
|
||||
char *res;
|
||||
char *cwd;
|
||||
|
||||
cwd = xgetcwd ();
|
||||
res = xmalloc (strlen (cwd) + strlen (ent->d_name) + 2);
|
||||
sprintf (res, "%s/%s", cwd, ent->d_name);
|
||||
strip_extra_slashes (res);
|
||||
free (cwd);
|
||||
|
||||
/* /dev/root is not a real block device keep looking, takes care
|
||||
of situation where root filesystem is on the same partition as
|
||||
grub files */
|
||||
|
||||
if (strcmp(res, "/dev/root") == 0)
|
||||
continue;
|
||||
|
||||
if (chdir (saved_cwd) < 0)
|
||||
grub_util_error ("Cannot restore the original directory");
|
||||
|
||||
free (saved_cwd);
|
||||
closedir (dp);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (chdir (saved_cwd) < 0)
|
||||
grub_util_error ("Cannot restore the original directory");
|
||||
|
||||
free (saved_cwd);
|
||||
closedir (dp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_guess_root_device (const char *dir)
|
||||
{
|
||||
struct stat st;
|
||||
char *os_dev;
|
||||
|
||||
if (stat (dir, &st) < 0)
|
||||
grub_util_error ("Cannot stat `%s'", dir);
|
||||
|
||||
/* This might be truly slow, but is there any better way? */
|
||||
os_dev = find_root_device ("/dev", st.st_dev);
|
||||
if (! os_dev)
|
||||
return 0;
|
||||
|
||||
#ifdef __linux__
|
||||
/* Check for LVM. */
|
||||
if (!strncmp (os_dev, "/dev/mapper/", 12))
|
||||
{
|
||||
char *grub_dev = xmalloc (strlen (os_dev) - 12);
|
||||
|
||||
strcpy (grub_dev, os_dev+12);
|
||||
|
||||
return grub_dev;
|
||||
}
|
||||
|
||||
if (!strncmp (os_dev, "/dev/md", 7))
|
||||
{
|
||||
char *p, *grub_dev = xmalloc (8);
|
||||
|
||||
p = strchr (os_dev, 'm');
|
||||
strncpy (grub_dev, p, 8);
|
||||
|
||||
return grub_dev;
|
||||
}
|
||||
#endif
|
||||
|
||||
return os_dev;
|
||||
}
|
|
@ -1,608 +0,0 @@
|
|||
/* grub-mkdevicemap.c - make a device map file automatically */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <grub/util/misc.h>
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <getopt.h>
|
||||
|
||||
#ifdef __NetBSD__
|
||||
/* NetBSD uses /boot for its boot block. */
|
||||
# define DEFAULT_DIRECTORY "/grub"
|
||||
#else
|
||||
# define DEFAULT_DIRECTORY "/boot/grub"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_DEVICE_MAP DEFAULT_DIRECTORY "/device.map"
|
||||
|
||||
#ifdef __linux__
|
||||
# if !defined(__GLIBC__) || \
|
||||
((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
|
||||
/* Maybe libc doesn't have large file support. */
|
||||
# include <linux/unistd.h> /* _llseek */
|
||||
# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
|
||||
# include <sys/ioctl.h> /* ioctl */
|
||||
# ifndef HDIO_GETGEO
|
||||
# define HDIO_GETGEO 0x0301 /* get device geometry */
|
||||
/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
|
||||
defined. */
|
||||
struct hd_geometry
|
||||
{
|
||||
unsigned char heads;
|
||||
unsigned char sectors;
|
||||
unsigned short cylinders;
|
||||
unsigned long start;
|
||||
};
|
||||
# endif /* ! HDIO_GETGEO */
|
||||
# ifndef FLOPPY_MAJOR
|
||||
# define FLOPPY_MAJOR 2 /* the major number for floppy */
|
||||
# endif /* ! FLOPPY_MAJOR */
|
||||
# ifndef MAJOR
|
||||
# define MAJOR(dev) \
|
||||
({ \
|
||||
unsigned long long __dev = (dev); \
|
||||
(unsigned) ((__dev >> 8) & 0xfff) \
|
||||
| ((unsigned int) (__dev >> 32) & ~0xfff); \
|
||||
})
|
||||
# endif /* ! MAJOR */
|
||||
# ifndef CDROM_GET_CAPABILITY
|
||||
# define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
|
||||
# endif /* ! CDROM_GET_CAPABILITY */
|
||||
# ifndef BLKGETSIZE
|
||||
# define BLKGETSIZE _IO(0x12,96) /* return device size */
|
||||
# endif /* ! BLKGETSIZE */
|
||||
#endif /* __linux__ */
|
||||
|
||||
/* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
|
||||
kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */
|
||||
#if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__)
|
||||
# define __FreeBSD_kernel__
|
||||
#endif
|
||||
#ifdef __FreeBSD_kernel__
|
||||
/* Obtain version of kFreeBSD headers */
|
||||
# include <osreldate.h>
|
||||
# ifndef __FreeBSD_kernel_version
|
||||
# define __FreeBSD_kernel_version __FreeBSD_version
|
||||
# endif
|
||||
|
||||
/* Runtime detection of kernel */
|
||||
# include <sys/utsname.h>
|
||||
int
|
||||
get_kfreebsd_version ()
|
||||
{
|
||||
struct utsname uts;
|
||||
int major;
|
||||
int minor;
|
||||
int v[2];
|
||||
|
||||
uname (&uts);
|
||||
sscanf (uts.release, "%d.%d", &major, &minor);
|
||||
|
||||
if (major >= 9)
|
||||
major = 9;
|
||||
if (major >= 5)
|
||||
{
|
||||
v[0] = minor/10; v[1] = minor%10;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[0] = minor%10; v[1] = minor/10;
|
||||
}
|
||||
return major*100000+v[0]*10000+v[1]*1000;
|
||||
}
|
||||
#endif /* __FreeBSD_kernel__ */
|
||||
|
||||
#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
# include <sys/ioctl.h> /* ioctl */
|
||||
# include <sys/disklabel.h>
|
||||
# include <sys/cdio.h> /* CDIOCCLRDEBUG */
|
||||
# if defined(__FreeBSD_kernel__)
|
||||
# include <sys/param.h>
|
||||
# if __FreeBSD_kernel_version >= 500040
|
||||
# include <sys/disk.h>
|
||||
# endif
|
||||
# endif /* __FreeBSD_kernel__ */
|
||||
#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
|
||||
|
||||
#ifdef HAVE_OPENDISK
|
||||
# include <util.h>
|
||||
#endif /* HAVE_OPENDISK */
|
||||
|
||||
#ifdef __linux__
|
||||
/* Check if we have devfs support. */
|
||||
static int
|
||||
have_devfs (void)
|
||||
{
|
||||
struct stat st;
|
||||
return stat ("/dev/.devfsd", &st) == 0;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
/* These three functions are quite different among OSes. */
|
||||
static void
|
||||
get_floppy_disk_name (char *name, int unit)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
/* GNU/Linux */
|
||||
if (have_devfs ())
|
||||
sprintf (name, "/dev/floppy/%d", unit);
|
||||
else
|
||||
sprintf (name, "/dev/fd%d", unit);
|
||||
#elif defined(__GNU__)
|
||||
/* GNU/Hurd */
|
||||
sprintf (name, "/dev/fd%d", unit);
|
||||
#elif defined(__FreeBSD_kernel__)
|
||||
/* kFreeBSD */
|
||||
if (get_kfreebsd_version () >= 400000)
|
||||
sprintf (name, "/dev/fd%d", unit);
|
||||
else
|
||||
sprintf (name, "/dev/rfd%d", unit);
|
||||
#elif defined(__NetBSD__)
|
||||
/* NetBSD */
|
||||
/* opendisk() doesn't work for floppies. */
|
||||
sprintf (name, "/dev/rfd%da", unit);
|
||||
#elif defined(__OpenBSD__)
|
||||
/* OpenBSD */
|
||||
sprintf (name, "/dev/rfd%dc", unit);
|
||||
#elif defined(__QNXNTO__)
|
||||
/* QNX RTP */
|
||||
sprintf (name, "/dev/fd%d", unit);
|
||||
#else
|
||||
# warning "BIOS floppy drives cannot be guessed in your operating system."
|
||||
/* Set NAME to a bogus string. */
|
||||
*name = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
get_ide_disk_name (char *name, int unit)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
/* GNU/Linux */
|
||||
sprintf (name, "/dev/hd%c", unit + 'a');
|
||||
#elif defined(__GNU__)
|
||||
/* GNU/Hurd */
|
||||
sprintf (name, "/dev/hd%d", unit);
|
||||
#elif defined(__FreeBSD_kernel__)
|
||||
/* kFreeBSD */
|
||||
if (get_kfreebsd_version () >= 400000)
|
||||
sprintf (name, "/dev/ad%d", unit);
|
||||
else
|
||||
sprintf (name, "/dev/rwd%d", unit);
|
||||
#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
|
||||
/* NetBSD */
|
||||
char shortname[16];
|
||||
int fd;
|
||||
|
||||
sprintf (shortname, "wd%d", unit);
|
||||
fd = opendisk (shortname, O_RDONLY, name,
|
||||
16, /* length of NAME */
|
||||
0 /* char device */
|
||||
);
|
||||
close (fd);
|
||||
#elif defined(__OpenBSD__)
|
||||
/* OpenBSD */
|
||||
sprintf (name, "/dev/rwd%dc", unit);
|
||||
#elif defined(__QNXNTO__)
|
||||
/* QNX RTP */
|
||||
/* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could
|
||||
contain SCSI disks. */
|
||||
sprintf (name, "/dev/hd%d", unit);
|
||||
#else
|
||||
# warning "BIOS IDE drives cannot be guessed in your operating system."
|
||||
/* Set NAME to a bogus string. */
|
||||
*name = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
get_scsi_disk_name (char *name, int unit)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
/* GNU/Linux */
|
||||
sprintf (name, "/dev/sd%c", unit + 'a');
|
||||
#elif defined(__GNU__)
|
||||
/* GNU/Hurd */
|
||||
sprintf (name, "/dev/sd%d", unit);
|
||||
#elif defined(__FreeBSD_kernel__)
|
||||
/* kFreeBSD */
|
||||
if (get_kfreebsd_version () >= 400000)
|
||||
sprintf (name, "/dev/da%d", unit);
|
||||
else
|
||||
sprintf (name, "/dev/rda%d", unit);
|
||||
#elif defined(__NetBSD__) && defined(HAVE_OPENDISK)
|
||||
/* NetBSD */
|
||||
char shortname[16];
|
||||
int fd;
|
||||
|
||||
sprintf (shortname, "sd%d", unit);
|
||||
fd = opendisk (shortname, O_RDONLY, name,
|
||||
16, /* length of NAME */
|
||||
0 /* char device */
|
||||
);
|
||||
close (fd);
|
||||
#elif defined(__OpenBSD__)
|
||||
/* OpenBSD */
|
||||
sprintf (name, "/dev/rsd%dc", unit);
|
||||
#elif defined(__QNXNTO__)
|
||||
/* QNX RTP */
|
||||
/* QNX RTP doesn't distinguish SCSI from IDE, so it is better to
|
||||
disable the detection of SCSI disks here. */
|
||||
*name = 0;
|
||||
#else
|
||||
# warning "BIOS SCSI drives cannot be guessed in your operating system."
|
||||
/* Set NAME to a bogus string. */
|
||||
*name = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static void
|
||||
get_dac960_disk_name (char *name, int controller, int drive)
|
||||
{
|
||||
sprintf (name, "/dev/rd/c%dd%d", controller, drive);
|
||||
}
|
||||
|
||||
static void
|
||||
get_ataraid_disk_name (char *name, int unit)
|
||||
{
|
||||
sprintf (name, "/dev/ataraid/d%c", unit + '0');
|
||||
}
|
||||
|
||||
static void
|
||||
get_i2o_disk_name (char *name, char unit)
|
||||
{
|
||||
sprintf (name, "/dev/i2o/hd%c", unit);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check if DEVICE can be read. If an error occurs, return zero,
|
||||
otherwise return non-zero. */
|
||||
int
|
||||
check_device (const char *device)
|
||||
{
|
||||
char buf[512];
|
||||
FILE *fp;
|
||||
|
||||
/* If DEVICE is empty, just return 1. */
|
||||
if (*device == 0)
|
||||
return 1;
|
||||
|
||||
fp = fopen (device, "r");
|
||||
if (! fp)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
#ifdef ENOMEDIUM
|
||||
case ENOMEDIUM:
|
||||
# if 0
|
||||
/* At the moment, this finds only CDROMs, which can't be
|
||||
read anyway, so leave it out. Code should be
|
||||
reactivated if `removable disks' and CDROMs are
|
||||
supported. */
|
||||
/* Accept it, it may be inserted. */
|
||||
return 1;
|
||||
# endif
|
||||
break;
|
||||
#endif /* ENOMEDIUM */
|
||||
default:
|
||||
/* Break case and leave. */
|
||||
break;
|
||||
}
|
||||
/* Error opening the device. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make sure CD-ROMs don't get assigned a BIOS disk number
|
||||
before SCSI disks! */
|
||||
#ifdef __linux__
|
||||
# ifdef CDROM_GET_CAPABILITY
|
||||
if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0)
|
||||
return 0;
|
||||
# else /* ! CDROM_GET_CAPABILITY */
|
||||
/* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */
|
||||
{
|
||||
struct hd_geometry hdg;
|
||||
struct stat st;
|
||||
|
||||
if (fstat (fileno (fp), &st))
|
||||
return 0;
|
||||
|
||||
/* If it is a block device and isn't a floppy, check if HDIO_GETGEO
|
||||
succeeds. */
|
||||
if (S_ISBLK (st.st_mode)
|
||||
&& MAJOR (st.st_rdev) != FLOPPY_MAJOR
|
||||
&& ioctl (fileno (fp), HDIO_GETGEO, &hdg))
|
||||
return 0;
|
||||
}
|
||||
# endif /* ! CDROM_GET_CAPABILITY */
|
||||
#endif /* __linux__ */
|
||||
|
||||
#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
# ifdef CDIOCCLRDEBUG
|
||||
if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0)
|
||||
return 0;
|
||||
# endif /* CDIOCCLRDEBUG */
|
||||
#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */
|
||||
|
||||
/* Attempt to read the first sector. */
|
||||
if (fread (buf, 1, 512, fp) != 512)
|
||||
{
|
||||
fclose (fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
make_device_map (const char *device_map, int floppy_disks)
|
||||
{
|
||||
FILE *fp;
|
||||
int num_hd = 0;
|
||||
int i;
|
||||
|
||||
if (strcmp (device_map, "-") == 0)
|
||||
fp = stdout;
|
||||
else
|
||||
fp = fopen (device_map, "w");
|
||||
|
||||
if (! fp)
|
||||
grub_util_error ("cannot open %s", device_map);
|
||||
|
||||
/* Floppies. */
|
||||
for (i = 0; i < floppy_disks; i++)
|
||||
{
|
||||
char name[16];
|
||||
struct stat st;
|
||||
|
||||
get_floppy_disk_name (name, i);
|
||||
if (stat (name, &st) < 0)
|
||||
break;
|
||||
/* In floppies, write the map, whether check_device succeeds
|
||||
or not, because the user just may not insert floppies. */
|
||||
if (fp)
|
||||
fprintf (fp, "(fd%d)\t%s\n", i, name);
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (have_devfs ())
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
char discn[32];
|
||||
char name[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
/* Linux creates symlinks "/dev/discs/discN" for convenience.
|
||||
The way to number disks is the same as GRUB's. */
|
||||
sprintf (discn, "/dev/discs/disc%d", num_hd);
|
||||
if (stat (discn, &st) < 0)
|
||||
break;
|
||||
|
||||
if (realpath (discn, name))
|
||||
{
|
||||
strcat (name, "/disc");
|
||||
fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
|
||||
}
|
||||
|
||||
num_hd++;
|
||||
}
|
||||
|
||||
goto finish;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
/* IDE disks. */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
char name[16];
|
||||
|
||||
get_ide_disk_name (name, i);
|
||||
if (check_device (name))
|
||||
{
|
||||
fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
|
||||
num_hd++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
/* ATARAID disks. */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
char name[20];
|
||||
|
||||
get_ataraid_disk_name (name, i);
|
||||
if (check_device (name))
|
||||
{
|
||||
fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
|
||||
num_hd++;
|
||||
}
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
/* The rest is SCSI disks. */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
char name[16];
|
||||
|
||||
get_scsi_disk_name (name, i);
|
||||
if (check_device (name))
|
||||
{
|
||||
fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
|
||||
num_hd++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
/* This is for DAC960 - we have
|
||||
/dev/rd/c<controller>d<logical drive>p<partition>.
|
||||
|
||||
DAC960 driver currently supports up to 8 controllers, 32 logical
|
||||
drives, and 7 partitions. */
|
||||
{
|
||||
int controller, drive;
|
||||
|
||||
for (controller = 0; controller < 8; controller++)
|
||||
{
|
||||
for (drive = 0; drive < 15; drive++)
|
||||
{
|
||||
char name[24];
|
||||
|
||||
get_dac960_disk_name (name, controller, drive);
|
||||
if (check_device (name))
|
||||
{
|
||||
fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
|
||||
num_hd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This is for I2O - we have /dev/i2o/hd<logical drive><partition> */
|
||||
{
|
||||
char unit;
|
||||
|
||||
for (unit = 'a'; unit < 'f'; unit++)
|
||||
{
|
||||
char name[24];
|
||||
|
||||
get_i2o_disk_name (name, unit);
|
||||
if (check_device (name))
|
||||
{
|
||||
fprintf (fp, "(hd%d)\t%s\n", num_hd, name);
|
||||
num_hd++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
finish:
|
||||
if (fp != stdout)
|
||||
fclose (fp);
|
||||
}
|
||||
|
||||
static struct option options[] =
|
||||
{
|
||||
{"device-map", required_argument, 0, 'm'},
|
||||
{"probe-second-floppy", no_argument, 0, 's'},
|
||||
{"no-floppy", no_argument, 0, 'n'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void
|
||||
usage (int status)
|
||||
{
|
||||
if (status)
|
||||
fprintf (stderr,
|
||||
"Try ``grub-mkdevicemap --help'' for more information.\n");
|
||||
else
|
||||
printf ("\
|
||||
Usage: grub-mkdevicemap [OPTION]...\n\
|
||||
\n\
|
||||
Generate a device map file automatically.\n\
|
||||
\n\
|
||||
-n, --no-floppy do not probe any floppy drive\n\
|
||||
-s, --probe-second-floppy probe the second floppy drive\n\
|
||||
-m, --device-map=FILE use FILE as the device map [default=%s]\n\
|
||||
-h, --help display this message and exit\n\
|
||||
-V, --version print version information and exit\n\
|
||||
-v, --verbose print verbose messages\n\
|
||||
\n\
|
||||
Report bugs to <%s>.\n\
|
||||
",
|
||||
DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
|
||||
|
||||
exit (status);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char *dev_map = 0;
|
||||
int floppy_disks = 1;
|
||||
|
||||
progname = "grub-mkdevicemap";
|
||||
|
||||
/* Check for options. */
|
||||
while (1)
|
||||
{
|
||||
int c = getopt_long (argc, argv, "snm:r:hVv", options, 0);
|
||||
|
||||
if (c == -1)
|
||||
break;
|
||||
else
|
||||
switch (c)
|
||||
{
|
||||
case 'm':
|
||||
if (dev_map)
|
||||
free (dev_map);
|
||||
|
||||
dev_map = xstrdup (optarg);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
floppy_disks = 0;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
floppy_disks = 2;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage (0);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
|
||||
return 0;
|
||||
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage (1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks);
|
||||
|
||||
free (dev_map);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,303 +0,0 @@
|
|||
/* grub-probe.c - probe device information for a given path */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2006 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/util/misc.h>
|
||||
#include <grub/device.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/fs.h>
|
||||
#include <grub/partition.h>
|
||||
#include <grub/pc_partition.h>
|
||||
#include <grub/machine/util/biosdisk.h>
|
||||
#include <grub/util/getroot.h>
|
||||
#include <grub/term.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <getopt.h>
|
||||
|
||||
#ifdef __NetBSD__
|
||||
/* NetBSD uses /boot for its boot block. */
|
||||
# define DEFAULT_DIRECTORY "/grub"
|
||||
#else
|
||||
# define DEFAULT_DIRECTORY "/boot/grub"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_DEVICE_MAP DEFAULT_DIRECTORY "/device.map"
|
||||
|
||||
#define PRINT_FS 0
|
||||
#define PRINT_DRIVE 1
|
||||
#define PRINT_DEVICE 2
|
||||
#define PRINT_PARTMAP 3
|
||||
|
||||
int print = PRINT_FS;
|
||||
|
||||
void
|
||||
grub_putchar (int c)
|
||||
{
|
||||
putchar (c);
|
||||
}
|
||||
|
||||
int
|
||||
grub_getkey (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
grub_term_t
|
||||
grub_term_get_current (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
grub_refresh (void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
probe (const char *path)
|
||||
{
|
||||
char *device_name;
|
||||
char *drive_name = 0;
|
||||
grub_device_t dev;
|
||||
grub_fs_t fs;
|
||||
|
||||
device_name = grub_guess_root_device (path);
|
||||
if (! device_name)
|
||||
{
|
||||
fprintf (stderr, "cannot find a device for %s.\n", path);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (print == PRINT_DEVICE)
|
||||
{
|
||||
printf ("%s\n", device_name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (device_name[0] == 'm' && device_name[1] == 'd'
|
||||
&& device_name[2] >= '0' && device_name[2] <= '9')
|
||||
{
|
||||
drive_name = xstrdup (device_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
drive_name = grub_util_biosdisk_get_grub_dev (device_name);
|
||||
if (! drive_name)
|
||||
{
|
||||
fprintf (stderr, "cannot find a GRUB drive for %s.\n", device_name);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (print == PRINT_DRIVE)
|
||||
{
|
||||
printf ("(%s)\n", drive_name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
grub_util_info ("opening %s", drive_name);
|
||||
dev = grub_device_open (drive_name);
|
||||
if (! dev)
|
||||
grub_util_error ("%s", grub_errmsg);
|
||||
|
||||
if (print == PRINT_PARTMAP)
|
||||
{
|
||||
if (dev->disk->partition == NULL)
|
||||
grub_util_error ("Cannot detect partition map for %s", drive_name);
|
||||
|
||||
if (strcmp (dev->disk->partition->partmap->name, "amiga_partition_map") == 0)
|
||||
printf ("amiga\n");
|
||||
else if (strcmp (dev->disk->partition->partmap->name, "apple_partition_map") == 0)
|
||||
printf ("apple\n");
|
||||
else if (strcmp (dev->disk->partition->partmap->name, "gpt_partition_map") == 0)
|
||||
printf ("gpt\n");
|
||||
else if (strcmp (dev->disk->partition->partmap->name, "pc_partition_map") == 0)
|
||||
printf ("pc\n");
|
||||
else if (strcmp (dev->disk->partition->partmap->name, "sun_partition_map") == 0)
|
||||
printf ("sun\n");
|
||||
else
|
||||
grub_util_error ("Unknown partition map %s", dev->disk->partition->partmap->name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
fs = grub_fs_probe (dev);
|
||||
if (! fs)
|
||||
grub_util_error ("%s", grub_errmsg);
|
||||
|
||||
printf ("%s\n", fs->name);
|
||||
|
||||
grub_device_close (dev);
|
||||
|
||||
end:
|
||||
|
||||
free (device_name);
|
||||
free (drive_name);
|
||||
}
|
||||
|
||||
static struct option options[] =
|
||||
{
|
||||
{"device-map", required_argument, 0, 'm'},
|
||||
{"target", required_argument, 0, 't'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void
|
||||
usage (int status)
|
||||
{
|
||||
if (status)
|
||||
fprintf (stderr,
|
||||
"Try ``grub-probe --help'' for more information.\n");
|
||||
else
|
||||
printf ("\
|
||||
Usage: grub-probe [OPTION]... PATH\n\
|
||||
\n\
|
||||
Probe device information for a given path.\n\
|
||||
\n\
|
||||
-m, --device-map=FILE use FILE as the device map [default=%s]\n\
|
||||
-t, --target=(fs|drive|device|partmap)\n\
|
||||
print filesystem module, GRUB drive, system device or partition map module [default=fs]\n\
|
||||
-h, --help display this message and exit\n\
|
||||
-V, --version print version information and exit\n\
|
||||
-v, --verbose print verbose messages\n\
|
||||
\n\
|
||||
Report bugs to <%s>.\n\
|
||||
",
|
||||
DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT);
|
||||
|
||||
exit (status);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char *dev_map = 0;
|
||||
char *path;
|
||||
|
||||
progname = "grub-probe";
|
||||
|
||||
/* Check for options. */
|
||||
while (1)
|
||||
{
|
||||
int c = getopt_long (argc, argv, "m:t:hVv", options, 0);
|
||||
|
||||
if (c == -1)
|
||||
break;
|
||||
else
|
||||
switch (c)
|
||||
{
|
||||
case 'm':
|
||||
if (dev_map)
|
||||
free (dev_map);
|
||||
|
||||
dev_map = xstrdup (optarg);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (!strcmp (optarg, "fs"))
|
||||
print = PRINT_FS;
|
||||
else if (!strcmp (optarg, "drive"))
|
||||
print = PRINT_DRIVE;
|
||||
else if (!strcmp (optarg, "device"))
|
||||
print = PRINT_DEVICE;
|
||||
else if (!strcmp (optarg, "partmap"))
|
||||
print = PRINT_PARTMAP;
|
||||
else
|
||||
usage (1);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage (0);
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
printf ("%s (%s) %s\n", progname, PACKAGE_NAME, PACKAGE_VERSION);
|
||||
return 0;
|
||||
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage (1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Obtain PATH. */
|
||||
if (optind >= argc)
|
||||
{
|
||||
fprintf (stderr, "No path is specified.\n");
|
||||
usage (1);
|
||||
}
|
||||
|
||||
if (optind + 1 != argc)
|
||||
{
|
||||
fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]);
|
||||
usage (1);
|
||||
}
|
||||
|
||||
path = argv[optind];
|
||||
|
||||
/* Initialize the emulated biosdisk driver. */
|
||||
grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
|
||||
grub_pc_partition_map_init ();
|
||||
grub_gpt_partition_map_init ();
|
||||
grub_raid_init ();
|
||||
grub_lvm_init ();
|
||||
|
||||
/* Initialize filesystems. */
|
||||
grub_fat_init ();
|
||||
grub_ext2_init ();
|
||||
grub_ufs_init ();
|
||||
grub_minix_init ();
|
||||
grub_jfs_init ();
|
||||
grub_xfs_init ();
|
||||
|
||||
/* Do it. */
|
||||
probe (path);
|
||||
|
||||
/* Free resources. */
|
||||
grub_ext2_fini ();
|
||||
grub_fat_fini ();
|
||||
grub_ufs_fini ();
|
||||
grub_minix_fini ();
|
||||
grub_jfs_fini ();
|
||||
grub_xfs_fini ();
|
||||
|
||||
grub_lvm_fini ();
|
||||
grub_raid_fini ();
|
||||
grub_gpt_partition_map_fini ();
|
||||
grub_pc_partition_map_fini ();
|
||||
grub_util_biosdisk_fini ();
|
||||
|
||||
free (dev_map);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue