#!/bin/sh
# rikkiti-esp-sync — keep the systemd-boot ESP in sync with /boot AND run the
# un-brickable-boot machinery (docs/47 Layers B + C). Fires from
# etc/kernel/{postinst,postrm}.d + etc/initramfs/post-update.d (kernel install/removal
# + every initramfs regen). Also shipped in the rikkiti-desktop deb, so it RETROFITS
# existing systemd-boot installs on `apt upgrade`.
#
# What it does on a real KERNEL change:
#   1. DKMS GATE — if an NVIDIA GPU + nvidia DKMS module are present, the new kernel
#      must have a BUILT module before it becomes the default. If not, KEEP the current
#      default kernel (a driver-less kernel would black-screen) and drop an update-warning
#      for the session to surface. (Layer B.)
#   2. Rotate the outgoing default kernel to /rikkiti/lastgood + write rikkiti-lastgood.conf
#      + the last-good pointer that rikkiti-boot-health reverts to. (Layer C.)
#   3. Copy the new kernel in as the default.
#   (initramfs-only regen of the same kernel just refreshes the default images.)
# Always: (re)write the "safe graphics" entry (software render) so it tracks the default.
#
# ★ INERT on anything that isn't our systemd-boot layout (legacy GRUB boxes) — exits 0,
#   touches nothing. This is what makes the deb safe to push to the whole fleet.
set -eu
ESP=/boot/efi
RIK="$ESP/rikkiti"
ENTRIES="$ESP/loader/entries"
[ -d "$RIK" ] && [ -d "$ENTRIES" ] || exit 0     # not our layout -> no-op (fleet-safe)

DRY=0; [ "${1:-}" = "--dry-run" ] && DRY=1
say(){ echo "rikkiti-esp-sync: $*"; }
copy(){ if [ "$DRY" = 1 ]; then echo "  would cp $1 -> $2"; else cp -f "$1" "$2"; fi; }
mkd(){  if [ "$DRY" = 1 ]; then echo "  would mkdir -p $1"; else mkdir -p "$1"; fi; }
writef(){ # $1=path $2=content
	if [ "$DRY" = 1 ]; then echo "  would write $1:"; printf '%s' "$2" | sed 's/^/        | /'
	else printf '%s' "$2" > "$1"; fi; }

KVER=$(ls /boot/vmlinuz-* 2>/dev/null | sed 's#.*/vmlinuz-##' | sort -V | tail -1)
[ -n "$KVER" ] || exit 0
STAMP="$RIK/kver"; CUR=$(cat "$STAMP" 2>/dev/null || echo "")

# Inherit the kernel cmdline (root=UUID=… rw quiet splash) from the live default entry
# so the revert/safe entries mount the same root; cache it for regen-only runs.
opts=$(sed -n 's/^options[[:space:]]*//p' "$ENTRIES/rikkiti.conf" 2>/dev/null | head -1)
[ -n "$opts" ] || opts=$(cat "$RIK/kopts" 2>/dev/null || echo "rw quiet splash")

# DKMS gate: OK unless an nvidia DKMS module exists but isn't built+installed for $KVER.
dkms_ok(){
	command -v dkms >/dev/null 2>&1 || return 0
	dkms status 2>/dev/null | grep -qi nvidia || return 0          # no nvidia dkms -> gate n/a
	dkms status 2>/dev/null | grep -i nvidia | grep -F "$KVER" | grep -qi installed
}

if [ "$KVER" != "$CUR" ]; then
	say "kernel change: $CUR -> $KVER"
	if dkms_ok; then
		# rotate outgoing default -> lastgood (only if we have a distinct previous kernel)
		if [ -f "$RIK/vmlinuz" ] && [ -n "$CUR" ]; then
			say "keeping previous kernel $CUR as last-good revert target"
			mkd "$RIK/lastgood"
			copy "$RIK/vmlinuz" "$RIK/lastgood/vmlinuz"
			copy "$RIK/initrd"  "$RIK/lastgood/initrd"
			writef "$ENTRIES/rikkiti-lastgood.conf" \
"title   Rikkiti OS (previous kernel $CUR)
linux   /rikkiti/lastgood/vmlinuz
initrd  /rikkiti/lastgood/initrd
options $opts
"
			writef "$RIK/last-good" "rikkiti-lastgood.conf"
		fi
		say "installing $KVER as the default"
		copy "/boot/vmlinuz-$KVER"    "$RIK/vmlinuz"
		copy "/boot/initrd.img-$KVER" "$RIK/initrd"
		writef "$STAMP" "$KVER"
		writef "$RIK/kopts" "$opts"
	else
		say "DKMS not built for $KVER — keeping default at $CUR, warning the user (Layer B gate)"
		mkd /var/lib/rikkiti
		writef /var/lib/rikkiti/update-warning \
"A kernel update ($KVER) couldn't build the NVIDIA driver, so Rikkiti kept your previous working kernel. Your system is safe to reboot; try the update again once a matching driver is available.
"
		logger -t rikkiti-esp-sync "DKMS not built for $KVER; kept default $CUR" 2>/dev/null || true
	fi
else
	# same kernel: just refresh the default images (e.g. an initramfs regen)
	copy "/boot/vmlinuz-$KVER"    "$RIK/vmlinuz"
	copy "/boot/initrd.img-$KVER" "$RIK/initrd"
fi

# safe-graphics entry always tracks the default kernel (software render via rikkiti.safe=1)
writef "$ENTRIES/rikkiti-safe.conf" \
"title   Rikkiti OS (safe graphics)
linux   /rikkiti/vmlinuz
initrd  /rikkiti/initrd
options $opts rikkiti.safe=1
"
exit 0
