2003-11-17 18:07:09 +00:00
|
|
|
/* getroot.c - Get root device */
|
|
|
|
/*
|
2004-04-04 13:46:03 +00:00
|
|
|
* GRUB -- GRand Unified Bootloader
|
2011-10-09 19:13:00 +00:00
|
|
|
* Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
|
2003-11-17 18:07:09 +00:00
|
|
|
*
|
2007-07-21 23:32:33 +00:00
|
|
|
* GRUB is free software: you can redistribute it and/or modify
|
2003-11-17 18:07:09 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2007-07-21 23:32:33 +00:00
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
2003-11-17 18:07:09 +00:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
2007-07-21 23:32:33 +00:00
|
|
|
* GRUB is distributed in the hope that it will be useful,
|
2003-11-17 18:07:09 +00:00
|
|
|
* 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
|
2007-07-21 23:32:33 +00:00
|
|
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
2003-11-17 18:07:09 +00:00
|
|
|
*/
|
|
|
|
|
2011-01-22 14:37:05 +00:00
|
|
|
#include <config-util.h>
|
2008-09-04 19:54:59 +00:00
|
|
|
#include <config.h>
|
2011-01-22 14:37:05 +00:00
|
|
|
|
2003-11-17 18:07:09 +00:00
|
|
|
#include <sys/stat.h>
|
2010-05-06 03:15:39 +00:00
|
|
|
#include <sys/types.h>
|
2010-07-30 19:43:12 +00:00
|
|
|
#include <assert.h>
|
2010-05-06 03:15:39 +00:00
|
|
|
#include <fcntl.h>
|
2003-11-17 18:07:09 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <dirent.h>
|
2010-05-04 03:39:03 +00:00
|
|
|
#include <errno.h>
|
2010-07-30 19:43:12 +00:00
|
|
|
#include <error.h>
|
2010-04-27 05:20:28 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2010-05-04 03:39:03 +00:00
|
|
|
#include <stdint.h>
|
2011-11-25 22:07:33 +00:00
|
|
|
#ifdef HAVE_LIMITS_H
|
|
|
|
#include <limits.h>
|
|
|
|
#endif
|
2010-08-01 12:47:14 +00:00
|
|
|
#include <grub/util/misc.h>
|
2011-10-09 19:13:00 +00:00
|
|
|
#include <grub/util/lvm.h>
|
2011-04-25 12:52:07 +00:00
|
|
|
#include <grub/cryptodisk.h>
|
2011-11-11 23:34:14 +00:00
|
|
|
#include <grub/i18n.h>
|
2008-05-16 21:39:52 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
#ifdef __linux__
|
|
|
|
#include <sys/ioctl.h> /* ioctl */
|
|
|
|
#include <sys/mount.h>
|
2010-11-08 15:51:50 +00:00
|
|
|
#endif
|
|
|
|
|
2012-04-21 14:49:56 +00:00
|
|
|
#include <sys/types.h>
|
2010-07-18 14:53:14 +00:00
|
|
|
|
2010-07-30 19:43:12 +00:00
|
|
|
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
|
|
|
# include <grub/util/libzfs.h>
|
|
|
|
# include <grub/util/libnvpair.h>
|
|
|
|
#endif
|
|
|
|
|
2010-04-27 05:20:28 +00:00
|
|
|
#include <grub/mm.h>
|
|
|
|
#include <grub/misc.h>
|
|
|
|
#include <grub/emu/misc.h>
|
|
|
|
#include <grub/emu/hostdisk.h>
|
|
|
|
#include <grub/emu/getroot.h>
|
2003-11-17 18:07:09 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
#if defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
|
|
|
|
#include <sys/mount.h>
|
2012-01-29 13:28:01 +00:00
|
|
|
#endif
|
|
|
|
|
2013-08-21 19:05:01 +00:00
|
|
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
2012-01-29 13:28:01 +00:00
|
|
|
# include <sys/ioctl.h>
|
|
|
|
# include <sys/disklabel.h> /* struct disklabel */
|
2012-02-03 11:32:21 +00:00
|
|
|
# include <sys/disk.h> /* struct dkwedge_info */
|
2013-09-22 05:36:17 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/mount.h>
|
2012-01-29 13:28:01 +00:00
|
|
|
#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
|
|
|
|
|
2013-08-21 19:05:01 +00:00
|
|
|
#if defined(__NetBSD__)
|
2012-01-29 13:28:01 +00:00
|
|
|
# include <sys/fdio.h>
|
2013-08-21 19:05:01 +00:00
|
|
|
#endif
|
2012-01-29 13:28:01 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
grub_disk_addr_t
|
|
|
|
grub_util_find_partition_start (const char *dev)
|
2011-04-22 00:46:36 +00:00
|
|
|
{
|
2013-09-22 05:36:17 +00:00
|
|
|
grub_disk_addr_t partition_start;
|
|
|
|
if (grub_util_device_is_mapped (dev)
|
|
|
|
&& grub_util_get_dm_node_linear_info (dev, 0, 0, &partition_start))
|
|
|
|
return partition_start;
|
2011-04-22 00:46:36 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
return grub_util_find_partition_start_os (dev);
|
2011-04-22 00:46:36 +00:00
|
|
|
}
|
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
void
|
|
|
|
grub_util_pull_device (const char *os_dev)
|
2009-11-24 07:20:48 +00:00
|
|
|
{
|
2013-09-22 05:36:17 +00:00
|
|
|
enum grub_dev_abstraction_types ab;
|
|
|
|
ab = grub_util_get_dev_abstraction (os_dev);
|
|
|
|
switch (ab)
|
2012-03-02 10:36:07 +00:00
|
|
|
{
|
2013-09-22 05:36:17 +00:00
|
|
|
case GRUB_DEV_ABSTRACTION_LVM:
|
2013-09-23 09:21:09 +00:00
|
|
|
grub_util_pull_lvm_by_command (os_dev);
|
2013-09-22 05:36:17 +00:00
|
|
|
/* Fallthrough in case that lvm-tools are unavailable. */
|
|
|
|
case GRUB_DEV_ABSTRACTION_LUKS:
|
|
|
|
grub_util_pull_devmapper (os_dev);
|
|
|
|
return;
|
2011-04-22 13:13:12 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
default:
|
|
|
|
if (grub_util_pull_device_os (os_dev, ab))
|
|
|
|
return;
|
|
|
|
case GRUB_DEV_ABSTRACTION_NONE:
|
|
|
|
free (grub_util_biosdisk_get_grub_dev (os_dev));
|
|
|
|
return;
|
2011-04-21 10:39:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
char *
|
|
|
|
grub_util_get_grub_dev (const char *os_dev)
|
2011-04-25 12:52:07 +00:00
|
|
|
{
|
2013-09-22 05:36:17 +00:00
|
|
|
char *ret;
|
2011-04-25 12:52:07 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
grub_util_pull_device (os_dev);
|
2011-04-25 12:52:07 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
ret = grub_util_get_devmapper_grub_dev (os_dev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
ret = grub_util_get_grub_dev_os (os_dev);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
return grub_util_biosdisk_get_grub_dev (os_dev);
|
2009-11-24 07:20:48 +00:00
|
|
|
}
|
2013-09-22 05:36:17 +00:00
|
|
|
|
2008-01-12 15:11:57 +00:00
|
|
|
int
|
2011-11-11 21:58:18 +00:00
|
|
|
grub_util_get_dev_abstraction (const char *os_dev)
|
2007-05-16 21:38:44 +00:00
|
|
|
{
|
2013-09-22 05:36:17 +00:00
|
|
|
enum grub_dev_abstraction_types ret;
|
|
|
|
|
2010-09-13 11:09:58 +00:00
|
|
|
/* User explicitly claims that this drive is visible by BIOS. */
|
|
|
|
if (grub_util_biosdisk_is_present (os_dev))
|
|
|
|
return GRUB_DEV_ABSTRACTION_NONE;
|
|
|
|
|
2011-04-21 10:39:31 +00:00
|
|
|
/* Check for LVM and LUKS. */
|
|
|
|
ret = grub_util_get_dm_abstraction (os_dev);
|
|
|
|
|
|
|
|
if (ret != GRUB_DEV_ABSTRACTION_NONE)
|
|
|
|
return ret;
|
2006-10-14 Yoshinori K. Okuji <okuji@enbug.org>
* DISTLIST: Added commands/echo.c, disk/lvm.c, disk/raid.c,
include/grub/bitmap.h, include/grub/lvm.h, include/grub/raid.h,
include/grub/i386/pc/vbeutil.h, include/grub/util/lvm.h,
include/grub/util/raid.h, util/lvm.c, util/raid.c, video/bitmap.c,
video/readers/tga.c and video/i386/pc/vbeutil.c.
2006-10-14 Jeroen Dekkers <jeroen@dekkers.cx>
Added support for RAID and LVM.
* disk/lvm.c: New file.
* disk/raid.c: Likewise.
* include/grub/lvm.h: Likewise.
* include/grub/raid.h: Likewise.
* include/grub/util/lvm.h: Likewise.
* include/grub/util/raid.h: Likewise.
* util/lvm.c: Likewise.
* util/raid.c: Likewise.
* include/grub/disk.h (grub_disk_dev_id): Add
GRUB_DISK_DEVICE_RAID_ID and GRUB_DISK_DEVICE_LVM_ID.
(grub_disk_get_size): New prototype.
* kern/disk.c (grub_disk_open): Check whether grub_partition_probe()
returns a partition.
(grub_disk_get_size): New function.
* kern/i386/pc/init.c (make_install_device): Copy the prefix
verbatim if grub_install_dos_part is -2.
* util/i386/pc/getroot.c (grub_guess_root_device): Support RAID
and LVM devices.
* util/i386/pc/grub-setup.c (setup): New argument
MUST_EMBED. Force embedding of GRUB when the argument is
true. Close FILE before returning.
(main): Add support for RAID and LVM.
* conf/common.rmk: Add RAID and LVM modules.
* conf/i386-pc.rmk (grub_setup_SOURCES): Add util/raid.c and
util/lvm.c.
(grub_emu_SOURCES): Add disk/raid.c and disk/lvm.c.
* kern/misc.c (grub_strstr): New function.
* include/grub/misc.h (grub_strstr): New prototype.
2006-10-14 15:24:53 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
return grub_util_get_dev_abstraction_os (os_dev);
|
2008-01-12 15:11:57 +00:00
|
|
|
}
|
|
|
|
|
2012-01-29 13:28:01 +00:00
|
|
|
static char *
|
2012-04-21 14:42:28 +00:00
|
|
|
convert_system_partition_to_system_disk (const char *os_dev, struct stat *st,
|
|
|
|
int *is_part)
|
2012-01-29 13:28:01 +00:00
|
|
|
{
|
2012-04-21 14:42:28 +00:00
|
|
|
*is_part = 0;
|
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
if (grub_util_device_is_mapped_stat (st))
|
|
|
|
return grub_util_devmapper_part_to_disk (st, is_part, os_dev);
|
2012-01-29 13:28:01 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
*is_part = 0;
|
2012-01-29 13:28:01 +00:00
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
return grub_util_part_to_disk (os_dev, st, is_part);
|
2012-01-29 13:28:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
find_system_device (const char *os_dev, struct stat *st, int convert, int add)
|
|
|
|
{
|
|
|
|
char *os_disk;
|
|
|
|
const char *drive;
|
2012-04-21 14:42:28 +00:00
|
|
|
int is_part;
|
2012-01-29 13:28:01 +00:00
|
|
|
|
|
|
|
if (convert)
|
2012-04-21 14:42:28 +00:00
|
|
|
os_disk = convert_system_partition_to_system_disk (os_dev, st, &is_part);
|
2012-01-29 13:28:01 +00:00
|
|
|
else
|
|
|
|
os_disk = xstrdup (os_dev);
|
|
|
|
if (! os_disk)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
drive = grub_hostdisk_os_dev_to_grub_drive (os_disk, add);
|
|
|
|
free (os_disk);
|
|
|
|
return drive;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note: we do not use the new partition naming scheme as dos_part does not
|
|
|
|
* necessarily correspond to an msdos partition.
|
|
|
|
*/
|
|
|
|
static char *
|
|
|
|
make_device_name (const char *drive, int dos_part, int bsd_part)
|
|
|
|
{
|
|
|
|
char *ret, *ptr, *end;
|
|
|
|
const char *iptr;
|
|
|
|
|
|
|
|
ret = xmalloc (strlen (drive) * 2
|
|
|
|
+ sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX"
|
|
|
|
",XXXXXXXXXXXXXXXXXXXXXXXXXX"));
|
|
|
|
end = (ret + strlen (drive) * 2
|
|
|
|
+ sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX"
|
|
|
|
",XXXXXXXXXXXXXXXXXXXXXXXXXX"));
|
|
|
|
ptr = ret;
|
|
|
|
for (iptr = drive; *iptr; iptr++)
|
|
|
|
{
|
2013-09-23 09:21:09 +00:00
|
|
|
if (*iptr == ',' || *iptr == '\\')
|
2012-01-29 13:28:01 +00:00
|
|
|
*ptr++ = '\\';
|
|
|
|
*ptr++ = *iptr;
|
|
|
|
}
|
|
|
|
*ptr = 0;
|
|
|
|
if (dos_part >= 0)
|
|
|
|
snprintf (ptr, end - ptr, ",%d", dos_part + 1);
|
|
|
|
ptr += strlen (ptr);
|
|
|
|
if (bsd_part >= 0)
|
|
|
|
snprintf (ptr, end - ptr, ",%d", bsd_part + 1);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-02-03 21:36:51 +00:00
|
|
|
char *
|
|
|
|
grub_util_get_os_disk (const char *os_dev)
|
|
|
|
{
|
2012-04-21 14:42:28 +00:00
|
|
|
int is_part;
|
2012-02-03 21:36:51 +00:00
|
|
|
|
|
|
|
grub_util_info ("Looking for %s", os_dev);
|
|
|
|
|
2013-09-24 17:17:24 +00:00
|
|
|
#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
|
2013-09-23 09:21:09 +00:00
|
|
|
struct stat st;
|
|
|
|
|
2012-02-03 21:36:51 +00:00
|
|
|
if (stat (os_dev, &st) < 0)
|
|
|
|
{
|
2012-02-05 10:07:33 +00:00
|
|
|
const char *errstr = strerror (errno);
|
|
|
|
grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot stat `%s': %s"),
|
|
|
|
os_dev, errstr);
|
|
|
|
grub_util_info (_("cannot stat `%s': %s"), os_dev, errstr);
|
2012-02-03 21:36:51 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-04-21 14:42:28 +00:00
|
|
|
return convert_system_partition_to_system_disk (os_dev, &st, &is_part);
|
2013-09-23 09:21:09 +00:00
|
|
|
#else
|
|
|
|
return convert_system_partition_to_system_disk (os_dev, NULL, &is_part);
|
|
|
|
#endif
|
2012-02-03 21:36:51 +00:00
|
|
|
}
|
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
#if !defined(__APPLE__)
|
2013-01-20 15:52:15 +00:00
|
|
|
/* Context for grub_util_biosdisk_get_grub_dev. */
|
|
|
|
struct grub_util_biosdisk_get_grub_dev_ctx
|
|
|
|
{
|
|
|
|
char *partname;
|
|
|
|
grub_disk_addr_t start;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Helper for grub_util_biosdisk_get_grub_dev. */
|
|
|
|
static int
|
|
|
|
find_partition (grub_disk_t dsk __attribute__ ((unused)),
|
|
|
|
const grub_partition_t partition, void *data)
|
|
|
|
{
|
|
|
|
struct grub_util_biosdisk_get_grub_dev_ctx *ctx = data;
|
|
|
|
grub_disk_addr_t part_start = 0;
|
|
|
|
grub_util_info ("Partition %d starts from %" PRIuGRUB_UINT64_T,
|
|
|
|
partition->number, partition->start);
|
|
|
|
|
|
|
|
part_start = grub_partition_get_start (partition);
|
|
|
|
|
|
|
|
if (ctx->start == part_start)
|
|
|
|
{
|
|
|
|
ctx->partname = grub_partition_get_name (partition);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-01-29 13:28:01 +00:00
|
|
|
char *
|
|
|
|
grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|
|
|
{
|
2013-09-24 17:17:24 +00:00
|
|
|
#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
|
2012-01-29 13:28:01 +00:00
|
|
|
struct stat st;
|
2013-09-23 09:21:09 +00:00
|
|
|
#endif
|
2012-01-29 13:28:01 +00:00
|
|
|
const char *drive;
|
|
|
|
char *sys_disk;
|
2012-04-21 14:42:28 +00:00
|
|
|
int is_part;
|
2012-01-29 13:28:01 +00:00
|
|
|
|
|
|
|
grub_util_info ("Looking for %s", os_dev);
|
|
|
|
|
2013-09-24 17:17:24 +00:00
|
|
|
#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
|
2012-01-29 13:28:01 +00:00
|
|
|
if (stat (os_dev, &st) < 0)
|
|
|
|
{
|
2012-02-05 10:07:33 +00:00
|
|
|
const char *errstr = strerror (errno);
|
|
|
|
grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot stat `%s': %s"), os_dev,
|
|
|
|
errstr);
|
|
|
|
grub_util_info (_("cannot stat `%s': %s"), os_dev, errstr);
|
2012-01-29 13:28:01 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
drive = find_system_device (os_dev, &st, 1, 1);
|
2013-09-23 09:21:09 +00:00
|
|
|
|
|
|
|
#if GRUB_DISK_DEVS_ARE_CHAR
|
|
|
|
if (! S_ISCHR (st.st_mode))
|
|
|
|
#else
|
|
|
|
if (! S_ISBLK (st.st_mode))
|
|
|
|
#endif
|
|
|
|
return make_device_name (drive, -1, -1);
|
|
|
|
|
2012-04-21 14:42:28 +00:00
|
|
|
sys_disk = convert_system_partition_to_system_disk (os_dev, &st, &is_part);
|
2013-09-23 09:21:09 +00:00
|
|
|
#else
|
|
|
|
drive = find_system_device (os_dev, NULL, 1, 1);
|
|
|
|
sys_disk = convert_system_partition_to_system_disk (os_dev, NULL, &is_part);
|
|
|
|
#endif
|
|
|
|
|
2012-06-14 17:16:30 +00:00
|
|
|
if (!sys_disk)
|
|
|
|
return 0;
|
2012-06-07 12:24:48 +00:00
|
|
|
grub_util_info ("%s is a parent of %s", sys_disk, os_dev);
|
2012-06-14 17:16:30 +00:00
|
|
|
if (!is_part)
|
2012-01-29 13:28:01 +00:00
|
|
|
{
|
|
|
|
free (sys_disk);
|
|
|
|
return make_device_name (drive, -1, -1);
|
|
|
|
}
|
|
|
|
free (sys_disk);
|
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
#if defined(__APPLE__)
|
|
|
|
/* Apple uses "/dev/r?disk[0-9]+(s[0-9]+)?". */
|
|
|
|
{
|
|
|
|
const char *p;
|
|
|
|
int disk = (grub_memcmp (os_dev, "/dev/disk", sizeof ("/dev/disk") - 1)
|
|
|
|
== 0);
|
|
|
|
int rdisk = (grub_memcmp (os_dev, "/dev/rdisk", sizeof ("/dev/rdisk") - 1)
|
|
|
|
== 0);
|
|
|
|
|
|
|
|
if (!disk && !rdisk)
|
|
|
|
return make_device_name (drive, -1, -1);
|
|
|
|
|
|
|
|
p = os_dev + sizeof ("/dev/disk") + rdisk - 1;
|
|
|
|
while (*p >= '0' && *p <= '9')
|
|
|
|
p++;
|
|
|
|
if (*p != 's')
|
|
|
|
return make_device_name (drive, -1, -1);
|
|
|
|
p++;
|
|
|
|
|
|
|
|
return make_device_name (drive, strtol (p, NULL, 10) - 1, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2012-01-29 13:28:01 +00:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
|
|
|
|
Cygwin /dev/sdXN emulation uses Windows partition mapping. It
|
|
|
|
does not count the extended partition and missing primary
|
|
|
|
partitions. Use same method as on Linux here.
|
|
|
|
|
|
|
|
For NetBSD and FreeBSD, proceed as for Linux, except that the start
|
|
|
|
sector is obtained from the disk label. */
|
|
|
|
{
|
2013-01-20 15:52:15 +00:00
|
|
|
char *name;
|
2012-01-29 13:28:01 +00:00
|
|
|
grub_disk_t disk;
|
2013-01-20 15:52:15 +00:00
|
|
|
struct grub_util_biosdisk_get_grub_dev_ctx ctx;
|
2012-01-29 13:28:01 +00:00
|
|
|
|
|
|
|
name = make_device_name (drive, -1, -1);
|
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
ctx.start = grub_util_find_partition_start (os_dev);
|
2012-01-29 13:28:01 +00:00
|
|
|
if (grub_errno != GRUB_ERR_NONE)
|
|
|
|
{
|
|
|
|
free (name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-09-22 05:36:17 +00:00
|
|
|
#if defined(__GNU__)
|
|
|
|
/* Some versions of Hurd use badly glued Linux code to handle partitions
|
|
|
|
resulting in partitions being promoted to disks. */
|
|
|
|
/* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?". */
|
|
|
|
if (ctx.start == (grub_disk_addr_t) -1)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
int dos_part = -1;
|
|
|
|
int bsd_part = -1;
|
|
|
|
|
|
|
|
p = strrchr (os_dev + sizeof ("/dev/hd") - 1, 's');
|
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
long int n;
|
|
|
|
char *q;
|
|
|
|
|
|
|
|
p++;
|
|
|
|
n = strtol (p, &q, 10);
|
|
|
|
if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX)
|
|
|
|
{
|
|
|
|
dos_part = (int) n - 1;
|
|
|
|
|
|
|
|
if (*q >= 'a' && *q <= 'g')
|
|
|
|
bsd_part = *q - 'a';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return make_device_name (drive, dos_part, bsd_part);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-01-20 15:52:15 +00:00
|
|
|
grub_util_info ("%s starts from %" PRIuGRUB_UINT64_T, os_dev, ctx.start);
|
2012-01-29 13:28:01 +00:00
|
|
|
|
2013-01-20 15:52:15 +00:00
|
|
|
if (ctx.start == 0 && !is_part)
|
2012-01-29 13:28:01 +00:00
|
|
|
return name;
|
|
|
|
|
|
|
|
grub_util_info ("opening the device %s", name);
|
|
|
|
disk = grub_disk_open (name);
|
|
|
|
free (name);
|
|
|
|
|
|
|
|
if (! disk)
|
|
|
|
{
|
|
|
|
/* We already know that the partition exists. Given that we already
|
|
|
|
checked the device map above, we can only get
|
|
|
|
GRUB_ERR_UNKNOWN_DEVICE at this point if the disk does not exist.
|
|
|
|
This can happen on Xen, where disk images in the host can be
|
|
|
|
assigned to devices that have partition-like names in the guest
|
|
|
|
but are really more like disks. */
|
|
|
|
if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
|
|
|
|
{
|
2012-06-14 17:16:30 +00:00
|
|
|
char *canon;
|
2012-01-29 13:28:01 +00:00
|
|
|
grub_util_warn
|
2012-02-03 10:56:49 +00:00
|
|
|
(_("disk does not exist, so falling back to partition device %s"),
|
2012-01-29 13:28:01 +00:00
|
|
|
os_dev);
|
2013-08-13 15:48:56 +00:00
|
|
|
grub_errno = GRUB_ERR_NONE;
|
2012-01-29 13:28:01 +00:00
|
|
|
|
2012-06-14 17:16:30 +00:00
|
|
|
canon = canonicalize_file_name (os_dev);
|
2013-09-24 17:17:24 +00:00
|
|
|
#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
|
2012-06-14 17:16:30 +00:00
|
|
|
drive = find_system_device (canon ? : os_dev, &st, 0, 1);
|
2013-09-23 09:21:09 +00:00
|
|
|
#else
|
|
|
|
drive = find_system_device (canon ? : os_dev, NULL, 0, 1);
|
|
|
|
#endif
|
2012-06-14 17:16:30 +00:00
|
|
|
if (canon)
|
|
|
|
free (canon);
|
2012-01-29 13:28:01 +00:00
|
|
|
return make_device_name (drive, -1, -1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-20 15:52:15 +00:00
|
|
|
name = grub_util_get_ldm (disk, ctx.start);
|
2012-01-29 13:28:01 +00:00
|
|
|
if (name)
|
|
|
|
return name;
|
|
|
|
|
2013-01-20 15:52:15 +00:00
|
|
|
ctx.partname = NULL;
|
2012-01-29 13:28:01 +00:00
|
|
|
|
2013-01-20 15:52:15 +00:00
|
|
|
grub_partition_iterate (disk, find_partition, &ctx);
|
2012-01-29 13:28:01 +00:00
|
|
|
if (grub_errno != GRUB_ERR_NONE)
|
|
|
|
{
|
|
|
|
grub_disk_close (disk);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-20 15:52:15 +00:00
|
|
|
if (ctx.partname == NULL)
|
2012-01-29 13:28:01 +00:00
|
|
|
{
|
|
|
|
grub_disk_close (disk);
|
|
|
|
grub_util_info ("cannot find the partition of `%s'", os_dev);
|
|
|
|
grub_error (GRUB_ERR_BAD_DEVICE,
|
|
|
|
"cannot find the partition of `%s'", os_dev);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-20 15:52:15 +00:00
|
|
|
name = grub_xasprintf ("%s,%s", disk->name, ctx.partname);
|
|
|
|
free (ctx.partname);
|
2012-01-29 13:28:01 +00:00
|
|
|
grub_disk_close (disk);
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
grub_util_biosdisk_is_present (const char *os_dev)
|
|
|
|
{
|
2013-09-24 17:17:24 +00:00
|
|
|
#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL
|
2012-01-29 13:28:01 +00:00
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat (os_dev, &st) < 0)
|
|
|
|
return 0;
|
|
|
|
|
2013-09-19 06:48:54 +00:00
|
|
|
int ret= (find_system_device (os_dev, &st, 1, 0) != NULL);
|
2013-09-24 16:58:33 +00:00
|
|
|
#else
|
|
|
|
int ret= (find_system_device (os_dev, NULL, 1, 0) != NULL);
|
|
|
|
#endif
|
2013-09-19 06:48:54 +00:00
|
|
|
grub_util_info ((ret ? "%s is present" : "%s is not present"),
|
|
|
|
os_dev);
|
|
|
|
return ret;
|
2012-01-29 13:28:01 +00:00
|
|
|
}
|
|
|
|
|
2011-07-08 11:33:12 +00:00
|
|
|
#ifdef HAVE_LIBZFS
|
|
|
|
static libzfs_handle_t *__libzfs_handle;
|
|
|
|
|
|
|
|
static void
|
|
|
|
fini_libzfs (void)
|
|
|
|
{
|
|
|
|
libzfs_fini (__libzfs_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
libzfs_handle_t *
|
|
|
|
grub_get_libzfs_handle (void)
|
|
|
|
{
|
|
|
|
if (! __libzfs_handle)
|
|
|
|
{
|
|
|
|
__libzfs_handle = libzfs_init ();
|
|
|
|
|
|
|
|
if (__libzfs_handle)
|
|
|
|
atexit (fini_libzfs);
|
|
|
|
}
|
|
|
|
|
|
|
|
return __libzfs_handle;
|
|
|
|
}
|
|
|
|
#endif /* HAVE_LIBZFS */
|
|
|
|
|