diff --git a/build.sh b/build.sh index 226f864..374aa36 100755 --- a/build.sh +++ b/build.sh @@ -39,7 +39,8 @@ pathlib.Path("dist/pico-main.py").write_text(pathlib.Path("pico/main.py").read_t print("copied pico-main.py") import zipfile # PM_K-1 CircuitPython drive bundle (download → unzip onto CIRCUITPY) with zipfile.ZipFile("dist/pm_k1_circuitpy.zip", "w", zipfile.ZIP_DEFLATED) as z: - for f in ("code.py", "boot.py", "programs.json", "font_s.bin", "font_m.bin", "font_l.bin", "README.md"): + for f in ("code.py", "boot.py", "programs.json", "font_s.bin", "font_m.bin", "font_l.bin", + "README.md", "protect-firmware.sh"): z.write("pico-cp/" + f, f) z.write("dist/editor.html", "editor.html") # offline copy of the editor, on the drive print("zipped pm_k1_circuitpy.zip") diff --git a/pico-cp/README.md b/pico-cp/README.md index 72da209..81047b5 100644 --- a/pico-cp/README.md +++ b/pico-cp/README.md @@ -36,6 +36,21 @@ If the editor says **no MIDI input is connected**, copy **`boot.py`** onto `CIRC **power-cycle** the Pico (`boot.py` only runs on a full reset). It frees a USB endpoint (drops the unused HID interface) so the MIDI port is guaranteed to appear alongside the drive. +## Protect the firmware (so end users only see the editor + their tracks) + +To stop someone accidentally deleting the firmware, **hide it** — the files keep running and +"Save to device" still works, but only `editor.html` + `programs.json` show in the file browser. +On the host, with the drive mounted, run the included helper (needs `fatattr`): + +``` +./protect-firmware.sh /media/$USER/CIRCUITPY # hides code.py, boot.py, font_*.bin, README, itself +``` + +(Reveal again with `fatattr -h `.) For a **hard lock** — nothing on the drive can be changed +from the computer at all — put `storage.remount("/", readonly=True)` in `boot.py`; but then the +editor's *Save to device* can't write either, so you'd reprogram by temporarily removing that line +(or gating it behind a held button at power-on). Hiding is usually the right balance. + ## Controls (same as the MicroPython build) - **Touch:** on‑screen `◀◀ / ▶ / ▶▶` (prev · play/stop · next) and `− / TAP / +`. diff --git a/pico-cp/protect-firmware.sh b/pico-cp/protect-firmware.sh new file mode 100755 index 0000000..a5608ab --- /dev/null +++ b/pico-cp/protect-firmware.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Hide the PM_K-1 firmware files on a CIRCUITPY drive so an end user only sees +# editor.html + programs.json — the two files they're meant to touch. The hidden +# files keep running, and the editor's "Save to device" still works (programs.json +# stays writable). This just prevents *accidental* deletion of the firmware. +# +# Run it on the HOST, pointing at the mounted drive: +# ./protect-firmware.sh /media/$USER/CIRCUITPY +# (defaults to the current directory if run from inside the drive). Needs `fatattr` +# (sudo apt install fatattr) — or use the mtools fallback printed below. +# +# To reveal them again: fatattr -h +set -euo pipefail +DIR="${1:-.}" +HIDE=(code.py boot.py font_s.bin font_m.bin font_l.bin README.md protect-firmware.sh boot_out.txt) + +if command -v fatattr >/dev/null 2>&1; then + for f in "${HIDE[@]}"; do + if [ -e "$DIR/$f" ]; then fatattr +h "$DIR/$f" && echo "hidden: $f"; fi + done + echo "Done — the drive now shows only editor.html + programs.json." +else + echo "fatattr not found. Install it: sudo apt install fatattr (or dnf/pacman equivalent)" + echo "Or, with mtools, run e.g.: mattrib -i /dev/sdX1 +h ::code.py ::boot.py ::font_*.bin" + exit 1 +fi