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