mirror of
https://github.com/Klipper4FlashForge/firmware.git
synced 2026-10-22 21:32:16 -05:00
Builds a modified FlashForge update package that the printer installs by itself from a USB stick, reusing FlashForge's own updater rather than a parallel one. Integration is a single file: /usr/prog/PROGRAM/software/firmwareExe is replaced with a shell script. Everything funnels through that binary, so app_startup.sh, rcS and the init chain stay completely stock. The genuine binary is kept as firmwareExe.stock and remains the default UI. Key findings from the stock firmware, each enforced by a test: - components named *.tar.xz are PLAIN tar; the installer runs bare `tar -xvf` - the .tgz is DES3-encrypted plain tar, not gzip - nothing in init starts Klipper -- firmwareExe runs start.sh, so replacing the UI without S70klipper leaves a printer that cannot move - the installer wipes the software dir before run.sh, so an uninstall package must ship the genuine firmwareExe rather than back one up - ssh already works: stock ships dropbear + an enabled S50dropbear, only the root password is missing Brick-safety is designed in, not bolted on: a five-rung profile ladder starting with a probe that changes nothing, a container-based simulation that actually runs the installer and asserts the printer would still boot, an uninstall round-trip test, and a SAFE-MODE latch for UI crash loops. 75 checks pass. Not yet run on hardware.
117 lines
4.8 KiB
Bash
117 lines
4.8 KiB
Bash
#!/usr/bin/env bash
|
|
# 3/3 -- repack work/software back into an installable USB package.
|
|
#
|
|
# ./pack.sh full package (keeps kernel/control/library)
|
|
# ./pack.sh --slim software component only (~26MB, fast to write/test)
|
|
# ./pack.sh --plain no encryption: emits runFirmwareExe.sh + payload
|
|
# for the /mnt/runFirmwareExe.sh dev path
|
|
set -euo pipefail
|
|
. "$(dirname "$0")/common.sh"
|
|
|
|
SLIM=0; PLAIN=0
|
|
for a in "$@"; do
|
|
case "$a" in
|
|
--slim) SLIM=1 ;;
|
|
--plain) PLAIN=1 ;;
|
|
*) echo "unknown option: $a" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
[ -d work/software ] || { echo "run ./unpack.sh first" >&2; exit 1; }
|
|
STOCK_SW_VER=$(cat work/.stock_sw_ver)
|
|
OUT_VER="${SW_VER:-$STOCK_SW_VER}"
|
|
|
|
rm -rf work/stage work/out
|
|
mkdir -p work/stage work/out
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 1. md5sum.list -- the installer hard-gates on this. Paths must be "./rel",
|
|
# and the list must not contain itself.
|
|
# ---------------------------------------------------------------------------
|
|
echo ">> regenerating md5sum.list"
|
|
( cd work/software
|
|
rm -f md5sum.list
|
|
find . -type f ! -name md5sum.list -print0 \
|
|
| sort -z \
|
|
| xargs -0 md5sum > md5sum.list
|
|
echo " $(wc -l < md5sum.list) entries" )
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 2. software-<ver>.tar.xz
|
|
#
|
|
# !! NOT actually xz-compressed. FlashForge's own components are PLAIN
|
|
# tar archives that merely carry a .tar.xz name -- verify with
|
|
# `file work/outer/software-*.tar.xz`. The stock installer extracts them
|
|
# with a bare `tar -xvf`, so a genuinely xz-compressed file here does not
|
|
# install. Keep this a plain tar.
|
|
# ---------------------------------------------------------------------------
|
|
echo ">> building software-$OUT_VER.tar.xz (plain tar, matching stock)"
|
|
tar -cf "work/stage/software-$OUT_VER.tar.xz" -C work/software .
|
|
ls -lh "work/stage/software-$OUT_VER.tar.xz" | awk '{print " "$5}'
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 3. the rest of the outer package
|
|
# ---------------------------------------------------------------------------
|
|
# The mod payload: rides in the outer package so it lands on /usr/data,
|
|
# not on the firmware partition.
|
|
if [ -d work/modpayload ]; then
|
|
# This one IS really xz: we extract it ourselves with `xz -dc`, and
|
|
# FlashForge's factory installer proves xz exists on the printer.
|
|
echo ">> compressing mod.tar.xz (Mainsail / HelixScreen / bin)"
|
|
tar -cf - -C work/modpayload . | xz -T0 -6 > work/stage/mod.tar.xz
|
|
ls -lh work/stage/mod.tar.xz | awk '{print " "$5}'
|
|
fi
|
|
|
|
# FlashForge's own installer, reused verbatim -- it already does the whole
|
|
# USB auto-install dance. We only change what it installs.
|
|
cp -f work/outer/runFirmwareExe.sh work/stage/
|
|
chmod +x work/stage/runFirmwareExe.sh
|
|
for f in start.img end.img play; do
|
|
[ -f "work/outer/$f" ] && cp -f "work/outer/$f" work/stage/
|
|
done
|
|
if [ "$SLIM" = "0" ]; then
|
|
for f in work/outer/kernel-*.tar.xz work/outer/control-*.tar.xz work/outer/library-*.tar.xz; do
|
|
[ -f "$f" ] && cp -f "$f" work/stage/
|
|
done
|
|
fi
|
|
echo ">> outer payload:"
|
|
ls -la work/stage | sed 's/^/ /'
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 4. emit
|
|
# ---------------------------------------------------------------------------
|
|
BASE="${MOD_NAME:-mod}-${MOD_VER:-1.0.0}"
|
|
|
|
if [ "$PLAIN" = "1" ]; then
|
|
# app_startup.sh also honours a bare /mnt/runFirmwareExe.sh -- no crypto,
|
|
# no .tgz. Copy the whole work/out/plain/ tree to the USB root.
|
|
mkdir -p work/out/plain
|
|
cp -a work/stage/. work/out/plain/
|
|
echo
|
|
echo "PLAIN package: work/out/plain/ -> copy its CONTENTS to the USB root"
|
|
else
|
|
echo ">> tarring + encrypting"
|
|
# Outer tar is NOT gzipped despite the .tgz name -- unTar pipes the
|
|
# decrypted stream straight into `tar xvf -`.
|
|
tar -cf - -C work/stage . \
|
|
| openssl des3 -salt -md md5 -k "$FF_KEY" \
|
|
> "work/out/Creator5Pro-${BASE}.tgz"
|
|
|
|
# The Pro's app_startup.sh globs Creator5Pro-*.tgz, the non-Pro globs
|
|
# Creator5-*.tgz. Ship both names (FlashForge does the same with its
|
|
# factory package -- the two files are byte-identical).
|
|
cp -f "work/out/Creator5Pro-${BASE}.tgz" "work/out/Creator5-${BASE}.tgz"
|
|
|
|
echo
|
|
echo "Packages:"
|
|
ls -lh work/out/*.tgz | awk '{print " "$9" "$5}'
|
|
echo
|
|
echo "Sanity check (decrypt + list):"
|
|
openssl des3 -d -k "$FF_KEY" -salt -md md5 -in "work/out/Creator5Pro-${BASE}.tgz" 2>/dev/null \
|
|
| tar -tvf - | sed 's/^/ /'
|
|
echo
|
|
echo "Copy BOTH .tgz files to the root of a FAT32 USB stick, plug it in,"
|
|
echo "and power the printer on. It installs and reboots by itself."
|
|
echo "Install log afterwards: /usr/data/mod-install.log"
|
|
fi
|