Rebuilt with KBUILD_BUILD_USER/HOST/TIMESTAMP pinned. Without them the kernel bakes the builder's user@hostname and wall-clock build time into /proc/version, which publishes operator identity in a public artifact and makes the build unreproducible. Pinned, anyone can rebuild and diff the bytes — the only trust story available for an unsigned community kernel. The installer refuses to run on anything but a Pi 4, refuses a mismatched image/modules pair (vermagic failure means no /dev/pps0 on a kernel that otherwise boots fine — silent and miserable to debug), verifies SHA256SUMS, never touches kernel8.img, and leaves rollback as deleting one config.txt line. Boot-tested on the Pi: Stratum 1, 273 ns offset, PPS handler confirmed NOT threaded. Binaries ship as release assets, not in git.
86 lines
3.4 KiB
Bash
Executable File
86 lines
3.4 KiB
Bash
Executable File
#!/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
|