86 lines
3.4 KiB
Bash
86 lines
3.4 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
#
|
||
|
|
# Install the Cuckoo Escapement PREEMPT_RT kernel on a Raspberry Pi 4.
|
||
|
|
#
|
||
|
|
# The design goal here is ONE THING: you must never need physical access to the
|
||
|
|
# SD card because of something this script did. So:
|
||
|
|
#
|
||
|
|
# - kernel8.img (the stock kernel) is never touched
|
||
|
|
# - the RT kernel installs under a NEW filename
|
||
|
|
# - the ONLY change to config.txt is a single appended line
|
||
|
|
#
|
||
|
|
# If it doesn't boot: pull the card, open config.txt on any machine (it's a FAT
|
||
|
|
# partition, so a Windows laptop will do), delete that one line, put it back.
|
||
|
|
# The stock kernel returns. That's the entire rollback.
|
||
|
|
#
|
||
|
|
# Run it FROM the directory holding the release files.
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
IMG_NAME="kernel-rt.img"
|
||
|
|
BOOT="/boot/firmware"
|
||
|
|
|
||
|
|
die() { printf '\nERROR: %s\n' "$1" >&2; exit 1; }
|
||
|
|
|
||
|
|
[[ $EUID -eq 0 ]] || die "run with sudo"
|
||
|
|
|
||
|
|
# --- Refuse to run on hardware this kernel was not built for. A bcm2711 kernel
|
||
|
|
# --- on a Pi 5 does not boot, and the failure mode is a black screen on a
|
||
|
|
# --- headless box, which is exactly what we promised wouldn't happen.
|
||
|
|
MODEL="$(tr -d '\0' < /proc/device-tree/model 2>/dev/null || echo unknown)"
|
||
|
|
case "$MODEL" in
|
||
|
|
*"Raspberry Pi 4"*|*"Raspberry Pi Compute Module 4"*|*"Raspberry Pi 400"*) ;;
|
||
|
|
*) die "this kernel is bcm2711 (Pi 4) only — found: $MODEL" ;;
|
||
|
|
esac
|
||
|
|
|
||
|
|
[[ "$(uname -m)" == "aarch64" ]] || die "need a 64-bit OS (uname -m says $(uname -m))"
|
||
|
|
[[ -d "$BOOT" ]] || die "$BOOT not found — is this Raspberry Pi OS?"
|
||
|
|
|
||
|
|
IMG_GZ="$(ls -1 kernel-rt-*.img.gz 2>/dev/null | head -1)" || true
|
||
|
|
MODS="$(ls -1 rt-modules-*.tar.gz 2>/dev/null | head -1)" || true
|
||
|
|
[[ -n "${IMG_GZ:-}" && -n "${MODS:-}" ]] || die "run this from the directory containing the release files"
|
||
|
|
|
||
|
|
# --- The image and the modules MUST come from the same build. A mismatched pair
|
||
|
|
# --- means modprobe fails on vermagic — and since pps-gpio is a module, that
|
||
|
|
# --- means no /dev/pps0 and no refclock, on a kernel that otherwise boots fine.
|
||
|
|
# --- Silent, and miserable to debug. Check it up front.
|
||
|
|
IMG_VER="${IMG_GZ#kernel-rt-}"; IMG_VER="${IMG_VER%.img.gz}"
|
||
|
|
MOD_VER="${MODS#rt-modules-}"; MOD_VER="${MOD_VER%.tar.gz}"
|
||
|
|
[[ "$IMG_VER" == "$MOD_VER" ]] \
|
||
|
|
|| die "image ($IMG_VER) and modules ($MOD_VER) are from different builds"
|
||
|
|
|
||
|
|
if [[ -f SHA256SUMS ]]; then
|
||
|
|
echo "==> verifying checksums"
|
||
|
|
sha256sum -c SHA256SUMS || die "checksum mismatch — do not install this"
|
||
|
|
else
|
||
|
|
echo "!! no SHA256SUMS present — skipping verification (not recommended)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "==> installing modules for $MOD_VER"
|
||
|
|
tar -C / -xzf "$MODS"
|
||
|
|
depmod -a "$MOD_VER"
|
||
|
|
|
||
|
|
echo "==> installing kernel as $BOOT/$IMG_NAME (kernel8.img left alone)"
|
||
|
|
zcat "$IMG_GZ" > "$BOOT/$IMG_NAME"
|
||
|
|
|
||
|
|
if grep -qE "^kernel=$IMG_NAME" "$BOOT/config.txt"; then
|
||
|
|
echo "==> config.txt already selects $IMG_NAME"
|
||
|
|
else
|
||
|
|
cp "$BOOT/config.txt" "$BOOT/config.txt.before-rt"
|
||
|
|
printf '\n# Cuckoo Escapement RT kernel. DELETE THIS LINE to boot the stock kernel.\nkernel=%s\n' \
|
||
|
|
"$IMG_NAME" >> "$BOOT/config.txt"
|
||
|
|
echo "==> appended 'kernel=$IMG_NAME' to config.txt (backup: config.txt.before-rt)"
|
||
|
|
fi
|
||
|
|
|
||
|
|
cat <<EOF
|
||
|
|
|
||
|
|
Done. Reboot, then confirm:
|
||
|
|
|
||
|
|
uname -a # expect $MOD_VER ... SMP PREEMPT_RT
|
||
|
|
ps -eo comm | grep irq/.*pps # expect NOTHING — the handler must not be
|
||
|
|
# a thread. If you see one, the patch isn't
|
||
|
|
# in this kernel and your jitter will be bad.
|
||
|
|
|
||
|
|
To roll back: delete the 'kernel=$IMG_NAME' line from $BOOT/config.txt
|
||
|
|
(or restore config.txt.before-rt) and reboot.
|
||
|
|
EOF
|