merge mainline to ia64

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-01-03 00:04:39 +01:00
commit 0f35c665e6
595 changed files with 62746 additions and 9109 deletions

View file

@ -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__)

View file

@ -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,
};

View file

@ -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 ();
}

View file

@ -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)

View file

@ -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;
}

View file

@ -40,3 +40,8 @@ grub_emu_init (void)
{
return;
}
void
grub_emu_post_init (void)
{
}

View file

@ -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)
{

View file

@ -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

View file

@ -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>