summaryrefslogtreecommitdiff
path: root/f3s/pi-netbsd/flash/95netbsdflash/flash.sh
blob: c15bb710cc002ebf7010a4d45b6c96934942d956 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/bin/sh
# dracut pre-mount hook (SOURCED by dracut init — must not call exit/return at
# top level in a way that aborts init; we keep all action inside an `if`).
#
# Trigger: a file `netbsd-flash-mode` (contents "dryrun" or "real") on the FAT
# /boot partition. If absent, this hook does nothing and normal boot continues.
#
# SAFETY: the very first thing we do once triggered is DISARM — delete
# config.txt and the trigger from the FAT partition — so that if anything later
# fails, a power-cycle boots normally back into Rocky (config.txt gone => the Pi
# firmware loads no initramfs).

FATDEV=/dev/mmcblk0p1
ROOTDEV=/dev/mmcblk0p3
DISK=/dev/mmcblk0

nf_log() { echo "netbsdflash: $*"; echo "netbsdflash: $*" > /dev/kmsg 2>/dev/null; }
nf_reboot() { sync; sleep 2; reboot -f 2>/dev/null; sleep 2; echo b > /proc/sysrq-trigger 2>/dev/null; sleep 15; }

mkdir -p /nf_fat /nf_root /nf_ram 2>/dev/null
NF_MODE=""
if mount -t vfat "$FATDEV" /nf_fat 2>/dev/null; then
    [ -f /nf_fat/netbsd-flash-mode ] && NF_MODE=$(tr -d ' \r\n' < /nf_fat/netbsd-flash-mode 2>/dev/null)
fi

if [ -n "$NF_MODE" ]; then
    nf_log "TRIGGERED mode=$NF_MODE"
    # --- DISARM FIRST (self-heal on any later failure) ---
    rm -f /nf_fat/config.txt /nf_fat/netbsd-flash-mode 2>/dev/null
    sync
    echo "FLASHER-RAN mode=$NF_MODE up=$(cat /proc/uptime 2>/dev/null)" > /nf_fat/flash-evidence.txt 2>/dev/null
    sync
    nf_log "disarmed; evidence written"

    # --- stage golden image from ext4 root into RAM ---
    NF_OK=1
    if ! mount -t ext4 -o ro "$ROOTDEV" /nf_root 2>/dev/null; then
        nf_log "FATAL mount root"; echo "FATAL mount-root" >> /nf_fat/flash-evidence.txt; NF_OK=0
    fi
    GZ=""
    for cand in /nf_root/home/paul/netbsd-*-golden.img.gz /nf_root/root/netbsd-*-golden.img.gz; do
        [ -f "$cand" ] && { GZ="$cand"; break; }
    done
    if [ "$NF_OK" = 1 ] && [ -z "$GZ" ]; then
        nf_log "FATAL image-missing"; echo "FATAL image-missing" >> /nf_fat/flash-evidence.txt; NF_OK=0
    fi
    if [ "$NF_OK" = 1 ]; then
        mount -t tmpfs -o size=550m tmpfs /nf_ram 2>/dev/null
        if cp "$GZ" /nf_ram/g.gz 2>/dev/null; then
            nf_log "staged $(wc -c < /nf_ram/g.gz 2>/dev/null) bytes in RAM"
        else
            nf_log "FATAL copy-to-RAM"; echo "FATAL copy-RAM" >> /nf_fat/flash-evidence.txt; NF_OK=0
        fi
    fi
    umount /nf_root 2>/dev/null
    sync

    if [ "$NF_OK" = 1 ] && [ "$NF_MODE" = dryrun ]; then
        bytes=$(gzip -dc /nf_ram/g.gz 2>/dev/null | wc -c); rc=$?
        nf_log "DRYRUN bytes=$bytes rc=$rc"
        echo "DRYRUN-RESULT bytes=$bytes rc=$rc" >> /nf_fat/flash-evidence.txt
        sync; umount /nf_fat 2>/dev/null
        nf_log "DRYRUN done; rebooting to Rocky"
        nf_reboot
    elif [ "$NF_OK" = 1 ]; then
        echo "REAL-START up=$(cat /proc/uptime 2>/dev/null)" >> /nf_fat/flash-evidence.txt
        sync; umount /nf_fat 2>/dev/null
        nf_log "REAL: writing image onto $DISK"
        gzip -dc /nf_ram/g.gz 2>/dev/null | dd of="$DISK" bs=4M conv=fsync 2>&1 | tail -2 | while read -r l; do nf_log "dd: $l"; done
        sync
        nf_log "REAL flash complete; rebooting into NetBSD"
        nf_reboot
    else
        # a FATAL occurred; config.txt already removed, so reboot -> Rocky
        sync; umount /nf_fat 2>/dev/null
        nf_log "aborted; rebooting to Rocky"
        nf_reboot
    fi
else
    # not triggered: clean up and let the normal boot proceed
    umount /nf_fat 2>/dev/null
fi