merge mainline into 4096
This commit is contained in:
commit
a5edbcb3a1
393 changed files with 15834 additions and 2186 deletions
13
grub-core/kern/emu/cache.c
Normal file
13
grub-core/kern/emu/cache.c
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
#if defined(__ia64__)
|
||||
#include <grub/cache.h>
|
||||
|
||||
void __clear_cache (char *beg, char *end);
|
||||
|
||||
void
|
||||
grub_arch_sync_caches (void *address, grub_size_t len)
|
||||
{
|
||||
__clear_cache (address, (char *) address + len);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -23,6 +23,7 @@ FUNCTION (grub_arch_sync_caches)
|
|||
.set macro
|
||||
#elif defined(__powerpc__)
|
||||
#include "../powerpc/cache.S"
|
||||
#elif defined(__ia64__)
|
||||
#else
|
||||
#error "No target cpu type is defined"
|
||||
#endif
|
|
@ -50,6 +50,15 @@ grub_emu_init (void)
|
|||
grub_no_autoload = 1;
|
||||
}
|
||||
|
||||
#ifdef __ia64__
|
||||
void grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)),
|
||||
grub_size_t *tramp, grub_size_t *got)
|
||||
{
|
||||
*tramp = 0;
|
||||
*got = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GRUB_LINKER_HAVE_INIT
|
||||
void
|
||||
grub_arch_dl_init_linker (void)
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include <stdint.h>
|
||||
#include <grub/util/misc.h>
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
# include <libdevmapper.h>
|
||||
#endif
|
||||
|
||||
#ifdef __GNU__
|
||||
#include <hurd.h>
|
||||
#include <hurd/lookup.h>
|
||||
|
@ -98,6 +102,14 @@ xgetcwd (void)
|
|||
|
||||
#ifdef __linux__
|
||||
|
||||
struct mountinfo_entry
|
||||
{
|
||||
int id;
|
||||
int major, minor;
|
||||
char enc_root[PATH_MAX], enc_path[PATH_MAX];
|
||||
char fstype[PATH_MAX], device[PATH_MAX];
|
||||
};
|
||||
|
||||
/* Statting something on a btrfs filesystem always returns a virtual device
|
||||
major/minor pair rather than the real underlying device, because btrfs
|
||||
can span multiple underlying devices (and even if it's currently only
|
||||
|
@ -105,75 +117,120 @@ xgetcwd (void)
|
|||
can't deal with the multiple-device case yet, but in the meantime, we can
|
||||
at least cope with the single-device case by scanning
|
||||
/proc/self/mountinfo. */
|
||||
static char *
|
||||
find_root_device_from_mountinfo (const char *dir)
|
||||
char *
|
||||
grub_find_root_device_from_mountinfo (const char *dir, char **relroot)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buf = NULL;
|
||||
size_t len = 0;
|
||||
char *ret = NULL;
|
||||
int entry_len = 0, entry_max = 4;
|
||||
struct mountinfo_entry *entries;
|
||||
struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" };
|
||||
int i;
|
||||
|
||||
if (! *dir)
|
||||
dir = "/";
|
||||
if (relroot)
|
||||
*relroot = NULL;
|
||||
|
||||
fp = fopen ("/proc/self/mountinfo", "r");
|
||||
if (! fp)
|
||||
return NULL; /* fall through to other methods */
|
||||
|
||||
entries = xmalloc (entry_max * sizeof (*entries));
|
||||
|
||||
/* First, build a list of relevant visible mounts. */
|
||||
while (getline (&buf, &len, fp) > 0)
|
||||
{
|
||||
int mnt_id, parent_mnt_id;
|
||||
unsigned int major, minor;
|
||||
char enc_root[PATH_MAX], enc_path[PATH_MAX];
|
||||
struct mountinfo_entry entry;
|
||||
int count;
|
||||
size_t enc_path_len;
|
||||
const char *sep;
|
||||
char fstype[PATH_MAX], device[PATH_MAX];
|
||||
struct stat st;
|
||||
|
||||
if (sscanf (buf, "%d %d %u:%u %s %s%n",
|
||||
&mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path,
|
||||
&count) < 6)
|
||||
&entry.id, &parent_entry.id, &entry.major, &entry.minor,
|
||||
entry.enc_root, entry.enc_path, &count) < 6)
|
||||
continue;
|
||||
|
||||
if (strcmp (enc_root, "/") != 0)
|
||||
continue; /* only a subtree is mounted */
|
||||
|
||||
enc_path_len = strlen (enc_path);
|
||||
enc_path_len = strlen (entry.enc_path);
|
||||
/* Check that enc_path is a prefix of dir. The prefix must either be
|
||||
the entire string, or end with a slash, or be immediately followed
|
||||
by a slash. */
|
||||
if (strncmp (dir, enc_path, enc_path_len) != 0 ||
|
||||
if (strncmp (dir, entry.enc_path, enc_path_len) != 0 ||
|
||||
(enc_path_len && dir[enc_path_len - 1] != '/' &&
|
||||
dir[enc_path_len] && dir[enc_path_len] != '/'))
|
||||
continue;
|
||||
|
||||
/* This is a parent of the requested directory. /proc/self/mountinfo
|
||||
is in mount order, so it must be the closest parent we've
|
||||
encountered so far. If it's virtual, return its device node;
|
||||
otherwise, carry on to try to find something closer. */
|
||||
|
||||
free (ret);
|
||||
ret = NULL;
|
||||
|
||||
if (major != 0)
|
||||
continue; /* not a virtual device */
|
||||
|
||||
sep = strstr (buf + count, " - ");
|
||||
if (!sep)
|
||||
continue;
|
||||
|
||||
sep += sizeof (" - ") - 1;
|
||||
if (sscanf (sep, "%s %s", fstype, device) != 2)
|
||||
if (sscanf (sep, "%s %s", entry.fstype, entry.device) != 2)
|
||||
continue;
|
||||
|
||||
if (stat (device, &st) < 0)
|
||||
/* Using the mount IDs, find out where this fits in the list of
|
||||
visible mount entries we've seen so far. There are three
|
||||
interesting cases. Firstly, it may be inserted at the end: this is
|
||||
the usual case of /foo/bar being mounted after /foo. Secondly, it
|
||||
may be inserted at the start: for example, this can happen for
|
||||
filesystems that are mounted before / and later moved under it.
|
||||
Thirdly, it may occlude part or all of the existing filesystem
|
||||
tree, in which case the end of the list needs to be pruned and this
|
||||
new entry will be inserted at the end. */
|
||||
if (entry_len >= entry_max)
|
||||
{
|
||||
entry_max <<= 1;
|
||||
entries = xrealloc (entries, entry_max * sizeof (*entries));
|
||||
}
|
||||
|
||||
if (!entry_len)
|
||||
{
|
||||
/* Initialise list. */
|
||||
entry_len = 2;
|
||||
entries[0] = parent_entry;
|
||||
entries[1] = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = entry_len - 1; i >= 0; i--)
|
||||
{
|
||||
if (entries[i].id == parent_entry.id)
|
||||
{
|
||||
/* Insert at end, pruning anything previously above this. */
|
||||
entry_len = i + 2;
|
||||
entries[i + 1] = entry;
|
||||
break;
|
||||
}
|
||||
else if (i == 0 && entries[i].id == entry.id)
|
||||
{
|
||||
/* Insert at start. */
|
||||
entry_len++;
|
||||
memmove (entries + 1, entries,
|
||||
(entry_len - 1) * sizeof (*entries));
|
||||
entries[0] = parent_entry;
|
||||
entries[1] = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now scan visible mounts for the ones we're interested in. */
|
||||
for (i = entry_len - 1; i >= 0; i--)
|
||||
{
|
||||
if (!*entries[i].device)
|
||||
continue;
|
||||
|
||||
if (!S_ISBLK (st.st_mode))
|
||||
continue; /* not a block device */
|
||||
|
||||
ret = strdup (device);
|
||||
ret = strdup (entries[i].device);
|
||||
if (relroot)
|
||||
*relroot = strdup (entries[i].enc_root);
|
||||
break;
|
||||
}
|
||||
|
||||
free (buf);
|
||||
free (entries);
|
||||
fclose (fp);
|
||||
return ret;
|
||||
}
|
||||
|
@ -301,7 +358,7 @@ grub_find_device (const char *dir, dev_t dev)
|
|||
|
||||
if (S_ISLNK (st.st_mode)) {
|
||||
#ifdef __linux__
|
||||
if (strcmp (dir, "mapper") == 0) {
|
||||
if (strcmp (dir, "mapper") == 0 || strcmp (dir, "/dev/mapper") == 0) {
|
||||
/* Follow symbolic links under /dev/mapper/; the canonical name
|
||||
may be something like /dev/dm-0, but the names under
|
||||
/dev/mapper/ are more human-readable and so we prefer them if
|
||||
|
@ -479,7 +536,7 @@ grub_find_device (const char *path, dev_t dev)
|
|||
char *
|
||||
grub_guess_root_device (const char *dir)
|
||||
{
|
||||
char *os_dev;
|
||||
char *os_dev = NULL;
|
||||
#ifdef __GNU__
|
||||
file_t file;
|
||||
mach_port_t *ports;
|
||||
|
@ -538,30 +595,49 @@ grub_guess_root_device (const char *dir)
|
|||
mach_port_deallocate (mach_task_self (), file);
|
||||
#else /* !__GNU__ */
|
||||
struct stat st;
|
||||
dev_t dev;
|
||||
|
||||
#ifdef __linux__
|
||||
os_dev = find_root_device_from_mountinfo (dir);
|
||||
if (os_dev)
|
||||
return os_dev;
|
||||
if (!os_dev)
|
||||
os_dev = grub_find_root_device_from_mountinfo (dir, NULL);
|
||||
#endif /* __linux__ */
|
||||
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
os_dev = find_root_device_from_libzfs (dir);
|
||||
if (os_dev)
|
||||
return os_dev;
|
||||
if (!os_dev)
|
||||
os_dev = find_root_device_from_libzfs (dir);
|
||||
#endif
|
||||
|
||||
if (os_dev)
|
||||
{
|
||||
char *tmp = os_dev;
|
||||
os_dev = canonicalize_file_name (os_dev);
|
||||
free (tmp);
|
||||
}
|
||||
|
||||
if (os_dev)
|
||||
{
|
||||
if (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) != 0)
|
||||
return os_dev;
|
||||
if (stat (os_dev, &st) < 0)
|
||||
grub_util_error ("cannot stat `%s'", os_dev);
|
||||
free (os_dev);
|
||||
dev = st.st_rdev;
|
||||
return grub_find_device ("/dev/mapper", dev);
|
||||
}
|
||||
|
||||
if (stat (dir, &st) < 0)
|
||||
grub_util_error ("cannot stat `%s'", dir);
|
||||
|
||||
dev = st.st_dev;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
/* Cygwin specific function. */
|
||||
os_dev = grub_find_device (dir, st.st_dev);
|
||||
os_dev = grub_find_device (dir, dev);
|
||||
|
||||
#else
|
||||
|
||||
/* This might be truly slow, but is there any better way? */
|
||||
os_dev = grub_find_device ("/dev", st.st_dev);
|
||||
os_dev = grub_find_device ("/dev", dev);
|
||||
#endif
|
||||
#endif /* !__GNU__ */
|
||||
|
||||
|
@ -569,32 +645,65 @@ grub_guess_root_device (const char *dir)
|
|||
}
|
||||
|
||||
static int
|
||||
grub_util_is_dmraid (const char *os_dev)
|
||||
grub_util_is_lvm (const char *os_dev)
|
||||
{
|
||||
if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/isw_", 16))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/hpt37x_", 19))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/hpt45x_", 19))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/via_", 16))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/lsi_", 16))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/pdc_", 16))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/jmicron_", 20))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/asr_", 16))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/sil_", 16))
|
||||
return 1;
|
||||
else if (! strncmp (os_dev, "/dev/mapper/ddf1_", 17))
|
||||
return 1;
|
||||
if ((strncmp ("/dev/mapper/", os_dev, 12) != 0))
|
||||
return 0;
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
{
|
||||
struct dm_tree *tree;
|
||||
uint32_t maj, min;
|
||||
struct dm_tree_node *node = NULL;
|
||||
const char *node_uuid;
|
||||
struct stat st;
|
||||
|
||||
return 0;
|
||||
if (stat (os_dev, &st) < 0)
|
||||
return 0;
|
||||
|
||||
tree = dm_tree_create ();
|
||||
if (! tree)
|
||||
{
|
||||
grub_printf ("Failed to create tree\n");
|
||||
grub_dprintf ("hostdisk", "dm_tree_create failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
maj = major (st.st_rdev);
|
||||
min = minor (st.st_rdev);
|
||||
|
||||
if (! dm_tree_add_dev (tree, maj, min))
|
||||
{
|
||||
grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
|
||||
dm_tree_free (tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = dm_tree_find_node (tree, maj, min);
|
||||
if (! node)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
|
||||
dm_tree_free (tree);
|
||||
return 0;
|
||||
}
|
||||
node_uuid = dm_tree_node_get_uuid (node);
|
||||
if (! node_uuid)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "%s has no DM uuid\n", os_dev);
|
||||
dm_tree_free (tree);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp (node_uuid, "LVM-", 4) != 0)
|
||||
{
|
||||
dm_tree_free (tree);
|
||||
return 0;
|
||||
}
|
||||
dm_tree_free (tree);
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
return 1;
|
||||
#endif /* HAVE_DEVICE_MAPPER */
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -606,13 +715,11 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
|
|||
return GRUB_DEV_ABSTRACTION_NONE;
|
||||
|
||||
/* Check for LVM. */
|
||||
if (!strncmp (os_dev, "/dev/mapper/", 12)
|
||||
&& ! grub_util_is_dmraid (os_dev)
|
||||
&& strncmp (os_dev, "/dev/mapper/mpath", 17) != 0)
|
||||
if (grub_util_is_lvm (os_dev))
|
||||
return GRUB_DEV_ABSTRACTION_LVM;
|
||||
|
||||
/* Check for RAID. */
|
||||
if (!strncmp (os_dev, "/dev/md", 7))
|
||||
if (!strncmp (os_dev, "/dev/md", 7) && ! grub_util_device_is_mapped (os_dev))
|
||||
return GRUB_DEV_ABSTRACTION_RAID;
|
||||
#endif
|
||||
|
||||
|
@ -622,7 +729,7 @@ grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused)))
|
|||
|
||||
#ifdef __linux__
|
||||
static char *
|
||||
get_mdadm_name (const char *os_dev)
|
||||
get_mdadm_uuid (const char *os_dev)
|
||||
{
|
||||
int mdadm_pipe[2];
|
||||
pid_t mdadm_pid;
|
||||
|
@ -674,19 +781,21 @@ get_mdadm_name (const char *os_dev)
|
|||
|
||||
while (getline (&buf, &len, mdadm) > 0)
|
||||
{
|
||||
if (strncmp (buf, "MD_NAME=", sizeof ("MD_NAME=") - 1) == 0)
|
||||
if (strncmp (buf, "MD_UUID=", sizeof ("MD_UUID=") - 1) == 0)
|
||||
{
|
||||
char *name_start, *colon;
|
||||
char *name_start, *ptri, *ptro;
|
||||
size_t name_len;
|
||||
|
||||
free (name);
|
||||
name_start = buf + sizeof ("MD_NAME=") - 1;
|
||||
/* Strip off the homehost if present. */
|
||||
colon = strchr (name_start, ':');
|
||||
name = strdup (colon ? colon + 1 : name_start);
|
||||
name_len = strlen (name);
|
||||
if (name[name_len - 1] == '\n')
|
||||
name[name_len - 1] = '\0';
|
||||
name_start = buf + sizeof ("MD_UUID=") - 1;
|
||||
ptro = name = xmalloc (strlen (name_start) + 1);
|
||||
for (ptri = name_start; *ptri && *ptri != '\n' && *ptri != '\r';
|
||||
ptri++)
|
||||
if ((*ptri >= '0' && *ptri <= '9')
|
||||
|| (*ptri >= 'a' && *ptri <= 'f')
|
||||
|| (*ptri >= 'A' && *ptri <= 'F'))
|
||||
*ptro++ = *ptri;
|
||||
*ptro = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -802,19 +911,26 @@ grub_util_get_grub_dev (const char *os_dev)
|
|||
|
||||
#ifdef __linux__
|
||||
{
|
||||
char *mdadm_name = get_mdadm_name (os_dev);
|
||||
char *mdadm_name = get_mdadm_uuid (os_dev);
|
||||
struct stat st;
|
||||
|
||||
if (mdadm_name)
|
||||
{
|
||||
char *newname;
|
||||
newname = xasprintf ("/dev/md/%s", mdadm_name);
|
||||
if (stat (newname, &st) == 0)
|
||||
const char *q;
|
||||
|
||||
for (q = os_dev + strlen (os_dev) - 1; q >= os_dev
|
||||
&& grub_isdigit (*q); q--);
|
||||
|
||||
if (q >= os_dev && *q == 'p')
|
||||
{
|
||||
free (grub_dev);
|
||||
grub_dev = xasprintf ("md/%s", mdadm_name);
|
||||
grub_dev = xasprintf ("mduuid/%s,%s", mdadm_name, q + 1);
|
||||
goto done;
|
||||
}
|
||||
free (newname);
|
||||
free (grub_dev);
|
||||
grub_dev = xasprintf ("mduuid/%s", mdadm_name);
|
||||
|
||||
done:
|
||||
free (mdadm_name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <grub/err.h>
|
||||
#include <grub/emu/misc.h>
|
||||
#include <grub/emu/hostdisk.h>
|
||||
#include <grub/emu/getroot.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/list.h>
|
||||
|
@ -139,6 +140,7 @@ struct grub_util_biosdisk_data
|
|||
char *dev;
|
||||
int access_mode;
|
||||
int fd;
|
||||
int is_disk;
|
||||
};
|
||||
|
||||
#ifdef __linux__
|
||||
|
@ -240,6 +242,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
data->dev = NULL;
|
||||
data->access_mode = 0;
|
||||
data->fd = -1;
|
||||
data->is_disk = 0;
|
||||
|
||||
/* Get the size. */
|
||||
#if defined(__MINGW32__)
|
||||
|
@ -281,6 +284,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
close (fd);
|
||||
goto fail;
|
||||
}
|
||||
data->is_disk = 1;
|
||||
|
||||
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
if (ioctl (fd, DIOCGMEDIASIZE, &nr))
|
||||
|
@ -342,18 +346,23 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
static int
|
||||
device_is_mapped (const char *dev)
|
||||
int
|
||||
grub_util_device_is_mapped (const char *dev)
|
||||
{
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
struct stat st;
|
||||
|
||||
if (!grub_device_mapper_supported ())
|
||||
return 0;
|
||||
|
||||
if (stat (dev, &st) < 0)
|
||||
return 0;
|
||||
|
||||
return dm_is_dm_major (major (st.st_rdev));
|
||||
}
|
||||
#else
|
||||
return 0;
|
||||
#endif /* HAVE_DEVICE_MAPPER */
|
||||
}
|
||||
|
||||
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
/* FIXME: geom actually gives us the whole container hierarchy.
|
||||
|
@ -429,7 +438,7 @@ find_partition_start (const char *dev)
|
|||
# endif /* !defined(HAVE_DIOCGDINFO) */
|
||||
|
||||
# ifdef HAVE_DEVICE_MAPPER
|
||||
if (grub_device_mapper_supported () && device_is_mapped (dev)) {
|
||||
if (grub_util_device_is_mapped (dev)) {
|
||||
struct dm_task *task = NULL;
|
||||
grub_uint64_t start, length;
|
||||
char *target_type, *params, *space;
|
||||
|
@ -532,9 +541,12 @@ devmapper_fail:
|
|||
# if !defined(HAVE_DIOCGDINFO)
|
||||
return hdg.start;
|
||||
# else /* defined(HAVE_DIOCGDINFO) */
|
||||
p_index = dev[strlen(dev) - 1] - 'a';
|
||||
|
||||
if (p_index >= label.d_npartitions)
|
||||
if (dev[0])
|
||||
p_index = dev[strlen(dev) - 1] - 'a';
|
||||
else
|
||||
p_index = -1;
|
||||
|
||||
if (p_index >= label.d_npartitions || p_index < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"no disk label entry for `%s'", dev);
|
||||
|
@ -558,7 +570,7 @@ struct linux_partition_cache
|
|||
struct linux_partition_cache *linux_partition_cache_list;
|
||||
|
||||
static int
|
||||
linux_find_partition (char *dev, unsigned long sector)
|
||||
linux_find_partition (char *dev, grub_disk_addr_t sector)
|
||||
{
|
||||
size_t len = strlen (dev);
|
||||
const char *format;
|
||||
|
@ -566,6 +578,7 @@ linux_find_partition (char *dev, unsigned long sector)
|
|||
int i;
|
||||
char real_dev[PATH_MAX];
|
||||
struct linux_partition_cache *cache;
|
||||
int missing = 0;
|
||||
|
||||
strcpy(real_dev, dev);
|
||||
|
||||
|
@ -574,6 +587,12 @@ linux_find_partition (char *dev, unsigned long sector)
|
|||
p = real_dev + len - 4;
|
||||
format = "part%d";
|
||||
}
|
||||
else if (strncmp (real_dev, "/dev/disk/by-id/",
|
||||
sizeof ("/dev/disk/by-id/") - 1) == 0)
|
||||
{
|
||||
p = real_dev + len;
|
||||
format = "-part%d";
|
||||
}
|
||||
else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9')
|
||||
{
|
||||
p = real_dev + len;
|
||||
|
@ -604,7 +623,13 @@ linux_find_partition (char *dev, unsigned long sector)
|
|||
|
||||
fd = open (real_dev, O_RDONLY);
|
||||
if (fd == -1)
|
||||
return 0;
|
||||
{
|
||||
if (missing++ < 10)
|
||||
continue;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
missing = 0;
|
||||
close (fd);
|
||||
|
||||
start = find_partition_start (real_dev);
|
||||
|
@ -675,7 +700,19 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
|||
{
|
||||
free (data->dev);
|
||||
if (data->fd != -1)
|
||||
close (data->fd);
|
||||
{
|
||||
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
|
||||
{
|
||||
fsync (data->fd);
|
||||
#ifdef __linux__
|
||||
if (data->is_disk)
|
||||
ioctl (data->fd, BLKFLSBUF, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
close (data->fd);
|
||||
data->fd = -1;
|
||||
}
|
||||
|
||||
/* Open the partition. */
|
||||
grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
|
||||
|
@ -686,10 +723,6 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Flush the buffer cache to the physical disk.
|
||||
XXX: This also empties the buffer cache. */
|
||||
ioctl (fd, BLKFLSBUF, 0);
|
||||
|
||||
data->dev = xstrdup (dev);
|
||||
data->access_mode = (flags & O_ACCMODE);
|
||||
data->fd = fd;
|
||||
|
@ -727,7 +760,18 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
|||
{
|
||||
free (data->dev);
|
||||
if (data->fd != -1)
|
||||
close (data->fd);
|
||||
{
|
||||
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
|
||||
{
|
||||
fsync (data->fd);
|
||||
#ifdef __linux__
|
||||
if (data->is_disk)
|
||||
ioctl (data->fd, BLKFLSBUF, 0);
|
||||
#endif
|
||||
}
|
||||
close (data->fd);
|
||||
data->fd = -1;
|
||||
}
|
||||
|
||||
fd = open (map[disk->id].device, flags);
|
||||
if (fd >= 0)
|
||||
|
@ -888,7 +932,6 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
!= (1 << disk->log_sector_size))
|
||||
{
|
||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
|
||||
close (fd);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
|
@ -938,6 +981,27 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_util_biosdisk_flush (struct grub_disk *disk)
|
||||
{
|
||||
struct grub_util_biosdisk_data *data = disk->data;
|
||||
|
||||
if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID)
|
||||
return GRUB_ERR_NONE;
|
||||
if (data->fd == -1)
|
||||
{
|
||||
data->fd = open_device (disk, 0, O_RDONLY);
|
||||
if (data->fd < 0)
|
||||
return grub_errno;
|
||||
}
|
||||
fsync (data->fd);
|
||||
#ifdef __linux__
|
||||
if (data->is_disk)
|
||||
ioctl (data->fd, BLKFLSBUF, 0);
|
||||
#endif
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_util_biosdisk_close (struct grub_disk *disk)
|
||||
{
|
||||
|
@ -945,7 +1009,11 @@ grub_util_biosdisk_close (struct grub_disk *disk)
|
|||
|
||||
free (data->dev);
|
||||
if (data->fd != -1)
|
||||
close (data->fd);
|
||||
{
|
||||
if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY)
|
||||
grub_util_biosdisk_flush (disk);
|
||||
close (data->fd);
|
||||
}
|
||||
free (data);
|
||||
}
|
||||
|
||||
|
@ -1115,6 +1183,54 @@ make_device_name (int drive, int dos_part, int bsd_part)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DEVICE_MAPPER
|
||||
static int
|
||||
grub_util_get_dm_node_linear_info (const char *dev,
|
||||
int *maj, int *min)
|
||||
{
|
||||
struct dm_task *dmt;
|
||||
void *next = NULL;
|
||||
uint64_t length, start;
|
||||
char *target, *params;
|
||||
char *ptr;
|
||||
int major, minor;
|
||||
|
||||
dmt = dm_task_create(DM_DEVICE_TABLE);
|
||||
if (!dmt)
|
||||
return 0;
|
||||
|
||||
if (!dm_task_set_name(dmt, dev))
|
||||
return 0;
|
||||
dm_task_no_open_count(dmt);
|
||||
if (!dm_task_run(dmt))
|
||||
return 0;
|
||||
next = dm_get_next_target(dmt, next, &start, &length,
|
||||
&target, ¶ms);
|
||||
if (grub_strcmp (target, "linear") != 0)
|
||||
return 0;
|
||||
major = grub_strtoul (params, &ptr, 10);
|
||||
if (grub_errno)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return 0;
|
||||
}
|
||||
if (*ptr != ':')
|
||||
return 0;
|
||||
ptr++;
|
||||
minor = grub_strtoul (ptr, 0, 10);
|
||||
if (grub_errno)
|
||||
{
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return 0;
|
||||
}
|
||||
if (maj)
|
||||
*maj = major;
|
||||
if (min)
|
||||
*min = minor;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *
|
||||
convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
|
||||
{
|
||||
|
@ -1291,9 +1407,40 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
|
|||
node = NULL;
|
||||
goto devmapper_out;
|
||||
}
|
||||
else if (strncmp (node_uuid, "DMRAID-", 7) != 0)
|
||||
if (strncmp (node_uuid, "LVM-", 4) == 0)
|
||||
{
|
||||
grub_dprintf ("hostdisk", "%s is an LVM\n", path);
|
||||
node = NULL;
|
||||
goto devmapper_out;
|
||||
}
|
||||
if (strncmp (node_uuid, "mpath-", 6) == 0)
|
||||
{
|
||||
/* Multipath partitions have partN-mpath-* UUIDs, and are
|
||||
linear mappings so are handled by
|
||||
grub_util_get_dm_node_linear_info. Multipath disks are not
|
||||
linear mappings and must be handled specially. */
|
||||
grub_dprintf ("hostdisk", "%s is a multipath disk\n", path);
|
||||
mapper_name = dm_tree_node_get_name (node);
|
||||
goto devmapper_out;
|
||||
}
|
||||
if (strncmp (node_uuid, "DMRAID-", 7) != 0)
|
||||
{
|
||||
int major, minor;
|
||||
const char *node_name;
|
||||
grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path);
|
||||
|
||||
if ((node_name = dm_tree_node_get_name (node))
|
||||
&& grub_util_get_dm_node_linear_info (node_name,
|
||||
&major, &minor))
|
||||
{
|
||||
if (tree)
|
||||
dm_tree_free (tree);
|
||||
free (path);
|
||||
char *ret = grub_find_device ("/dev/mapper",
|
||||
(major << 8) | minor);
|
||||
return ret;
|
||||
}
|
||||
|
||||
node = NULL;
|
||||
goto devmapper_out;
|
||||
}
|
||||
|
@ -1530,6 +1677,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
if (stat (os_dev, &st) < 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev);
|
||||
grub_util_info ("cannot stat `%s'", os_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1538,6 +1686,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
|||
{
|
||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
"no mapping exists for `%s'", os_dev);
|
||||
grub_util_info ("no mapping exists for `%s'", os_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "../mips/dl.c"
|
||||
#elif defined(__powerpc__)
|
||||
#include "../powerpc/dl.c"
|
||||
#elif defined(__ia64__)
|
||||
#include "../ia64/dl.c"
|
||||
#else
|
||||
#error "No target cpu type is defined"
|
||||
#endif
|
||||
|
|
|
@ -415,6 +415,18 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
|||
if (offset == 0)
|
||||
{
|
||||
free (buf);
|
||||
#ifdef __linux__
|
||||
{
|
||||
char *bind;
|
||||
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
|
||||
if (bind && bind[0] && bind[1])
|
||||
{
|
||||
buf3 = bind;
|
||||
goto parsedir;
|
||||
}
|
||||
grub_free (bind);
|
||||
}
|
||||
#endif
|
||||
free (buf2);
|
||||
#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR)
|
||||
if (poolfs)
|
||||
|
@ -437,6 +449,21 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
|||
}
|
||||
free (buf);
|
||||
buf3 = xstrdup (buf2 + offset);
|
||||
buf2[offset] = 0;
|
||||
#ifdef __linux__
|
||||
{
|
||||
char *bind;
|
||||
grub_free (grub_find_root_device_from_mountinfo (buf2, &bind));
|
||||
if (bind && bind[0] && bind[1])
|
||||
{
|
||||
char *temp = buf3;
|
||||
buf3 = grub_xasprintf ("%s%s%s", bind, buf3[0] == '/' ?"":"/", buf3);
|
||||
grub_free (temp);
|
||||
}
|
||||
grub_free (bind);
|
||||
}
|
||||
#endif
|
||||
|
||||
free (buf2);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
|
@ -452,6 +479,7 @@ grub_make_system_path_relative_to_its_root (const char *path)
|
|||
}
|
||||
#endif
|
||||
|
||||
parsedir:
|
||||
/* Remove trailing slashes, return empty string if root directory. */
|
||||
len = strlen (buf3);
|
||||
while (len > 0 && buf3[len - 1] == '/')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue