On Linux, read partition start offsets from sysfs if possible
This lets us cope with block device drivers that don't implement HDIO_GETGEO. Fixes Ubuntu bug #1237519. * grub-core/osdep/linux/hostdisk.c (sysfs_partition_path): New function. (sysfs_partition_start): Likewise. (grub_util_find_partition_start_os): Try sysfs_partition_start before HDIO_GETGEO.
This commit is contained in:
parent
bbeee1c4a3
commit
0480665b9d
2 changed files with 101 additions and 0 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2013-12-05 Colin Watson <cjwatson@ubuntu.com>
|
||||||
|
|
||||||
|
On Linux, read partition start offsets from sysfs if possible, to
|
||||||
|
cope with block device drivers that don't implement HDIO_GETGEO.
|
||||||
|
Fixes Ubuntu bug #1237519.
|
||||||
|
|
||||||
|
* grub-core/osdep/linux/hostdisk.c (sysfs_partition_path): New
|
||||||
|
function.
|
||||||
|
(sysfs_partition_start): Likewise.
|
||||||
|
(grub_util_find_partition_start_os): Try sysfs_partition_start
|
||||||
|
before HDIO_GETGEO.
|
||||||
|
|
||||||
2013-12-05 Leif Lindholm <leif.lindholm@linaro.org>
|
2013-12-05 Leif Lindholm <leif.lindholm@linaro.org>
|
||||||
|
|
||||||
* grub-core/kern/fdt.c: Update struct size when adding node.
|
* grub-core/kern/fdt.c: Update struct size when adding node.
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <grub/emu/misc.h>
|
#include <grub/emu/misc.h>
|
||||||
#include <grub/emu/hostdisk.h>
|
#include <grub/emu/hostdisk.h>
|
||||||
#include <grub/emu/getroot.h>
|
#include <grub/emu/getroot.h>
|
||||||
|
#include <grub/emu/exec.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/i18n.h>
|
#include <grub/i18n.h>
|
||||||
#include <grub/list.h>
|
#include <grub/list.h>
|
||||||
|
@ -39,6 +40,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -93,12 +95,99 @@ grub_util_get_fd_size_os (grub_util_fd_t fd, const char *name, unsigned *log_sec
|
||||||
return nr;
|
return nr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
sysfs_partition_path (const char *dev, const char *entry)
|
||||||
|
{
|
||||||
|
const char *argv[7];
|
||||||
|
int fd;
|
||||||
|
pid_t pid;
|
||||||
|
FILE *udevadm;
|
||||||
|
char *buf = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
char *path = NULL;
|
||||||
|
|
||||||
|
argv[0] = "udevadm";
|
||||||
|
argv[1] = "info";
|
||||||
|
argv[2] = "--query";
|
||||||
|
argv[3] = "path";
|
||||||
|
argv[4] = "--name";
|
||||||
|
argv[5] = dev;
|
||||||
|
argv[6] = NULL;
|
||||||
|
|
||||||
|
pid = grub_util_exec_pipe (argv, &fd);
|
||||||
|
|
||||||
|
if (!pid)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Parent. Read udevadm's output. */
|
||||||
|
udevadm = fdopen (fd, "r");
|
||||||
|
if (!udevadm)
|
||||||
|
{
|
||||||
|
grub_util_warn (_("Unable to open stream from %s: %s"),
|
||||||
|
"udevadm", strerror (errno));
|
||||||
|
close (fd);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getline (&buf, &len, udevadm) > 0)
|
||||||
|
{
|
||||||
|
char *newline;
|
||||||
|
|
||||||
|
newline = strchr (buf, '\n');
|
||||||
|
if (newline)
|
||||||
|
*newline = '\0';
|
||||||
|
path = xasprintf ("/sys%s/%s", buf, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (udevadm)
|
||||||
|
fclose (udevadm);
|
||||||
|
waitpid (pid, NULL, 0);
|
||||||
|
free (buf);
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sysfs_partition_start (const char *dev, grub_disk_addr_t *start)
|
||||||
|
{
|
||||||
|
char *path;
|
||||||
|
FILE *fp;
|
||||||
|
unsigned long long val;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
path = sysfs_partition_path (dev, "start");
|
||||||
|
if (!path)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fp = grub_util_fopen (path, "r");
|
||||||
|
if (!fp)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (fscanf (fp, "%llu", &val) == 1)
|
||||||
|
{
|
||||||
|
*start = (grub_disk_addr_t) val;
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
free (path);
|
||||||
|
if (fp)
|
||||||
|
fclose (fp);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
grub_disk_addr_t
|
grub_disk_addr_t
|
||||||
grub_util_find_partition_start_os (const char *dev)
|
grub_util_find_partition_start_os (const char *dev)
|
||||||
{
|
{
|
||||||
|
grub_disk_addr_t start;
|
||||||
grub_util_fd_t fd;
|
grub_util_fd_t fd;
|
||||||
struct hd_geometry hdg;
|
struct hd_geometry hdg;
|
||||||
|
|
||||||
|
if (sysfs_partition_start (dev, &start))
|
||||||
|
return start;
|
||||||
|
|
||||||
fd = open (dev, O_RDONLY);
|
fd = open (dev, O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue