Kernel release 6.18.38-rt-cuckoo+: reproducible build, guarded installer
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.
This commit is contained in:
parent
6b6d80ded3
commit
3b505644b2
15 changed files with 333 additions and 62 deletions
85
kernel/release/install-rt-kernel.sh
Executable file
85
kernel/release/install-rt-kernel.sh
Executable file
|
|
@ -0,0 +1,85 @@
|
|||
#!/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
|
||||
Loading…
Add table
Add a link
Reference in a new issue