merge mainline to ia64
This commit is contained in:
commit
0f35c665e6
595 changed files with 62746 additions and 9109 deletions
|
@ -7,7 +7,20 @@
|
|||
#elif defined(__sparc__)
|
||||
#include "../sparc64/cache.S"
|
||||
#elif defined(__mips__)
|
||||
#include "../mips/cache.S"
|
||||
/* On MIPS we must go through standard functions. */
|
||||
#include <grub/symbol.h>
|
||||
|
||||
FUNCTION (grub_cpu_flush_cache)
|
||||
FUNCTION (grub_arch_sync_caches)
|
||||
.set nomacro
|
||||
.set noreorder
|
||||
lui $t0, %hi(_flush_cache)
|
||||
addui $t0, $t0, %lo(_flush_cache)
|
||||
move $a3, $zero
|
||||
jr $t0
|
||||
nop
|
||||
.set reorder
|
||||
.set macro
|
||||
#elif defined(__powerpc__)
|
||||
#include "../powerpc/cache.S"
|
||||
#elif defined(__ia64__)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <config-util.h>
|
||||
|
||||
/* For compatibility. */
|
||||
#ifndef A_NORMAL
|
||||
|
@ -37,6 +38,8 @@
|
|||
# include <ncurses.h>
|
||||
#elif defined(HAVE_CURSES_H)
|
||||
# include <curses.h>
|
||||
#else
|
||||
#error What the hell?
|
||||
#endif
|
||||
|
||||
static int grub_console_attr = A_NORMAL;
|
||||
|
@ -102,63 +105,32 @@ grub_ncurses_setcolorstate (struct grub_term_output *term,
|
|||
}
|
||||
}
|
||||
|
||||
static int saved_char = ERR;
|
||||
|
||||
static int
|
||||
grub_ncurses_checkkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Check for SAVED_CHAR. This should not be true, because this
|
||||
means checkkey is called twice continuously. */
|
||||
if (saved_char != ERR)
|
||||
return saved_char;
|
||||
|
||||
wtimeout (stdscr, 100);
|
||||
c = getch ();
|
||||
/* If C is not ERR, then put it back in the input queue. */
|
||||
if (c != ERR)
|
||||
{
|
||||
saved_char = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused)))
|
||||
{
|
||||
int c;
|
||||
|
||||
/* If checkkey has already got a character, then return it. */
|
||||
if (saved_char != ERR)
|
||||
{
|
||||
c = saved_char;
|
||||
saved_char = ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
wtimeout (stdscr, -1);
|
||||
c = getch ();
|
||||
}
|
||||
wtimeout (stdscr, 100);
|
||||
c = getch ();
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case ERR:
|
||||
return -1;
|
||||
case KEY_LEFT:
|
||||
c = GRUB_TERM_LEFT;
|
||||
c = GRUB_TERM_KEY_LEFT;
|
||||
break;
|
||||
|
||||
case KEY_RIGHT:
|
||||
c = GRUB_TERM_RIGHT;
|
||||
c = GRUB_TERM_KEY_RIGHT;
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
c = GRUB_TERM_UP;
|
||||
c = GRUB_TERM_KEY_UP;
|
||||
break;
|
||||
|
||||
case KEY_DOWN:
|
||||
c = GRUB_TERM_DOWN;
|
||||
c = GRUB_TERM_KEY_DOWN;
|
||||
break;
|
||||
|
||||
case KEY_IC:
|
||||
|
@ -166,30 +138,30 @@ grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused)))
|
|||
break;
|
||||
|
||||
case KEY_DC:
|
||||
c = GRUB_TERM_DC;
|
||||
c = GRUB_TERM_KEY_DC;
|
||||
break;
|
||||
|
||||
case KEY_BACKSPACE:
|
||||
/* XXX: For some reason ncurses on xterm does not return
|
||||
KEY_BACKSPACE. */
|
||||
case 127:
|
||||
c = GRUB_TERM_BACKSPACE;
|
||||
c = '\b';
|
||||
break;
|
||||
|
||||
case KEY_HOME:
|
||||
c = GRUB_TERM_HOME;
|
||||
c = GRUB_TERM_KEY_HOME;
|
||||
break;
|
||||
|
||||
case KEY_END:
|
||||
c = GRUB_TERM_END;
|
||||
c = GRUB_TERM_KEY_END;
|
||||
break;
|
||||
|
||||
case KEY_NPAGE:
|
||||
c = GRUB_TERM_NPAGE;
|
||||
c = GRUB_TERM_KEY_NPAGE;
|
||||
break;
|
||||
|
||||
case KEY_PPAGE:
|
||||
c = GRUB_TERM_PPAGE;
|
||||
c = GRUB_TERM_KEY_PPAGE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -288,7 +260,6 @@ grub_ncurses_fini (struct grub_term_output *term __attribute__ ((unused)))
|
|||
static struct grub_term_input grub_ncurses_term_input =
|
||||
{
|
||||
.name = "console",
|
||||
.checkkey = grub_ncurses_checkkey,
|
||||
.getkey = grub_ncurses_getkey,
|
||||
};
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <grub/kernel.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/emu/misc.h>
|
||||
#include <grub/disk.h>
|
||||
|
||||
void
|
||||
grub_register_exported_symbols (void)
|
||||
|
@ -56,5 +57,24 @@ void grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)),
|
|||
*tramp = 0;
|
||||
*got = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GRUB_LINKER_HAVE_INIT
|
||||
void
|
||||
grub_arch_dl_init_linker (void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
grub_emu_post_init (void)
|
||||
{
|
||||
grub_lvm_fini ();
|
||||
grub_mdraid09_fini ();
|
||||
grub_mdraid1x_fini ();
|
||||
grub_raid_fini ();
|
||||
grub_raid_init ();
|
||||
grub_mdraid09_init ();
|
||||
grub_mdraid1x_init ();
|
||||
grub_lvm_init ();
|
||||
}
|
||||
|
|
|
@ -189,31 +189,40 @@ find_root_device_from_libzfs (const char *dir)
|
|||
{
|
||||
zpool_handle_t *zpool;
|
||||
libzfs_handle_t *libzfs;
|
||||
nvlist_t *nvlist;
|
||||
nvlist_t **nvlist_array;
|
||||
nvlist_t *config, *vdev_tree;
|
||||
nvlist_t **children, **path;
|
||||
unsigned int nvlist_count;
|
||||
unsigned int i;
|
||||
|
||||
libzfs = grub_get_libzfs_handle ();
|
||||
if (! libzfs)
|
||||
return NULL;
|
||||
|
||||
zpool = zpool_open (libzfs, poolname);
|
||||
nvlist = zpool_get_config (zpool, NULL);
|
||||
config = zpool_get_config (zpool, NULL);
|
||||
|
||||
if (nvlist_lookup_nvlist (nvlist, "vdev_tree", &nvlist) != 0)
|
||||
if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0)
|
||||
error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")");
|
||||
|
||||
if (nvlist_lookup_nvlist_array (nvlist, "children", &nvlist_array, &nvlist_count) != 0)
|
||||
if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0)
|
||||
error (1, errno, "nvlist_lookup_nvlist_array (\"children\")");
|
||||
assert (nvlist_count > 0);
|
||||
|
||||
do
|
||||
while (nvlist_lookup_nvlist_array (children[0], "children",
|
||||
&children, &nvlist_count) == 0)
|
||||
assert (nvlist_count > 0);
|
||||
|
||||
for (i = 0; i < nvlist_count; i++)
|
||||
{
|
||||
assert (nvlist_count > 0);
|
||||
} while (nvlist_lookup_nvlist_array (nvlist_array[0], "children",
|
||||
&nvlist_array, &nvlist_count) == 0);
|
||||
if (nvlist_lookup_string (children[i], "path", &device) != 0)
|
||||
error (1, errno, "nvlist_lookup_string (\"path\")");
|
||||
|
||||
if (nvlist_lookup_string (nvlist_array[0], "path", &device) != 0)
|
||||
error (1, errno, "nvlist_lookup_string (\"path\")");
|
||||
struct stat st;
|
||||
if (stat (device, &st) == 0)
|
||||
break;
|
||||
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
zpool_close (zpool);
|
||||
}
|
||||
|
@ -228,8 +237,8 @@ find_root_device_from_libzfs (const char *dir)
|
|||
|
||||
#ifdef __MINGW32__
|
||||
|
||||
static char *
|
||||
find_root_device (const char *dir __attribute__ ((unused)),
|
||||
char *
|
||||
grub_find_device (const char *dir __attribute__ ((unused)),
|
||||
dev_t dev __attribute__ ((unused)))
|
||||
{
|
||||
return 0;
|
||||
|
@ -237,13 +246,22 @@ find_root_device (const char *dir __attribute__ ((unused)),
|
|||
|
||||
#elif ! defined(__CYGWIN__)
|
||||
|
||||
static char *
|
||||
find_root_device (const char *dir, dev_t dev)
|
||||
char *
|
||||
grub_find_device (const char *dir, dev_t dev)
|
||||
{
|
||||
DIR *dp;
|
||||
char *saved_cwd;
|
||||
struct dirent *ent;
|
||||
|
||||
if (! dir)
|
||||
{
|
||||
#ifdef __CYGWIN__
|
||||
return NULL;
|
||||
#else
|
||||
dir = "/dev";
|
||||
#endif
|
||||
}
|
||||
|
||||
dp = opendir (dir);
|
||||
if (! dp)
|
||||
return 0;
|
||||
|
@ -292,7 +310,7 @@ find_root_device (const char *dir, dev_t dev)
|
|||
/* Find it recursively. */
|
||||
char *res;
|
||||
|
||||
res = find_root_device (ent->d_name, dev);
|
||||
res = grub_find_device (ent->d_name, dev);
|
||||
|
||||
if (res)
|
||||
{
|
||||
|
@ -402,8 +420,8 @@ get_bootsec_serial (const char *os_dev, int mbr)
|
|||
return serial;
|
||||
}
|
||||
|
||||
static char *
|
||||
find_cygwin_root_device (const char *path, dev_t dev)
|
||||
char *
|
||||
grub_find_device (const char *path, dev_t dev)
|
||||
{
|
||||
/* No root device for /cygdrive. */
|
||||
if (dev == (DEV_CYGDRIVE_MAJOR << 16))
|
||||
|
@ -424,7 +442,7 @@ find_cygwin_root_device (const char *path, dev_t dev)
|
|||
|
||||
/* Cygwin returns the partition serial number in stat.st_dev.
|
||||
This is never identical to the device number of the emulated
|
||||
/dev/sdXN device, so above find_root_device () does not work.
|
||||
/dev/sdXN device, so above grub_find_device () does not work.
|
||||
Search the partition with the same serial in boot sector instead. */
|
||||
char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */
|
||||
int d;
|
||||
|
@ -529,12 +547,12 @@ grub_guess_root_device (const char *dir)
|
|||
|
||||
#ifdef __CYGWIN__
|
||||
/* Cygwin specific function. */
|
||||
os_dev = find_cygwin_root_device (dir, st.st_dev);
|
||||
os_dev = grub_find_device (dir, st.st_dev);
|
||||
|
||||
#else
|
||||
|
||||
/* This might be truly slow, but is there any better way? */
|
||||
os_dev = find_root_device ("/dev", st.st_dev);
|
||||
os_dev = grub_find_device ("/dev", st.st_dev);
|
||||
#endif
|
||||
#endif /* !__GNU__ */
|
||||
|
||||
|
@ -564,6 +582,8 @@ grub_util_is_dmraid (const char *os_dev)
|
|||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/ddf1_", 17))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -572,6 +592,10 @@ int
|
|||
grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
|
||||
{
|
||||
#ifdef __linux__
|
||||
/* User explicitly claims that this drive is visible by BIOS. */
|
||||
if (grub_util_biosdisk_is_present (os_dev))
|
||||
return GRUB_DEV_ABSTRACTION_NONE;
|
||||
|
||||
/* Check for LVM. */
|
||||
if (!strncmp (os_dev, "/dev/mapper/", 12)
|
||||
&& ! grub_util_is_dmraid (os_dev)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* hostdisk.c - emulate biosdisk */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010 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
|
||||
|
@ -102,13 +102,22 @@ struct hd_geometry
|
|||
# include <libdevmapper.h>
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
# define HAVE_DIOCGDINFO
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/disklabel.h> /* struct disklabel */
|
||||
#else /* !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) */
|
||||
# undef HAVE_DIOCGDINFO
|
||||
#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
# ifdef HAVE_GETRAWPARTITION
|
||||
# include <util.h> /* getrawpartition */
|
||||
# endif /* HAVE_GETRAWPARTITION */
|
||||
# include <sys/fdio.h>
|
||||
# ifndef FLOPPY_MAJOR
|
||||
# define FLOPPY_MAJOR 2
|
||||
# endif /* ! FLOPPY_MAJOR */
|
||||
# ifndef RAW_FLOPPY_MAJOR
|
||||
# define RAW_FLOPPY_MAJOR 9
|
||||
# endif /* ! RAW_FLOPPY_MAJOR */
|
||||
|
@ -221,7 +230,6 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"no mapping exists for `%s'", name);
|
||||
|
||||
disk->has_partitions = 1;
|
||||
disk->id = drive;
|
||||
disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data));
|
||||
data->dev = NULL;
|
||||
|
@ -329,17 +337,17 @@ device_is_mapped (const char *dev)
|
|||
}
|
||||
#endif /* HAVE_DEVICE_MAPPER */
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__)
|
||||
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
|
||||
static grub_disk_addr_t
|
||||
find_partition_start (const char *dev)
|
||||
{
|
||||
int fd;
|
||||
# if !defined(__NetBSD__)
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
struct hd_geometry hdg;
|
||||
# else /* defined(__NetBSD__) */
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
struct disklabel label;
|
||||
int p_index;
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
# endif /* !defined(HAVE_DIOCGDINFO) */
|
||||
|
||||
# ifdef HAVE_DEVICE_MAPPER
|
||||
if (grub_device_mapper_supported () && device_is_mapped (dev)) {
|
||||
|
@ -413,36 +421,38 @@ devmapper_fail:
|
|||
if (fd == -1)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
# if !defined(__NetBSD__)
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
"cannot open `%s' while attempting to get disk geometry", dev);
|
||||
# else /* defined(__NetBSD__) */
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
"cannot open `%s' while attempting to get disk label", dev);
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
# endif /* !defined(HAVE_DIOCGDINFO) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
# if !defined(__NetBSD__)
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
if (ioctl (fd, HDIO_GETGEO, &hdg))
|
||||
# else /* defined(__NetBSD__) */
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
# if defined(__NetBSD__)
|
||||
configure_device_driver (fd);
|
||||
# endif /* defined(__NetBSD__) */
|
||||
if (ioctl (fd, DIOCGDINFO, &label) == -1)
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
# endif /* !defined(HAVE_DIOCGDINFO) */
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
# if !defined(__NetBSD__)
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
"cannot get disk geometry of `%s'", dev);
|
||||
# else /* defined(__NetBSD__) */
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
"cannot get disk label of `%s'", dev);
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
# endif /* !defined(HAVE_DIOCGDINFO) */
|
||||
close (fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
|
||||
# if !defined(__NetBSD__)
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
return hdg.start;
|
||||
# else /* defined(__NetBSD__) */
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
p_index = dev[strlen(dev) - 1] - 'a';
|
||||
|
||||
if (p_index >= label.d_npartitions)
|
||||
|
@ -452,9 +462,9 @@ devmapper_fail:
|
|||
return 0;
|
||||
}
|
||||
return (grub_disk_addr_t) label.d_partitions[p_index].p_offset;
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
# endif /* !defined(HAVE_DIOCGDINFO) */
|
||||
}
|
||||
#endif /* __linux__ || __CYGWIN__ */
|
||||
#endif /* __linux__ || __CYGWIN__ || HAVE_DIOCGDINFO */
|
||||
|
||||
#ifdef __linux__
|
||||
/* Cache of partition start sectors for each disk. */
|
||||
|
@ -956,13 +966,16 @@ read_device_map (const char *dev_map)
|
|||
#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].device = xmalloc (PATH_MAX);
|
||||
if (! realpath (p, map[drive].device))
|
||||
grub_util_error ("cannot get the real path of `%s'", p);
|
||||
#else
|
||||
map[drive].device = xstrdup (p);
|
||||
symbolic links. Leave /dev/mapper/ alone, though. */
|
||||
if (strncmp (p, "/dev/mapper/", 12) != 0)
|
||||
{
|
||||
map[drive].device = xmalloc (PATH_MAX);
|
||||
if (! realpath (p, map[drive].device))
|
||||
grub_util_error ("cannot get the real path of `%s'", p);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
map[drive].device = xstrdup (p);
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
|
@ -994,8 +1007,7 @@ grub_util_biosdisk_fini (void)
|
|||
|
||||
/*
|
||||
* Note: we do not use the new partition naming scheme as dos_part does not
|
||||
* necessarily correspond to an msdos partition. See e.g. the FreeBSD code
|
||||
* in function grub_util_biosdisk_get_grub_dev.
|
||||
* necessarily correspond to an msdos partition.
|
||||
*/
|
||||
static char *
|
||||
make_device_name (int drive, int dos_part, int bsd_part)
|
||||
|
@ -1117,6 +1129,16 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
|
|||
return path;
|
||||
}
|
||||
|
||||
if (strncmp ("md", p, 2) == 0
|
||||
&& p[2] >= '0' && p[2] <= '9')
|
||||
{
|
||||
char *ptr = p + 2;
|
||||
while (*ptr >= '0' && *ptr <= '9')
|
||||
ptr++;
|
||||
*ptr = 0;
|
||||
return path;
|
||||
}
|
||||
|
||||
/* If this is an IDE, SCSI or Virtio disk. */
|
||||
if (strncmp ("vdisk", p, 5) == 0
|
||||
&& p[5] >= 'a' && p[5] <= 'z')
|
||||
|
@ -1130,36 +1152,42 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
|
|||
|| strncmp ("sd", p, 2) == 0)
|
||||
&& p[2] >= 'a' && p[2] <= 'z')
|
||||
{
|
||||
/* /dev/[hsv]d[a-z][0-9]* */
|
||||
p[3] = '\0';
|
||||
char *pp = p + 2;
|
||||
while (*pp >= 'a' && *pp <= 'z')
|
||||
pp++;
|
||||
/* /dev/[hsv]d[a-z]+[0-9]* */
|
||||
*pp = '\0';
|
||||
return path;
|
||||
}
|
||||
|
||||
/* If this is a Xen virtual block device. */
|
||||
if ((strncmp ("xvd", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z')
|
||||
{
|
||||
/* /dev/xvd[a-z][0-9]* */
|
||||
p[4] = '\0';
|
||||
char *pp = p + 3;
|
||||
while (*pp >= 'a' && *pp <= 'z')
|
||||
pp++;
|
||||
/* /dev/xvd[a-z]+[0-9]* */
|
||||
*pp = '\0';
|
||||
return path;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
/* If this is a DM-RAID device. */
|
||||
if ((strncmp ("mapper/", p, 7) == 0))
|
||||
/* If this is a DM-RAID device.
|
||||
Compare os_dev rather than path here, since nodes under
|
||||
/dev/mapper/ are often symlinks. */
|
||||
if ((strncmp ("/dev/mapper/", os_dev, 12) == 0))
|
||||
{
|
||||
static struct dm_tree *tree = NULL;
|
||||
struct dm_tree *tree;
|
||||
uint32_t maj, min;
|
||||
struct dm_tree_node *node, *child;
|
||||
struct dm_tree_node *node = NULL, *child;
|
||||
void *handle;
|
||||
const char *node_uuid, *mapper_name, *child_uuid, *child_name;
|
||||
|
||||
if (! tree)
|
||||
tree = dm_tree_create ();
|
||||
const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name;
|
||||
|
||||
tree = dm_tree_create ();
|
||||
if (! tree)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "dm_tree_create failed\n");
|
||||
return NULL;
|
||||
goto devmapper_out;
|
||||
}
|
||||
|
||||
maj = major (st->st_rdev);
|
||||
|
@ -1167,29 +1195,30 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
|
|||
if (! dm_tree_add_dev (tree, maj, min))
|
||||
{
|
||||
grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
|
||||
return NULL;
|
||||
goto devmapper_out;
|
||||
}
|
||||
|
||||
node = dm_tree_find_node (tree, maj, min);
|
||||
if (! node)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
|
||||
return NULL;
|
||||
goto devmapper_out;
|
||||
}
|
||||
node_uuid = dm_tree_node_get_uuid (node);
|
||||
if (! node_uuid)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "%s has no DM uuid\n", path);
|
||||
return NULL;
|
||||
node = NULL;
|
||||
goto devmapper_out;
|
||||
}
|
||||
else if (strncmp (node_uuid, "DMRAID-", 7) != 0)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path);
|
||||
return NULL;
|
||||
node = NULL;
|
||||
goto devmapper_out;
|
||||
}
|
||||
|
||||
handle = NULL;
|
||||
mapper_name = NULL;
|
||||
/* Counter-intuitively, device-mapper refers to the disk-like
|
||||
device containing a DM-RAID partition device as a "child" of
|
||||
the partition device. */
|
||||
|
@ -1219,17 +1248,20 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
|
|||
mapper_name = child_name;
|
||||
|
||||
devmapper_out:
|
||||
if (! mapper_name)
|
||||
if (! mapper_name && node)
|
||||
{
|
||||
/* This is a DM-RAID disk, not a partition. */
|
||||
mapper_name = dm_tree_node_get_name (node);
|
||||
if (! mapper_name)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "%s has no DM name\n", path);
|
||||
return NULL;
|
||||
}
|
||||
grub_dprintf ("hostdisk", "%s has no DM name\n", path);
|
||||
}
|
||||
return xasprintf ("/dev/mapper/%s", mapper_name);
|
||||
if (tree)
|
||||
dm_tree_free (tree);
|
||||
free (path);
|
||||
if (mapper_name)
|
||||
return xasprintf ("/dev/mapper/%s", mapper_name);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
#endif /* HAVE_DEVICE_MAPPER */
|
||||
}
|
||||
|
@ -1333,13 +1365,37 @@ device_is_wholedisk (const char *os_dev)
|
|||
}
|
||||
#endif /* defined(__NetBSD__) */
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
static int
|
||||
find_system_device (const char *os_dev, struct stat *st)
|
||||
device_is_wholedisk (const char *os_dev)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0)
|
||||
return 0;
|
||||
|
||||
for (p = os_dev + sizeof ("/dev/") - 1; *p; ++p)
|
||||
if (grub_isdigit (*p))
|
||||
{
|
||||
if (strchr (p, 's'))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
|
||||
|
||||
static int
|
||||
find_system_device (const char *os_dev, struct stat *st, int convert, int add)
|
||||
{
|
||||
unsigned int i;
|
||||
char *os_disk;
|
||||
|
||||
os_disk = convert_system_partition_to_system_disk (os_dev, st);
|
||||
if (convert)
|
||||
os_disk = convert_system_partition_to_system_disk (os_dev, st);
|
||||
else
|
||||
os_disk = xstrdup (os_dev);
|
||||
if (! os_disk)
|
||||
return -1;
|
||||
|
||||
|
@ -1352,6 +1408,9 @@ find_system_device (const char *os_dev, struct stat *st)
|
|||
return i;
|
||||
}
|
||||
|
||||
if (!add)
|
||||
return -1;
|
||||
|
||||
if (i == ARRAY_SIZE (map))
|
||||
grub_util_error (_("device count exceeds limit"));
|
||||
|
||||
|
@ -1361,6 +1420,17 @@ find_system_device (const char *os_dev, struct stat *st)
|
|||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
grub_util_biosdisk_is_present (const char *os_dev)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat (os_dev, &st) < 0)
|
||||
return 0;
|
||||
|
||||
return find_system_device (os_dev, &st, 1, 0) != -1;
|
||||
}
|
||||
|
||||
char *
|
||||
grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
||||
{
|
||||
|
@ -1373,7 +1443,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
drive = find_system_device (os_dev, &st);
|
||||
drive = find_system_device (os_dev, &st, 1, 1);
|
||||
if (drive < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
|
@ -1392,7 +1462,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
#endif
|
||||
return make_device_name (drive, -1, -1);
|
||||
|
||||
#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__)
|
||||
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO)
|
||||
/* 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
|
||||
|
@ -1402,8 +1472,8 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
does not count the extended partition and missing primary
|
||||
partitions. Use same method as on Linux here.
|
||||
|
||||
For NetBSD, proceed as for Linux, except that the start sector is
|
||||
obtained from the disk label. */
|
||||
For NetBSD and FreeBSD, proceed as for Linux, except that the start
|
||||
sector is obtained from the disk label. */
|
||||
{
|
||||
char *name, *partname;
|
||||
grub_disk_t disk;
|
||||
|
@ -1431,13 +1501,13 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
|
||||
name = make_device_name (drive, -1, -1);
|
||||
|
||||
# if !defined(__NetBSD__)
|
||||
# if !defined(HAVE_DIOCGDINFO)
|
||||
if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
|
||||
return name;
|
||||
# else /* defined(__NetBSD__) */
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
/* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
|
||||
* different, we know that os_dev cannot be a floppy device. */
|
||||
# endif /* !defined(__NetBSD__) */
|
||||
# endif /* !defined(HAVE_DIOCGDINFO) */
|
||||
|
||||
start = find_partition_start (os_dev);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
|
@ -1456,7 +1526,32 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
free (name);
|
||||
|
||||
if (! disk)
|
||||
return 0;
|
||||
{
|
||||
/* 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)
|
||||
{
|
||||
grub_util_warn
|
||||
("disk does not exist, so falling back to partition device %s",
|
||||
os_dev);
|
||||
|
||||
drive = find_system_device (os_dev, &st, 0, 1);
|
||||
if (drive < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"no mapping exists for `%s'", os_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return make_device_name (drive, -1, -1);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
partname = NULL;
|
||||
grub_partition_iterate (disk, find_partition);
|
||||
|
@ -1506,41 +1601,6 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
return make_device_name (drive, dos_part, bsd_part);
|
||||
}
|
||||
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
|
||||
/* FreeBSD uses "/dev/[a-z]+[0-9]+([sp][0-9]+[a-z]?)?". */
|
||||
{
|
||||
int dos_part = -1;
|
||||
int bsd_part = -1;
|
||||
|
||||
if (strncmp ("/dev/", os_dev, 5) == 0)
|
||||
{
|
||||
const char *p;
|
||||
char *q;
|
||||
long int n;
|
||||
|
||||
for (p = os_dev + 5; *p; ++p)
|
||||
if (grub_isdigit(*p))
|
||||
{
|
||||
p = strpbrk (p, "sp"); /* msdos or apple (or ... ?) partition map */
|
||||
if (p)
|
||||
{
|
||||
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';
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -1552,3 +1612,38 @@ grub_util_biosdisk_get_osdev (grub_disk_t disk)
|
|||
{
|
||||
return map[disk->id].device;
|
||||
}
|
||||
|
||||
int
|
||||
grub_util_biosdisk_is_floppy (grub_disk_t disk)
|
||||
{
|
||||
struct stat st;
|
||||
int fd;
|
||||
|
||||
fd = open (map[disk->id].device, O_RDONLY);
|
||||
/* Shouldn't happen. */
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
|
||||
/* Shouldn't happen either. */
|
||||
if (fstat (fd, &st) < 0)
|
||||
return 0;
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
if (major(st.st_rdev) == RAW_FLOPPY_MAJOR)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#if defined(FLOPPY_MAJOR)
|
||||
if (major(st.st_rdev) == FLOPPY_MAJOR)
|
||||
#else
|
||||
/* Some kernels (e.g. kFreeBSD) don't have a static major number
|
||||
for floppies, but they still use a "fd[0-9]" pathname. */
|
||||
if (map[disk->id].device[5] == 'f'
|
||||
&& map[disk->id].device[6] == 'd'
|
||||
&& map[disk->id].device[7] >= '0'
|
||||
&& map[disk->id].device[7] <= '9')
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -40,3 +40,8 @@ grub_emu_init (void)
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
grub_emu_post_init (void)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -190,13 +189,16 @@ main (int argc, char *argv[])
|
|||
grub_emu_init ();
|
||||
grub_console_init ();
|
||||
grub_host_init ();
|
||||
grub_hostfs_init ();
|
||||
|
||||
/* XXX: This is a bit unportable. */
|
||||
grub_util_biosdisk_init (dev_map);
|
||||
|
||||
grub_init_all ();
|
||||
|
||||
grub_hostfs_init ();
|
||||
|
||||
grub_emu_post_init ();
|
||||
|
||||
/* Make sure that there is a root device. */
|
||||
if (! root_dev)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config-util.h>
|
||||
#include <config.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
@ -61,6 +62,15 @@
|
|||
# include <sys/mount.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_MNTTAB_H
|
||||
# include <stdio.h> /* Needed by sys/mnttab.h. */
|
||||
# include <sys/mnttab.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
# include <sys/mkdev.h> /* makedev */
|
||||
#endif
|
||||
|
||||
int verbosity;
|
||||
|
||||
void
|
||||
|
@ -151,7 +161,7 @@ vasprintf (char **buf, const char *fmt, va_list ap)
|
|||
/* Should be large enough. */
|
||||
*buf = xmalloc (512);
|
||||
|
||||
return vsprintf (*buf, fmt, ap);
|
||||
return vsnprintf (*buf, 512, fmt, ap);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -165,7 +175,7 @@ asprintf (char **buf, const char *fmt, ...)
|
|||
va_list ap;
|
||||
|
||||
va_start (ap, fmt);
|
||||
status = vasprintf (*buf, fmt, ap);
|
||||
status = vasprintf (buf, fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
return status;
|
||||
|
@ -282,18 +292,52 @@ grub_get_libzfs_handle (void)
|
|||
void
|
||||
grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs)
|
||||
{
|
||||
struct statfs mnt;
|
||||
char *slash;
|
||||
|
||||
*poolname = *poolfs = NULL;
|
||||
|
||||
if (statfs (dir, &mnt) != 0)
|
||||
return;
|
||||
#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME)
|
||||
/* FreeBSD and GNU/kFreeBSD. */
|
||||
{
|
||||
struct statfs mnt;
|
||||
|
||||
if (strcmp (mnt.f_fstypename, "zfs") != 0)
|
||||
return;
|
||||
if (statfs (dir, &mnt) != 0)
|
||||
return;
|
||||
|
||||
*poolname = xstrdup (mnt.f_mntfromname);
|
||||
if (strcmp (mnt.f_fstypename, "zfs") != 0)
|
||||
return;
|
||||
|
||||
*poolname = xstrdup (mnt.f_mntfromname);
|
||||
}
|
||||
#elif defined(HAVE_GETEXTMNTENT)
|
||||
/* Solaris. */
|
||||
{
|
||||
struct stat st;
|
||||
struct extmnttab mnt;
|
||||
|
||||
if (stat (dir, &st) != 0)
|
||||
return;
|
||||
|
||||
FILE *mnttab = fopen ("/etc/mnttab", "r");
|
||||
if (! mnttab)
|
||||
return;
|
||||
|
||||
while (getextmntent (mnttab, &mnt, sizeof (mnt)) == 0)
|
||||
{
|
||||
if (makedev (mnt.mnt_major, mnt.mnt_minor) == st.st_dev
|
||||
&& !strcmp (mnt.mnt_fstype, "zfs"))
|
||||
{
|
||||
*poolname = xstrdup (mnt.mnt_special);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose (mnttab);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! *poolname)
|
||||
return;
|
||||
|
||||
slash = strchr (*poolname, '/');
|
||||
if (slash)
|
||||
|
@ -372,6 +416,10 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
|||
{
|
||||
free (buf);
|
||||
free (buf2);
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
if (poolfs)
|
||||
return xasprintf ("/%s/@", poolfs);
|
||||
#endif
|
||||
return xstrdup ("");
|
||||
}
|
||||
else
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config-util.h>
|
||||
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/mm.h>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue