#!/bin/sh
set -eu

script_dir=$(CDPATH= cd -- "$(dirname "$0")" && pwd)
kernel="$script_dir/bzImage"
initrd="$script_dir/initrd"
cmdline=$(tr '\n' ' ' < "$script_dir/cmdline" | sed 's/[[:space:]]\+/ /g; s/^ //; s/ $//')
extra_args="${KEXEC_KERNEL_APPEND:-}"
extra_initrd="${KEXEC_EXTRA_INITRD:-}"
tmp_initrd=
execute_delay="${KEXEC_EXEC_DELAY:-3}"

cleanup() {
  [ -n "${tmp_initrd:-}" ] && rm -f "$tmp_initrd"
}

trap cleanup EXIT INT TERM

[ -r "$kernel" ] || {
  echo "missing kernel image: $kernel" >&2
  exit 1
}
[ -r "$initrd" ] || {
  echo "missing initrd image: $initrd" >&2
  exit 1
}

if [ -n "$extra_initrd" ]; then
  [ -r "$extra_initrd" ] || {
    echo "extra initrd is not readable: $extra_initrd" >&2
    exit 1
  }
  tmp_initrd=$(mktemp "${TMPDIR:-/tmp}/guix-kexec-initrd.XXXXXX")
  cat "$initrd" "$extra_initrd" >"$tmp_initrd"
  initrd="$tmp_initrd"
fi

if [ -n "$extra_args" ]; then
  cmdline="$cmdline $extra_args"
fi

if [ -n "${KEXEC_BIN:-}" ]; then
  kexec_bin="$KEXEC_BIN"
elif [ -x "$script_dir/kexec-static" ]; then
  kexec_bin="$script_dir/kexec-static"
elif command -v kexec >/dev/null 2>&1; then
  kexec_bin=$(command -v kexec)
else
  echo "kexec binary not found and no bundled fallback present" >&2
  exit 1
fi

kexec_load_flags=
if printf '%s\n' "6.1" "$(uname -r)" | sort -c -V 2>/dev/null; then
  kexec_load_flags="--kexec-syscall-auto"
fi

echo "kexec: loading $kernel"
echo "kexec: initrd=$initrd ($(wc -c < "$initrd") bytes)"
"$kexec_bin" --load "$kernel" $kexec_load_flags --initrd="$initrd" --command-line="$cmdline" --no-checks
echo "machine will boot into guix in ${execute_delay}s"
if [ -e /dev/kmsg ]; then
  exec >/dev/kmsg 2>&1
else
  exec >/dev/null 2>&1
fi
nohup sh -c "sleep '$execute_delay' && exec '$kexec_bin' -e" &
