121 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
#!/usr/bin/env bash
 | 
						|
# Copyright (C) 2023  Umorpha Systems
 | 
						|
# SPDX-License-Identifier: AGPL-3.0-or-later
 | 
						|
 | 
						|
set -euE -o pipefail
 | 
						|
 | 
						|
v() {
 | 
						|
	printf >&2 '  $ %s\n' "${*@Q}"
 | 
						|
	"$@"
 | 
						|
}
 | 
						|
 | 
						|
main() {
 | 
						|
	local rootfs size
 | 
						|
	case "$1" in
 | 
						|
		*rootfs*)
 | 
						|
			rootfs="$1"
 | 
						|
			size=$(stat --format='%s' -- "$rootfs")
 | 
						|
			;;
 | 
						|
		--stdin=*)
 | 
						|
			rootfs=/dev/stdin
 | 
						|
			size=${1#--stdin=}
 | 
						|
			;;
 | 
						|
		*)
 | 
						|
			echo >&2 "!! Filename '${1}' does not look like a rootfs filename"
 | 
						|
			return 2
 | 
						|
			;;
 | 
						|
	esac
 | 
						|
 | 
						|
	########################################################################
 | 
						|
 | 
						|
	cleanup=()
 | 
						|
	_do_cleanup() {
 | 
						|
		if [[ $? == 0 ]]; then
 | 
						|
			echo ":: Cleaning up..."
 | 
						|
		else
 | 
						|
			echo >&2 "!! ERROR! Cleaning up..."
 | 
						|
		fi
 | 
						|
		for (( i=${#cleanup[@]}-1; i >= 0; i-- )); do
 | 
						|
			eval "${cleanup[$i]}"
 | 
						|
		done
 | 
						|
	}
 | 
						|
	trap '_do_cleanup' EXIT
 | 
						|
 | 
						|
	########################################################################
 | 
						|
 | 
						|
	local booted other
 | 
						|
	booted=$(awk '$2 == "/run/umorpha-root/root"{print $1}' </proc/mounts)
 | 
						|
	booted=${booted##*_}
 | 
						|
	if [[ $booted == a ]]; then
 | 
						|
		other=b
 | 
						|
	else
 | 
						|
		other=a
 | 
						|
	fi
 | 
						|
 | 
						|
	echo ":: Installing '${rootfs}' to slot '$other'"
 | 
						|
 | 
						|
	v rm -f -- "/boot/grub/grub_$other.cfg"
 | 
						|
 | 
						|
	if [[ -e /dev/mapper/vg_umorpha-lv_root_$other ]]; then
 | 
						|
		# Ugg, lvresize exits with non-zero for no-ops, which we can't
 | 
						|
		# even really do a pre-flight check for since it might round a
 | 
						|
		# size up.
 | 
						|
		v lvresize --size="${size}b" "/dev/mapper/vg_umorpha-lv_root_$other" || true
 | 
						|
	else
 | 
						|
		v lvcreate --zero=y --wipesignatures=y --yes --name="lv_root_$other" \
 | 
						|
			 --size="${size}b" vg_umorpha
 | 
						|
	fi
 | 
						|
	if [[ "$rootfs" == /dev/stdin ]]; then
 | 
						|
		v pv --size="${size}" >"/dev/mapper/vg_umorpha-lv_root_$other"
 | 
						|
	else
 | 
						|
		v pv -- "$rootfs" >"/dev/mapper/vg_umorpha-lv_root_$other"
 | 
						|
	fi
 | 
						|
 | 
						|
	########################################################################
 | 
						|
 | 
						|
	local tmpdir
 | 
						|
	tmpdir="$(mktemp -dt "${0##*/}.XXXXXXXXXX")"
 | 
						|
	cleanup+="rmdir -- ${tmpdir@Q}"
 | 
						|
 | 
						|
	########################################################################
 | 
						|
 | 
						|
	echo ":: Configuring boot"
 | 
						|
 | 
						|
	local selector_boot selector_root selector_overlay
 | 
						|
	selector_root="$(   blkid --output=export "/dev/mapper/vg_umorpha-lv_root_$other" | grep ^UUID=)"
 | 
						|
	selector_boot="$(   xargs -a /proc/cmdline printf '%s\n' | sed -n 's/^boot=//p')"
 | 
						|
	selector_overlay="$(xargs -a /proc/cmdline printf '%s\n' | sed -n 's/^overlay=//p')"
 | 
						|
	v declare -p selector_boot selector_root selector_overlay
 | 
						|
 | 
						|
	mkdir "$tmpdir/mnt"
 | 
						|
	cleanup+=("rmdir -- ${tmpdir@Q}/mnt")
 | 
						|
	v mount -o ro -- "/dev/mapper/vg_umorpha-lv_root_$other" "$tmpdir/mnt"
 | 
						|
	cleanup+=("v umount ${tmpdir@Q}/mnt")
 | 
						|
 | 
						|
	v mount -o bind -- /etc/mkinitcpio.d "${tmpdir}/mnt/etc/mkinitcpio.d"
 | 
						|
	cleanup+=("v umount ${tmpdir@Q}/mnt/etc/mkinitcpio.d")
 | 
						|
 | 
						|
	v mount -o bind -- /boot "${tmpdir}/mnt/boot"
 | 
						|
	cleanup+=("v umount ${tmpdir@Q}/mnt/boot")
 | 
						|
 | 
						|
	{
 | 
						|
		for krnl in "$tmpdir/mnt"/usr/lib/modules/*/vmlinuz; do
 | 
						|
			pkgbase=$(cat -- ${krnl%vmlinuz}pkgbase)
 | 
						|
			cat <<-EOF
 | 
						|
				menuentry 'Parabola GNU/Linux-libre, slot ${other}, ${pkgbase} kernel'
 | 
						|
				  set search --no-floppy --fs-uuid --set=root ${selector_boot#UUID=}
 | 
						|
				  echo 'Loading ${pkgbase} kernel...'
 | 
						|
				  linux /vmlinuz-${pkgbase} root=$selector_root overlay=$selector_overlay boot=$selector_boot rw
 | 
						|
				  echo 'Loading initial ramdisk...'
 | 
						|
				  initrd /initramfs-${pkgbase}.img
 | 
						|
				  echo 'Booting...'
 | 
						|
				  boot
 | 
						|
			EOF
 | 
						|
		done
 | 
						|
	} | install -Dm600 /dev/stdin "/boot/grub/grub_$other.cfg"
 | 
						|
 | 
						|
	v arch-chroot -- "$tmpdir/mnt" sh -c "printf '%s\n' usr/lib/modules/*/vmlinuz | /usr/share/libalpm/scripts/mkinitcpio install"
 | 
						|
}
 | 
						|
 | 
						|
main "$@"
 |