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.
This commit is contained in:
Jonas 'Sortie' Termansen 2023-08-07 21:31:59 +02:00
parent c4b878beb7
commit 938f2390dd
18 changed files with 609 additions and 223 deletions

View File

@ -1,2 +1,2 @@
chmod +x -- '10_sortix'
chmod +x -- 'update-grub' chmod +x -- 'update-grub'
chmod +x -- 'util/grub.d/10_sortix.in'

View File

@ -1,77 +1,58 @@
diff -Paur --no-dereference -- grub.upstream/10_sortix grub/10_sortix diff -Paur --no-dereference -- grub.upstream/Makefile.in grub/Makefile.in
--- grub.upstream/10_sortix --- grub.upstream/Makefile.in
+++ grub/10_sortix +++ grub/Makefile.in
@@ -0,0 +1,70 @@ @@ -1212,6 +1212,7 @@
+#!/bin/sh -e util/grub.d/10_kfreebsd.in util/grub.d/10_illumos.in \
+! [ -e /etc/sortix-release ] && exit 0 util/grub.d/10_netbsd.in util/grub.d/10_linux.in \
+. /etc/sortix-release util/grub.d/10_xnu.in util/grub.d/20_linux_xen.in \
+find_mountpoint() {( + util/grub.d/10_sortix.in \
+ FILE="$1" util/grub.d/30_os-prober.in util/grub.d/40_custom.in \
+ DEVICE=$(grub-probe -t device -- "$FILE") util/grub.d/41_custom.in util/grub-mkconfig.in \
+ while [ "$FILE" != "/" ]; do util/grub-set-default.in util/grub-reboot.in \
+ PARENT="$(dirname -- "$FILE")" @@ -2372,7 +2373,7 @@
+ if [ x"$(grub-probe -t device -- "$PARENT")" != x"$DEVICE" ]; then CCASFLAGS_LIBRARY =
+ echo "$FILE"
+ exit 0 # Other variables
+ fi -grubconfdir = $(sysconfdir)/grub.d
+ FILE="$PARENT" +grubconfdir = $(sysconfdir)/default/grub.d
+ done platformdir = $(pkglibdir)/$(target_cpu)-$(platform)
+ echo "$FILE" starfielddir = $(pkgdatadir)/themes/starfield
+ exit 0 CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion
+)} @@ -2440,6 +2441,7 @@
+mountpoint_relative() {( grubconf_SCRIPTS = 00_header $(am__append_57) $(am__append_61) \
+ REL="" $(am__append_65) $(am__append_69) $(am__append_73) \
+ FILE="$1" $(am__append_77) $(am__append_81) $(am__append_85) \
+ DEVICE=$(grub-probe -t device -- "$FILE") + 10_sortix \
+ while [ "$FILE" != "/" ]; do 30_os-prober 40_custom 41_custom
+ PARENT="$(dirname -- "$FILE")" noinst_LIBRARIES = libgrubkern.a libgrubmods.a libgrubgcry.a
+ if [ x"$(grub-probe -t device -- "$PARENT")" != x"$DEVICE" ]; then dist_noinst_DATA = grub-core/kern/disk_common.c \
+ echo "$REL" @@ -2460,6 +2462,7 @@
+ exit 0 util/grub.d/00_header.in $(am__append_60) $(am__append_64) \
+ fi $(am__append_68) $(am__append_72) $(am__append_76) \
+ REL="/$(basename -- "$FILE")$REL" $(am__append_80) $(am__append_84) $(am__append_88) \
+ FILE="$PARENT" + util/grub.d/10_sortix.in \
+ done util/grub.d/30_os-prober.in util/grub.d/40_custom.in \
+ echo "$REL" util/grub.d/41_custom.in util/grub-mkconfig.in \
+ exit 0 util/grub-set-default.in util/grub-reboot.in \
+)} @@ -2640,6 +2643,7 @@
+BOOT_MNT=$(find_mountpoint /boot) $(am__append_62) $(am__append_66) $(am__append_70) \
+BOOT_REL=$(mountpoint_relative /boot) $(am__append_74) $(am__append_78) $(am__append_82) \
+DEVICE=$(grub-probe -t device -- "$BOOT_MNT") $(am__append_86) 30_os-prober 40_custom 41_custom \
+FS_UUID=$(grub-probe -t fs_uuid -- "$BOOT_MNT") + 10_sortix \
+HINTS_STRING=$(grub-probe -t hints_string -- "$BOOT_MNT") $(am__append_89) grub-mkconfig $(am__append_90) \
+PARTMAP=$(grub-probe -t partmap -- "$BOOT_MNT") grub-set-default $(am__append_91) grub-reboot \
+FS=$(grub-probe -t fs -- "$BOOT_MNT") grub-mkconfig_lib $(am__append_92) grub-kbdcomp grub-shell \
+echo "Found $PRETTY_NAME on $DEVICE" >&2 @@ -12086,6 +12090,10 @@
+cat > "$0.cache" << EOF @COND_HOST_XNU_TRUE@ (for x in util/grub.d/10_xnu.in ; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
+menuentry "$PRETTY_NAME (on $DEVICE)" --unrestricted { @COND_HOST_XNU_TRUE@ chmod a+x 10_xnu
+ insmod part_$PARTMAP
+ insmod $FS +10_sortix: $(top_builddir)/config.status util/grub.d/10_sortix.in
+ search --no-floppy --fs-uuid --set=root $HINTS_STRING $FS_UUID + (for x in util/grub.d/10_sortix.in ; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
+ if [ -e $BOOT_REL/sortix.bin.xz ]; then + chmod a+x 10_sortix
+ insmod xzio +
+ multiboot $BOOT_REL/sortix.bin.xz @COND_HOST_LINUX_TRUE@20_linux_xen: $(top_builddir)/config.status util/grub.d/20_linux_xen.in
+ elif [ -e $BOOT_REL/sortix.bin.gz ]; then @COND_HOST_LINUX_TRUE@ (for x in util/grub.d/20_linux_xen.in ; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:-
+ insmod gzio @COND_HOST_LINUX_TRUE@ chmod a+x 20_linux_xen
+ 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/build-aux/config.sub grub/build-aux/config.sub diff -Paur --no-dereference -- grub.upstream/build-aux/config.sub grub/build-aux/config.sub
--- grub.upstream/build-aux/config.sub --- grub.upstream/build-aux/config.sub
+++ grub/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 FREETYPE=$ac_cv_prog_FREETYPE
if test -n "$FREETYPE"; then if test -n "$FREETYPE"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE" >&5 { $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 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.upstream/grub-core/lib/libgcrypt-grub/cipher/rijndael.c
+++ grub/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 @@ @@ -0,0 +1,2 @@
+#!/bin/sh -e +#!/bin/sh -e
+exec grub-mkconfig -o /boot/grub/grub.cfg "$@" +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 diff -Paur --no-dereference -- grub.upstream/util/getroot.c grub/util/getroot.c
--- grub.upstream/util/getroot.c --- grub.upstream/util/getroot.c
+++ grub/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 #else
/* Linux counts partitions uniformly, whether a BSD partition or a DOS /* 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 diff -Paur --no-dereference -- grub.upstream/util/grub-fstest.c grub/util/grub-fstest.c
--- grub.upstream/util/grub-fstest.c --- grub.upstream/util/grub-fstest.c
+++ grub/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 diff -Paur --no-dereference -- grub.upstream/util/grub-mkconfig.in grub/util/grub-mkconfig.in
--- grub.upstream/util/grub-mkconfig.in --- grub.upstream/util/grub-mkconfig.in
+++ grub/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 esac
done done
@ -767,6 +763,196 @@ diff -Paur --no-dereference -- grub.upstream/util/grub-mkconfig.in grub/util/gru
set $grub_probe dummy set $grub_probe dummy
if test -f "$1"; then 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 diff -Paur --no-dereference -- grub.upstream/util/misc.c grub/util/misc.c
--- grub.upstream/util/misc.c --- grub.upstream/util/misc.c
+++ grub/util/misc.c +++ grub/util/misc.c

View File

@ -1,6 +1,5 @@
#!/bin/sh -e #!/bin/sh -e
cp update-grub "$TIX_INSTALL_DIR$EXEC_PREFIX/sbin/update-grub" 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 if [ ! -e "$TIX_INSTALL_DIR$PREFIX/share/grub/unicode.pf2" ]; then
# Cheat as I'm not sure how to get this when cross-building. # Cheat as I'm not sure how to get this when cross-building.
[ -e /share/grub/unicode.pf2 ] && [ -e /share/grub/unicode.pf2 ] &&

View File

@ -90,7 +90,7 @@ and if
is set to is set to
.Sy no , .Sy no ,
then regenerate then regenerate
.Pa /etc/grub.d/10_sortix.cache . .Pa /etc/default/grub.d/10_sortix.cache .
.El .El
.Pp .Pp
The defaults will be used if The defaults will be used if

View File

@ -69,6 +69,74 @@ releasing Sortix x.y, foo." to allow the maintainer to easily
.Xr grep 1 .Xr grep 1
for it after a release. for it after a release.
.Sh CHANGES .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 .Ss Third generation Tix
The tix binary package format has upgraded from generation 2 to 3 and has a new 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. 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 unless the kernel command line contains
.Fl \-no-random-seed . .Fl \-no-random-seed .
The GRUB port has been updated with an improved 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. script that will automatically emit the appropriate GRUB commands.
.Pp .Pp
Users using the included GRUB will need to update to the latest GRUB port 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 or
.Xr sysmerge 8 .Xr sysmerge 8
or manually, the or manually, the
.Pa /etc/grub.d/10_sortix .Pa /etc/default/grub.d/10_sortix
script can be invoked, which will generate a 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 fragment that can be spliced into the configuration of another GRUB
installation. installation.
.Pp .Pp

View File

@ -6,7 +6,7 @@
.Nd layout of filesystems .Nd layout of filesystems
.Sh DESCRIPTION .Sh DESCRIPTION
The filesystem hierarchy is as follows: The filesystem hierarchy is as follows:
.Bl -tag -width "1234567891012" .Bl -tag -width "/boot/sysmerge"
.It Pa / .It Pa /
Root directory. Root directory.
.It Pa /bin .It Pa /bin
@ -16,6 +16,10 @@ Boot programs,
.Xr kernel 7 , .Xr kernel 7 ,
.Xr initrd 7 , .Xr initrd 7 ,
bootloader. bootloader.
.It Pa /boot/sysmerge
Temporary area for
.Xr sysmerge 8
delayed upgrades.
.It Pa /dev .It Pa /dev
Devices. Devices.
.It Pa /etc .It Pa /etc

View File

@ -529,7 +529,7 @@ If the included GRUB bootloader is used, after making the above edit, run
.Xr update-grub 8 .Xr update-grub 8
within the new installation to regenerate the bootloader configuration. within the new installation to regenerate the bootloader configuration.
Note that 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 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 package is updated or reinstalled, in which case you must make this change again
and run and run
@ -537,12 +537,12 @@ and run
again. again.
.Pp .Pp
If the included GRUB bootloader is not used, but instead the 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 fragment is spliced into another GRUB installation, make the above change and
then run the then run the
.Pa /etc/grub.d/10_sortix .Pa /etc/default/grub.d/10_sortix
command and use the freshly regenerated command and use the freshly regenerated
.Pa /etc/grub.d/10_sortix.cache .Pa /etc/default/grub.d/10_sortix.cache
fragment instead. fragment instead.
.Sh SEE ALSO .Sh SEE ALSO
.Xr chkblayout 1 , .Xr chkblayout 1 ,

View File

@ -46,6 +46,9 @@ install: all
install sysinstall $(DESTDIR)$(SBINDIR) install sysinstall $(DESTDIR)$(SBINDIR)
install sysmerge $(DESTDIR)$(SBINDIR) install sysmerge $(DESTDIR)$(SBINDIR)
install sysupgrade $(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 mkdir -p $(DESTDIR)$(MANDIR)/man8
cp sysinstall.8 $(DESTDIR)$(MANDIR)/man8/sysinstall.8 cp sysinstall.8 $(DESTDIR)$(MANDIR)/man8/sysinstall.8
cp sysmerge.8 $(DESTDIR)$(MANDIR)/man8/sysmerge.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-passwd
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-group 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-tix3g
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-grub-cache
sysinstall: $(SYSINSTALL_OBJS) sysinstall: $(SYSINSTALL_OBJS)
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount -ldisplay $(CC) $(SYSINSTALL_OBJS) -o $@ -lmount -ldisplay

29
sysinstall/grub Executable file
View File

@ -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

View File

@ -463,6 +463,28 @@ void upgrade_prepare(const struct release* old_release,
// Delay deleting installed.list since it's needed for the upgrade. // Delay deleting installed.list since it's needed for the upgrade.
hook_want_finalization(target_prefix, "sortix-1.1-tix3g"); 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, void upgrade_finalize(const struct release* old_release,

27
sysinstall/prepare Executable file
View File

@ -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

View File

@ -991,12 +991,13 @@ int main(void)
execute((const char*[]) { "chroot", "-d", ".", "update-grub", NULL }, execute((const char*[]) { "chroot", "-d", ".", "update-grub", NULL },
"_eqQ"); "_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"); printf(" - Creating bootloader fragment...\n");
execute((const char*[]) { "chroot", "-d", ".", execute((const char*[]) { "chroot", "-d", ".",
"/etc/grub.d/10_sortix", NULL }, "_eq"); "/etc/grub.d/default/10_sortix",
NULL }, "_eq");
} }
printf(" - Finishing installation...\n"); printf(" - Finishing installation...\n");
_exit(0); _exit(0);
@ -1530,8 +1531,9 @@ int main(void)
if ( strcasecmp(accept_grub, "no") == 0 ) if ( strcasecmp(accept_grub, "no") == 0 )
text("You did not accept a bootloader and need to set up bootloading " text("You did not accept a bootloader and need to set up bootloading "
"yourself. /etc/grub.d/10_sortix.cache is a GRUB configuration " "yourself. /etc/default/grub.d/10_sortix.cache is a GRUB "
"fragment that boots the newly installed system.\n\n"); "configuration fragment that boots the newly installed system."
"\n\n");
text("Upon boot, you'll be greeted with a login screen. Enter your " text("Upon boot, you'll be greeted with a login screen. Enter your "
"credentials to get a command line. Login as user 'poweroff' as " "credentials to get a command line. Login as user 'poweroff' as "

View File

@ -124,52 +124,50 @@ This option is implied unless
is passed. is passed.
.It Fl w , Fl \-wait .It Fl w , Fl \-wait
Wait until the next boot to complete the upgrade, rather than finishing it now. 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 .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 .Xr kernel 7
with the new kernel has a new
and
.Xr initrd 7 .Xr initrd 7
with an initrd that runs that runs
.Sy /sysmerge/sbin/sysmerge --booting .Sy /sysmerge/sbin/sysmerge --booting
on boot through the on boot through the
.Sy chain-merge .Sy chain-merge
.Xr init 8 .Xr init 8
boot target. boot target, which performs the operating system upgrade.
Backups are made of the The bootloader configuration is regenerated with a menu option to perform
.Xr kernel 7 the upgrade if grub is enabled in
and .Xr upgrade.conf 5 ,
.Xr initrd 7 otherwise the
such that the operation can be rolled back. .Pa /etc/default/grub.d/10_sortix.cache
bootloader fragment can be used to manually bootload the upgrade.
.El .El
.Sh FILES .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 .It Pa /boot/sortix.bin
system Old system
.Xr kernel 7 .Xr kernel 7 .
.It Pa /boot/sortix.bin.sysmerge.orig
system
.Xr kernel 7
(backup)
.It Pa /boot/sortix.initrd .It Pa /boot/sortix.initrd
system Old system
.Xr initrd 7 .Xr initrd 7 .
.It Pa /boot/sortix.initrd.sysmerge.orig .It Pa /boot/sysmerge/
system New system kernel and initrd files.
.Xr initrd 7 .It Pa /etc/default/grub.d/10_sortix.cache
(backup) GRUB configuration fragment that boots the new system.
.It Pa /etc/machine .It Pa /etc/machine
processor platform of this installation Processor platform of this installation.
.It Pa /etc/sortix-release .It Pa /etc/sortix-release
the current system release The current system release.
.It Pa /etc/upgrade.conf .It Pa /etc/upgrade.conf
controls the bootloader upgrade behavior (see Controls the bootloader upgrade behavior (see
.Xr upgrade.conf 5 ) .Xr upgrade.conf 5 ) .
.It Pa /share/sysinstall/hooks .It Pa /share/sysinstall/hooks/
A file per upgrade hook indicating that it doesn't need to be run. A file per upgrade hook indicating that it doesn't need to be run.
.It Pa /sysmerge .It Pa /sysmerge/
pending upgrade is stored here The pending systen upgrade is stored here.
.El .El
.Sh SEE ALSO .Sh SEE ALSO
.Xr development 7 , .Xr development 7 ,

View File

@ -86,20 +86,32 @@ static bool is_partition_name(const char* path)
static bool has_pending_upgrade(const char* target) 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"); 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"); err(2, "malloc");
bool result = access_or_die(kernel, F_OK) == 0 || bool result = access_or_die(sysmerge, F_OK) == 0 ||
access_or_die(initrd, F_OK) == 0 || access_or_die(boot_sysmerge, F_OK) == 0;
access_or_die(sysmerge, F_OK) == 0;
free(kernel);
free(initrd);
free(sysmerge); free(sysmerge);
free(boot_sysmerge);
return result; 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[]) int main(int argc, char* argv[])
{ {
setvbuf(stdout, NULL, _IOLBF, 0); // Pipes. setvbuf(stdout, NULL, _IOLBF, 0); // Pipes.
@ -207,20 +219,24 @@ int main(int argc, char* argv[])
if ( !has_system ) if ( !has_system )
system = false; 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; bool did_cancel = false;
if ( !no_cancel && has_pending_upgrade(target) ) 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"); 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"); err(2, "malloc");
rename(kernel, kernel_real);
rename(initrd, initrd_real);
execute((const char*[]) { "rm", "-rf", "--", sysmerge, NULL }, ""); 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"); printf("Cancelled pending system upgrade.\n");
did_cancel = true; did_cancel = true;
} }
@ -290,14 +306,6 @@ int main(int argc, char* argv[])
// TODO: Check for version (skipping, downgrading). // 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 = bool can_run_new_abi =
abi_compatible(new_release.abi_major, new_release.abi_minor, abi_compatible(new_release.abi_major, new_release.abi_minor,
old_release.abi_major, old_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* system_path = join_paths(target, "sysmerge/tix/sysmerge.system");
char* ports_path = join_paths(target, "sysmerge/tix/sysmerge.ports"); char* ports_path = join_paths(target, "sysmerge/tix/sysmerge.ports");
char* full_path = join_paths(target, "sysmerge/tix/sysmerge.full"); char* full_path = join_paths(target, "sysmerge/tix/sysmerge.full");
char* kernel = join_paths(target, "boot/sortix.bin.sysmerge.orig"); char* ready_path = join_paths(target, "sysmerge/tix/sysmerge.ready");
char* kernel_real = join_paths(target, "boot/sortix.bin"); char* sysmerge_boot = join_paths(target, "sysmerge/boot");
char* kernel_new = join_paths(target, "sysmerge/boot/sortix.bin"); char* boot_sysmerge = join_paths(target, "boot/sysmerge");
char* initrd = join_paths(target, "boot/sortix.initrd.sysmerge.orig"); if ( !system_path || !ports_path || !full_path || !ready_path ||
char* initrd_real = join_paths(target, "boot/sortix.initrd"); !sysmerge_boot || !boot_sysmerge )
if ( !system_path || !ports_path || !full_path || !kernel ||
!kernel_real || !kernel_new || !initrd || !initrd_real )
err(2, "malloc"); err(2, "malloc");
if ( full ) if ( full )
{ {
int fd = open(full_path, O_WRONLY | O_CREAT); int fd = open(full_path, O_WRONLY | O_CREAT);
@ -445,11 +452,25 @@ int main(int argc, char* argv[])
err(2, "%s", ports_path); err(2, "%s", ports_path);
close(fd); close(fd);
} }
execute((const char*[]) { "cp", kernel_real, kernel, NULL }, "e");
execute((const char*[]) { "cp", initrd_real, initrd, NULL }, "e"); // Generate the new initrd in /sysmerge/boot.
execute((const char*[]) { "cp", kernel_new, kernel_real, NULL }, "e"); execute((const char*[]) { "/sysmerge/libexec/sysmerge/prepare",
execute((const char*[]) { "/sysmerge/sbin/update-initrd", NULL }, "ce", NULL }, "ce", target);
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", printf("The system will be upgraded to %s on the next boot.\n",
new_release.pretty_name); new_release.pretty_name);
@ -477,21 +498,20 @@ int main(int argc, char* argv[])
return 0; 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 ) if ( has_system && booting )
{ {
char* kernel = join_paths(target, "boot/sortix.bin.sysmerge.orig"); char* ready_path = join_paths(target, "sysmerge/tix/sysmerge.ready");
char* initrd = join_paths(target, "boot/sortix.initrd.sysmerge.orig"); if ( !ready_path )
char* sysmerge = join_paths(target, "sysmerge");
if ( !kernel || !initrd || !sysmerge )
err(2, "malloc"); err(2, "malloc");
unlink(kernel); unlink(ready_path);
unlink(initrd); free(ready_path);
execute((const char*[]) { "rm", "-rf", "--", sysmerge, NULL }, "");
free(kernel);
free(initrd);
free(sysmerge);
} }
// 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 ) if ( has_system && access_or_die("/etc/fstab", F_OK) == 0 )
{ {
printf(" - Creating initrd...\n"); 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); err(2, "Failed to find device of filesystem: %s", boot_path);
close(boot_fd); close(boot_fd);
free(boot_path); free(boot_path);
// TODO: A better design for finding the parent block device of a // TODO: A better design for finding the parent block device.
// partition without scanning every block device.
if ( is_partition_name(boot_device) ) if ( is_partition_name(boot_device) )
*strrchr(boot_device, 'p') = '\0'; *strrchr(boot_device, 'p') = '\0';
printf(" - Installing bootloader...\n"); printf(" - Installing bootloader...\n");
execute((const char*[]) { "grub-install", boot_device, execute((const char*[]) { "grub-install", boot_device,
NULL }, "ceqQ", target); NULL }, "ceqQ", target);
free(boot_device); 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 ) if ( new_release.pretty_name )

View File

@ -920,12 +920,13 @@ int main(void)
"_eqQ"); "_eqQ");
} }
else if ( conf.system && 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"); printf(" - Creating bootloader fragment...\n");
execute((const char*[]) { "chroot", "-d", ".", execute((const char*[]) { "chroot", "-d", ".",
"/etc/grub.d/10_sortix", NULL }, "_eq"); "/etc/grub.d/default/10_sortix", NULL },
"_eq");
} }
printf(" - Finishing upgrade...\n"); printf(" - Finishing upgrade...\n");
_exit(0); _exit(0);

View File

@ -16,9 +16,12 @@
# update-initrd # update-initrd
# Generate an initrd(7) that locates and chain boots the real root filesystem. # 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 set -e
sysroot= sysroot=
sysmerge=false
dashdash= dashdash=
previous_option= previous_option=
@ -35,6 +38,7 @@ for argument do
esac esac
case $dashdash$argument in case $dashdash$argument in
--) dashdash=yes ;; --) dashdash=yes ;;
--sysmerge) sysmerge=true ;;
--sysroot=*) sysroot=$parameter ;; --sysroot=*) sysroot=$parameter ;;
--sysroot) previous_option=sysroot ;; --sysroot) previous_option=sysroot ;;
-*) echo "$0: unrecognized option $argument" >&2 -*) echo "$0: unrecognized option $argument" >&2
@ -49,17 +53,20 @@ if test -n "$previous_option"; then
exit 1 exit 1
fi fi
sysmerge=false root="$sysroot"
exec_prefix="$sysroot" output="$sysroot"
if [ -d "$sysroot/sysmerge" ]; then if $sysmerge; then
# If an upgrade is pending, invoke the update-initrd of the new system, if root="$sysroot/sysmerge"
# we're not already it. output="$root"
if [ "$(realpath -- "$(which -- "$0")")" != \ # TODO: After releasing Sortix 1.1, remove the check for /sysmerge as the old
"$(realpath -- "$sysroot/sysmerge/sbin/update-initrd")" ]; then # update-initrd will invoke the newer version and expect the new version
exec "$sysroot/sysmerge/sbin/update-initrd" "$@" # to notice that it is the version in /sysmerge. However, write the new
fi # 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 sysmerge=true
exec_prefix="$sysroot/sysmerge" root="$sysroot/sysmerge"
output="$sysroot"
fi fi
if [ ! -e "$sysroot/etc/fstab" ]; then if [ ! -e "$sysroot/etc/fstab" ]; then
echo "$0: $sysroot/etc/fstab: Need a filesystem table to make an initrd" >&2 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 trap 'rm -rf "$tmp"' EXIT HUP INT QUIT TERM
mkdir "$tmp/bin" mkdir "$tmp/bin"
mkdir "$tmp/sbin" mkdir "$tmp/sbin"
cp "$exec_prefix/sbin/init" "$tmp/sbin" cp "$root/sbin/init" "$tmp/sbin"
cp "$exec_prefix/sbin/extfs" "$tmp/sbin" cp "$root/sbin/extfs" "$tmp/sbin"
test -f "$exec_prefix/sbin/fsck.ext2" && test -f "$root/sbin/fsck.ext2" &&
cp "$exec_prefix/sbin/fsck.ext2" "$tmp/sbin" cp "$root/sbin/fsck.ext2" "$tmp/sbin"
mkdir "$tmp/etc" mkdir "$tmp/etc"
cp "$sysroot/etc/fstab" "$tmp/etc/fstab" cp "$sysroot/etc/fstab" "$tmp/etc/fstab"
mkdir "$tmp/etc/init" mkdir "$tmp/etc/init"
@ -85,7 +92,7 @@ else
require chain exit-code require chain exit-code
EOF EOF
fi fi
mkdir -p "$sysroot/boot" mkdir -p "$output/boot"
LC_AL=C ls -A "$tmp" | 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 - --numeric-owner --owner=0 --group=0 -T -

View File

@ -6,6 +6,7 @@
.Nd generate initialization ramdisk .Nd generate initialization ramdisk
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm update-initrd .Nm update-initrd
.Op Fl \-sysmerge
.Op Fl \-sysroot Ns "=" Ns Ar sysroot .Op Fl \-sysroot Ns "=" Ns Ar sysroot
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm update-initrd .Nm update-initrd
@ -31,19 +32,20 @@ should be regenerated by invoking
.Nm . .Nm .
.Pp .Pp
.Nm .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 is written as a script so the initrd of the new system can produced even
across incompatible ABI changes. across incompatible ABI changes.
.Pp .Pp
The options are as follows: The options are as follows:
.Bl -tag -width "12345678" .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 .It Fl \-sysroot Ns "=" Ns Ar sysroot
Rather than generating an Rather than generating an
.Xr initrd 7 .Xr initrd 7