From 958ee2216874b6587ff0534fa7030e06a58167ce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 8 Nov 2011 12:38:30 +0100 Subject: [PATCH] Illumos support. * Makefile.util.def (10_illumos): New script. * configure.ac: Set COND_HOST_ILLUMOS. * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__sun__]: Support Illumos calls. (find_partition_start) [__sun__]: Likewise. (convert_system_partition_to_system_disk) [__sun__]: Likewise. (device_is_wholedisk) [__sun__]: Handle Illumos naming scheme. (grub_util_biosdisk_get_grub_dev) [__sun__]: Handle Illumos. * util/getroot.c (find_root_device_from_libzfs) [__sun__]: Return raw device. * util/grub-probe.c (probe) [__sun__]: Do character check. * util/grub.d/10_illumos.in: New file. --- ChangeLog | 17 +++++++++ Makefile.util.def | 7 ++++ configure.ac | 2 + grub-core/kern/emu/hostdisk.c | 72 +++++++++++++++++++++++++++++------ util/getroot.c | 19 ++++++++- util/grub-probe.c | 2 +- util/grub.d/10_illumos.in | 54 ++++++++++++++++++++++++++ 7 files changed, 159 insertions(+), 14 deletions(-) create mode 100644 util/grub.d/10_illumos.in diff --git a/ChangeLog b/ChangeLog index c7f8d3c7b..edb0b2c10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2011-11-08 Vladimir Serbinenko + + Illumos support. + + * Makefile.util.def (10_illumos): New script. + * configure.ac: Set COND_HOST_ILLUMOS. + * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__sun__]: + Support Illumos calls. + (find_partition_start) [__sun__]: Likewise. + (convert_system_partition_to_system_disk) [__sun__]: Likewise. + (device_is_wholedisk) [__sun__]: Handle Illumos naming scheme. + (grub_util_biosdisk_get_grub_dev) [__sun__]: Handle Illumos. + * util/getroot.c (find_root_device_from_libzfs) [__sun__]: Return raw + device. + * util/grub-probe.c (probe) [__sun__]: Do character check. + * util/grub.d/10_illumos.in: New file. + 2011-11-08 Vladimir Serbinenko Support escaped commas in hostdisk. diff --git a/Makefile.util.def b/Makefile.util.def index 15a309367..8742d1583 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -367,6 +367,13 @@ script = { condition = COND_HOST_KFREEBSD; }; +script = { + name = '10_illumos'; + common = util/grub.d/10_illumos.in; + installdir = grubconf; + condition = COND_HOST_ILLUMOS; +}; + script = { name = '10_netbsd'; common = util/grub.d/10_netbsd.in; diff --git a/configure.ac b/configure.ac index 6aafdf13d..e707081a7 100644 --- a/configure.ac +++ b/configure.ac @@ -154,6 +154,7 @@ case "$host_os" in linux*) host_kernel=linux ;; freebsd* | kfreebsd*-gnu) host_kernel=kfreebsd ;; netbsd*) host_kernel=netbsd ;; + solaris*) host_kernel=illumos ;; cygwin) host_kernel=windows ;; esac @@ -974,6 +975,7 @@ AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd]) AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows]) AM_CONDITIONAL([COND_HOST_KFREEBSD], [test x$host_kernel = xkfreebsd]) +AM_CONDITIONAL([COND_HOST_ILLUMOS], [test x$host_kernel = xillumos]) AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x]) AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 4d5c28631..7074fa8c1 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -98,6 +98,10 @@ struct hd_geometry # define FLOPPY_MAJOR 2 #endif +#if defined (__sun__) +# include +#endif + #if defined(__APPLE__) # include #endif @@ -252,11 +256,11 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name), grub_uint64_t grub_util_get_fd_sectors (int fd, unsigned *log_secsize) { -#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) # if defined(__NetBSD__) struct disklabel label; -# else +# elif defined (__sun__) + struct dk_minfo minfo; +#else unsigned long long nr; # endif unsigned sector_size, log_sector_size; @@ -265,7 +269,11 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) if (fstat (fd, &st) < 0) grub_util_error ("fstat failed"); -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ + defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) \ + || defined (__sun__) + +# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__) if (! S_ISCHR (st.st_mode)) # else if (! S_ISBLK (st.st_mode)) @@ -279,6 +287,8 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) # elif defined(__NetBSD__) configure_device_driver (fd); if (ioctl (fd, DIOCGDINFO, &label) == -1) +# elif defined (__sun__) + if (!ioctl (fd, DKIOCGMEDIAINFO, &minfo)) # else if (ioctl (fd, BLKGETSIZE64, &nr)) # endif @@ -287,13 +297,14 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (ioctl (fd, DIOCGSECTORSIZE, §or_size)) goto fail; +# elif defined(__sun__) + sector_size = minfo.dki_lbsize; # elif defined(__NetBSD__) sector_size = label.d_secsize; # else if (ioctl (fd, BLKSSZGET, §or_size)) goto fail; # endif - if (sector_size & (sector_size - 1) || !sector_size) goto fail; for (log_sector_size = 0; @@ -307,6 +318,8 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) return nr; # elif defined(__NetBSD__) return label.d_secperunit; +# elif defined (__sun__) + return minfo.dki_capacity; # else if (nr & ((1 << log_sector_size) - 1)) grub_util_error ("unaligned device size"); @@ -315,11 +328,15 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) # endif fail: + /* In GNU/Hurd, stat() will return the right size. */ #elif !defined (__GNU__) # warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal." #endif + sector_size = 512; + log_sector_size = 9; + if (log_secsize) *log_secsize = 9; @@ -419,12 +436,14 @@ find_partition_start (const char *dev) return out; } -#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) +#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined (__sun__) static grub_disk_addr_t find_partition_start (const char *dev) { int fd; -# if !defined(HAVE_DIOCGDINFO) +#ifdef __sun__ + struct extpart_info pinfo; +# elif !defined(HAVE_DIOCGDINFO) struct hd_geometry hdg; # else /* defined(HAVE_DIOCGDINFO) */ struct disklabel label; @@ -511,7 +530,9 @@ devmapper_fail: return 0; } -# if !defined(HAVE_DIOCGDINFO) +#if defined(__sun__) + if (ioctl (fd, DKIOCEXTPARTINFO, &pinfo)) +# elif !defined(HAVE_DIOCGDINFO) if (ioctl (fd, HDIO_GETGEO, &hdg)) # else /* defined(HAVE_DIOCGDINFO) */ # if defined(__NetBSD__) @@ -532,7 +553,9 @@ devmapper_fail: close (fd); -# if !defined(HAVE_DIOCGDINFO) +#ifdef __sun__ + return pinfo.p_start; +# elif !defined(HAVE_DIOCGDINFO) return hdg.start; # else /* defined(HAVE_DIOCGDINFO) */ if (dev[0]) @@ -1568,12 +1591,37 @@ devmapper_out: } return path; +#elif defined (__sun__) + char *colon = grub_strrchr (os_dev, ':'); + if (grub_memcmp (os_dev, "/devices", sizeof ("/devices") - 1) == 0 + && colon) + { + char *ret = xmalloc (colon - os_dev + sizeof (":q,raw")); + grub_memcpy (ret, os_dev, colon - os_dev); + grub_memcpy (ret + (colon - os_dev), ":q,raw", sizeof (":q,raw")); + return ret; + } + else + return xstrdup (os_dev); #else # warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly." return xstrdup (os_dev); #endif } +#if defined(__sun__) +static int +device_is_wholedisk (const char *os_dev) +{ + if (grub_memcmp (os_dev, "/devices/", sizeof ("/devices/") - 1) != 0) + return 1; + if (grub_memcmp (os_dev + strlen (os_dev) - (sizeof (":q,raw") - 1), + ":q,raw", (sizeof (":q,raw") - 1)) == 0) + return 1; + return 0; +} +#endif + #if defined(__linux__) || defined(__CYGWIN__) static int device_is_wholedisk (const char *os_dev) @@ -1700,14 +1748,14 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) convert_system_partition_to_system_disk (os_dev, &st)) == 0) return make_device_name (drive, -1, -1); -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__) if (! S_ISCHR (st.st_mode)) #else if (! S_ISBLK (st.st_mode)) #endif return make_device_name (drive, -1, -1); -#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__sun__) /* Linux counts partitions uniformly, whether a BSD partition or a DOS partition, so mapping them to GRUB devices is not trivial. @@ -1747,7 +1795,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) name = make_device_name (drive, -1, -1); -# if !defined(HAVE_DIOCGDINFO) +# if !defined(HAVE_DIOCGDINFO) && !defined(__sun__) if (MAJOR (st.st_rdev) == FLOPPY_MAJOR) return name; # else /* defined(HAVE_DIOCGDINFO) */ diff --git a/util/getroot.c b/util/getroot.c index 3d6f9370c..8fce283bc 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -61,6 +61,11 @@ # include #endif +#ifdef __sun__ +# include +# include +#endif + #include #include #include @@ -289,7 +294,19 @@ find_root_device_from_libzfs (const char *dir) struct stat st; if (stat (device, &st) == 0) { - device = xstrdup (device); +#ifdef __sun__ + if (grub_memcmp (device, "/dev/dsk/", sizeof ("/dev/dsk/") - 1) + == 0) + device = xasprintf ("/dev/rdsk/%s", + device + sizeof ("/dev/dsk/") - 1); + else if (grub_memcmp (device, "/devices", sizeof ("/devices") - 1) + == 0 + && grub_memcmp (device + strlen (device) - 4, + ",raw", 4) != 0) + device = xasprintf ("%s,raw", device); + else +#endif + device = xstrdup (device); break; } diff --git a/util/grub-probe.c b/util/grub-probe.c index ae58c89f3..54b9d03c6 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -171,7 +171,7 @@ probe (const char *path, char *device_name) if (path == NULL) { -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__sun__) if (! grub_util_check_char_device (device_name)) grub_util_error ("%s is not a character device", device_name); #else diff --git a/util/grub.d/10_illumos.in b/util/grub.d/10_illumos.in new file mode 100644 index 000000000..2b87dfa4f --- /dev/null +++ b/util/grub.d/10_illumos.in @@ -0,0 +1,54 @@ +#! /bin/sh +set -e + +# grub-mkconfig helper script. +# Copyright (C) 2006,2007,2008,2009,2010,2011 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +libdir=@libdir@ +datarootdir=@datarootdir@ +. ${libdir}/@PACKAGE@/grub-mkconfig_lib + +export TEXTDOMAIN=@PACKAGE@ +export TEXTDOMAINDIR=@localedir@ + +CLASS="--class os" + +case "${GRUB_DISTRIBUTOR}" in + *) + OS="Illumos" + CLASS="--class illumos ${CLASS}" + ;; +esac + +echo "menuentry '${OS}' ${CLASS} {" +save_default_entry | sed -e "s/^/\t/" +prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" +message="$(gettext_printf "Loading kernel of Illumos ...")" + cat << EOF + insmod gzio + if cpuid -l ; then + ISADIR=amd64 + else + ISADIR= + fi + zfs-bootfs $($grub_mkrelpath /) ZFS_BOOTFS + multiboot $($grub_mkrelpath /platform/i86pc/kernel)/\$ISADIR/unix /platform/i86pc/kernel/\$ISADIR/unix -B \$ZFS_BOOTFS,console=text + module $($grub_mkrelpath /platform/i86pc)/\$ISADIR/boot_archive /platform/i86pc/\$ISADIR/boot_archive +} +EOF