From 938f2390dd9689c6a1d5c1ea284c234cc0667739 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Mon, 7 Aug 2023 21:31:59 +0200 Subject: [PATCH] Support system upgrades and configuration in GRUB. Move /etc/default/grub to /etc/grub as it's owned by the sysadmin. Move /etc/grub.d to /etc/default/grub.d as it's owned by the system. Support /etc/grub's GRUB_CMDLINE_SORTIX in 10_sortix. Remove the old /etc/grub.d/10_sortix.cache with a compatibility hook as it has moved to /etc/default/grub.d/10_sortix.cache. --- ports/grub/grub.execpatch | 2 +- ports/grub/grub.patch | 370 ++++++++++++++----- ports/grub/grub.post-install | 1 - share/man/man5/upgrade.conf.5 | 2 +- share/man/man7/following-development.7 | 74 +++- share/man/man7/hier.7 | 6 +- share/man/man7/installation.7 | 8 +- share/sysinstall/hooks/sortix-1.1-grub-cache | 0 sysinstall/Makefile | 4 + sysinstall/grub | 29 ++ sysinstall/hooks.c | 22 ++ sysinstall/prepare | 27 ++ sysinstall/sysinstall.c | 12 +- sysinstall/sysmerge.8 | 60 ++- sysinstall/sysmerge.c | 151 +++++--- sysinstall/sysupgrade.c | 7 +- update-initrd/update-initrd | 39 +- update-initrd/update-initrd.8 | 18 +- 18 files changed, 609 insertions(+), 223 deletions(-) create mode 100644 share/sysinstall/hooks/sortix-1.1-grub-cache create mode 100755 sysinstall/grub create mode 100755 sysinstall/prepare diff --git a/ports/grub/grub.execpatch b/ports/grub/grub.execpatch index 063bb676..0cbb6c01 100644 --- a/ports/grub/grub.execpatch +++ b/ports/grub/grub.execpatch @@ -1,2 +1,2 @@ -chmod +x -- '10_sortix' chmod +x -- 'update-grub' +chmod +x -- 'util/grub.d/10_sortix.in' diff --git a/ports/grub/grub.patch b/ports/grub/grub.patch index bf5faf9d..813397d2 100644 --- a/ports/grub/grub.patch +++ b/ports/grub/grub.patch @@ -1,77 +1,58 @@ -diff -Paur --no-dereference -- grub.upstream/10_sortix grub/10_sortix ---- grub.upstream/10_sortix -+++ grub/10_sortix -@@ -0,0 +1,70 @@ -+#!/bin/sh -e -+! [ -e /etc/sortix-release ] && exit 0 -+. /etc/sortix-release -+find_mountpoint() {( -+ FILE="$1" -+ DEVICE=$(grub-probe -t device -- "$FILE") -+ while [ "$FILE" != "/" ]; do -+ PARENT="$(dirname -- "$FILE")" -+ if [ x"$(grub-probe -t device -- "$PARENT")" != x"$DEVICE" ]; then -+ echo "$FILE" -+ exit 0 -+ fi -+ FILE="$PARENT" -+ done -+ echo "$FILE" -+ exit 0 -+)} -+mountpoint_relative() {( -+ REL="" -+ FILE="$1" -+ DEVICE=$(grub-probe -t device -- "$FILE") -+ while [ "$FILE" != "/" ]; do -+ PARENT="$(dirname -- "$FILE")" -+ if [ x"$(grub-probe -t device -- "$PARENT")" != x"$DEVICE" ]; then -+ echo "$REL" -+ exit 0 -+ fi -+ REL="/$(basename -- "$FILE")$REL" -+ FILE="$PARENT" -+ done -+ echo "$REL" -+ exit 0 -+)} -+BOOT_MNT=$(find_mountpoint /boot) -+BOOT_REL=$(mountpoint_relative /boot) -+DEVICE=$(grub-probe -t device -- "$BOOT_MNT") -+FS_UUID=$(grub-probe -t fs_uuid -- "$BOOT_MNT") -+HINTS_STRING=$(grub-probe -t hints_string -- "$BOOT_MNT") -+PARTMAP=$(grub-probe -t partmap -- "$BOOT_MNT") -+FS=$(grub-probe -t fs -- "$BOOT_MNT") -+echo "Found $PRETTY_NAME on $DEVICE" >&2 -+cat > "$0.cache" << EOF -+menuentry "$PRETTY_NAME (on $DEVICE)" --unrestricted { -+ insmod part_$PARTMAP -+ insmod $FS -+ search --no-floppy --fs-uuid --set=root $HINTS_STRING $FS_UUID -+ if [ -e $BOOT_REL/sortix.bin.xz ]; then -+ insmod xzio -+ multiboot $BOOT_REL/sortix.bin.xz -+ elif [ -e $BOOT_REL/sortix.bin.gz ]; then -+ insmod gzio -+ multiboot $BOOT_REL/sortix.bin.gz -+ else -+ multiboot $BOOT_REL/sortix.bin -+ fi -+ if [ -e $BOOT_REL/random.seed ]; then -+ module $BOOT_REL/random.seed --random-seed -+ fi -+ if [ -e $BOOT_REL/sortix.initrd.xz ]; then -+ insmod xzio -+ module $BOOT_REL/sortix.initrd.xz -+ elif [ -e $BOOT_REL/sortix.initrd.gz ]; then -+ insmod gzio -+ module $BOOT_REL/sortix.initrd.gz -+ else -+ module $BOOT_REL/sortix.initrd -+ fi -+} -+EOF -+cat "$0.cache" +diff -Paur --no-dereference -- grub.upstream/Makefile.in grub/Makefile.in +--- grub.upstream/Makefile.in ++++ grub/Makefile.in +@@ -1212,6 +1212,7 @@ + util/grub.d/10_kfreebsd.in util/grub.d/10_illumos.in \ + util/grub.d/10_netbsd.in util/grub.d/10_linux.in \ + util/grub.d/10_xnu.in util/grub.d/20_linux_xen.in \ ++ util/grub.d/10_sortix.in \ + util/grub.d/30_os-prober.in util/grub.d/40_custom.in \ + util/grub.d/41_custom.in util/grub-mkconfig.in \ + util/grub-set-default.in util/grub-reboot.in \ +@@ -2372,7 +2373,7 @@ + CCASFLAGS_LIBRARY = + + # Other variables +-grubconfdir = $(sysconfdir)/grub.d ++grubconfdir = $(sysconfdir)/default/grub.d + platformdir = $(pkglibdir)/$(target_cpu)-$(platform) + starfielddir = $(pkgdatadir)/themes/starfield + CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion +@@ -2440,6 +2441,7 @@ + grubconf_SCRIPTS = 00_header $(am__append_57) $(am__append_61) \ + $(am__append_65) $(am__append_69) $(am__append_73) \ + $(am__append_77) $(am__append_81) $(am__append_85) \ ++ 10_sortix \ + 30_os-prober 40_custom 41_custom + noinst_LIBRARIES = libgrubkern.a libgrubmods.a libgrubgcry.a + dist_noinst_DATA = grub-core/kern/disk_common.c \ +@@ -2460,6 +2462,7 @@ + util/grub.d/00_header.in $(am__append_60) $(am__append_64) \ + $(am__append_68) $(am__append_72) $(am__append_76) \ + $(am__append_80) $(am__append_84) $(am__append_88) \ ++ util/grub.d/10_sortix.in \ + util/grub.d/30_os-prober.in util/grub.d/40_custom.in \ + util/grub.d/41_custom.in util/grub-mkconfig.in \ + util/grub-set-default.in util/grub-reboot.in \ +@@ -2640,6 +2643,7 @@ + $(am__append_62) $(am__append_66) $(am__append_70) \ + $(am__append_74) $(am__append_78) $(am__append_82) \ + $(am__append_86) 30_os-prober 40_custom 41_custom \ ++ 10_sortix \ + $(am__append_89) grub-mkconfig $(am__append_90) \ + grub-set-default $(am__append_91) grub-reboot \ + grub-mkconfig_lib $(am__append_92) grub-kbdcomp grub-shell \ +@@ -12086,6 +12090,10 @@ + @COND_HOST_XNU_TRUE@ (for x in util/grub.d/10_xnu.in ; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:- + @COND_HOST_XNU_TRUE@ chmod a+x 10_xnu + ++10_sortix: $(top_builddir)/config.status util/grub.d/10_sortix.in ++ (for x in util/grub.d/10_sortix.in ; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:- ++ chmod a+x 10_sortix ++ + @COND_HOST_LINUX_TRUE@20_linux_xen: $(top_builddir)/config.status util/grub.d/20_linux_xen.in + @COND_HOST_LINUX_TRUE@ (for x in util/grub.d/20_linux_xen.in ; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:- + @COND_HOST_LINUX_TRUE@ chmod a+x 20_linux_xen diff -Paur --no-dereference -- grub.upstream/build-aux/config.sub grub/build-aux/config.sub --- grub.upstream/build-aux/config.sub +++ grub/build-aux/config.sub @@ -226,6 +207,18 @@ diff -Paur --no-dereference -- grub.upstream/configure grub/configure FREETYPE=$ac_cv_prog_FREETYPE if test -n "$FREETYPE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE" >&5 +diff -Paur --no-dereference -- grub.upstream/grub-core/Makefile.in grub/grub-core/Makefile.in +--- grub.upstream/grub-core/Makefile.in ++++ grub/grub-core/Makefile.in +@@ -13658,7 +13658,7 @@ + CCASFLAGS_LIBRARY = $(CCASFLAGS_PLATFORM) + + # Other variables +-grubconfdir = $(sysconfdir)/grub.d ++grubconfdir = $(sysconfdir)/default/grub.d + platformdir = $(pkglibdir)/$(target_cpu)-$(platform) + starfielddir = $(pkgdatadir)/themes/starfield + CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion diff -Paur --no-dereference -- grub.upstream/grub-core/lib/libgcrypt-grub/cipher/rijndael.c grub/grub-core/lib/libgcrypt-grub/cipher/rijndael.c --- grub.upstream/grub-core/lib/libgcrypt-grub/cipher/rijndael.c +++ grub/grub-core/lib/libgcrypt-grub/cipher/rijndael.c @@ -665,6 +658,18 @@ diff -Paur --no-dereference -- grub.upstream/update-grub grub/update-grub @@ -0,0 +1,2 @@ +#!/bin/sh -e +exec grub-mkconfig -o /boot/grub/grub.cfg "$@" +diff -Paur --no-dereference -- grub.upstream/util/bash-completion.d/Makefile.in grub/util/bash-completion.d/Makefile.in +--- grub.upstream/util/bash-completion.d/Makefile.in ++++ grub/util/bash-completion.d/Makefile.in +@@ -1022,7 +1022,7 @@ + bash_completion_script = grub + EXTRA_DIST = $(bash_completion_source) + CLEANFILES = $(bash_completion_script) config.log +-bashcompletiondir = $(sysconfdir)/bash_completion.d ++bashcompletiondir = $(sysconfdir)/default/bash_completion.d + bashcompletion_DATA = $(bash_completion_script) + all: all-am + diff -Paur --no-dereference -- grub.upstream/util/getroot.c grub/util/getroot.c --- grub.upstream/util/getroot.c +++ grub/util/getroot.c @@ -707,23 +712,6 @@ diff -Paur --no-dereference -- grub.upstream/util/getroot.c grub/util/getroot.c #else /* Linux counts partitions uniformly, whether a BSD partition or a DOS -diff -Paur --no-dereference -- grub.upstream/util/grub.d/00_header.in grub/util/grub.d/00_header.in ---- grub.upstream/util/grub.d/00_header.in -+++ grub/util/grub.d/00_header.in -@@ -27,6 +27,13 @@ - - . "$pkgdatadir/grub-mkconfig_lib" - -+if [ -f "/etc/grubpw" ]; then -+ echo 'insmod password_pbkdf2' -+ echo 'set superusers="root"' -+ echo "password_pbkdf2 root $(cat /etc/grubpw)" -+ echo -+fi -+ - # Do this as early as possible, since other commands might depend on it. - # (e.g. the `loadfont' command might need lvm or raid modules) - for i in ${GRUB_PRELOAD_MODULES} ; do diff -Paur --no-dereference -- grub.upstream/util/grub-fstest.c grub/util/grub-fstest.c --- grub.upstream/util/grub-fstest.c +++ grub/util/grub-fstest.c @@ -739,7 +727,15 @@ diff -Paur --no-dereference -- grub.upstream/util/grub-fstest.c grub/util/grub-f diff -Paur --no-dereference -- grub.upstream/util/grub-mkconfig.in grub/util/grub-mkconfig.in --- grub.upstream/util/grub-mkconfig.in +++ grub/util/grub-mkconfig.in -@@ -102,27 +102,6 @@ +@@ -38,6 +38,7 @@ + + grub_cfg="" + grub_mkconfig_dir="${sysconfdir}"/grub.d ++grub_mkconfig_default_dir="${sysconfdir}"/default/grub.d + + self=`basename $0` + +@@ -102,27 +103,6 @@ esac done @@ -767,6 +763,196 @@ diff -Paur --no-dereference -- grub.upstream/util/grub-mkconfig.in grub/util/gru set $grub_probe dummy if test -f "$1"; then : +@@ -147,8 +127,8 @@ + GRUB_FS="$(stat -f --printf=%T / || echo unknown)" + fi + +-if test -f ${sysconfdir}/default/grub ; then +- . ${sysconfdir}/default/grub ++if test -f ${sysconfdir}/grub ; then ++ . ${sysconfdir}/grub + fi + + # XXX: should this be deprecated at some point? +@@ -211,6 +191,7 @@ + GRUB_CMDLINE_NETBSD \ + GRUB_CMDLINE_NETBSD_DEFAULT \ + GRUB_CMDLINE_GNUMACH \ ++ GRUB_CMDLINE_SORTIX \ + GRUB_TERMINAL_INPUT \ + GRUB_TERMINAL_OUTPUT \ + GRUB_SERIAL_COMMAND \ +@@ -243,12 +224,23 @@ + # DO NOT EDIT THIS FILE + # + # It is automatically generated by $self using templates +-# from ${grub_mkconfig_dir} and settings from ${sysconfdir}/default/grub ++# from ${grub_mkconfig_dir} and ${grub_mkconfig_default_dir} ++# and settings from ${sysconfdir}/grub + # + EOF + +- +-for i in "${grub_mkconfig_dir}"/* ; do ++# PATCH: /etc/grub.d overrides /etc/default/grub.d, although it's unsupported to ++# override the 10_sortix file and /etc/grub should be used if possible. ++for n in $({ if [ -d "${grub_mkconfig_dir}" ]; then ++ ls -- "${grub_mkconfig_dir}" ++ fi ++ if [ -d "${grub_mkconfig_default_dir}" ]; then ++ ls -- "${grub_mkconfig_default_dir}" ++ fi; } | LC_ALL=C sort -u); do ++ i="${grub_mkconfig_dir}/$n" ++ if [ ! -f "$i" -a -f "${grub_mkconfig_default_dir}/$n" ]; then ++ i="${grub_mkconfig_default_dir}/$n" ++ fi + case "$i" in + # emacsen backup files. FIXME: support other editors + *~) ;; +@@ -269,7 +261,7 @@ + if ! ${grub_script_check} ${grub_cfg}.new; then + # TRANSLATORS: %s is replaced by filename + gettext_printf "Syntax errors are detected in generated GRUB config file. +-Ensure that there are no errors in /etc/default/grub ++Ensure that there are no errors in /etc/grub + and /etc/grub.d/* files or please file a bug report with + %s file attached." "${grub_cfg}.new" >&2 + echo >&2 +diff -Paur --no-dereference -- grub.upstream/util/grub.d/00_header.in grub/util/grub.d/00_header.in +--- grub.upstream/util/grub.d/00_header.in ++++ grub/util/grub.d/00_header.in +@@ -27,6 +27,13 @@ + + . "$pkgdatadir/grub-mkconfig_lib" + ++if [ -f "/etc/grubpw" ]; then ++ echo 'insmod password_pbkdf2' ++ echo 'set superusers="root"' ++ echo "password_pbkdf2 root $(cat /etc/grubpw)" ++ echo ++fi ++ + # Do this as early as possible, since other commands might depend on it. + # (e.g. the `loadfont' command might need lvm or raid modules) + for i in ${GRUB_PRELOAD_MODULES} ; do +diff -Paur --no-dereference -- grub.upstream/util/grub.d/10_sortix.in grub/util/grub.d/10_sortix.in +--- grub.upstream/util/grub.d/10_sortix.in ++++ grub/util/grub.d/10_sortix.in +@@ -0,0 +1,92 @@ ++#!/bin/sh ++ ++set -e ++ ++rm -f "$0.cache.new" ++ ++# This script will run on the previous stable release during a sysmerge(8) with ++# a potentially old version of GRUB installed. ++ ++# Detect if a system upgrade is ready and emit a bootloader entry using the new ++# script if we're not already it. This script provides a stable interface where ++# the new release helps the old system figure out how to boot the new system. ++PREFIX= ++BOOT_DIR=/boot ++UPGRADE=false ++if [ "$1" = --sysmerge ]; then ++ PREFIX=/sysmerge ++ BOOT_DIR=/boot/sysmerge ++ UPGRADE=true ++elif [ -e /sysmerge/tix/sysmerge.ready ]; then ++ # Write the upgrade menu entry before the old menu entry. ++ /sysmerge/libexec/sysmerge/grub --sysmerge > "$0.cache.new" ++fi ++ ++# Allow this script to be run standalone outside of grub-mkconfig. ++if [ -z "$pkgdatadir" -a -f /etc/grub ]; then ++ . /etc/grub ++fi ++ ++if [ ! -e "$PREFIX/etc/sortix-release" ]; then ++ exit 0 ++fi ++. "$PREFIX/etc/sortix-release" ++ ++if $UPGRADE; then ++ PRETTY_NAME="Upgrade to $PRETTY_NAME" ++fi ++ ++find_mountpoint() {( ++ FILE="$1" ++ DEVICE=$(grub-probe -t device -- "$FILE") ++ while [ "$FILE" != "/" ]; do ++ PARENT="$(dirname -- "$FILE")" ++ if [ x"$(grub-probe -t device -- "$PARENT")" != x"$DEVICE" ]; then ++ echo "$FILE" ++ exit 0 ++ fi ++ FILE="$PARENT" ++ done ++ echo "$FILE" ++ exit 0 ++)} ++ ++mountpoint_relative() {( ++ REL="" ++ FILE="$1" ++ DEVICE=$(grub-probe -t device -- "$FILE") ++ while [ "$FILE" != "/" ]; do ++ PARENT="$(dirname -- "$FILE")" ++ if [ x"$(grub-probe -t device -- "$PARENT")" != x"$DEVICE" ]; then ++ echo "$REL" ++ exit 0 ++ fi ++ REL="/$(basename -- "$FILE")$REL" ++ FILE="$PARENT" ++ done ++ echo "$REL" ++ exit 0 ++)} ++ ++BOOT_MNT=$(find_mountpoint /boot) ++BOOT_REL=$(mountpoint_relative "$BOOT_DIR") ++OLD_BOOT_REL=$(mountpoint_relative /boot) ++DEVICE=$(grub-probe -t device -- "$BOOT_MNT") ++FS_UUID=$(grub-probe -t fs_uuid -- "$BOOT_MNT") ++HINTS_STRING=$(grub-probe -t hints_string -- "$BOOT_MNT") ++PARTMAP=$(grub-probe -t partmap -- "$BOOT_MNT") ++FS=$(grub-probe -t fs -- "$BOOT_MNT") ++ ++echo "Found $PRETTY_NAME on $DEVICE" >&2 ++cat >> "$0.cache.new" << EOF ++menuentry "$PRETTY_NAME (on $DEVICE)" --unrestricted { ++ insmod part_$PARTMAP ++ insmod $FS ++ search --no-floppy --fs-uuid --set=root $HINTS_STRING $FS_UUID ++ multiboot $BOOT_REL/sortix.bin $GRUB_CMDLINE_SORTIX ++ module $OLD_BOOT_REL/random.seed --random-seed ++ module $BOOT_REL/sortix.initrd ++} ++EOF ++mv "$0.cache.new" "$0.cache" ++cat "$0.cache" +diff -Paur --no-dereference -- grub.upstream/util/grub.d/README grub/util/grub.d/README +--- grub.upstream/util/grub.d/README ++++ grub/util/grub.d/README +@@ -1,11 +1,15 @@ +- +-All executable files in this directory are processed in shell expansion order. ++All executable files in /etc/grub.d and /etc/grub.d/default are processed in ++shell expansion order. + + 00_*: Reserved for 00_header. + 10_*: Native boot entries. + 20_*: Third party apps (e.g. memtest86+). + ++Files in /etc/grub.d override files in /etc/grub.d/default if they exist. It is ++unsupported to override the native bootloader file 10_sortix since the ++configuration will be updated across releases ++ + The number namespace in-between is configurable by system installer and/or + administrator. For example, you can add an entry to boot another OS as + 01_otheros, 11_otheros, etc, depending on the position you want it to occupy in +-the menu; and then adjust the default setting via /etc/default/grub. ++the menu; and then adjust the default setting via /etc/grub. diff -Paur --no-dereference -- grub.upstream/util/misc.c grub/util/misc.c --- grub.upstream/util/misc.c +++ grub/util/misc.c diff --git a/ports/grub/grub.post-install b/ports/grub/grub.post-install index 827f136f..ffa35618 100755 --- a/ports/grub/grub.post-install +++ b/ports/grub/grub.post-install @@ -1,6 +1,5 @@ #!/bin/sh -e cp update-grub "$TIX_INSTALL_DIR$EXEC_PREFIX/sbin/update-grub" -cp 10_sortix "$TIX_INSTALL_DIR$PREFIX/etc/grub.d/10_sortix" if [ ! -e "$TIX_INSTALL_DIR$PREFIX/share/grub/unicode.pf2" ]; then # Cheat as I'm not sure how to get this when cross-building. [ -e /share/grub/unicode.pf2 ] && diff --git a/share/man/man5/upgrade.conf.5 b/share/man/man5/upgrade.conf.5 index 93956581..c0db9a6e 100644 --- a/share/man/man5/upgrade.conf.5 +++ b/share/man/man5/upgrade.conf.5 @@ -90,7 +90,7 @@ and if is set to .Sy no , then regenerate -.Pa /etc/grub.d/10_sortix.cache . +.Pa /etc/default/grub.d/10_sortix.cache . .El .Pp The defaults will be used if diff --git a/share/man/man7/following-development.7 b/share/man/man7/following-development.7 index c3364cc5..314ebff2 100644 --- a/share/man/man7/following-development.7 +++ b/share/man/man7/following-development.7 @@ -69,6 +69,74 @@ releasing Sortix x.y, foo." to allow the maintainer to easily .Xr grep 1 for it after a release. .Sh CHANGES +.Ss Support system upgrades and configuration in GRUB +The GRUB configuration now implements the +.Pa /etc +and +.Pa /etc/default +configuration split per +.Xr hier 7 +and +.Xr sysmerge 8 +now collaborates with system upgrades to boot them correctly. +Installations with manually configured bootloaders may need updating. +.Pp +Notably +.Pa /etc/default/grub +has been moved to +.Pa /etc/grub +since it is owned by the system administrator and there is no counterpart with +operating system provided defaults. +.Pp +Additionally +.Pa /etc/grub.d +has been moved into +.Pa /etc/default/grub.d +since it provides operating system defaults. +The system administrator can now create the +.Pa /etc/grub.d +directory manually to override files in +.Pa /etc/default/grub.d , +although overriding +.Pa 10_sortix +is unsupported. +.Pp +.Pa 10_sortix +now supports the +.Pa GRUB_CMDLINE_SORTIX +variable in +.Pa /etc/grub +to specify kernel command line options. +.Pp +.Xr sysmerge 8 +now colloborates with the +.Xr update-initrd 8 +and +.Pa 10_sortix +scripts in the new system to prepare the upgrade system's kernel files in +.Pa /boot/sysmerge/ . +If the GRUB bootloader is accepted, then +.Pa /boot/grub/grub.cfg +is regenerated with a menu entry to perform the upgrade. +The +.Pa /boot/sortix.bin +and +.Pa /boot/sortix.initrd +files are no longer replaced with the new versions and continue to boot the old +system without upgrading. +Any manual bootloader configuration must be configured to instead load the +kernel and initrd from +.Pa /boot/sysmerge/ +(if they exist). +The +.Pa /etc/default/grub.d/10_sortix.cache +file will demonstrate how to boot the new system using GRUB after starting a +.Xr sysmerge 8 +(if the grub port is installed). +.Pp +An upgrade hook will delete the obsolete stale +.Pa /etc/grub.d/10_sortix.cache +file. .Ss Third generation Tix The tix binary package format has upgraded from generation 2 to 3 and has a new internal layout that can be directly extracted into the filesystem. @@ -315,7 +383,7 @@ The kernel will issue a security warning if it was booted without a random seed, unless the kernel command line contains .Fl \-no-random-seed . The GRUB port has been updated with an improved -.Pa /etc/grub.d/10_sortix +.Pa /etc/default/grub.d/10_sortix script that will automatically emit the appropriate GRUB commands. .Pp Users using the included GRUB will need to update to the latest GRUB port @@ -341,9 +409,9 @@ If the GRUB port is installed, but not used, then if that port is updated with or .Xr sysmerge 8 or manually, the -.Pa /etc/grub.d/10_sortix +.Pa /etc/default/grub.d/10_sortix script can be invoked, which will generate a -.Pa /etc/grub.d/10_sortix.cache +.Pa /etc/default/grub.d/10_sortix.cache fragment that can be spliced into the configuration of another GRUB installation. .Pp diff --git a/share/man/man7/hier.7 b/share/man/man7/hier.7 index 953b60b0..5d0c916d 100644 --- a/share/man/man7/hier.7 +++ b/share/man/man7/hier.7 @@ -6,7 +6,7 @@ .Nd layout of filesystems .Sh DESCRIPTION The filesystem hierarchy is as follows: -.Bl -tag -width "1234567891012" +.Bl -tag -width "/boot/sysmerge" .It Pa / Root directory. .It Pa /bin @@ -16,6 +16,10 @@ Boot programs, .Xr kernel 7 , .Xr initrd 7 , bootloader. +.It Pa /boot/sysmerge +Temporary area for +.Xr sysmerge 8 +delayed upgrades. .It Pa /dev Devices. .It Pa /etc diff --git a/share/man/man7/installation.7 b/share/man/man7/installation.7 index b4f36f1b..2d0f008d 100644 --- a/share/man/man7/installation.7 +++ b/share/man/man7/installation.7 @@ -529,7 +529,7 @@ If the included GRUB bootloader is used, after making the above edit, run .Xr update-grub 8 within the new installation to regenerate the bootloader configuration. Note that -.Pa /etc/grub.d/10_sortix +.Pa /etc/default/grub.d/10_sortix is part of the GRUB package and local changes will be undone when the GRUB package is updated or reinstalled, in which case you must make this change again and run @@ -537,12 +537,12 @@ and run again. .Pp If the included GRUB bootloader is not used, but instead the -.Pa /etc/grub.d/10_sortix.cache +.Pa /etc/default/grub.d/10_sortix.cache fragment is spliced into another GRUB installation, make the above change and then run the -.Pa /etc/grub.d/10_sortix +.Pa /etc/default/grub.d/10_sortix command and use the freshly regenerated -.Pa /etc/grub.d/10_sortix.cache +.Pa /etc/default/grub.d/10_sortix.cache fragment instead. .Sh SEE ALSO .Xr chkblayout 1 , diff --git a/share/sysinstall/hooks/sortix-1.1-grub-cache b/share/sysinstall/hooks/sortix-1.1-grub-cache new file mode 100644 index 00000000..e69de29b diff --git a/sysinstall/Makefile b/sysinstall/Makefile index d4b5aa2f..2f18a750 100644 --- a/sysinstall/Makefile +++ b/sysinstall/Makefile @@ -46,6 +46,9 @@ install: all install sysinstall $(DESTDIR)$(SBINDIR) install sysmerge $(DESTDIR)$(SBINDIR) install sysupgrade $(DESTDIR)$(SBINDIR) + mkdir -p $(DESTDIR)$(LIBEXECDIR)/sysmerge + install prepare $(DESTDIR)$(LIBEXECDIR)/sysmerge + install grub $(DESTDIR)$(LIBEXECDIR)/sysmerge mkdir -p $(DESTDIR)$(MANDIR)/man8 cp sysinstall.8 $(DESTDIR)$(MANDIR)/man8/sysinstall.8 cp sysmerge.8 $(DESTDIR)$(MANDIR)/man8/sysmerge.8 @@ -59,6 +62,7 @@ install: all touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-passwd touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-group touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-tix3g + touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-grub-cache sysinstall: $(SYSINSTALL_OBJS) $(CC) $(SYSINSTALL_OBJS) -o $@ -lmount -ldisplay diff --git a/sysinstall/grub b/sysinstall/grub new file mode 100755 index 00000000..27afce28 --- /dev/null +++ b/sysinstall/grub @@ -0,0 +1,29 @@ +#!/bin/sh +# Copyright (c) 2023 Jonas 'Sortie' Termansen. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# grub +# Output the GRUB configuration needed to boot the sysmerge(8) --wait upgrade. + +# This script will run on the previous stable release during a sysmerge(8) as a +# high-level entry point to help the previous system generate the grub config to +# boot the new system. This script minimizes the interface between the old and +# new system to allow change. This script is ordinarily invoked by 10_sortix +# from the grub port. + +set -e + +# The old system has copied the new kernel and initrd files from /sysmerge/boot +# to /boot/sysmerge and we need to configure grub to boot them. +/sysmerge/etc/default/grub.d/10_sortix --sysmerge diff --git a/sysinstall/hooks.c b/sysinstall/hooks.c index 6d733bf3..8a7bcad4 100644 --- a/sysinstall/hooks.c +++ b/sysinstall/hooks.c @@ -463,6 +463,28 @@ void upgrade_prepare(const struct release* old_release, // Delay deleting installed.list since it's needed for the upgrade. hook_want_finalization(target_prefix, "sortix-1.1-tix3g"); } + + // TODO: After releasing Sortix 1.1, remove this compatibility. + if ( hook_needs_to_be_run(source_prefix, target_prefix, + "sortix-1.1-grub-cache") ) + { + char* path = join_paths(target_prefix, "/etc/grub.d/10_sortix.cache"); + if ( !path ) + { + warn("malloc"); + _exit(2); + } + if ( !access_or_die(path, F_OK) ) + { + printf(" - Removing /etc/grub.d/10_sortix.cache...\n"); + if ( unlink(path) < 0 ) + { + warn("unlink: %s", path); + _exit(2); + } + } + free(path); + } } void upgrade_finalize(const struct release* old_release, diff --git a/sysinstall/prepare b/sysinstall/prepare new file mode 100755 index 00000000..ece6a242 --- /dev/null +++ b/sysinstall/prepare @@ -0,0 +1,27 @@ +#!/bin/sh +# Copyright (c) 2023 Jonas 'Sortie' Termansen. +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# prepare +# Prepare a sysmerge(8) --wait upgrade on the next boot. + +# This script will run on the previous stable release during a sysmerge(8) as a +# high-level entry point to help the previous system generate the kernel and +# initrd files for the new system. This script minimizes the interface between +# the old and new system to allow change. The working directory is the directory +# the sysmerge upgrade is pending inside, usually /sysmerge. + +set -e + +/sysmerge/sbin/update-initrd --sysmerge diff --git a/sysinstall/sysinstall.c b/sysinstall/sysinstall.c index 832c9c1b..b87eec42 100644 --- a/sysinstall/sysinstall.c +++ b/sysinstall/sysinstall.c @@ -991,12 +991,13 @@ int main(void) execute((const char*[]) { "chroot", "-d", ".", "update-grub", NULL }, "_eqQ"); } - else if ( access_or_die("/etc/grub.d/10_sortix", F_OK) == 0 ) + else if ( access_or_die("/etc/default/grub.d/10_sortix", F_OK) == 0 ) { - // Help dual booters by making /etc/grub.d/10_sortix.cache. + // Help dual booters by making /etc/grub.d/default/10_sortix.cache. printf(" - Creating bootloader fragment...\n"); execute((const char*[]) { "chroot", "-d", ".", - "/etc/grub.d/10_sortix", NULL }, "_eq"); + "/etc/grub.d/default/10_sortix", + NULL }, "_eq"); } printf(" - Finishing installation...\n"); _exit(0); @@ -1530,8 +1531,9 @@ int main(void) if ( strcasecmp(accept_grub, "no") == 0 ) text("You did not accept a bootloader and need to set up bootloading " - "yourself. /etc/grub.d/10_sortix.cache is a GRUB configuration " - "fragment that boots the newly installed system.\n\n"); + "yourself. /etc/default/grub.d/10_sortix.cache is a GRUB " + "configuration fragment that boots the newly installed system." + "\n\n"); text("Upon boot, you'll be greeted with a login screen. Enter your " "credentials to get a command line. Login as user 'poweroff' as " diff --git a/sysinstall/sysmerge.8 b/sysinstall/sysmerge.8 index 72c483da..260c2c6f 100644 --- a/sysinstall/sysmerge.8 +++ b/sysinstall/sysmerge.8 @@ -124,52 +124,50 @@ This option is implied unless is passed. .It Fl w , Fl \-wait Wait until the next boot to complete the upgrade, rather than finishing it now. -This installs into the +The upgrade is installed into the .Pa /sysmerge -directory instead and replaces the +directory instead, with the new kernel and initrd files in +.Pa /boot/sysmerge . +The new .Xr kernel 7 -with the new kernel -and +has a new .Xr initrd 7 -with an initrd that runs +that runs .Sy /sysmerge/sbin/sysmerge --booting on boot through the .Sy chain-merge .Xr init 8 -boot target. -Backups are made of the -.Xr kernel 7 -and -.Xr initrd 7 -such that the operation can be rolled back. +boot target, which performs the operating system upgrade. +The bootloader configuration is regenerated with a menu option to perform +the upgrade if grub is enabled in +.Xr upgrade.conf 5 , +otherwise the +.Pa /etc/default/grub.d/10_sortix.cache +bootloader fragment can be used to manually bootload the upgrade. .El .Sh FILES -.Bl -tag -width "/boot/sortix.initrd.sysmerge.orig" -compact +.Bl -tag -width "/etc/default/grub.d/10_sortix.cache" -compact .It Pa /boot/sortix.bin -system -.Xr kernel 7 -.It Pa /boot/sortix.bin.sysmerge.orig -system -.Xr kernel 7 -(backup) +Old system +.Xr kernel 7 . .It Pa /boot/sortix.initrd -system -.Xr initrd 7 -.It Pa /boot/sortix.initrd.sysmerge.orig -system -.Xr initrd 7 -(backup) +Old system +.Xr initrd 7 . +.It Pa /boot/sysmerge/ +New system kernel and initrd files. +.It Pa /etc/default/grub.d/10_sortix.cache +GRUB configuration fragment that boots the new system. .It Pa /etc/machine -processor platform of this installation +Processor platform of this installation. .It Pa /etc/sortix-release -the current system release +The current system release. .It Pa /etc/upgrade.conf -controls the bootloader upgrade behavior (see -.Xr upgrade.conf 5 ) -.It Pa /share/sysinstall/hooks +Controls the bootloader upgrade behavior (see +.Xr upgrade.conf 5 ) . +.It Pa /share/sysinstall/hooks/ A file per upgrade hook indicating that it doesn't need to be run. -.It Pa /sysmerge -pending upgrade is stored here +.It Pa /sysmerge/ +The pending systen upgrade is stored here. .El .Sh SEE ALSO .Xr development 7 , diff --git a/sysinstall/sysmerge.c b/sysinstall/sysmerge.c index 27d31d1b..0ed71b1f 100644 --- a/sysinstall/sysmerge.c +++ b/sysinstall/sysmerge.c @@ -86,20 +86,32 @@ static bool is_partition_name(const char* path) static bool has_pending_upgrade(const char* target) { - char* kernel = join_paths(target, "boot/sortix.bin.sysmerge.orig"); - char* initrd = join_paths(target, "boot/sortix.initrd.sysmerge.orig"); char* sysmerge = join_paths(target, "sysmerge"); - if ( !kernel || !initrd || !sysmerge ) + char* boot_sysmerge = join_paths(target, "boot/sysmerge"); + if ( !sysmerge || !boot_sysmerge ) err(2, "malloc"); - bool result = access_or_die(kernel, F_OK) == 0 || - access_or_die(initrd, F_OK) == 0 || - access_or_die(sysmerge, F_OK) == 0; - free(kernel); - free(initrd); + bool result = access_or_die(sysmerge, F_OK) == 0 || + access_or_die(boot_sysmerge, F_OK) == 0; free(sysmerge); + free(boot_sysmerge); return result; } +static void update_grub(struct conf* conf, const char* target) +{ + if ( conf->grub ) + { + printf(" - Configuring bootloader...\n"); + execute((const char*[]) { "update-grub", NULL }, "ceqQ", target); + } + else if ( access_or_die("/etc/default/grub.d/10_sortix", F_OK) == 0 ) + { + printf(" - Creating bootloader fragment...\n"); + execute((const char*[]) { "/etc/default/grub.d/10_sortix", NULL }, + "ceq", target); + } +} + int main(int argc, char* argv[]) { setvbuf(stdout, NULL, _IOLBF, 0); // Pipes. @@ -207,20 +219,24 @@ int main(int argc, char* argv[]) if ( !has_system ) system = false; + struct conf conf; + conf_init(&conf); + char* conf_path = join_paths(target, "etc/upgrade.conf"); + if ( !conf_path ) + err(2, "malloc"); + if ( !conf_load(&conf, conf_path) && errno != ENOENT ) + err(2, conf_path); + bool did_cancel = false; if ( !no_cancel && has_pending_upgrade(target) ) { - char* kernel = join_paths(target, "boot/sortix.bin.sysmerge.orig"); - char* kernel_real = join_paths(target, "boot/sortix.bin"); - char* initrd = join_paths(target, "boot/sortix.initrd.sysmerge.orig"); - char* initrd_real = join_paths(target, "boot/sortix.initrd"); char* sysmerge = join_paths(target, "sysmerge"); - if ( !kernel || !kernel_real || !initrd || !initrd_real || !sysmerge ) + char* boot_sysmerge = join_paths(target, "boot/sysmerge"); + if ( !sysmerge || !boot_sysmerge ) err(2, "malloc"); - rename(kernel, kernel_real); - rename(initrd, initrd_real); execute((const char*[]) { "rm", "-rf", "--", sysmerge, NULL }, ""); - execute((const char*[]) { "update-initrd", NULL }, "ce", target); + execute((const char*[]) { "rm", "-rf", "--", boot_sysmerge, NULL }, ""); + update_grub(&conf, target); printf("Cancelled pending system upgrade.\n"); did_cancel = true; } @@ -290,14 +306,6 @@ int main(int argc, char* argv[]) // TODO: Check for version (skipping, downgrading). - struct conf conf; - conf_init(&conf); - char* conf_path = join_paths(target, "etc/upgrade.conf"); - if ( !conf_path ) - err(2, "malloc"); - if ( !conf_load(&conf, conf_path) && errno != ENOENT ) - err(2, conf_path); - bool can_run_new_abi = abi_compatible(new_release.abi_major, new_release.abi_minor, old_release.abi_major, old_release.abi_minor); @@ -416,14 +424,13 @@ int main(int argc, char* argv[]) char* system_path = join_paths(target, "sysmerge/tix/sysmerge.system"); char* ports_path = join_paths(target, "sysmerge/tix/sysmerge.ports"); char* full_path = join_paths(target, "sysmerge/tix/sysmerge.full"); - char* kernel = join_paths(target, "boot/sortix.bin.sysmerge.orig"); - char* kernel_real = join_paths(target, "boot/sortix.bin"); - char* kernel_new = join_paths(target, "sysmerge/boot/sortix.bin"); - char* initrd = join_paths(target, "boot/sortix.initrd.sysmerge.orig"); - char* initrd_real = join_paths(target, "boot/sortix.initrd"); - if ( !system_path || !ports_path || !full_path || !kernel || - !kernel_real || !kernel_new || !initrd || !initrd_real ) + char* ready_path = join_paths(target, "sysmerge/tix/sysmerge.ready"); + char* sysmerge_boot = join_paths(target, "sysmerge/boot"); + char* boot_sysmerge = join_paths(target, "boot/sysmerge"); + if ( !system_path || !ports_path || !full_path || !ready_path || + !sysmerge_boot || !boot_sysmerge ) err(2, "malloc"); + if ( full ) { int fd = open(full_path, O_WRONLY | O_CREAT); @@ -445,11 +452,25 @@ int main(int argc, char* argv[]) err(2, "%s", ports_path); close(fd); } - execute((const char*[]) { "cp", kernel_real, kernel, NULL }, "e"); - execute((const char*[]) { "cp", initrd_real, initrd, NULL }, "e"); - execute((const char*[]) { "cp", kernel_new, kernel_real, NULL }, "e"); - execute((const char*[]) { "/sysmerge/sbin/update-initrd", NULL }, "ce", - target); + + // Generate the new initrd in /sysmerge/boot. + execute((const char*[]) { "/sysmerge/libexec/sysmerge/prepare", + NULL }, "ce", target); + + // Move the kernel and initrd files to the boot partition where the + // bootloader is guaranteed to be able to read them. + execute((const char*[]) { "rm", "-rf", "--", boot_sysmerge, + NULL }, "e"); + execute((const char*[]) { "cp", "-RT", "--", sysmerge_boot, + boot_sysmerge, NULL }, "e"); + + // Signal the sysmerge upgrade is ready and isn't partial. + int fd = open(ready_path, O_WRONLY | O_CREAT); + if ( fd < 0 ) + err(2, "%s", ready_path); + close(fd); + + update_grub(&conf, target); printf("The system will be upgraded to %s on the next boot.\n", new_release.pretty_name); @@ -477,21 +498,20 @@ int main(int argc, char* argv[]) return 0; } + // Remove the upgrade readiness marker now that the upgrade has gone through + // such that the bootloader configuration and initrds don't try to do the + // upgrade again. if ( has_system && booting ) { - char* kernel = join_paths(target, "boot/sortix.bin.sysmerge.orig"); - char* initrd = join_paths(target, "boot/sortix.initrd.sysmerge.orig"); - char* sysmerge = join_paths(target, "sysmerge"); - if ( !kernel || !initrd || !sysmerge ) + char* ready_path = join_paths(target, "sysmerge/tix/sysmerge.ready"); + if ( !ready_path ) err(2, "malloc"); - unlink(kernel); - unlink(initrd); - execute((const char*[]) { "rm", "-rf", "--", sysmerge, NULL }, ""); - free(kernel); - free(initrd); - free(sysmerge); + unlink(ready_path); + free(ready_path); } + // Update the initrd and bootloader. The new bootloader config won't refer + // to the upgrade as it's complete and the marker is gone. if ( has_system && access_or_die("/etc/fstab", F_OK) == 0 ) { printf(" - Creating initrd...\n"); @@ -510,23 +530,40 @@ int main(int argc, char* argv[]) err(2, "Failed to find device of filesystem: %s", boot_path); close(boot_fd); free(boot_path); - // TODO: A better design for finding the parent block device of a - // partition without scanning every block device. + // TODO: A better design for finding the parent block device. if ( is_partition_name(boot_device) ) *strrchr(boot_device, 'p') = '\0'; printf(" - Installing bootloader...\n"); execute((const char*[]) { "grub-install", boot_device, - NULL }, "ceqQ", target); + NULL }, "ceqQ", target); free(boot_device); - printf(" - Configuring bootloader...\n"); - execute((const char*[]) { "update-grub", NULL }, "ceqQ", target); - } - else if ( access_or_die("/etc/grub.d/10_sortix", F_OK) == 0 ) - { - printf(" - Creating bootloader fragment...\n"); - execute((const char*[]) { "/etc/grub.d/10_sortix", NULL }, "ceq", - target); } + + update_grub(&conf, target); + } + + // Finally clean up /sysmerge and /boot/sysmerge. They were left alone so + // the system remained bootable with the idempotent upgrade if it failed + // midway. Okay there's a bit of race conditions in grub-install, though the + // replacement of grub.cfg is atomic. Everything now points into the new + // system and nothing refers to the sysmerge directories. + if ( has_system && booting ) + { + // TODO: After releasing Sortix 1.1, remove sysmerge.orig compatibility. + char* kernel = join_paths(target, "boot/sortix.bin.sysmerge.orig"); + char* initrd = join_paths(target, "boot/sortix.initrd.sysmerge.orig"); + char* sysmerge = join_paths(target, "sysmerge"); + char* boot_sysmerge = join_paths(target, "boot/sysmerge"); + if ( !kernel || !initrd || !sysmerge || !boot_sysmerge ) + err(2, "malloc"); + unlink(kernel); + unlink(initrd); + execute((const char*[]) { "rm", "-rf", "--", sysmerge, NULL }, ""); + execute((const char*[]) { "rm", "-rf", "--", boot_sysmerge, NULL }, ""); + free(kernel); + free(initrd); + free(sysmerge); + free(boot_sysmerge); } if ( new_release.pretty_name ) diff --git a/sysinstall/sysupgrade.c b/sysinstall/sysupgrade.c index 9a0f4251..fcf71f79 100644 --- a/sysinstall/sysupgrade.c +++ b/sysinstall/sysupgrade.c @@ -920,12 +920,13 @@ int main(void) "_eqQ"); } else if ( conf.system && - access_or_die("etc/grub.d/10_sortix", F_OK) == 0 ) + access_or_die("etc/default/grub.d/10_sortix", F_OK) == 0 ) { - // Help dual booters by making /etc/grub.d/10_sortix.cache. + // Help dual booters by making /etc/default/grub.d/10_sortix.cache. printf(" - Creating bootloader fragment...\n"); execute((const char*[]) { "chroot", "-d", ".", - "/etc/grub.d/10_sortix", NULL }, "_eq"); + "/etc/grub.d/default/10_sortix", NULL }, + "_eq"); } printf(" - Finishing upgrade...\n"); _exit(0); diff --git a/update-initrd/update-initrd b/update-initrd/update-initrd index 0d767eec..51b5e1d2 100755 --- a/update-initrd/update-initrd +++ b/update-initrd/update-initrd @@ -16,9 +16,12 @@ # update-initrd # Generate an initrd(7) that locates and chain boots the real root filesystem. +# This script will run on the previous stable release during a sysmerge(8). + set -e sysroot= +sysmerge=false dashdash= previous_option= @@ -35,6 +38,7 @@ for argument do esac case $dashdash$argument in --) dashdash=yes ;; + --sysmerge) sysmerge=true ;; --sysroot=*) sysroot=$parameter ;; --sysroot) previous_option=sysroot ;; -*) echo "$0: unrecognized option $argument" >&2 @@ -49,17 +53,20 @@ if test -n "$previous_option"; then exit 1 fi -sysmerge=false -exec_prefix="$sysroot" -if [ -d "$sysroot/sysmerge" ]; then - # If an upgrade is pending, invoke the update-initrd of the new system, if - # we're not already it. - if [ "$(realpath -- "$(which -- "$0")")" != \ - "$(realpath -- "$sysroot/sysmerge/sbin/update-initrd")" ]; then - exec "$sysroot/sysmerge/sbin/update-initrd" "$@" - fi +root="$sysroot" +output="$sysroot" +if $sysmerge; then + root="$sysroot/sysmerge" + output="$root" +# TODO: After releasing Sortix 1.1, remove the check for /sysmerge as the old +# update-initrd will invoke the newer version and expect the new version +# to notice that it is the version in /sysmerge. However, write the new +# initrd to /boot rather than /sysmerge/boot since 1.0 doesn't implement +# the new scheme. +elif [ -e /sysmerge -a "$0" = /sysmerge/sbin/update-initrd ]; then sysmerge=true - exec_prefix="$sysroot/sysmerge" + root="$sysroot/sysmerge" + output="$sysroot" fi if [ ! -e "$sysroot/etc/fstab" ]; then echo "$0: $sysroot/etc/fstab: Need a filesystem table to make an initrd" >&2 @@ -69,10 +76,10 @@ tmp=$(mktemp -d) trap 'rm -rf "$tmp"' EXIT HUP INT QUIT TERM mkdir "$tmp/bin" mkdir "$tmp/sbin" -cp "$exec_prefix/sbin/init" "$tmp/sbin" -cp "$exec_prefix/sbin/extfs" "$tmp/sbin" -test -f "$exec_prefix/sbin/fsck.ext2" && -cp "$exec_prefix/sbin/fsck.ext2" "$tmp/sbin" +cp "$root/sbin/init" "$tmp/sbin" +cp "$root/sbin/extfs" "$tmp/sbin" +test -f "$root/sbin/fsck.ext2" && +cp "$root/sbin/fsck.ext2" "$tmp/sbin" mkdir "$tmp/etc" cp "$sysroot/etc/fstab" "$tmp/etc/fstab" mkdir "$tmp/etc/init" @@ -85,7 +92,7 @@ else require chain exit-code EOF fi -mkdir -p "$sysroot/boot" +mkdir -p "$output/boot" LC_AL=C ls -A "$tmp" | -tar -C "$tmp" -cf "$sysroot/boot/sortix.initrd" \ +tar -C "$tmp" -cf "$output/boot/sortix.initrd" \ --numeric-owner --owner=0 --group=0 -T - diff --git a/update-initrd/update-initrd.8 b/update-initrd/update-initrd.8 index bc954ef0..6090c8b6 100644 --- a/update-initrd/update-initrd.8 +++ b/update-initrd/update-initrd.8 @@ -6,6 +6,7 @@ .Nd generate initialization ramdisk .Sh SYNOPSIS .Nm update-initrd +.Op Fl \-sysmerge .Op Fl \-sysroot Ns "=" Ns Ar sysroot .Sh DESCRIPTION .Nm update-initrd @@ -31,19 +32,20 @@ should be regenerated by invoking .Nm . .Pp .Nm -is aware of -.Xr sysmerge 8 -pending upgrades and will instead invoke the new -.Nm -in -.Pa /sysmerge -if an upgrade is pending. -.Nm is written as a script so the initrd of the new system can produced even across incompatible ABI changes. .Pp The options are as follows: .Bl -tag -width "12345678" +.It Fl \-sysmerge +Generate an +.Xr initrd 7 +for the pending upgrade in +.Pa /sysmerge +inside the sysroot. +This must be used in combination with invoking the matching +.Pa /sysmerge/sbin/update-initrd +program directly for forward compatibility. .It Fl \-sysroot Ns "=" Ns Ar sysroot Rather than generating an .Xr initrd 7