From: Christian Franke <Christian.Franke@t-online.de>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: Re: [PATCH] biosdisk, getroot for Cygwin
Date: Wed, 07 May 2008 22:42:23 +0200 [thread overview]
Message-ID: <4822142F.1040505@t-online.de> (raw)
In-Reply-To: <47473879.1020004@t-online.de>
[-- Attachment #1: Type: text/plain, Size: 1008 bytes --]
Updated version of the patch. It adds the functionality necessary for
grub-probe on Cygwin.
It also fixes 2 bugs in strip_extra_slashes() and __GNU__ get_os_disk()
Christian
2008-05-07 Christian Franke <franke@computer.org>
* util/biosdisk.c: [__CYGWIN__] Add includes.
(grub_util_biosdisk_open): Use Linux code also for Cygwin.
(get_os_disk): Move variable declarations to OS specific
parts to avoid warning.
[__GNU__] (get_os_disk): Fix /dev/sdXsN case.
[__CYGWIN__] (get_os_disk): Add Cygwin /dev/sdXN device names.
(grub_util_biosdisk_get_grub_dev): Use Linux code also for
Cygwin.
* util/getroot.c: [__CYGWIN__] Add includes.
(strip_extra_slashes): Fix "/" case.
[__CYGWIN__] (get_win32_path): New function.
[__CYGWIN__] (grub_get_prefix): Add conversion to win32 path.
[__CYGWIN__] (find_root_device): Disable.
[__CYGWIN__] (get_bootsec_serial): New function.
[__CYGWIN__] (find_cygwin_root_device): Likewise.
[__CYGWIN__] (grub_util_get_grub_dev): Disable /dev/mapper check.
[-- Attachment #2: grub2-biosdisk-getroot-2.patch --]
[-- Type: text/x-patch, Size: 8177 bytes --]
diff --git a/util/biosdisk.c b/util/biosdisk.c
index e6e7f51..1b164a9 100644
--- a/util/biosdisk.c
+++ b/util/biosdisk.c
@@ -77,6 +77,14 @@ struct hd_geometry
# endif /* ! LOOP_MAJOR */
#endif /* __linux__ */
+#ifdef __CYGWIN__
+# include <sys/ioctl.h>
+# include <cygwin/fs.h> /* BLKGETSIZE64 */
+# include <cygwin/hdreg.h> /* HDIO_GETGEO */
+# define MAJOR(dev) ((unsigned) ((dev) >> 16))
+# define FLOPPY_MAJOR 2
+#endif
+
static char *map[256];
#ifdef __linux__
@@ -162,7 +170,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
disk->id = drive;
/* Get the size. */
-#ifdef __linux__
+#if defined(__linux__) || defined(__CYGWIN__)
{
unsigned long long nr;
int fd;
@@ -603,16 +611,14 @@ make_device_name (int drive, int dos_part, int bsd_part)
static char *
get_os_disk (const char *os_dev)
{
- char *path, *p;
-
#if defined(__linux__)
- path = xmalloc (PATH_MAX);
+ char *path = xmalloc (PATH_MAX);
if (! realpath (os_dev, path))
return 0;
if (strncmp ("/dev/", path, 5) == 0)
{
- p = path + 5;
+ char *p = path + 5;
/* If this is an IDE disk. */
if (strncmp ("ide/", p, 4) == 0)
@@ -659,15 +665,21 @@ get_os_disk (const char *os_dev)
return path;
#elif defined(__GNU__)
- path = xstrdup (os_dev);
+ char *path = xstrdup (os_dev);
if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0)
{
- p = strchr (path, 's');
+ char *p = strchr (path + 7, 's');
if (p)
*p = '\0';
}
return path;
+#elif defined(__CYGWIN__)
+ char *path = xstrdup (os_dev);
+ if (strncmp ("/dev/sd", path, 7) == 0 && 'a' <= path[7] && path[7] <= 'z')
+ path[8] = 0;
+ return path;
+
#else
# warning "The function `get_os_disk' might not work on your OS correctly."
return xstrdup (os_dev);
@@ -718,11 +730,15 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
if (! S_ISBLK (st.st_mode))
return make_device_name (drive, -1, -1);
-#if defined(__linux__)
+#if defined(__linux__) || defined(__CYGWIN__)
/* 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
- compare it with each partition GRUB recognizes. */
+ compare it with each partition GRUB recognizes.
+
+ Cygwin /dev/sdXN emulation uses Windows partition mapping. It
+ does not count the extended partition and missing primary
+ partitions. Use same method as on Linux here. */
{
char *name;
grub_disk_t disk;
diff --git a/util/getroot.c b/util/getroot.c
index 5a98218..e74ef78 100644
--- a/util/getroot.c
+++ b/util/getroot.c
@@ -22,6 +22,13 @@
#include <string.h>
#include <dirent.h>
+#ifdef __CYGWIN__
+# include <sys/fcntl.h>
+# include <sys/cygwin.h>
+# include <limits.h>
+# define DEV_CYGDRIVE_MAJOR 98
+#endif
+
#include <grub/util/misc.h>
#include <grub/util/biosdisk.h>
#include <grub/util/getroot.h>
@@ -40,7 +47,8 @@ strip_extra_slashes (char *dir)
}
else if (p[1] == '\0')
{
- p[0] = '\0';
+ if (p > dir)
+ p[0] = '\0';
break;
}
@@ -64,6 +72,30 @@ xgetcwd (void)
return path;
}
+#ifdef __CYGWIN__
+/* Convert POSIX path to Win32 path,
+ remove drive letter, replace backslashes. */
+static char *
+get_win32_path (const char *path)
+{
+ char winpath[PATH_MAX];
+ cygwin_conv_to_full_win32_path (path, winpath);
+
+ int len = strlen (winpath);
+ if (len > 2 && winpath[1] == ':')
+ {
+ len -= 2;
+ memmove (winpath, winpath + 2, len + 1);
+ }
+
+ int i;
+ for (i = 0; i < len; i++)
+ if (winpath[i] == '\\')
+ winpath[i] = '/';
+ return xstrdup (winpath);
+}
+#endif
+
char *
grub_get_prefix (const char *dir)
{
@@ -116,6 +148,19 @@ grub_get_prefix (const char *dir)
if (chdir (saved_cwd) < 0)
grub_util_error ("Cannot change directory to `%s'", dir);
+#ifdef __CYGWIN__
+ if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16))
+ {
+ /* Reached some mount point not below /cygdrive.
+ GRUB does not know Cygwin's emulated mounts,
+ convert to Win32 path. */
+ grub_util_info ("Cygwin prefix = %s", prefix);
+ char * wprefix = get_win32_path (prefix);
+ free (prefix);
+ prefix = wprefix;
+ }
+#endif
+
free (saved_cwd);
free (abs_dir);
free (prev_dir);
@@ -124,6 +169,8 @@ grub_get_prefix (const char *dir)
return prefix;
}
+#ifndef __CYGWIN__
+
static char *
find_root_device (const char *dir, dev_t dev)
{
@@ -216,6 +263,89 @@ find_root_device (const char *dir, dev_t dev)
return 0;
}
+#else /* __CYGWIN__ */
+
+/* Read drive/partition serial number from mbr/boot sector,
+ return 0 on read error, ~0 on unknown serial. */
+static unsigned
+get_bootsec_serial (const char *os_dev, int mbr)
+{
+ /* Read boot sector. */
+ int fd = open (os_dev, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ unsigned char buf[0x200];
+ int n = read (fd, buf, sizeof (buf));
+ close (fd);
+ if (n != sizeof(buf))
+ return 0;
+
+ /* Check signature. */
+ if (!(buf[0x1fe] == 0x55 && buf[0x1ff] == 0xaa))
+ return ~0;
+
+ /* Serial number offset depends on boot sector type. */
+ if (mbr)
+ n = 0x1b8;
+ else if (memcmp (buf + 0x03, "NTFS", 4) == 0)
+ n = 0x048;
+ else if (memcmp (buf + 0x52, "FAT32", 5) == 0)
+ n = 0x043;
+ else if (memcmp (buf + 0x36, "FAT", 3) == 0)
+ n = 0x027;
+ else
+ return ~0;
+ unsigned serial = *(unsigned *)(buf + n);
+ if (serial == 0)
+ return ~0;
+ return serial;
+}
+
+static char *
+find_cygwin_root_device (const char *path, dev_t dev)
+{
+ /* No root device for /cygdrive. */
+ if (dev == (DEV_CYGDRIVE_MAJOR << 16))
+ return 0;
+
+ /* Convert to full POSIX and Win32 path. */
+ char fullpath[PATH_MAX], winpath[PATH_MAX];
+ cygwin_conv_to_full_posix_path (path, fullpath);
+ cygwin_conv_to_full_win32_path (fullpath, winpath);
+
+ /* If identical, this is no real filesystem path. */
+ if (strcmp (fullpath, winpath) == 0)
+ return 0;
+
+ /* Check for floppy drive letter. */
+ if (winpath[0] && winpath[1] == ':' && strchr ("AaBb", winpath[0]))
+ return xstrdup (strchr ("Aa", winpath[0]) ? "/dev/fd0" : "/dev/fd1");
+
+ /* 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.
+ Search the partion with the same serial in boot sector instead. */
+ char devpath[sizeof ("/dev/sda15") + 13];
+ int d;
+ for (d = 'a'; d <= 'z'; d++) {
+ sprintf (devpath, "/dev/sd%c", d);
+ if (get_bootsec_serial (devpath, 1) == 0)
+ continue;
+ int p;
+ for (p = 1; p <= 15; p++) {
+ sprintf (devpath, "/dev/sd%c%d", d, p);
+ unsigned ser = get_bootsec_serial (devpath, 0);
+ if (ser == 0)
+ break;
+ if (ser != (unsigned)~0 && dev == (dev_t)ser)
+ return xstrdup (devpath);
+ }
+ }
+ return 0;
+}
+
+#endif /* __CYGWIN__ */
+
char *
grub_guess_root_device (const char *dir)
{
@@ -225,6 +355,7 @@ grub_guess_root_device (const char *dir)
if (stat (dir, &st) < 0)
grub_util_error ("Cannot stat `%s'", dir);
+#ifndef __CYGWIN__
#ifdef __linux__
/* We first try to find the device in the /dev/mapper directory. If
we don't do this, we get useless device names like /dev/dm-0 for
@@ -242,12 +373,19 @@ grub_guess_root_device (const char *dir)
os_dev = find_root_device ("/dev", st.st_dev);
}
+#else
+ /* Cygwin specific function. */
+ os_dev = find_cygwin_root_device (dir, st.st_dev);
+
+#endif /* __CYGWIN__ */
+
return os_dev;
}
int
grub_util_get_dev_abstraction (const char *os_dev)
{
+#ifndef __CYGWIN__
/* Check for LVM. */
if (!strncmp (os_dev, "/dev/mapper/", 12))
return GRUB_DEV_ABSTRACTION_LVM;
@@ -255,6 +393,7 @@ grub_util_get_dev_abstraction (const char *os_dev)
/* Check for RAID. */
if (!strncmp (os_dev, "/dev/md", 7))
return GRUB_DEV_ABSTRACTION_RAID;
+#endif /* !__CYGWIN__ */
/* No abstraction found. */
return GRUB_DEV_ABSTRACTION_NONE;
next prev parent reply other threads:[~2008-05-07 20:42 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-23 20:30 [PATCH] biosdisk, getroot for Cygwin Christian Franke
2008-05-07 20:42 ` Christian Franke [this message]
2008-05-09 12:45 ` Robert Millan
2008-05-09 17:32 ` Christian Franke
2008-05-11 21:04 ` Christian Franke
2008-05-12 15:25 ` Robert Millan
2008-05-13 21:17 ` Christian Franke
2008-05-16 21:43 ` Christian Franke
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4822142F.1040505@t-online.de \
--to=christian.franke@t-online.de \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.