From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1VoXs4-00069l-1R for mharc-grub-devel@gnu.org; Thu, 05 Dec 2013 07:17:32 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44022) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VoXrz-00068l-Rg for grub-devel@gnu.org; Thu, 05 Dec 2013 07:17:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VoXry-0001WN-HY for grub-devel@gnu.org; Thu, 05 Dec 2013 07:17:27 -0500 Received: from v6.chiark.greenend.org.uk ([2001:ba8:1e3::]:43030 helo=chiark.greenend.org.uk) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VoXry-0001WE-Bp for grub-devel@gnu.org; Thu, 05 Dec 2013 07:17:26 -0500 Received: from [172.20.153.9] (helo=riva.pelham.vpn.ucam.org) by chiark.greenend.org.uk (Debian Exim 4.72 #1) with esmtps (return-path cjwatson@ubuntu.com) id 1VoXrx-00023f-Bz for grub-devel@gnu.org; Thu, 05 Dec 2013 12:17:25 +0000 Received: from ns1.pelham.vpn.ucam.org ([172.20.153.2] helo=riva.ucam.org) by riva.pelham.vpn.ucam.org with esmtps (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1VoXrw-0004R4-Dr for grub-devel@gnu.org; Thu, 05 Dec 2013 12:17:24 +0000 Date: Thu, 5 Dec 2013 12:17:23 +0000 From: Colin Watson To: grub-devel@gnu.org Subject: [PATCH] On Linux, read partition start offsets from sysfs if possible Message-ID: <20131205121723.GN16147@riva.ucam.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:ba8:1e3:: X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Dec 2013 12:17:29 -0000 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. --- ChangeLog | 12 ++++++ grub-core/osdep/linux/hostdisk.c | 89 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/ChangeLog b/ChangeLog index d60acab..d08d841 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2013-12-05 Colin Watson + + 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 Vladimir Serbinenko Handle unaligned .bss on sparc64. diff --git a/grub-core/osdep/linux/hostdisk.c b/grub-core/osdep/linux/hostdisk.c index a2c80f3..74d87a4 100644 --- a/grub-core/osdep/linux/hostdisk.c +++ b/grub-core/osdep/linux/hostdisk.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -93,12 +95,99 @@ grub_util_get_fd_size_os (grub_util_fd_t fd, const char *name, unsigned *log_sec 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_util_find_partition_start_os (const char *dev) { + grub_disk_addr_t start; grub_util_fd_t fd; struct hd_geometry hdg; + if (sysfs_partition_start (dev, &start)) + return start; + fd = open (dev, O_RDONLY); if (fd == -1) { -- 1.8.4.4