grub2/grub2-s390x-04-grub2-install.patch
Dr. Werner Fink b05b350108 Accepting request 228323 from home:michael-chang:SLE12
- snapper rollback support (fate#317062)
  * add btrfs_follow_default.patch
  * add suse_btrfs_grub2_install.sh
  * add 80_suse_btrfs_snapshot
  * refresh grub2-snapper-plugin.sh

- add grub2-x86_64-xen subpackage (bnc#863821)

- ieee1275: check for IBM pseries emulated machine (bnc#869964) 
- added patches:
  * grub2-ppc64-build-ppc64-32bit.patch

- Build ppc64 as 32bit
- added patches:
  * grub2-ppc64-build-ppc64-32bit.patch

- Rename PowerPC patches so it will have architecture in it's name 
- added patches:
  * grub2-ppc64le-01-Add-Little-Endian-support-for-Power64-to-the-build.patch
  * grub2-ppc64le-02-Build-grub-as-O1-until-we-add-savegpr-and-restgpr-ro.patch
  * grub2-ppc64le-03-disable-creation-of-vsx-and-altivec-instructions.patch
  * grub2-ppc64le-04-powerpc64-LE-s-linker-knows-how-to-handle-the-undefi.patch
  * grub2-ppc64le-05-grub-install-can-now-recognize-and-install-a-LE-grub.patch
  * grub2-ppc64le-06-set-the-ABI-version-to-0x02-in-the-e_flag-of-the-PPC.patch
  * grub2-ppc64le-07-Add-IEEE1275_ADDR-helper.patch
  * grub2-ppc64le-08-Fix-some-more-warnings-when-casting.patch
  * grub2-ppc64le-09-Add-powerpc64-types.patch
  * grub2-ppc64le-10-powerpc64-is-not-necessarily-BigEndian-anymore.patch
  * grub2-ppc64le-11-Fix-warnings-when-building-powerpc-linux-loader-64bi.patch
  * grub2-ppc64le-12-GRUB_ELF_R_PPC_-processing-is-applicable-only-for-32.patch

OBS-URL: https://build.opensuse.org/request/show/228323
OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=81
2014-03-31 19:51:24 +00:00

888 lines
25 KiB
Diff

From: Raymund Will <rw@suse.com>
Subject: Allow s390x-emu to be "installed"
References: fate#314213
Patch-Mainline: no
---
Makefile.util.def | 39 +++
configure.ac | 9
grub-core/Makefile.core.def | 7
grub-core/osdep/basic/no_platform.c | 7
grub-core/osdep/unix/platform.c | 13 +
grub-core/osdep/windows/platform.c | 6
include/grub/util/install.h | 4
util/grub-install-common.c | 1
util/grub-install.c | 51 +++++
util/s390x/dracut-grub2.sh.in | 69 ++++++
util/s390x/dracut-module-setup.sh.in | 17 +
util/s390x/zipl2grub.conf.in | 26 ++
util/s390x/zipl2grub.pl.in | 346 +++++++++++++++++++++++++++++++++++
13 files changed, 591 insertions(+), 4 deletions(-)
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -350,6 +350,7 @@ program = {
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
cppflags = '-DGRUB_SETUP_FUNC=grub_util_bios_setup';
+ emu_condition = COND_NOT_s390x;
};
program = {
@@ -370,6 +371,7 @@ program = {
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
cppflags = '-DGRUB_SETUP_FUNC=grub_util_sparc_setup';
+ emu_condition = COND_NOT_s390x;
};
program = {
@@ -385,6 +387,7 @@ program = {
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)';
+ emu_condition = COND_NOT_s390x;
};
program = {
@@ -415,6 +418,7 @@ program = {
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+ emu_condition = COND_NOT_s390x;
};
data = {
@@ -620,7 +624,7 @@ program = {
common = grub-core/disk/host.c;
common = util/resolve.c;
- enable = noemu;
+ emu_condition = COND_s390x;
common = grub-core/kern/emu/argp_common.c;
common = grub-core/osdep/init.c;
@@ -688,6 +692,38 @@ script = {
};
script = {
+ name = zipl2grub.pl;
+ common = util/s390x/zipl2grub.pl.in;
+ enable = emu;
+ emu_condition = COND_s390x;
+ installdir = platform;
+};
+
+data = {
+ name = zipl2grub.conf.in;
+ common = util/s390x/zipl2grub.conf.in;
+ installdir = grubconf;
+ enable = emu;
+ emu_condition = COND_s390x;
+};
+
+script = {
+ name = dracut-module-setup.sh;
+ common = util/s390x/dracut-module-setup.sh.in;
+ enable = emu;
+ emu_condition = COND_s390x;
+ installdir = platform;
+};
+
+script = {
+ name = dracut-grub.sh;
+ common = util/s390x/dracut-grub2.sh.in;
+ enable = emu;
+ emu_condition = COND_s390x;
+ installdir = platform;
+};
+
+script = {
name = grub-mkconfig_lib;
common = util/grub-mkconfig_lib.in;
installdir = noinst;
@@ -1281,6 +1317,7 @@ program = {
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
+ emu_condition = COND_NOT_s390x;
};
program = {
--- a/configure.ac
+++ b/configure.ac
@@ -177,9 +177,9 @@ if test x$platform != xemu ; then
esac
fi
-if test x"$target_cpu-$platform" = xsparc64-emu ; then
- target_m64=1 ;
-fi
+case x"$target_cpu-$platform" in
+ xsparc64-emu | xs390x-emu) target_m64=1 ;;
+esac
case "$target_os" in
windows* | mingw32*) target_os=cygwin ;;
@@ -1665,6 +1665,9 @@ AM_CONDITIONAL([COND_arm_uboot], [test x
AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi])
AM_CONDITIONAL([COND_arm64], [test x$target_cpu = xarm64 ])
AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi])
+AM_CONDITIONAL([COND_s390x], [test x$target_cpu = xs390x ])
+AM_CONDITIONAL([COND_NOT_s390x], [test x$target_cpu != xs390x ])
+AM_CONDITIONAL([COND_s390x_emu], [test x$target_cpu = xs390x -a x$platform = xemu])
AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd])
AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -1064,6 +1064,7 @@ module = {
module = {
name = videotest;
common = commands/videotest.c;
+ emu_condition = COND_NOT_s390x;
};
module = {
@@ -1477,6 +1478,7 @@ module = {
common = gfxmenu/gui_progress_bar.c;
common = gfxmenu/gui_util.c;
common = gfxmenu/gui_string_util.c;
+ emu_condition = COND_NOT_s390x;
};
module = {
@@ -1856,11 +1858,13 @@ module = {
name = gfxterm;
common = term/gfxterm.c;
enable = videomodules;
+ emu_condition = COND_NOT_s390x;
};
module = {
name = gfxterm_background;
common = term/gfxterm_background.c;
+ emu_condition = COND_NOT_s390x;
};
module = {
@@ -1975,6 +1979,7 @@ module = {
enable = x86_64_efi;
enable = emu;
enable = xen;
+ emu_condition = COND_NOT_s390x;
};
module = {
@@ -1990,6 +1995,7 @@ module = {
module = {
name = gfxterm_menu;
common = tests/gfxterm_menu.c;
+ emu_condition = COND_NOT_s390x;
};
module = {
@@ -2142,6 +2148,7 @@ module = {
enable = x86_64_efi;
enable = emu;
enable = xen;
+ emu_condition = COND_NOT_s390x;
};
module = {
--- a/grub-core/osdep/basic/no_platform.c
+++ b/grub-core/osdep/basic/no_platform.c
@@ -44,3 +44,10 @@ grub_install_sgi_setup (const char *inst
{
grub_util_error ("%s", _("no SGI routines are available for your platform"));
}
+
+void
+grub_install_zipl (const char *D, const char *s, const char *d, int i, int f)
+{
+ grub_util_error ("%s", _("no zIPL routines are available for your platform"));
+}
+
--- a/grub-core/osdep/unix/platform.c
+++ b/grub-core/osdep/unix/platform.c
@@ -233,3 +233,16 @@ grub_install_sgi_setup (const char *inst
imgfile, destname, NULL });
grub_util_warn ("%s", _("You will have to set `SystemPartition' and `OSLoader' manually."));
}
+
+void
+grub_install_zipl (const char *scriptdir, const char *script,
+ const char *dest, int install, int force)
+{
+ char *path = grub_util_path_concat (2, scriptdir, script);
+ if (grub_util_exec ((const char * []){ path,
+ install ? "" : "--debug",
+ verbosity ? "-v" : "",
+ force ? "--force" : "",
+ "-z", dest, NULL }))
+ grub_util_error (_("`%s' failed.\n"), script);
+}
--- a/grub-core/osdep/windows/platform.c
+++ b/grub-core/osdep/windows/platform.c
@@ -422,3 +422,9 @@ grub_install_sgi_setup (const char *inst
{
grub_util_error ("%s", _("no SGI routines are available for your platform"));
}
+
+void
+grub_install_zipl (const char *D, const char *s, const char *d, int i, int f)
+{
+ grub_util_error ("%s", _("no zIPL routines are available for your platform"));
+}
--- a/include/grub/util/install.h
+++ b/include/grub/util/install.h
@@ -99,6 +99,7 @@ enum grub_install_plat
GRUB_INSTALL_PLATFORM_I386_XEN,
GRUB_INSTALL_PLATFORM_X86_64_XEN,
GRUB_INSTALL_PLATFORM_ARM64_EFI,
+ GRUB_INSTALL_PLATFORM_S390X_EMU,
GRUB_INSTALL_PLATFORM_MAX
};
@@ -217,6 +218,9 @@ void
grub_install_sgi_setup (const char *install_device,
const char *imgfile, const char *destname);
+void
+grub_install_zipl (const char *D, const char *s, const char *d, int i, int f);
+
int
grub_install_compress_gzip (const char *src, const char *dest);
int
--- a/util/grub-install-common.c
+++ b/util/grub-install-common.c
@@ -665,6 +665,7 @@ static struct
[GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" },
[GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" },
[GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" },
+ [GRUB_INSTALL_PLATFORM_S390X_EMU] = { "s390x", "emu" },
};
char *
--- a/util/grub-install.c
+++ b/util/grub-install.c
@@ -66,6 +66,7 @@ static int force_file_id = 0;
static char *disk_module = NULL;
static char *efidir = NULL;
static char *macppcdir = NULL;
+static char *zipldir = NULL;
static int force = 0;
static int have_abstractions = 0;
static int have_cryptodisk = 0;
@@ -107,6 +108,7 @@ enum
OPTION_NO_BOOTSECTOR,
OPTION_NO_RS_CODES,
OPTION_MACPPC_DIRECTORY,
+ OPTION_ZIPL_DIRECTORY,
OPTION_LABEL_FONT,
OPTION_LABEL_COLOR,
OPTION_LABEL_BGCOLOR,
@@ -182,6 +184,11 @@ argp_parser (int key, char *arg, struct
efidir = xstrdup (arg);
return 0;
+ case OPTION_ZIPL_DIRECTORY:
+ free (zipldir);
+ zipldir = xstrdup (arg);
+ return 0;
+
case OPTION_DISK_MODULE:
free (disk_module);
disk_module = xstrdup (arg);
@@ -299,6 +306,8 @@ static struct argp_option options[] = {
N_("use DIR as the EFI System Partition root."), 2},
{"macppc-directory", OPTION_MACPPC_DIRECTORY, N_("DIR"), 0,
N_("use DIR for PPC MAC install."), 2},
+ {"zipl-directory", OPTION_ZIPL_DIRECTORY, N_("DIR"), 0,
+ N_("use DIR as the zIPL Boot Partition root."), 2},
{"label-font", OPTION_LABEL_FONT, N_("FILE"), 0, N_("use FILE as font for label"), 2},
{"label-color", OPTION_LABEL_COLOR, N_("COLOR"), 0, N_("use COLOR for label"), 2},
{"label-bgcolor", OPTION_LABEL_BGCOLOR, N_("COLOR"), 0, N_("use COLOR for label background"), 2},
@@ -325,6 +334,8 @@ get_default_platform (void)
return "arm64-efi";
#elif defined (__amd64__) || defined (__x86_64__) || defined (__i386__)
return grub_install_get_default_x86_platform ();
+#elif defined (__s390x__)
+ return "s390x-emu";
#else
return NULL;
#endif
@@ -484,6 +495,8 @@ have_bootdev (enum grub_install_plat pl)
case GRUB_INSTALL_PLATFORM_I386_XEN:
case GRUB_INSTALL_PLATFORM_X86_64_XEN:
+
+ case GRUB_INSTALL_PLATFORM_S390X_EMU:
return 0;
/* pacify warning. */
@@ -895,6 +908,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
case GRUB_INSTALL_PLATFORM_I386_XEN:
case GRUB_INSTALL_PLATFORM_X86_64_XEN:
+ case GRUB_INSTALL_PLATFORM_S390X_EMU:
break;
case GRUB_INSTALL_PLATFORM_I386_QEMU:
@@ -940,6 +954,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
case GRUB_INSTALL_PLATFORM_I386_XEN:
case GRUB_INSTALL_PLATFORM_X86_64_XEN:
+ case GRUB_INSTALL_PLATFORM_S390X_EMU:
free (install_device);
install_device = NULL;
break;
@@ -1201,6 +1216,20 @@ main (int argc, char *argv[])
}
}
+ if (platform == GRUB_INSTALL_PLATFORM_S390X_EMU)
+ {
+ if (!zipldir)
+ {
+ char *d = grub_util_path_concat (2, bootdir, "zipl");
+ if (!grub_util_is_directory (d))
+ {
+ free (d);
+ grub_util_error ("%s", _("cannot find zIPL directory"));
+ }
+ zipldir = d;
+ }
+ }
+
grub_install_copy_files (grub_install_source_directory,
grubdir, platform);
@@ -1445,6 +1474,7 @@ main (int argc, char *argv[])
case GRUB_INSTALL_PLATFORM_ARM_UBOOT:
case GRUB_INSTALL_PLATFORM_I386_XEN:
case GRUB_INSTALL_PLATFORM_X86_64_XEN:
+ case GRUB_INSTALL_PLATFORM_S390X_EMU:
grub_util_warn ("%s", _("no hints available for your platform. Expect reduced performance"));
break;
/* pacify warning. */
@@ -1557,6 +1587,10 @@ main (int argc, char *argv[])
strcpy (mkimage_target, "sparc64-ieee1275-raw");
core_name = "core.img";
break;
+ case GRUB_INSTALL_PLATFORM_S390X_EMU:
+ strcpy (mkimage_target, "grub2-emu");
+ core_name = mkimage_target;
+ break;
/* pacify warning. */
case GRUB_INSTALL_PLATFORM_MAX:
break;
@@ -1572,6 +1606,7 @@ main (int argc, char *argv[])
core_name);
char *prefix = xasprintf ("%s%s", prefix_drive ? : "",
relative_grubdir);
+ if (core_name != mkimage_target)
grub_install_make_image_wrap (/* source dir */ grub_install_source_directory,
/*prefix */ prefix,
/* output */ imgfile,
@@ -1610,6 +1645,17 @@ main (int argc, char *argv[])
/* image target */ mkimage_target, 0);
}
break;
+
+ case GRUB_INSTALL_PLATFORM_S390X_EMU:
+#if 0
+ {
+ char *dst = grub_util_path_concat (2, platdir, "grub2-emu");
+ grub_install_copy_file ("/usr/bin/grub2-emu", dst, 1);
+ free (dst);
+ }
+#endif
+ break;
+
case GRUB_INSTALL_PLATFORM_ARM_EFI:
case GRUB_INSTALL_PLATFORM_ARM64_EFI:
case GRUB_INSTALL_PLATFORM_IA64_EFI:
@@ -1871,6 +1917,11 @@ main (int argc, char *argv[])
}
break;
+ case GRUB_INSTALL_PLATFORM_S390X_EMU:
+ grub_install_zipl (grub_install_source_directory, "zipl2grub.pl",
+ zipldir, install_bootsector, force);
+ break;
+
case GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON:
case GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS:
case GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS:
--- /dev/null
+++ b/util/s390x/dracut-grub2.sh.in
@@ -0,0 +1,69 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+#getargbool() { true; }
+
+if getargbool 0 initgrub && [ ! -e /grub2b0rken ] || [ -e /grub2force ]; then
+ #type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
+ checkro() {
+ local dev mp fs opts dc
+ local rofs=false
+ while read dev mp fs opts dc; do
+ [ "$mp" = "/sysroot" ] || continue
+ case ",$opts," in
+ (*,ro,*) rofs=true;;
+ esac
+ done < /proc/mounts
+ echo $rofs
+ }
+ checkd() {
+ [ -d $1 ] && echo true || echo false
+ }
+ getterm() {
+ local term="$(getarg TERM)"
+ [ -z "$term" ] && term=dumb
+ echo $term
+ }
+
+ exec_prefix=@exec_prefix@
+ bindir=@bindir@
+ if [ -e /sysroot$bindir/grub2-emu ]; then
+
+
+ export TERM=$(getterm)
+ export grub2rofs=$(checkro)
+ export grub2sysfs=$(checkd /sysroot/sys/kernel)
+ export grub2procfs=$(checkd /sysroot/proc/slef)
+ export -p > /tmp/grub2env
+ cat /proc/mounts > /tmp/grub2mounts
+
+ _ctty="$(RD_DEBUG= getarg rd.ctty=)" && _ctty="/dev/${_ctty##*/}"
+ if [ -z "$_ctty" ]; then
+ _ctty=console
+ while [ -f /sys/class/tty/$_ctty/active ]; do
+ _ctty=$(cat /sys/class/tty/$_ctty/active)
+ _ctty=${_ctty##* } # last one in the list
+ done
+ _ctty=/dev/$_ctty
+ fi
+ [ -c "$_ctty" ] || _ctty=/dev/tty1
+ case "$(/usr/bin/setsid --help 2>&1)" in *--ctty*) CTTY="--ctty";; esac
+
+ CTTY="$CTTY --wait"
+ $grub2rofs || mount -o remount,ro /sysroot
+ $grub2sysfs || mount --bind {,/sysroot}/sys
+ $grub2procfs || mount --bind {,/sysroot}/proc
+
+ info "Trying grub2emu (ro=$grub2rofs, TERM=$TERM)..."
+ setsid $CTTY -- chroot /sysroot $bindir/grub2-emu -X -X 0<>$_ctty 1>&0 2>&0
+ if [ -e /grub2force ] && [ $(cat /sys/kernel/kexec_loaded) = 1 ]; then
+ systemctl kexec
+ fi
+ $grub2procfs || umount /sysroot/proc
+ $grub2sysfs || umount /sysroot/sys
+ $grub2rofs || mount -o remount,rw /sysroot
+ else
+ info "No $bindir/grub2-emu in /sysroot--trying to proceed without kexec..."
+ fi
+fi
+
--- /dev/null
+++ b/util/s390x/dracut-module-setup.sh.in
@@ -0,0 +1,17 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+# called by dracut
+check() {
+ local _arch=$(uname -m)
+ [ "$_arch" = "s390" -o "$_arch" = "s390x" ] || return 1
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook cleanup 99 "$moddir/grub2.sh"
+ #inst_multiple grub2-emu kexec
+}
+
--- /dev/null
+++ b/util/s390x/zipl2grub.conf.in
@@ -0,0 +1,26 @@
+## This is the template for '@zipldir@/config' and is subject to
+## rpm's %config file handling in case of grub2-s390x-emu package update.
+
+[defaultboot]
+defaultmenu = menu
+
+[grub2]
+ target = @zipldir@
+ ramdisk = @zipldir@/initrd,0x2000000
+ image = @zipldir@/image
+ parameters = "root=@GRUB_DEVICE@ @GRUB_CMDLINE_LINUX@ @GRUB_CMDLINE_LINUX_DEFAULT@ initgrub quiet splash=silent "
+
+[skip-grub2]
+ target = @zipldir@
+ ramdisk = @zipldir@/initrd,0x2000000
+ image = @zipldir@/image
+ parameters = "root=@GRUB_DEVICE@ @GRUB_CMDLINE_LINUX@ @GRUB_CMDLINE_LINUX_DEFAULT@ "
+
+:menu
+ target = @zipldir@
+ timeout = 16
+ default = 1
+ prompt = 1
+ 1 = grub2
+ 2 = skip-grub2
+
--- /dev/null
+++ b/util/s390x/zipl2grub.pl.in
@@ -0,0 +1,346 @@
+#!/usr/bin/perl
+use strict;
+
+my $C = $0; $C =~ s{^.*/}{};
+
+my $in = '@sysconfdir@/default/zipl2grub.conf.in';
+my $default = '@sysconfdir@/default/grub';
+my $fallback = '@sysconfdir@/zipl.conf';
+my $sysconfbl = '@sysconfdir@/sysconfig/bootloader';
+my $zipldir = "";
+my $running = "";
+my $refresh = 1; # needs to default to "on" until most bugs are shaken out!
+my $force = 0;
+my $verbose = 0;
+my $debug = 0;
+my $miss = 0;
+my $cfg = "";
+my %C;
+
+$C{GRUB_CMDLINE_LINUX} = ""; # force existence!
+
+sub Panic($$) {
+ printf( STDERR "%s", $_[1]);
+ exit( $_[0]);
+}
+sub Info($$) {
+ printf( STDERR "%s", $_[1]) if ($_[0] <= $verbose);
+}
+sub System(@) {
+ my (@C) =@_;
+ Info( 1, "+ " . join( " ", @C) . "\n");
+ return 0 if ($debug);
+ system( @C);
+ if ($? == -1) {
+ Panic( $?, "$C[0]: Failed to execute: $!\n");
+ } elsif ($? & 127) {
+ Panic( $?, sprintf( "$C[0]: Died with signal %d with%s coredump\n",
+ ($? & 127), ($? & 128) ? '' : 'out'));
+ } elsif ( $? >> 8 != 0 ) {
+ Panic( $?, "$C[0]: Failed\n");
+ }
+ return( 0);
+}
+sub cp($$) {
+ my @C = ( "cp", "-p", $_[0], $_[1]);
+ System( @C);
+}
+sub rm($) {
+ return( 0) unless ( -l $_[0] || -e $_[0]);
+ Info( 2, "+ rm $_[0]\n");
+ return 0 if ($debug);
+ unlink( $_[0]) || Panic( 1, "$C: unlink: $!.\n");
+}
+sub mv($$) {
+ Info( 1, "+ mv $_[0] $_[1]\n");
+ return 0 if ($debug);
+ rename($_[0], $_[1]) || Panic( 1, "$C: rename: $!.\n");
+}
+sub ln($$) {
+ Info( 1, "+ ln -sf $_[0] $_[1]\n");
+ return 0 if ($debug);
+ rm( $_[1]);
+ symlink($_[0], $_[1]) || Panic( 1, "$C: symlink: $!.\n");
+}
+sub BootCopy($$$) {
+ my( $file, $dir, $tgt) = @_;
+ my $curr = "$dir/$tgt";
+ my $prev = "$dir/$tgt.prev";
+ Info(4, "Copy /boot/$file $dir $tgt\n");
+ if ( -l $curr ) {
+ my $curf = readlink( $curr);
+ if ( $curf ne $file ) {
+ if ( -l $prev ) {
+ my $pref = readlink( $prev);
+ rm( $pref);
+ }
+ mv( $curr, $prev);
+ }
+ }
+ cp( "/boot/$file", "$dir/$file");
+ ln( $file, $curr);
+}
+sub MkInitrd($$$) {
+ my( $initrd, $dir, $version) = @_;
+ my @C = ( "dracut", "--hostonly", "--force", "$dir/$initrd", $version);
+ System( @C);
+ ln( $initrd, "$dir/initrd");
+}
+sub ChkInitrd($$) {
+ my( $dir, $initrd) = @_;
+ my $found = 0;
+ my $d = $dir;
+ my $pattern = qr{lib/dracut/hooks/cleanup/99-grub2.sh};
+ my $show = "cleanup/99-grub2.sh";
+
+ return $found unless (-r "$dir/$initrd");
+
+ my $modinst = "/usr/lib/dracut/modules.d/99grub2/module-setup.sh";
+ if ( -r $modinst ) {
+ my( $hook, $ord, $script);
+ my $pat = qr{^\s*inst_hook\s+(\S+)\s+([0-9]+)\s+\"\$moddir/(grub2\.sh)\"};
+ open( IN, "< $modinst") || die;
+ while ( <IN> ) {
+ next unless ($_ =~ $pat);
+ $show = "$1/$2-$3";
+ $pattern = qr{lib/dracut/hooks/$show}o;
+ last;
+ }
+ close( IN);
+ }
+
+ Info( 3, "+ zcat $d/$initrd | cpio -it | grep '$show'\n");
+ open( IN, "zcat $d/$initrd | cpio -it 2>/dev/null |") ||
+ Panic( 1, "$C: cpio: $!.\n");
+ while ( <IN> ) {
+ $found = 1 if ($_ =~ $pattern);
+ }
+ close( IN);
+ return $found;
+}
+
+sub Usage($) {
+ my @cat = ("",
+ "Parameter error.",
+ "zIPL directory missing.",
+ "Configuration template missing.",
+ "Configuration template unreadable.",
+ "zIPL directory not accesible.",
+ ""
+ );
+ my $msg = "";
+
+ $msg .= sprintf( "%s: %s\n", $C, $cat[$_[0]]) if ($_[0] > 0);
+ $msg .= "Usage: $C [-v] [-d] [-f] [-T template] [-z ZIPLDIR]\n";
+ Panic( $_[0], $msg . "\n");
+}
+
+die if ($[ != 0);
+while ( $#ARGV >= 0 ) {
+ $_ = shift;
+ next if /^$/;
+ last if /^--$/;
+ (/^--verbose$/ || /^-v$/) && ($verbose++, next);
+ (/^--quiet$/ || /^-q$/) && ($verbose = 0, next);
+ (/^--debug$/ || /^-d$/) && ($debug = 1, $verbose++, next);
+ (/^--force$/ || /^-f$/) && ($force = $refresh = 1, next);
+ (/^--refresh$/ || /^-r$/) && ($refresh = 1, next);
+ (/^--keep$/ || /^-k$/) && ($refresh = 0, next);
+ (/^--?help/ || /^-h/) && (Usage(0));
+ (/^--zipldir$/ || /^-z$/) && ($zipldir = shift || Usage(2), next);
+ (/^--template$/ || /^-T$/) && ($in = shift || Usage(3), next);
+ (/^-/) && (Usage(1));
+ Usage(1);
+}
+Usage(4) if (! -r $in);
+
+if ($zipldir) {
+ $C{zipldir} = $zipldir; # command-line wins
+} elsif ( exists( $C{zipldir}) ) {
+ $zipldir = $C{zipldir}; # otherwise fall back to config
+} else {
+ $zipldir = $C{zipldir} = "/boot/zipl"; # but don't proceed without...
+}
+Usage(5) if (! -d $zipldir);
+if ( $zipldir eq "/boot" ) {
+ Panic( 5, "$C: zIPL directory '/boot' not supported!\n");
+}
+
+if ( ! -r $default && ! -r $fallback && ! -r $sysconfbl ) {
+ Panic( 0, "$C: No configuration files found. Retry later!\n");
+}
+if ( -r $default ) {
+ open( IN, "< $default") || die;
+ while ( <IN> ) {
+ chomp;
+ s{^\s*#.*$}{};
+ next if m{^\s*$};
+ s{x}{\x01xx\x01}g;
+ s{\\\"}{\x01x1\x01}g;
+ s{\\\'}{\x01x2\x01}g;
+ Info( 5, "<$_>\n");
+ if ( m{^([^\s=]+)='([^']*)'\s*(?:#.*)?$} ||
+ m{^([^\s=]+)="([^"]*)"\s*(?:#.*)?$} ||
+ m{^([^\s=]+)=(\S*)\s*(?:#.*)?$} ) {
+ my ( $k, $v) = ($1, $2);
+ $v =~ s{\x01x2\x01}{\\'}g;
+ $v =~ s{\x01x1\x01}{\\"}g;
+ $v =~ s{\x01xx\x01}{x}g;
+ $C{$k} = $v;
+ next;
+ }
+ print( STDERR "$default:$.: parse error ignored.\n");
+ }
+ close( IN);
+}
+
+if ( ! exists( $C{GRUB_DEVICE}) &&
+ (! exists( $C{GRUB_CMDLINE_LINUX_DEFAULT}) ||
+ $C{GRUB_CMDLINE_LINUX_DEFAULT} eq "quiet splash=silent") &&
+ -r $fallback ) {
+ # configuration incomplete, let's try fallback
+ open( IN, "< $fallback") || die;
+ my $section = "";
+ while( <IN> ){
+ if ( m{^\[([^\]]+)\]\s*$} ) {
+ $section = $1;
+ }
+ if ( $section eq "ipl" &&
+ m{^\s*parameters\s*=\s*\"root=(\S+)(?:\s*|\s+([^\"]+))\"} ) {
+ $C{GRUB_DEVICE} = $1;
+ $C{GRUB_CMDLINE_LINUX_DEFAULT} = $2 if (defined($2) && $2 !~ m{^\s*$});
+ last;
+ }
+ }
+ close( IN);
+ $default = $fallback;
+}
+if ( ! exists( $C{GRUB_DEVICE}) ) {
+ my( $dev, $uuid, $type, $subvol) = ("", "", "", "");
+ chomp( $dev = qx{grub2-probe --target=device /});
+ chomp( $uuid = qx{grub2-probe --device $dev --target=fs_uuid});
+ $subvol =~ s{^/}{};
+ if ($dev && $uuid) {
+ $C{GRUB_DEVICE} = "UUID=$uuid";
+ chomp( $type = qx{stat -f --printf='%T' /});
+ chomp( $subvol = qx{grub2-mkrelpath /}) if ( $type eq "btrfs" );
+ $C{GRUB_DEVICE} .= " rootflags=subvol=$subvol" if ($subvol);
+ }
+}
+if ( ! exists( $C{GRUB_DEVICE}) && -r "/etc/fstab" ) {
+ my( $dev, $type);
+ open( IN, "< /etc/fstab") || die;
+ while ( <IN> ) {
+ next if ( m{^\s*#} );
+ ($dev, $type) = (m{^(\S+)\s+/\s+(\S+)\s+\S+\s+\S+\s+\S+\s*(?:#.*)?$});
+ last if (defined( $dev));
+ }
+ close( IN);
+ $C{GRUB_DEVICE} = $dev;
+ # ToDo: is static 'subvol=@' good enough?
+ $C{GRUB_DEVICE} .= ' rootflags=subvol=@' if ($type eq "btrfs");
+}
+if ( (! exists( $C{GRUB_CMDLINE_LINUX_DEFAULT}) ||
+ $C{GRUB_CMDLINE_LINUX_DEFAULT} eq "quiet splash=silent") &&
+ -r $sysconfbl) {
+ open( IN, "< $sysconfbl") || die;
+ while ( <IN> ) {
+ next if ( m{^\s*#} );
+ if ( m{^DEFAULT_APPEND=".*"(?:\s*|\s+#.*)$} ) {
+ $C{GRUB_CMDLINE_LINUX_DEFAULT} = $1;
+ }
+ }
+ close( IN);
+}
+
+ if ( ! exists( $C{GRUB_DEVICE})) {
+ Panic( 0, "$C: Default not ready and no fallback. Please retry later!\n");
+ }
+
+if ( $debug && $verbose > 2 ) {
+ foreach ( sort( keys( %C)) ) {
+ printf( "%s=\"%s\"\n", $_, $C{$_});
+ }
+}
+
+open( IN, "< $in") ||
+ Panic( 1, "$C: Failed to open 'zipl.conf' template: $!.\n");
+while ( <IN> ) {
+ Info( 3, "$.. <$_$.. >");
+ if ( $. == 1 && m{^## This} ) {
+ $_ = "## This file was written by 'grub2-install/$C'\n" .
+ "## filling '$in' as template\n";
+ } elsif ( $. == 2 && m{^## rpm's} ) {
+ $_ = "## with values from '$default'.\n" .
+ "## In-place modifications will eventually go missing!\n";
+ }
+ while ( m{\@([^\@\s]+)\@} ) {
+ my $k = $1;
+ my $v;
+ if ( exists( $C{$k}) ) {
+ $v = $C{$k};
+ } else {
+ $v = $k;
+ $miss++;
+ }
+ s{\@$k\@}{$v}g;
+ }
+ Info( 2, $_);
+ $cfg .= $_;
+}
+if ( $miss ) {
+ Info( 1, "Partially filled config:\n===\n$cfg===\n");
+ Panic( 1, "$C: 'zipl.conf' template could not be filled. \n");
+}
+
+my $ziplconf = "$zipldir/config";
+if ( ! $debug ) {
+ open( OUT, "> $ziplconf") || die;
+ print( OUT $cfg) || die;
+ close( OUT);
+}
+
+# copy out kernel and initrd
+my $defimage = "/boot/image";
+my $definitrd = "/boot/initrd";
+my $ziplimage = "$zipldir/image";
+my $ziplinitrd = "$zipldir/initrd";
+my $Image = "$defimage";
+
+if ( ! $running && ! $force ) {
+ chomp( $running = qx{uname -r});
+ Info( 1, "preferred kernel: '$running'\n");
+ $Image .= "-$running";
+}
+if ( ! -r $Image ) {
+ $Image = $defimage;
+}
+Panic( 1, "$C: kernel '$Image' not readable!?\n") unless (-r $Image);
+
+if ( -l $Image ) {
+ $Image = readlink( $Image);
+}
+my ($image, $version) = ($Image =~ m{^(?:/boot/)?([^-]+-(.+))$});
+my $initrd = "initrd-$version";
+
+if ( !defined($image) || !defined($version) || ! -r "/boot/$image" ) {
+ Panic( 1, "$C: weird $Image. This should never happen!\n");
+}
+
+if ( ! -r $ziplimage || ! -r $ziplinitrd || $refresh ) {
+ BootCopy( $image, $zipldir, "image");
+ BootCopy( $initrd, $zipldir, "initrd") if (-r "/boot/$initrd");
+}
+if ( ! ChkInitrd( $zipldir, "initrd")) {
+ MkInitrd( $initrd, $zipldir, $version);
+}
+if ( ! ChkInitrd( $zipldir, "initrd")) {
+ Info( 0, "$C: dracut does not work as expected! Help needed!\n");
+ $miss++;
+}
+
+# now: go for it!
+my @C = ( "/sbin/zipl", (($verbose) ? "-Vnc" : "-nc"), "$ziplconf" );
+System( @C);
+exit( $miss);
+