2008-05-16 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. [__linux__] (grub_guess_root_device): Add early returns to simplify structure. [__CYGWIN__] (grub_guess_root_device): Call find_cygwin_root_device. [__linux__] (grub_util_get_dev_abstraction): Enable LVM and RAID check for Linux only.
This commit is contained in:
parent
a079699e97
commit
eedf167fef
3 changed files with 199 additions and 18 deletions
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
||||||
|
2008-05-16 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.
|
||||||
|
[__linux__] (grub_guess_root_device): Add early returns to simplify
|
||||||
|
structure.
|
||||||
|
[__CYGWIN__] (grub_guess_root_device): Call find_cygwin_root_device.
|
||||||
|
[__linux__] (grub_util_get_dev_abstraction): Enable LVM and RAID
|
||||||
|
check for Linux only.
|
||||||
|
|
||||||
2008-05-15 Bean <bean123ch@gmail.com>
|
2008-05-15 Bean <bean123ch@gmail.com>
|
||||||
|
|
||||||
* kern/i386/pc/startup.S (grub_console_getkey): Workaround for the
|
* kern/i386/pc/startup.S (grub_console_getkey): Workaround for the
|
||||||
|
|
|
@ -77,6 +77,14 @@ struct hd_geometry
|
||||||
# endif /* ! LOOP_MAJOR */
|
# endif /* ! LOOP_MAJOR */
|
||||||
#endif /* __linux__ */
|
#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];
|
static char *map[256];
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -162,7 +170,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||||
disk->id = drive;
|
disk->id = drive;
|
||||||
|
|
||||||
/* Get the size. */
|
/* Get the size. */
|
||||||
#ifdef __linux__
|
#if defined(__linux__) || defined(__CYGWIN__)
|
||||||
{
|
{
|
||||||
unsigned long long nr;
|
unsigned long long nr;
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -616,16 +624,14 @@ make_device_name (int drive, int dos_part, int bsd_part)
|
||||||
static char *
|
static char *
|
||||||
get_os_disk (const char *os_dev)
|
get_os_disk (const char *os_dev)
|
||||||
{
|
{
|
||||||
char *path, *p;
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
path = xmalloc (PATH_MAX);
|
char *path = xmalloc (PATH_MAX);
|
||||||
if (! realpath (os_dev, path))
|
if (! realpath (os_dev, path))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (strncmp ("/dev/", path, 5) == 0)
|
if (strncmp ("/dev/", path, 5) == 0)
|
||||||
{
|
{
|
||||||
p = path + 5;
|
char *p = path + 5;
|
||||||
|
|
||||||
/* If this is an IDE disk. */
|
/* If this is an IDE disk. */
|
||||||
if (strncmp ("ide/", p, 4) == 0)
|
if (strncmp ("ide/", p, 4) == 0)
|
||||||
|
@ -692,15 +698,21 @@ get_os_disk (const char *os_dev)
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
#elif defined(__GNU__)
|
#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)
|
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)
|
if (p)
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
}
|
}
|
||||||
return path;
|
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
|
#else
|
||||||
# warning "The function `get_os_disk' might not work on your OS correctly."
|
# warning "The function `get_os_disk' might not work on your OS correctly."
|
||||||
return xstrdup (os_dev);
|
return xstrdup (os_dev);
|
||||||
|
@ -751,11 +763,15 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev)
|
||||||
if (! S_ISBLK (st.st_mode))
|
if (! S_ISBLK (st.st_mode))
|
||||||
return make_device_name (drive, -1, -1);
|
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
|
/* Linux counts partitions uniformly, whether a BSD partition or a DOS
|
||||||
partition, so mapping them to GRUB devices is not trivial.
|
partition, so mapping them to GRUB devices is not trivial.
|
||||||
Here, get the start sector of a partition by HDIO_GETGEO, and
|
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;
|
char *name;
|
||||||
grub_disk_t disk;
|
grub_disk_t disk;
|
||||||
|
|
152
util/getroot.c
152
util/getroot.c
|
@ -22,6 +22,13 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <dirent.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/misc.h>
|
||||||
#include <grub/util/biosdisk.h>
|
#include <grub/util/biosdisk.h>
|
||||||
#include <grub/util/getroot.h>
|
#include <grub/util/getroot.h>
|
||||||
|
@ -40,6 +47,7 @@ strip_extra_slashes (char *dir)
|
||||||
}
|
}
|
||||||
else if (p[1] == '\0')
|
else if (p[1] == '\0')
|
||||||
{
|
{
|
||||||
|
if (p > dir)
|
||||||
p[0] = '\0';
|
p[0] = '\0';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -64,6 +72,30 @@ xgetcwd (void)
|
||||||
return path;
|
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 *
|
char *
|
||||||
grub_get_prefix (const char *dir)
|
grub_get_prefix (const char *dir)
|
||||||
{
|
{
|
||||||
|
@ -116,6 +148,19 @@ grub_get_prefix (const char *dir)
|
||||||
if (chdir (saved_cwd) < 0)
|
if (chdir (saved_cwd) < 0)
|
||||||
grub_util_error ("Cannot change directory to `%s'", dir);
|
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 (saved_cwd);
|
||||||
free (abs_dir);
|
free (abs_dir);
|
||||||
free (prev_dir);
|
free (prev_dir);
|
||||||
|
@ -124,6 +169,8 @@ grub_get_prefix (const char *dir)
|
||||||
return prefix;
|
return prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __CYGWIN__
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
find_root_device (const char *dir, dev_t dev)
|
find_root_device (const char *dir, dev_t dev)
|
||||||
{
|
{
|
||||||
|
@ -216,6 +263,92 @@ find_root_device (const char *dir, dev_t dev)
|
||||||
return 0;
|
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]; /* Size + Paranoia. */
|
||||||
|
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 *
|
char *
|
||||||
grub_guess_root_device (const char *dir)
|
grub_guess_root_device (const char *dir)
|
||||||
{
|
{
|
||||||
|
@ -230,17 +363,24 @@ grub_guess_root_device (const char *dir)
|
||||||
we don't do this, we get useless device names like /dev/dm-0 for
|
we don't do this, we get useless device names like /dev/dm-0 for
|
||||||
LVM. */
|
LVM. */
|
||||||
os_dev = find_root_device ("/dev/mapper", st.st_dev);
|
os_dev = find_root_device ("/dev/mapper", st.st_dev);
|
||||||
|
if (os_dev)
|
||||||
|
return os_dev;
|
||||||
|
|
||||||
/* The same applies to /dev/evms directory (for EVMS volumes). */
|
/* The same applies to /dev/evms directory (for EVMS volumes). */
|
||||||
if (! os_dev)
|
|
||||||
os_dev = find_root_device ("/dev/evms", st.st_dev);
|
os_dev = find_root_device ("/dev/evms", st.st_dev);
|
||||||
|
if (os_dev)
|
||||||
if (! os_dev)
|
return os_dev;
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
/* Cygwin specific function. */
|
||||||
|
os_dev = find_cygwin_root_device (dir, st.st_dev);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
/* This might be truly slow, but is there any better way? */
|
/* This might be truly slow, but is there any better way? */
|
||||||
os_dev = find_root_device ("/dev", st.st_dev);
|
os_dev = find_root_device ("/dev", st.st_dev);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
return os_dev;
|
return os_dev;
|
||||||
}
|
}
|
||||||
|
@ -248,6 +388,7 @@ grub_guess_root_device (const char *dir)
|
||||||
int
|
int
|
||||||
grub_util_get_dev_abstraction (const char *os_dev)
|
grub_util_get_dev_abstraction (const char *os_dev)
|
||||||
{
|
{
|
||||||
|
#ifdef __linux__
|
||||||
/* Check for LVM. */
|
/* Check for LVM. */
|
||||||
if (!strncmp (os_dev, "/dev/mapper/", 12))
|
if (!strncmp (os_dev, "/dev/mapper/", 12))
|
||||||
return GRUB_DEV_ABSTRACTION_LVM;
|
return GRUB_DEV_ABSTRACTION_LVM;
|
||||||
|
@ -255,6 +396,7 @@ grub_util_get_dev_abstraction (const char *os_dev)
|
||||||
/* Check for RAID. */
|
/* Check for RAID. */
|
||||||
if (!strncmp (os_dev, "/dev/md", 7))
|
if (!strncmp (os_dev, "/dev/md", 7))
|
||||||
return GRUB_DEV_ABSTRACTION_RAID;
|
return GRUB_DEV_ABSTRACTION_RAID;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* No abstraction found. */
|
/* No abstraction found. */
|
||||||
return GRUB_DEV_ABSTRACTION_NONE;
|
return GRUB_DEV_ABSTRACTION_NONE;
|
||||||
|
|
Loading…
Reference in a new issue